📄 dynsched.cpp
字号:
// DynSched.cpp,v 1.49 2004/01/01 06:27:17 bala Exp
//
// ============================================================================
//
// = LIBRARY
// sched
//
// = FILENAME
// DynSched.cpp
//
// = CREATION DATE
// 23 January 1997
//
// = AUTHOR
// Chris Gill
//
// ============================================================================
#include "DynSched.h"
#include "ace/Basic_Types.h"
#include "ace/Sched_Params.h"
#include "ace/OS_NS_stdio.h"
#include "ace/Null_Mutex.h"
#if ! defined (__ACE_INLINE__)
#include "DynSched.i"
#endif /* __ACE_INLINE__ */
ACE_RCSID(Sched, DynSched, "DynSched.cpp,v 1.49 2004/01/01 06:27:17 bala Exp")
//////////////////////
// Helper functions //
//////////////////////
// compare the DFS finish times of two task entries, order higher time *first*
#if defined (ACE_HAS_WINCE)
int _cdecl compare_entry_finish_times (const void *first, const void *second)
#else
extern "C" int compare_entry_finish_times (const void *first, const void *second)
#endif // ACE_HAS_WINCE
{
// sort blank entries to the end
if (! first)
{
return (second) ? 1 : 0;
}
else if (! second)
{
return -1;
}
const Task_Entry *first_entry =
* ACE_static_cast (const Task_Entry *const *, first);
const Task_Entry *second_entry =
* ACE_static_cast (const Task_Entry *const *, second);
// sort blank entries to the end
if (! first_entry)
{
return (second_entry) ? 1 : 0;
}
else if (! second_entry)
{
return -1;
}
if (first_entry->finished () > second_entry->finished ())
{
return -1;
}
else if (first_entry->finished () < second_entry->finished ())
{
return 1;
}
return 0;
}
//////////////////////////////////////////
// class ACE_DynScheduler member functions //
//////////////////////////////////////////
const char *
ACE_DynScheduler::status_message (ACE_DynScheduler::status_t status)
{
switch (status)
{
case NOT_SCHEDULED :
return "NOT_SCHEDULED";
case SUCCEEDED :
return "SUCCEEDED";
case ST_NO_TASKS_REGISTERED :
return "ST_NO_TASKS_REGISTERED";
case ST_TASK_ALREADY_REGISTERED :
return "TASK_ALREADY_REGISTERED";
case ST_BAD_INTERNAL_POINTER :
return "BAD_INTERNAL_POINTER";
case ST_VIRTUAL_MEMORY_EXHAUSTED :
return "VIRTUAL_MEMORY_EXHAUSTED";
case ST_UNKNOWN_TASK :
return "UNKNOWN_TASK";
case TASK_COUNT_MISMATCH :
return "TASK_COUNT_MISMATCH";
case THREAD_COUNT_MISMATCH :
return "THREAD_COUNT_MISMATCH";
case INVALID_PRIORITY :
return "INVALID_PRIORITY";
case TWO_WAY_DISJUNCTION :
return "TWO_WAY_DISJUNCTION (IGNORED)";
case TWO_WAY_CONJUNCTION :
return "TWO_WAY_CONJUNCTION (IGNORED)";
case UNRECOGNIZED_INFO_TYPE :
return "UNRECOGNIZED_INFO_TYPE (IGNORED)";
// The following are only used during scheduling (in the case of
// off-line scheduling, they are only used prior to runtime).
// To save a little code space (280 bytes on g++ 2.7.2/Solaris 2.5.1),
// we could conditionally compile them so that they're not in the
// runtime version.
case ST_UTILIZATION_BOUND_EXCEEDED :
return "UTILIZATION_BOUND_EXCEEDED";
case ST_INSUFFICIENT_THREAD_PRIORITY_LEVELS :
return "INSUFFICIENT_THREAD_PRIORITY_LEVELS";
case ST_CYCLE_IN_DEPENDENCIES :
return "CYCLE_IN_DEPENDENCIES";
case ST_UNRESOLVED_REMOTE_DEPENDENCIES :
return "ST_UNRESOLVED_REMOTE_DEPENDENCIES";
case ST_UNRESOLVED_LOCAL_DEPENDENCIES :
return "ST_UNRESOLVED_LOCAL_DEPENDENCIES";
case ST_INVALID_PRIORITY_ORDERING :
return "INVALID_PRIORITY_ORDERING";
case UNABLE_TO_OPEN_SCHEDULE_FILE :
return "UNABLE_TO_OPEN_SCHEDULE_FILE";
case UNABLE_TO_WRITE_SCHEDULE_FILE :
return "UNABLE_TO_WRITE_SCHEDULE_FILE";
// End of config-only status values.
default:
break;
}
return "UNKNOWN STATUS";
}
// = Utility function for creating an entry for determining
// the severity of an anomaly detected during scheduling.
ACE_DynScheduler::Anomaly_Severity
ACE_DynScheduler::anomaly_severity (ACE_DynScheduler::status_t status)
{
// Determine severity of the anomaly
switch (status)
{
// Fatal anomalies reflect unrecoverable internal scheduler errors
case ST_BAD_INTERNAL_POINTER :
case ST_VIRTUAL_MEMORY_EXHAUSTED :
case THREAD_COUNT_MISMATCH :
case TASK_COUNT_MISMATCH :
return RtecScheduler::ANOMALY_FATAL;
// Errors reflect severe problems with given scheduling information
case UNABLE_TO_OPEN_SCHEDULE_FILE :
case UNABLE_TO_WRITE_SCHEDULE_FILE :
case NOT_SCHEDULED :
case ST_UNRESOLVED_LOCAL_DEPENDENCIES :
case ST_UNKNOWN_TASK :
case ST_CYCLE_IN_DEPENDENCIES :
case ST_INVALID_PRIORITY_ORDERING :
return RtecScheduler::ANOMALY_ERROR;
// Warnings reflect serious problems with given scheduling information
case ST_TASK_ALREADY_REGISTERED :
case ST_UNRESOLVED_REMOTE_DEPENDENCIES :
case ST_UTILIZATION_BOUND_EXCEEDED :
case ST_INSUFFICIENT_THREAD_PRIORITY_LEVELS :
case TWO_WAY_DISJUNCTION :
case TWO_WAY_CONJUNCTION :
case UNRECOGNIZED_INFO_TYPE :
case ST_NO_TASKS_REGISTERED :
return RtecScheduler::ANOMALY_WARNING;
// Produce a lowest severity anomaly for any unknown status value
default:
return RtecScheduler::ANOMALY_NONE;
}
}
// = Utility function for creating an entry for the
// log of anomalies detected during scheduling.
ACE_DynScheduler::Scheduling_Anomaly *
ACE_DynScheduler::create_anomaly (ACE_DynScheduler::status_t status)
{
ACE_DynScheduler::Scheduling_Anomaly * anomaly;
ACE_NEW_RETURN (anomaly, ACE_DynScheduler::Scheduling_Anomaly, 0);
anomaly->severity = anomaly_severity (status);
anomaly->description = status_message (status);
return anomaly;
}
ACE_DynScheduler::ACE_DynScheduler ()
// Set the minimum and maximum priority to those for the current platform.
// This shouldn't be necessary, but UPSingleProcessorOrb::initialize_reactors
// creates threads before the Event Channel calls Scheduler::init ().
: minimum_priority_ (ACE_Sched_Params::priority_min (ACE_SCHED_FIFO,
ACE_SCOPE_PROCESS))
, maximum_priority_ (ACE_Sched_Params::priority_max (ACE_SCHED_FIFO,
ACE_SCOPE_PROCESS))
, task_entries_ (0)
, ordered_task_entries_ (0)
, thread_delineators_ (0)
, ordered_thread_dispatch_entries_ (0)
, dispatch_entries_ (0)
, config_info_entries_ (0)
, expanded_dispatches_ (0)
, ordered_dispatch_entries_ (0)
, dispatch_entry_count_ (0)
, threads_ (0)
, timeline_ (0)
, lock_ ()
, rt_info_entries_ ()
, handles_ (0)
, runtime_filename_ (0)
, rt_info_filename_ (0)
, timeline_filename_ (0)
, tasks_ (0)
, status_ (NOT_SCHEDULED)
, output_level_ (0)
, frame_size_ (1)
, critical_set_frame_size_ (0)
, utilization_ (0.0)
, critical_set_utilization_ (0.0)
, minimum_priority_queue_ (0)
, minimum_guaranteed_priority_queue_ (-1)
, up_to_date_ (0)
, min_dispatch_id_ (0)
, max_dispatch_id_ (0)
{
}
ACE_DynScheduler::~ACE_DynScheduler ()
{
// release all resources used for the most recent schedule
reset ();
}
void
ACE_DynScheduler::init (const OS_Priority minimum_priority,
const OS_Priority maximum_priority,
const char *runtime_filename,
const char *rt_info_filename,
const char *timeline_filename)
{
minimum_priority_ = minimum_priority;
maximum_priority_ = maximum_priority;
runtime_filename_ = runtime_filename;
rt_info_filename_ = rt_info_filename;
timeline_filename_ = timeline_filename;
}
// = initializes the scheduler.
ACE_DynScheduler::status_t
ACE_DynScheduler::register_task (RT_Info *rt_info, handle_t &handle)
{
ACE_DynScheduler::status_t ret = ST_UNKNOWN_TASK;
// check the pointer we were passed
if (! rt_info)
{
handle = 0;
return ret;
}
// try to store the new task's information . . .
switch (rt_info_entries_.insert (rt_info))
{
case 0 : // successfully inserted
{
rt_info->handle = (handle = ++handles_);
ret = SUCCEEDED;
// zero out the task entry ACT used by the scheduler
rt_info->volatile_token = 0;
// make sure the schedule is reset when a new task is registered
reset ();
if (output_level () >= 5)
{
ACE_OS::printf ("registered task \"%s\" with RT_Info at %p\n",
(const char*)(rt_info->entry_point), rt_info);
}
}
break;
case 1 : // the entry had already been inserted
handle = 0;
ret = ST_TASK_ALREADY_REGISTERED;
break;
default :
// case -1 : insert failed, probably because virtual memory exhaused
handle = 0;
ret = ST_VIRTUAL_MEMORY_EXHAUSTED;
break;
}
return ret;
}
// = registers a task.
ACE_DynScheduler::status_t
ACE_DynScheduler::get_rt_info (Object_Name name,
RT_Info* &rtinfo)
{
handle_t handle;
// This makes a copy. We can optimize this with our own string
// class.
ACE_CString lookup (name);
// Search the map for the <name>. If found, return the RT_Info.
if (info_collection_.find (lookup, rtinfo) >= 0)
{
// If we find it, return.
return SUCCEEDED;
}
else
// Otherwise, make one, bind it, and register it.
{
rtinfo = new RT_Info;
rtinfo->info_type = RtecScheduler::OPERATION;
rtinfo->entry_point = CORBA::string_dup(name);
// Bind the rtinfo to the name.
if (info_collection_.bind (lookup, rtinfo) != 0)
{
delete rtinfo;
rtinfo = 0;
return FAILED; // Error!
}
else
{
// Register the task
status_t result = this->register_task (rtinfo, handle);
if (result == SUCCEEDED)
{
rtinfo->handle = handle;
return ST_UNKNOWN_TASK; // Didn't find it, but made one!
}
else
{
rtinfo->handle = 0;
return FAILED;
}
}
}
}
int ACE_DynScheduler::priority (
const RtecScheduler::handle_t handle,
RtecScheduler::OS_Priority &priority,
RtecScheduler::Preemption_Subpriority_t &subpriority,
RtecScheduler::Preemption_Priority_t &preemption_prio)
{
// look up the RT_Info that has the given handle
RT_Info *rt_info = 0;
if (lookup_rt_info (handle, rt_info) == SUCCEEDED)
{
// copy the priority values from the RT_Info
priority = rt_info->priority;
subpriority = rt_info->preemption_subpriority;
preemption_prio = rt_info->preemption_priority;
return 0;
}
else
{
// RT_Info not found: assign default priority values
priority = minimum_priority_;
subpriority = ACE_Scheduler_MIN_SUB_PRIORITY;
preemption_prio = ACE_Scheduler_MAX_PREEMPTION_PRIORITY;
if (output_level () >= 3)
{
ACE_OS::printf ("preemption_prio %d: min %d, pri %d, min_pri %d\n",
preemption_prio, minimum_priority_queue (),
priority, minimum_priority_);
}
return -1;
}
}
// "priority" is the OS thread priority that was assigned to the Task that
// was assigned "handle". "subpriority" combines the dynamic and static
// subpriorities of the Task that was assigned handle. "preemption_prio"
// is a platform-independent priority queue number, ranging from a
// highest priority value of 0 to the lowest priority value, which is
// returned by "minimum_priority_queue ()". The current and deadline times
// supplied are used to compute the operation's dynamic subpriority
// Returns 0 on success, or -1 if an invalid handle was supplied.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -