📄 strategy_scheduler.cpp
字号:
// rescheduled, and to the timeline entry heading the bilinked list of
// timeline entries to be removed.
Dispatch_Entry *removed_dispatch_entry
= &(link->entry ().dispatch_entry());
TimeLine_Entry *remove_entry = & (link->entry ());
// Put the dispatch entry into the set of entries that will be
// rescheduled at the end of this method (tail recursively).
reschedule_queue.enqueue_tail (removed_dispatch_entry);
// Advance the iterator to the next timeline entry (if there is one)
// that is not for the dispatch entry being removed.
while (iter.done () == 0)
{
// Point to the current link.
if ((iter.next (link) == 0) || (! link))
{
return ST_BAD_INTERNAL_POINTER;
}
// Advance until a different dispatch entry is found,
// or we run off the end of the timeline.
if (&(link->entry ().dispatch_entry ()) ==
removed_dispatch_entry)
{
iter.advance ();
}
else
{
break;
}
}
// Remove entries corresponding to the rescheduled
// dispatch from the timeline and destroy them.
TimeLine_Entry *next_remove_entry = 0;
while (remove_entry)
{
next_remove_entry = remove_entry->next ();
timeline_->remove (TimeLine_Entry_Link (*remove_entry));
delete remove_entry;
remove_entry = next_remove_entry;
}
}
// Exit the outer loop if there are no more entries in the timeline.
if (iter.done () != 0)
{
break;
}
// If there's room, schedule a new timeline entry for the dispatch.
if (link->entry ().start() > last_stop)
{
ACE_NEW_RETURN (
current_entry,
TimeLine_Entry (
dispatch_entry,
last_stop,
(((remaining_time + last_stop) < link->entry ().start())
? (remaining_time + last_stop) : link->entry ().start()),
dispatch_entry.arrival (),
dispatch_entry.deadline (),
(TimeLine_Entry *) 0, last_entry),
ST_VIRTUAL_MEMORY_EXHAUSTED);
// Patch up the pointers within the list of entries for this dispatch.
if (last_entry)
{
last_entry->next (current_entry);
}
last_entry = current_entry;
timeline_->insert(TimeLine_Entry_Link(*current_entry));
// Update the remaining time and last stop values.
remaining_time -= ((remaining_time < (link->entry ().start() - last_stop))
? remaining_time : (link->entry ().start() - last_stop));
}
// Update the last stop time.
if (last_stop < link->entry ().stop ())
{
last_stop = link->entry ().stop ();
}
}
// If there is still dispatch time remaining, and we've
// reached the end of the list, insert what's left.
if (remaining_time > 0U)
{
ACE_NEW_RETURN (
current_entry,
TimeLine_Entry (
dispatch_entry,
last_stop,
remaining_time + last_stop,
dispatch_entry.arrival (),
dispatch_entry.deadline (),
0, last_entry),
ST_VIRTUAL_MEMORY_EXHAUSTED);
// Patch up the pointers within the list of entries for this dispatch.
if (last_entry)
{
last_entry->next (current_entry);
}
timeline_->insert(TimeLine_Entry_Link(*current_entry));
}
return status;
}
////////////////////////////////////////////////////////////////////
// class template ACE_Strategy_Scheduler_Factory member functions //
////////////////////////////////////////////////////////////////////
// = Constructs and returns a scheduler strategized with
// an instance of the the parameterized strategy type.
template <class STRATEGY> ACE_Strategy_Scheduler *
ACE_Strategy_Scheduler_Factory<STRATEGY>::create (RtecScheduler::Preemption_Priority_t minimum_critical_priority)
{
ACE_Strategy_Scheduler *the_scheduler = 0;
STRATEGY *the_strategy;
ACE_NEW_RETURN(the_strategy, STRATEGY(minimum_critical_priority), 0);
ACE_NEW_RETURN (the_scheduler, ACE_Strategy_Scheduler (*the_strategy), 0);
return the_scheduler;
}
/////////////////////////////////////////////////////////////////
// abstract base class ACE_Scheduler_Strategy member functions //
/////////////////////////////////////////////////////////////////
// = Constructor.
ACE_Scheduler_Strategy::ACE_Scheduler_Strategy (
ACE_DynScheduler::Preemption_Priority minimum_critical_priority)
: minimum_critical_priority_ (minimum_critical_priority)
{
}
// = Compares two dispatch entries using the specific priority, dynamic
// subpriority, and static subpriority method definitions provided by
// the derived strategy class to produce the strategy specific sort
// ordering: returns -1 if the first Dispatch_Entry is greater in the order,
// 0 if they are equivalent, or 1 if the second Dispatch_Entry is greater in
// the order.
int
ACE_Scheduler_Strategy::sort_comp
(const Dispatch_Entry &first_entry,
const Dispatch_Entry &second_entry)
{
// Order first by the priority ordering.
int result = priority_comp (first_entry, second_entry);
// Within same priority, order by dynamic subpriority.
if (result == 0)
{
result = dynamic_subpriority_comp (first_entry, second_entry);
}
// If same dynamic subpriority, order by static subpriority.
if (result == 0)
{
result = static_subpriority_comp (first_entry, second_entry);
}
return result;
}
// = Provides a lowest level ordering based first on importance (descending),
// and then on the dependency topological sort finishing time (ascending).
int
ACE_Scheduler_Strategy::static_subpriority_comp (
const Dispatch_Entry &first_entry,
const Dispatch_Entry &second_entry)
{
// Order first by importance assigned to underlying RT_Info (descending).
if (first_entry.task_entry ().rt_info ()->importance >
second_entry.task_entry ().rt_info ()->importance)
{
return -1;
}
else if (first_entry.task_entry ().rt_info ()->importance <
second_entry.task_entry ().rt_info ()->importance)
{
return 1;
}
else
{
// Order last by the topological sort finishing time (ascending).
if (first_entry.task_entry ().finished () <
second_entry.task_entry ().finished ())
{
return -1;
}
else if (first_entry.task_entry ().finished () >
second_entry.task_entry ().finished ())
{
return 1;
}
else
{
return 0;
}
}
}
// = Base class supplies default behavior: returns 0
// for minimum critical priority number.
ACE_DynScheduler::Preemption_Priority
ACE_Scheduler_Strategy::minimum_critical_priority ()
{
return 0;
}
/////////////////////////////////////////////////////////////////////////
// class ACE_MUF_Scheduler_Strategy static data member initializations //
/////////////////////////////////////////////////////////////////////////
ACE_MUF_Scheduler_Strategy * ACE_MUF_Scheduler_Strategy::instance_ = 0;
///////////////////////////////////////////////////////
// class ACE_MUF_Scheduler_Strategy member functions //
///////////////////////////////////////////////////////
// = Returns an instance of the strategy.
ACE_MUF_Scheduler_Strategy *
ACE_MUF_Scheduler_Strategy::instance ()
{
if (0 == ACE_MUF_Scheduler_Strategy::instance_)
{
ACE_NEW_RETURN (ACE_MUF_Scheduler_Strategy::instance_,
ACE_MUF_Scheduler_Strategy, 0);
}
return ACE_MUF_Scheduler_Strategy::instance_;
}
// = Compares two dispatch entries by maximum criticality: returns -1 if the
// first Dispatch_Entry is greater in the order, 0 if they're equivalent, or
// 1 if the second Dispatch_Entry is greater in the order.
int
ACE_MUF_Scheduler_Strategy::priority_comp (const Dispatch_Entry &first_entry,
const Dispatch_Entry &second_entry)
{
// Order by criticality (descending).
if (first_entry.task_entry ().rt_info ()->criticality >
second_entry.task_entry ().rt_info ()->criticality)
{
return -1;
}
else if (first_entry.task_entry ().rt_info ()->criticality <
second_entry.task_entry ().rt_info ()->criticality)
{
return 1;
}
else
{
return 0; // Same priority level.
}
}
// = Sorts the dispatch entry pointer array in descending urgency order.
void
ACE_MUF_Scheduler_Strategy::sort (Dispatch_Entry **dispatch_entries, u_int size)
{
ACE_OS::qsort ((void *) dispatch_entries,
size,
sizeof (Dispatch_Entry *),
(COMP_FUNC) ACE_MUF_Scheduler_Strategy::sort_function);
}
// = Default constructor.
ACE_MUF_Scheduler_Strategy::ACE_MUF_Scheduler_Strategy (
ACE_DynScheduler::Preemption_Priority minimum_critical_priority)
:ACE_Scheduler_Strategy (minimum_critical_priority)
{
}
// = Virtual destructor.
ACE_MUF_Scheduler_Strategy::~ACE_MUF_Scheduler_Strategy ()
{
}
// = Returns a dynamic subpriority value for the given entry and the
// current time: if the operation has non-negative laxity, then the
// value is positive, and a lower laxity gives a higher dynamic
// subpriority; if the operation has negative laxity, the value
// is the (negative) laxity value.
long
ACE_MUF_Scheduler_Strategy::dynamic_subpriority (Dispatch_Entry &entry,
RtecScheduler::Time current_time)
{
long laxity =
ACE_U64_TO_U32 (entry.deadline () - current_time -
entry.task_entry ().rt_info ()->worst_case_execution_time);
return (laxity > 0) ? LONG_MAX - laxity : laxity;
}
// = Orders two dispatch entries by ascending laxity: returns -1 if the
// first Dispatch_Entry is greater in the order, 0 if they're equivalent,
// 1 if the second Dispatch_Entry is greater in the order.
int
ACE_MUF_Scheduler_Strategy::dynamic_subpriority_comp
(const Dispatch_Entry &first_entry,
const Dispatch_Entry &second_entry)
{
// Order by descending dynamic priority according to ascending laxity.
u_long laxity1 =
ACE_U64_TO_U32 (first_entry.deadline () - first_entry.arrival () -
first_entry.task_entry ().rt_info ()->worst_case_execution_time);
u_long laxity2 =
ACE_U64_TO_U32 (second_entry.deadline () - first_entry.arrival () -
second_entry.task_entry ().rt_info ()->worst_case_execution_time);
if (laxity1 < laxity2)
{
return -1;
}
else if (laxity1 > laxity2)
{
return 1;
}
else
{
return 0;
}
}
// = Comparison function to pass to qsort.
int
ACE_MUF_Scheduler_Strategy::sort_function (void *arg1, void *arg2)
{
return ACE_MUF_Scheduler_Strategy::instance ()->
sort_comp (** ACE_static_cast (Dispatch_Entry **, arg1),
** ACE_static_cast (Dispatch_Entry **, arg2));
}
// = Returns the minimum critical priority number.
ACE_DynScheduler::Preemption_Priority
ACE_MUF_Scheduler_Strategy::minimum_critical_priority ()
{
return minimum_critical_priority_;
}
// = Provides the dispatching queue type for the given dispatch entry.
ACE_DynScheduler::Dispatching_Type
ACE_MUF_Scheduler_Strategy::dispatch_type (const Dispatch_Entry &entry)
{
ACE_UNUSED_ARG (entry);
return RtecScheduler::LAXITY_DISPATCHING;
}
/////////////////////////////////////////////////////////////////////////
// class ACE_RMS_Scheduler_Strategy static data member initializations //
/////////////////////////////////////////////////////////////////////////
ACE_RMS_Scheduler_Strategy * ACE_RMS_Scheduler_Strategy::instance_ = 0;
///////////////////////////////////////////////////////
// class ACE_RMS_Scheduler_Strategy member functions //
///////////////////////////////////////////////////////
// = Returns an instance of the strategy.
ACE_RMS_Scheduler_Strategy *
ACE_RMS_Scheduler_Strategy::instance ()
{
if (0 == ACE_RMS_Scheduler_Strategy::instance_)
{
ACE_NEW_RETURN (ACE_RMS_Scheduler_Strategy::instance_,
ACE_RMS_Scheduler_Strategy, 0);
}
return ACE_RMS_Scheduler_Strategy::instance_;
}
// = Compares two dispatch entries by minimum period: returns -1 if the
// first Dispatch_Entry is greater in the order, 0 if they're equivalent,
// or 1 if the second Dispatch_Entry is greater in the order.
int
ACE_RMS_Scheduler_Strategy::priority_comp (const Dispatch_Entry &first_entry,
const Dispatch_Entry &second_entry)
{
// compare by decreasing dispatch period
if ((first_entry.deadline () - first_entry.arrival ()) <
(second_entry.deadline () - second_entry.arrival ()))
{
return -1;
}
else if ((first_entry.deadline () - first_entry.arrival ()) >
(second_entry.deadline () - second_entry.arrival ()))
{
return 1;
}
else
{
return 0; // same priority level
}
}
// = Sorts the dispatch entry pointer array in descending RMS (rate) order.
void
ACE_RMS_Scheduler_Strategy::sort (
Dispatch_Entry **dispatch_entries_, u_int size)
{
ACE_OS::qsort ((void *) dispatch_entries_,
size,
sizeof (Dispatch_Entry *),
(COMP_FUNC) ACE_RMS_Scheduler_Strategy::sort_function);
}
// = Default constructor.
ACE_RMS_Scheduler_Strategy::ACE_RMS_Scheduler_Strategy (
ACE_DynScheduler::Preemption_Priority minimum_critical_priority)
:ACE_Scheduler_Strategy (minimum_critical_priority)
{
}
// = Virtual destructor.
ACE_RMS_Scheduler_Strategy::~ACE_RMS_Scheduler_Strategy ()
{
}
// = All entries have the same dynamic subpriority value.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -