📄 schedentry.cpp
字号:
"// %s\n",
(const char*) this->rt_info ()->entry_point);
unresolved_remotes +=
ACE_CString (string_buffer);
}
// Check for and warn about unresolved local dependencies in
// the ONE_WAY call graph.
if ((*link)->dependency_type () == RtecBase::ONE_WAY_CALL
&& (*link)->caller ().has_unresolved_local_dependencies ()
&& ! this->has_unresolved_local_dependencies ())
{
// Propagate the unresolved local dependency flag, and
// issue a debug scheduler warning.
this->has_unresolved_local_dependencies (1);
ACE_DEBUG ((LM_DEBUG,
"Warning: an operation identified by "
"\"%s\" has unresolved local dependencies.\n",
(const char*) this->rt_info ()->entry_point));
// Record entry point in list of unresolved local dependencies
ACE_OS::sprintf (string_buffer,
"// %s\n",
(const char*) this->rt_info ()->entry_point);
unresolved_locals +=
ACE_CString (string_buffer);
}
frame_size = ACE::minimum_frame_size (frame_size,
(*link)->caller ().effective_period_);
}
}
// Reframe dispatches in the set to the new frame size (expands the
// set's effective period to be the new enclosing frame).
if (reframe (dispatch_entries,
*this, dispatches_,
effective_period_,
frame_size) < 0)
return -1;
// A container and iterator for virtual dispatch sets over which the
// conjunction will operate
ACE_Ordered_MultiSet <Dispatch_Proxy_Iterator *> conj_set;
ACE_Ordered_MultiSet_Iterator <Dispatch_Proxy_Iterator *> conj_set_iter (conj_set);
// Iterate over the dependencies, and for each of the given call
// type, create a Dispatch_Proxy_Iterator for the caller's dispatch
// set, using the caller's period, the total frame size, and the
// number of calls: if any of the sets is empty, just return 0;
for (dep_iter.first ();
dep_iter.done () == 0;
dep_iter.advance ())
{
Task_Entry_Link **link;
if (dep_iter.next (link) == 0
|| link == 0
|| *link == 0)
return -1;
// The link matches the dependency type given.
if ((*link)->dependency_type () == dt)
{
Dispatch_Proxy_Iterator *proxy_ptr;
ACE_NEW_RETURN (proxy_ptr,
Dispatch_Proxy_Iterator ((*link)->caller ().dispatches_,
(*link)->caller ().effective_period_,
frame_size,
(*link)->number_of_calls ()),
-1);
// If there are no entries in the virtual set, we're done.
if (proxy_ptr->done ())
return 0;
else if (conj_set.insert (proxy_ptr, conj_set_iter) < 0)
return -1;
}
}
// loop, adding conjunctive dispatches, until one of the conjunctive
// dispatch sources runs out of entries over the total frame
conj_set_iter.first ();
int more_dispatches = (conj_set_iter.done ()) ? 0 : 1;
while (more_dispatches)
{
Time arrival = 0;
Time deadline = 0;
Preemption_Priority priority = 0;
OS_Priority OS_priority = 0;
for (conj_set_iter.first ();
conj_set_iter.done () == 0;
conj_set_iter.advance ())
{
// initialize to earliest arrival and deadline, and highest priority
arrival = 0;
deadline = 0;
priority = 0;
OS_priority = 0;
// Policy: conjunctively dispatched operations get the
// latest deadline of any of the dispatches in the
// conjunction at the time they were dispatched - when and
// if it is useful to change any of the merge policies, this
// should be one of the decisions factored out into the
// conjunctive merge strategy class.
// Policy: conjunctively dispatched operations get the
// lowest priority of any of the dispatches in the
// conjunction at the time they were dispatched - when and
// if it is useful to change any of the merge policies, this
// should be one of the decisions factored out into the
// conjunctive merge strategy class.
// Obtain a pointer to the current dispatch proxy iterator.
Dispatch_Proxy_Iterator **proxy_iter;
if (conj_set_iter.next (proxy_iter) == 0
|| proxy_iter == 0
|| *proxy_iter == 0)
return -1;
// Use latest arrival, latest deadline, lowest priority (0 is highest).
if (arrival <= (*proxy_iter)->arrival ())
arrival = (*proxy_iter)->arrival ();
if (deadline <= (*proxy_iter)->deadline ())
deadline = (*proxy_iter)->deadline ();
if (priority <= (*proxy_iter)->priority ())
{
priority = (*proxy_iter)->priority ();
OS_priority = (*proxy_iter)->OS_priority ();
}
(*proxy_iter)->advance ();
if ((*proxy_iter)->done ())
more_dispatches = 0;
}
Dispatch_Entry *entry_ptr;
ACE_NEW_RETURN (entry_ptr,
Dispatch_Entry (arrival,
deadline,
priority,
OS_priority,
*this),
-1);
// If even one new dispatch was inserted, result is "something
// happened".
result = 1;
// Add the new dispatch entry to the set of all dispatches, and
// a link to it to the dispatch links for this task entry.
if (dispatch_entries.insert (entry_ptr) < 0)
return -1;
// Use iterator for efficient insertion into the dispatch set.
ACE_Ordered_MultiSet_Iterator <Dispatch_Entry_Link> insert_iter (dispatches_);
if (dispatches_.insert (Dispatch_Entry_Link (*entry_ptr),
insert_iter) < 0)
return -1;
// TBD - Clients are not assigned priority, but rather obtain it
// from their call dependencies. We could complain here if
// there is a priority specified that doesn't match (or is lower
// QoS?)
}
return result;
}
// This static method is used to reframe an existing dispatch set to
// the given new period multiplier, creating new instances of each
// existing dispatch (with adjusted arrival and deadline) in each
// successive sub-frame. Returns 1 if the set was reframed to a new
// period, 0 if the set was not changed (the new period was not a
// multiple of the old one), or -1 if an error occurred.
int
Task_Entry::reframe (ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_entries,
Task_Entry &owner,
ACE_Ordered_MultiSet <Dispatch_Entry_Link> &set,
u_long &set_period, u_long new_period)
{
int result = 0;
// if the set period is zero, treat it as uninitialized,
// and simply value the set period with the new period
if (set_period)
{
// make sure the new period is greater than the current
// set period, and that they are harmonically related
if (new_period <= set_period)
// return an error if they're not harmonically related,
// do nothing if set's frame is a multiple of the new frame
return (set_period % new_period) ? -1 : 0;
else if (new_period % set_period)
return -1;
// make a shallow copy of the set in a new ordered multiset
// using the Dispatch_Entry_Link smart pointers
ACE_Ordered_MultiSet <Dispatch_Entry_Link> new_set;
ACE_Ordered_MultiSet_Iterator <Dispatch_Entry_Link> new_iter (new_set);
ACE_Ordered_MultiSet_Iterator <Dispatch_Entry_Link> set_iter (set);
for (set_iter.first (); set_iter.done () == 0; set_iter.advance ())
{
Dispatch_Entry_Link *link;
if (set_iter.next (link) == 0)
return -1;
else if (new_set.insert (*link, new_iter) < 0)
return -1;
}
// Do a deep copy merge back into the set using the new period
// and starting after the 0th sub-frame: this puts all
// dispatches after the 0th sub-frame of the new period into the
// set, and leaves existing dispatches in the 0th sub-frame of
// the new period in the set as well.
result = merge_frames (dispatch_entries,
owner,
set,
new_set,
new_period,
set_period,
1,
1);
}
// update the set's period to be the new frame
set_period = new_period;
return result;
}
// This static method is used to merge an existing dispatch set,
// multiplied by the given multipliers for the period and number of
// instances in each period of each existing dispatch, into the given
// "into" set, without affecting the "from set".
int
Task_Entry::merge_frames (ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_entries,
Task_Entry &owner,
ACE_Ordered_MultiSet <Dispatch_Entry_Link> &dest,
ACE_Ordered_MultiSet <Dispatch_Entry_Link> &src,
u_long &dest_period,
u_long src_period,
u_long number_of_calls,
u_long starting_dest_sub_frame)
{
int status = 0;
// reframe dispatches in the destination set to the new frame size
// (expands the destination set's period to be the new enclosing frame)
if (reframe (dispatch_entries,
owner,
dest,
dest_period,
ACE::minimum_frame_size (dest_period,
src_period)) < 0)
return -1;
// use iterator for efficient insertion into the destination set
ACE_Ordered_MultiSet_Iterator <Dispatch_Entry_Link> dest_iter (dest);
// do virtual iteration over the source set in the new frame, adding
// adjusted dispatch entries to the destination
Dispatch_Proxy_Iterator src_iter (src,
src_period,
dest_period,
number_of_calls,
starting_dest_sub_frame);
for (src_iter.first (starting_dest_sub_frame);
src_iter.done () == 0;
src_iter.advance ())
{
// Policy: disjunctively dispatched operations get their
// deadline and priority from the original dispatch - when and
// if it is useful to change any of the merge policies, this
// should be one of the decisions factored out into the
// disjunctive merge strategy class.
Dispatch_Entry *entry_ptr;
ACE_NEW_RETURN (entry_ptr,
Dispatch_Entry (src_iter.arrival (),
src_iter.deadline (),
src_iter.priority (),
src_iter.OS_priority (),
owner),
-1);
// if even one new dispatch was inserted, status is "something happened".
status = 1;
// add the new dispatch entry to the set of all dispatches, and
// a link to it to the dispatch links for this task entry
if (dispatch_entries.insert (entry_ptr) < 0)
return -1;
else if (dest.insert (Dispatch_Entry_Link (*entry_ptr), dest_iter) < 0)
return -1;
// TBD - Clients are not assigned priority, but rather obtain it
// from their call dependencies. We could complain here if
// there is a priority specified that doesn't match (or is lower
// QoS?)
}
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -