summaryrefslogtreecommitdiff
path: root/TAO
diff options
context:
space:
mode:
authorcdgill <cdgill@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1998-10-19 03:24:48 +0000
committercdgill <cdgill@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1998-10-19 03:24:48 +0000
commit6b15c6af8646485c6072fe14835b31094bf43d35 (patch)
treec1239013b4c3806d4247e72db122b304d1f33e34 /TAO
parent043e6bfff776fee364fcbbde2cbbbfb95e78780d (diff)
downloadATCD-6b15c6af8646485c6072fe14835b31094bf43d35.tar.gz
Now propagating unresolved remote dependency warnings, added ability to generate schedule table even with warnings
Diffstat (limited to 'TAO')
-rw-r--r--TAO/ChangeLog-98c15
-rw-r--r--TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.cpp31
-rw-r--r--TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp8
-rw-r--r--TAO/orbsvcs/orbsvcs/Sched/SchedEntry.cpp120
-rw-r--r--TAO/orbsvcs/orbsvcs/Sched/SchedEntry.h119
-rw-r--r--TAO/orbsvcs/orbsvcs/Sched/SchedEntry.i30
-rw-r--r--TAO/orbsvcs/orbsvcs/Sched/Scheduler.h1
-rw-r--r--TAO/orbsvcs/tests/Sched_Conf/README42
-rw-r--r--TAO/orbsvcs/tests/Sched_Conf/Sched_Conf.cpp76
-rw-r--r--TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Runtime.h32
10 files changed, 325 insertions, 149 deletions
diff --git a/TAO/ChangeLog-98c b/TAO/ChangeLog-98c
index e1a08a51b56..b9d5fedb6ae 100644
--- a/TAO/ChangeLog-98c
+++ b/TAO/ChangeLog-98c
@@ -1,3 +1,18 @@
+Sun Oct 18 22:05:00 1998 Chris Gill <cdgill@cs.wustl.edu>
+
+ * orbsvcs/tests/Sched_Conf/Sched_Conf.cpp
+ orbsvcs/tests/Sched_Conf/Sched_Conf_Runtime.cpp
+ orbsvcs/orbsvcs/Sched/Config_Scheduler.cpp
+ orbsvcs/orbsvcs/Sched/DynSched.cpp
+ orbsvcs/orbsvcs/Sched/SchedEntry.{cpp,h,i}
+ orbsvcs/orbsvcs/Sched/Scheduler.h:
+ Propagated warnings for unresolved remote RT_Info dependencies
+ throughout the call graph in the strategized scheduler, enabled
+ schedule table generation even when there are unresolved remote
+ dependencies or the utilization bound is exceeded. These changes
+ allow iterative development of a schedule with useful scheduler
+ warnings in debug mode.
+
Sun Oct 18 21:40:23 1998 Sergio Flores <sergio@tango.cs.wustl.edu>
* performance-tests/Cubit/TAO/MT_Cubit/Task_Client.cpp:
diff --git a/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.cpp b/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.cpp
index f3ab7a88383..0dc1025acee 100644
--- a/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.cpp
+++ b/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.cpp
@@ -252,11 +252,34 @@ void ACE_Config_Scheduler::compute_scheduling (CORBA::Long minimum_priority,
ACE_UNUSED_ARG (_env);
impl->init (minimum_priority, maximum_priority);
- if (impl->schedule () != BaseSchedImplType::SUCCEEDED)
+
+ BaseSchedImplType::status_t schedule_status;
+ schedule_status = impl->schedule ();
+ switch (schedule_status)
{
- // TODO: throw something.
- ACE_ERROR ((LM_ERROR, "schedule failed\n"));
- return;
+ // If we succeeded with no warnings, do nothing.
+ case BaseSchedImplType::SUCCEEDED:
+ break;
+
+ // Issue a warning if there were unresolved remote dependencies.
+ case BaseSchedImplType::ST_UNRESOLVED_REMOTE_DEPENDENCIES:
+ ACE_DEBUG ((LM_DEBUG,
+ "Warning: schedule has unresolved "
+ "remote dependencies\n."));
+ break;
+
+ // Issue a warning if the schedule is not feasible.
+ case BaseSchedImplType::ST_UTILIZATION_BOUND_EXCEEDED:
+ ACE_DEBUG ((LM_DEBUG,
+ "Warning: schedule exceeds utilization bound\n."));
+ break;
+
+ // On any other kind of scheduling error,
+ // abort without generating a schedule.
+ default:
+ // TODO: throw something.
+ ACE_ERROR ((LM_ERROR, "Schedule failed\n"));
+ return;
}
// return the set of scheduled RT_Infos
diff --git a/TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp b/TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp
index cb2d19fe2c5..8ba959ee59d 100644
--- a/TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp
+++ b/TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp
@@ -1091,11 +1091,13 @@ ACE_DynScheduler::identify_threads (void)
}
else if (task_entries_ [i].rt_info ()->info_type == RtecScheduler::REMOTE_DEPENDANT)
{
- // Warn about unresolved remote dependencies
- result = ST_UNRESOLVED_REMOTE_DEPENDENCIES;
+ // Warn about unresolved remote dependencies, mark the task entry
+ result = ST_UNRESOLVED_REMOTE_DEPENDENCIES;
+ task_entries_ [i].has_unresolved_remote_dependencies (1);
ACE_DEBUG (
(LM_DEBUG,
- "An operation identified by \"%s\" has unresolved remote dependencies\n.",
+ "Warning: an operation identified by "
+ "\"%s\" has unresolved remote dependencies\n.",
(const char*) task_entries_ [i].rt_info ()->entry_point));
}
else
diff --git a/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.cpp b/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.cpp
index ff2072d4dcd..45fdf921a99 100644
--- a/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.cpp
+++ b/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.cpp
@@ -92,14 +92,15 @@ u_long minimum_frame_size (u_long period1, u_long period2)
//////////////////////
Task_Entry::Task_Entry ()
- : rt_info_ (0)
- , effective_period_(0)
- , dfs_status_ (NOT_VISITED)
- , discovered_ (-1)
- , finished_ (-1)
- , is_thread_delineator_ (0)
- , calls_ ()
- , callers_ ()
+ : rt_info_ (0),
+ effective_period_(0),
+ dfs_status_ (NOT_VISITED),
+ discovered_ (-1),
+ finished_ (-1),
+ is_thread_delineator_ (0),
+ has_unresolved_remote_dependencies_ (0),
+ calls_ (),
+ callers_ ()
{
}
@@ -123,8 +124,9 @@ Task_Entry::~Task_Entry ()
}
}
-// merge dispatches according to info type and type of call,
-// update relevant scheduling characteristics for this entry
+// Merge dispatches according to info type and type of call,
+// update relevant scheduling characteristics for this entry.
+
int
Task_Entry::merge_dispatches (ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_entries)
{
@@ -133,7 +135,7 @@ Task_Entry::merge_dispatches (ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_ent
{
case RtecScheduler::DISJUNCTION:
- // prohibit two-way dispatches of a disjunction group,
+ // Prohibit two-way dispatches of a disjunction group,
// and disjunctively merge its one-way dispatches.
// NOTE: one interpretation of disjunction for two-way calls
// is that the caller calls one OR the other, but this
@@ -148,7 +150,7 @@ Task_Entry::merge_dispatches (ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_ent
case RtecScheduler::CONJUNCTION:
- // prohibit two-way dispatches of a conjunction group,
+ // Prohibit two-way dispatches of a conjunction group,
// and conjunctively merge its one-way dispatches.
// NOTE: one interpretation of disjunction for two-way calls
// is that the caller calls BOTH, so that there is a
@@ -167,7 +169,7 @@ Task_Entry::merge_dispatches (ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_ent
case RtecScheduler::OPERATION:
case RtecScheduler::REMOTE_DEPENDANT:
- // disjunctively merge the operation's two-way dispatches,
+ // Disjunctively merge the operation's two-way dispatches,
// and conjunctively merge its one-way dispatches.
result = disjunctive_merge (RtecScheduler::TWO_WAY_CALL, dispatch_entries);
if (result == 0)
@@ -180,7 +182,7 @@ Task_Entry::merge_dispatches (ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_ent
default:
- // there should not be any other kind of RT_Info, or if
+ // There should not be any other kind of RT_Info, or if
// there is, the above switch logic is in need of repair.
result = -1;
break;
@@ -191,7 +193,7 @@ Task_Entry::merge_dispatches (ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_ent
-// prohibit calls of the given type: currently used to enforce
+// Prohibit calls of the given type: currently used to enforce
// the notion that two-way calls to disjunctive or conjunctive
// RT_Infos do not have any defined meaning, and thus should be
// considered dependency specification errors: if these constraints
@@ -200,8 +202,8 @@ Task_Entry::merge_dispatches (ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_ent
int
Task_Entry::prohibit_dispatches (Dependency_Type dt)
{
- // iterate over the set of dependencies, ensuring
- // none of them has the given dependency type
+ // Iterate over the set of dependencies, ensuring
+ // none of them has the given dependency type.
ACE_Unbounded_Set_Iterator <Task_Entry_Link *> iter (callers_);
while (! iter.done ())
{
@@ -219,16 +221,17 @@ Task_Entry::prohibit_dispatches (Dependency_Type dt)
}
-// perform disjunctive merge of arrival times of oneway calls:
+// Perform disjunctive merge of arrival times of oneway calls:
// all arrival times of all dependencies are duplicated by the
-// multiplier and repetition over the new frame size and merged
+// multiplier and repetition over the new frame size.
+
int
Task_Entry::disjunctive_merge (
Dependency_Type dt,
ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_entries)
{
- // iterate over the set of dependencies, ensuring
- // none of them has the given dependency type
+ // Iterate over the set of dependencies, merging dispatches
+ // of the callers over the enclosing frame size.
ACE_Unbounded_Set_Iterator <Task_Entry_Link *> iter (callers_);
while (! iter.done ())
{
@@ -241,7 +244,23 @@ Task_Entry::disjunctive_merge (
// the link matches the dependency type given
if ((*link)->dependency_type () == dt)
{
- // merge the caller's dispatches into the current set
+ // Check for and warn about unresolved remote
+ // dependencies in the ONE_WAY call graph.
+ if ((*link)->dependency_type () == RtecScheduler::ONE_WAY_CALL &&
+ (*link)->caller ().has_unresolved_remote_dependencies () &&
+ ! this->has_unresolved_remote_dependencies ())
+ {
+ // Propagate the unresolved remote dependency
+ // flag, and issue a debug scheduler warning.
+ this->has_unresolved_remote_dependencies (1);
+ ACE_DEBUG (
+ (LM_DEBUG,
+ "Warning: an operation identified by "
+ "\"%s\" has unresolved remote dependencies.\n",
+ (const char*) this->rt_info ()->entry_point));
+ }
+
+ // Merge the caller's dispatches into the current set.
if (merge_frames (dispatch_entries, *this, dispatches_,
(*link)->caller ().dispatches_, effective_period_,
(*link)->caller ().effective_period_,
@@ -257,12 +276,13 @@ Task_Entry::disjunctive_merge (
return 0;
}
-// perform conjunctive merge of arrival times of calls:
+// Perform conjunctive merge of arrival times of calls:
// all arrival times of all dependencies are duplicated by the
// multiplier and repetition over the new frame size and then
// iteratively merged by choosing the maximal arrival time at
// the current position in each queue (iteration is in lockstep
// over all queues, and ends when any queue ends).
+
int
Task_Entry::conjunctive_merge (
Dependency_Type dt,
@@ -270,7 +290,7 @@ Task_Entry::conjunctive_merge (
{
int result = 0;
- // iterate over the dependencies, and determine the total frame size
+ // Iterate over the dependencies, and determine the total frame size.
u_long frame_size = 1;
ACE_Unbounded_Set_Iterator <Task_Entry_Link *> dep_iter (callers_);
for (dep_iter.first (); dep_iter.done () == 0; dep_iter.advance ())
@@ -281,27 +301,43 @@ Task_Entry::conjunctive_merge (
return -1;
}
- // the link matches the dependency type given
+ // The link matches the dependency type given.
if ((*link)->dependency_type () == dt)
{
+ // Check for and warn about unresolved remote
+ // dependencies in the ONE_WAY call graph.
+ if ((*link)->dependency_type () == RtecScheduler::ONE_WAY_CALL &&
+ (*link)->caller ().has_unresolved_remote_dependencies () &&
+ ! this->has_unresolved_remote_dependencies ())
+ {
+ // Propagate the unresolved remote dependency
+ // flag, and issue a debug scheduler warning.
+ this->has_unresolved_remote_dependencies (1);
+ ACE_DEBUG (
+ (LM_DEBUG,
+ "Warning: an operation identified by "
+ "\"%s\" has unresolved remote dependencies.\n",
+ (const char*) this->rt_info ()->entry_point));
+ }
+
frame_size = 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)
+ // 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 set and iterator for virtual dispatch sets
- // over which the conjunction will iterate
+ // 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,
+ // 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;
@@ -313,7 +349,7 @@ Task_Entry::conjunctive_merge (
return -1;
}
- // the link matches the dependency type given
+ // The link matches the dependency type given.
if ((*link)->dependency_type () == dt)
{
Dispatch_Proxy_Iterator *proxy_ptr;
@@ -324,7 +360,7 @@ Task_Entry::conjunctive_merge (
frame_size, (*link)->number_of_calls ()),
-1);
- // if there are no entries in the virtual set, we're done
+ // If there are no entries in the virtual set, we're done.
if (proxy_ptr->done ())
{
return 0;
@@ -369,14 +405,14 @@ Task_Entry::conjunctive_merge (
// should be one of the decisions factored out into the conjunctive merge
// strategy class.
- // obtain a pointer to the current dispatch proxy iterator
+ // Obtain a pointer to the current dispatch proxy iterator.
Dispatch_Proxy_Iterator **proxy_iter;
if ((conj_set_iter.next (proxy_iter) == 0) || (! proxy_iter) || (! (*proxy_iter)))
{
return -1;
}
- // use latest arrival, latest deadline, lowest priority (0 is highest)
+ // Use latest arrival, latest deadline, lowest priority (0 is highest).
if (arrival <= (*proxy_iter)->arrival ())
{
arrival = (*proxy_iter)->arrival ();
@@ -403,17 +439,17 @@ Task_Entry::conjunctive_merge (
Dispatch_Entry (arrival, deadline, priority, OS_priority, *this),
-1);
- // if even one new dispatch was inserted, result is "something happened".
+ // 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
+ // 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
+ // 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)
{
@@ -428,12 +464,13 @@ Task_Entry::conjunctive_merge (
return result;
}
-// this static method is used to reframe an existing dispatch set
+// 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,
@@ -480,7 +517,7 @@ Task_Entry::reframe (
}
}
- // do a deep copy merge back into the set using the new period and starting
+ // 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.
@@ -496,10 +533,11 @@ Task_Entry::reframe (
}
-// this static method is used to merge an existing dispatch set,
+// 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,
diff --git a/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.h b/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.h
index 185139ca700..496c242fd08 100644
--- a/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.h
+++ b/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.h
@@ -13,7 +13,7 @@
// 7 February 1998
//
// = AUTHOR
-// Chris Gill
+// Chris Gill <cdgill@cs.wustl.edu>
//
// ============================================================================
@@ -27,15 +27,13 @@
// Helper Functions //
//////////////////////
-// TBD - move this to the ACE class
-// Euclid's greatest common divisor algorithm
+// Euclid's greatest common divisor algorithm.
u_long gcd (u_long x, u_long y);
-// TBD - move this to the ACE class
-// calculate the minimum frame size
+// Calculates the minimum enclosing frame size for the given periods.
u_long minimum_frame_size (u_long period1, u_long period2);
-// forward declaration of classes
+// Forward declaration of classes.
class Task_Entry;
class Task_Entry_Link;
class Dispatch_Entry;
@@ -65,30 +63,35 @@ public:
typedef RtecScheduler::Dependency_Type Dependency_Type;
Dispatch_Entry_Link (Dispatch_Entry &d);
- // ctor
+ // Constructor.
Dispatch_Entry_Link (const Dispatch_Entry_Link &d);
- // copy ctor
+ // Copy constructor.
~Dispatch_Entry_Link ();
- // dtor
+ // Destructor.
- // TBD - make this a global comparison operator
- // instead of a class member function
int operator < (const Dispatch_Entry_Link &d) const;
- // LT comparator
+ // Less than comparison operator.
Dispatch_Entry &dispatch_entry () const;
- // accessor for reference to dispatch entry
+ // Accessor for reference to the dispatch entry.
private:
Dispatch_Entry &dispatch_entry_;
+ // Dispatch entry to which the smart pointer refers.
};
-// Wrapper for the RT_Info, which aggregates all its dispatches
+
class TAO_ORBSVCS_Export Task_Entry
+// = TITLE
+// Task Entry.
+//
+// = DESCRIPTION
+// Wrapper for the RT_Info, which aggregates all its dispatches.
+//
{
public:
@@ -103,72 +106,89 @@ public:
typedef RtecScheduler::Info_Type Info_Type;
typedef RtecScheduler::Dependency_Type Dependency_Type;
- // info for DFS traversal, topological sort of call graph
+ // Info for DFS traversal, topological sort of call graph.
enum DFS_Status {NOT_VISITED, VISITED, FINISHED};
- // ctor
+ // Constructor.
Task_Entry ();
- // dtor
+ // Destructor.
~Task_Entry ();
- // merge dispatches according to info type, update
+ // Merges dispatches according to info type, update
// relevant scheduling characteristics for this entry.
- // Returns 0 if all is well, or -1 if an error occurred
+ // Returns 0 if all is well, or -1 if an error occurred.
int merge_dispatches (
ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_entries);
- // get, set pointer to underlying RT_Info
+ // Gets the pointer to the underlying RT_Info.
RT_Info *rt_info () const;
- void rt_info (RT_Info *info);
+ // Sets the pointer to the underlying RT_Info.
+ void rt_info (RT_Info *info);
- // get effective period for the task entry
+ // Gets the effective period for the task entry.
Period effective_period () const;
+
+ // Sets the effective period for the task entry.
void effective_period (Period p);
- // set/get time when node was discovered in DFS traversal
+ // Sets when the node was discovered in DFS traversal.
void discovered (long l);
+
+ // Gets when the node was discovered in DFS traversal.
long discovered () const;
- // set/get time when node was finished in DFS traversal
+ // Sets when the node was finished in DFS traversal.
void finished (long l);
+
+ // Gets when the node was finished in DFS traversal.
long finished () const;
- // set/get DFS traversal status of node
+ // Sets DFS traversal status of the node.
void dfs_status (DFS_Status ds);
+
+ // Gets DFS traversal status of the node.
DFS_Status dfs_status () const;
- // set/get flag indicating whether node is a thread delineator
+ // Sets a flag indicating whether node is a thread delineator.
void is_thread_delineator (int i);
+
+ // Gets the flag indicating whether node is a thread delineator.
int is_thread_delineator () const;
- // get set of links to Task Entries which this entry calls
+ // Sets a flag indicating whether node has unresolved remote dependencies.
+ void has_unresolved_remote_dependencies (int i);
+
+ // Gets the flag indicating whether node has unresolved remote dependencies.
+ int has_unresolved_remote_dependencies () const;
+
+ // Gets the set of links to Task Entries which this entry calls.
ACE_Unbounded_Set <Task_Entry_Link *> & calls ();
- // get set of links to Task Entries which call this entry
+ // Gets the set of links to Task Entries which call this entry.
ACE_Unbounded_Set <Task_Entry_Link *> & callers ();
- // get set of arrivals in the effective period
+ // Gets the set of arrivals in the effective period.
ACE_Ordered_MultiSet<Dispatch_Entry_Link> &dispatches ();
- // get the type of Info the entry wraps
+ // Gets the type of RT_Info the entry wraps.
Info_Type info_type () const;
- // effective execution time for the task entry
+ // Gets the effective execution time for the task entry.
u_long effective_execution_time () const;
private:
- // prohibit calls of the given type: currently used to enforce
+ // Prohibits calls of the given type: currently used to enforce
// the notion that two-way calls to disjunctive or conjunctive
// RT_Infos do not have any defined meaning, and thus should be
// considered dependency specification errors: if these constraints
- // are removed in the future, this method should be removed as well
+ // are removed in the future, this method should be removed as well.
// Returns 0 if all is well, or -1 if an error has occurred.
int prohibit_dispatches (Dependency_Type dt);
- // performs disjunctive merge of arrival times of calls of the given
+ // Performs a disjunctive merge of arrival times of calls of the given
// type: all arrival times of all callers of that type are duplicated by
// the multiplier and repetition over the new frame size and merged.
// Returns 0 if all is well, or -1 if an error has occurred.
@@ -176,9 +196,9 @@ private:
Dependency_Type dt,
ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_entries);
- // perform conjunctive merge of arrival times of calls of the given
+ // Performs a conjunctive merge of arrival times of calls of the given
// type: all arrival times of all callers of that type are duplicated
- // by the multiplier and repetition over the new frame size and then
+ // by the multiplier and repetition over the new frame size and then
// iteratively merged by choosing the maximal arrival time at
// the current position in each queue (iteration is in lockstep
// over all queues, and ends when any queue ends). Returns 0 if
@@ -188,7 +208,7 @@ private:
ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_entries);
- // this static method is used to reframe an existing dispatch set
+ // 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
@@ -199,7 +219,7 @@ private:
ACE_Ordered_MultiSet <Dispatch_Entry_Link> &set,
u_long &set_period, u_long new_period);
- // this static method is used to merge an existing dispatch set,
+ // 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". Returns 1 if
@@ -214,30 +234,41 @@ private:
u_long number_of_calls = 1,
u_long starting_dest_sub_frame = 0);
- // pointer to the underlying RT_Info
+ // A pointer to the underlying RT_Info.
RT_Info *rt_info_;
- // effective period for the task entry
+ // The effective period for the task entry.
u_long effective_period_;
- // set of arrivals in the effective period
+ // The set of arrivals in the entry's effective period.
ACE_Ordered_MultiSet<Dispatch_Entry_Link> dispatches_;
+ // Depth-first-search status of the entry.
DFS_Status dfs_status_;
+
+ // Depth-first-search discovery order of the entry.
long discovered_;
+
+ // Depth-first-search completion order of the entry.
long finished_;
- // info for identifying threads in the oneway call graph
+ // Flag identifying threads in the call graph.
int is_thread_delineator_;
- // get set of links to Task Entries which this entry calls
+ // Flag indicating whether or not there are unresolved remote
+ // dependencies in the entry's dependency call chain.
+ int has_unresolved_remote_dependencies_;
+
+ // Set of links to Task Entries which this entry calls.
ACE_Unbounded_Set <Task_Entry_Link *> calls_;
- // get set of links to Task Entries which call this entry
+ // Set of links to Task Entries which call this entry.
ACE_Unbounded_Set <Task_Entry_Link *> callers_;
+
};
+// Wrapper for dependencies between RT_Infos
class TAO_ORBSVCS_Export Task_Entry_Link
{
public:
diff --git a/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.i b/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.i
index 772770706b2..f016b0ebeb4 100644
--- a/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.i
+++ b/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.i
@@ -87,33 +87,57 @@ Task_Entry::dfs_status (Task_Entry::DFS_Status ds)
dfs_status_ = ds;
}
+// Sets a flag indicating whether node is a thread delineator.
+
ACE_INLINE void
Task_Entry::is_thread_delineator (int i)
{
is_thread_delineator_ = i;
}
+// Gets the flag indicating whether node is a thread delineator.
+
ACE_INLINE int
Task_Entry::is_thread_delineator () const
{
return is_thread_delineator_;
}
-// access set of Task Entries on which this entry depends
+// Sets a flag indicating whether node has unresolved remote dependencies.
+
+ACE_INLINE void
+Task_Entry::has_unresolved_remote_dependencies (int i)
+{
+ has_unresolved_remote_dependencies_ = i;
+}
+
+// Gets the flag indicating whether node has unresolved remote dependencies.
+
+ACE_INLINE int
+Task_Entry::has_unresolved_remote_dependencies () const
+{
+ return has_unresolved_remote_dependencies_;
+}
+
+
+// Gets the set of Task Entries on which this entry depends.
+
ACE_INLINE ACE_Unbounded_Set <Task_Entry_Link *> &
Task_Entry::calls ()
{
return calls_;
}
-// access set of Task Entries which depend on this entry
+// Gets the set of Task Entries which depend on this entry.
+
ACE_INLINE ACE_Unbounded_Set <Task_Entry_Link *> &
Task_Entry::callers ()
{
return callers_;
}
-// get set of arrivals in the effective period
+// Gets set of arrivals in the entry's effective period.
+
ACE_INLINE ACE_Ordered_MultiSet<Dispatch_Entry_Link> &
Task_Entry::dispatches ()
{
diff --git a/TAO/orbsvcs/orbsvcs/Sched/Scheduler.h b/TAO/orbsvcs/orbsvcs/Sched/Scheduler.h
index 752d0cc4a1c..90106022157 100644
--- a/TAO/orbsvcs/orbsvcs/Sched/Scheduler.h
+++ b/TAO/orbsvcs/orbsvcs/Sched/Scheduler.h
@@ -82,6 +82,7 @@ public:
, ST_UTILIZATION_BOUND_EXCEEDED
, ST_INSUFFICIENT_THREAD_PRIORITY_LEVELS
, ST_CYCLE_IN_DEPENDENCIES
+ , ST_UNRESOLVED_REMOTE_DEPENDENCIES
, UNABLE_TO_OPEN_SCHEDULE_FILE
, UNABLE_TO_WRITE_SCHEDULE_FILE
};
diff --git a/TAO/orbsvcs/tests/Sched_Conf/README b/TAO/orbsvcs/tests/Sched_Conf/README
new file mode 100644
index 00000000000..e787e7d690a
--- /dev/null
+++ b/TAO/orbsvcs/tests/Sched_Conf/README
@@ -0,0 +1,42 @@
+Overview:
+
+ The scheduling service can run in one of two different modes of
+ operation, an off-line configuration mode, and a run-time execution mode.
+ The application uses the Scheduler_Factory to specify in which mode
+ it would like to use the scheduling service.
+
+ In the configuration mode, the application registers RT_Infos containing
+ operation characteristics with the off-line scheduler, and also specifies
+ operation dependencies. The Event Channel also registers RT_Infos for its
+ own operations, and specifies any additional dependencies introduced by
+ subscription or event correllation.
+
+ Once all operations are registered, the application invokes the
+ scheduler's compute_scheduling method. The scheduler generates a
+ "schedule" consisting of operation priorities and sub-priorities, and
+ determines whether or not the schedule is feasible. The scheduler also
+ produces queue specification information that can be used to configure
+ the dispatching module's number and kinds of queues (this
+ automatic dispatching module configuration will appear in a TAO release
+ *very* soon). The application then may ask the config scheduler to dump
+ it's schedule to a header file.
+
+ The Sched_Conf.cpp file in this directory is an example of how this is done.
+ Building and running the Sched_Conf executable will produce a header file
+ called Sched_Conf_Runtime.h, which is included by Sched_Conf_Runtime.cpp.
+
+ The dumped header file contains tables with the static scheduling and
+ configuration information. The Sched_Conf_Runtime application passes this
+ information to the run-time scheduler at start-up. The application may also
+ re-register its operations to verify the correct operations were loaded. The
+ Sched_Conf_Runtime does this, and in fact exercises a number of methods
+ of the run-time scheduler to ensure it gives correct responses for the
+ table of operations with which it was instantiated.
+
+Program operation:
+
+ build Sched_Conf
+ run Sched_Conf
+ build Sched_Conf_Runtime
+ run Sched_Conf_Runtime
+
diff --git a/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf.cpp b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf.cpp
index a66376473f9..ff3e11e5422 100644
--- a/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf.cpp
+++ b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf.cpp
@@ -60,11 +60,11 @@ main (int argc, char *argv[])
const int operation_count = 16;
ACE_Scheduler_Factory::POD_RT_Info config_infos[operation_count] = {
// 20 Hz high criticality supplier
- { "high_20_S", // entry point
+ { "high_20_S", // entry point
0, // handle
- 0, // worst case execution time
- 0, // typical execution time (unused)
- 0, // cached execution time
+ 5000, // worst case execution time
+ 5000, // typical execution time (unused)
+ 5000, // cached execution time
500000, // period (100 ns)
RtecScheduler::HIGH_CRITICALITY, // criticality
RtecScheduler::LOW_IMPORTANCE, // importance
@@ -76,11 +76,11 @@ main (int argc, char *argv[])
RtecScheduler::OPERATION // info type
},
// 20 Hz low criticality supplier
- { "low_20_S", // entry point
+ { "low_20_S", // entry point
0, // handle
- 0, // worst case execution time
- 0, // typical execution time (unused)
- 0, // cached execution time
+ 5000, // worst case execution time
+ 5000, // typical execution time (unused)
+ 5000, // cached execution time
500000, // period (100 ns)
RtecScheduler::LOW_CRITICALITY, // criticality
RtecScheduler::HIGH_IMPORTANCE, // importance
@@ -92,12 +92,12 @@ main (int argc, char *argv[])
RtecScheduler::OPERATION // info type
},
// 10 Hz high criticality supplier
- { "high_10_S", // entry point
+ { "high_10_S", // entry point
0, // handle
- 0, // worst case execution time
- 0, // typical execution time (unused)
- 0, // cached execution time
- 1000000, // period (100 ns)
+ 10000, // worst case execution time
+ 10000, // typical execution time (unused)
+ 10000, // cached execution time
+ 1000000, // period (100 ns)
RtecScheduler::HIGH_CRITICALITY, // criticality
RtecScheduler::LOW_IMPORTANCE, // importance
0, // quantum (unused)
@@ -110,9 +110,9 @@ main (int argc, char *argv[])
// 10 Hz low criticality supplier
{ "low_10_S", // entry point
0, // handle
- 0, // worst case execution time
- 0, // typical execution time (unused)
- 0, // cached execution time
+ 10000, // worst case execution time
+ 10000, // typical execution time (unused)
+ 10000, // cached execution time
1000000, // period (100 ns)
RtecScheduler::LOW_CRITICALITY, // criticality
RtecScheduler::HIGH_IMPORTANCE, // importance
@@ -126,9 +126,9 @@ main (int argc, char *argv[])
// 5 Hz high criticality supplier
{ "high_05_S", // entry point
0, // handle
- 0, // worst case execution time
- 0, // typical execution time (unused)
- 0, // cached execution time
+ 20000, // worst case execution time
+ 20000, // typical execution time (unused)
+ 20000, // cached execution time
2000000, // period (100 ns)
RtecScheduler::HIGH_CRITICALITY, // criticality
RtecScheduler::LOW_IMPORTANCE, // importance
@@ -142,9 +142,9 @@ main (int argc, char *argv[])
// 5 Hz low criticality supplier
{ "low_05_S", // entry point
0, // handle
- 0, // worst case execution time
- 0, // typical execution time (unused)
- 0, // cached execution time
+ 20000, // worst case execution time
+ 20000, // typical execution time (unused)
+ 20000, // cached execution time
2000000, // period (100 ns)
RtecScheduler::LOW_CRITICALITY, // criticality
RtecScheduler::HIGH_IMPORTANCE, // importance
@@ -155,37 +155,37 @@ main (int argc, char *argv[])
0, // Preemption priority
RtecScheduler::OPERATION // info type
},
- // 1 Hz high criticality supplier
- { "high_01_S", // entry point
+ // 1 Hz high criticality supplier (declares a rate but no threads)
+ { "high_01_S", // entry point
0, // handle
- 0, // worst case execution time
- 0, // typical execution time (unused)
- 0, // cached execution time
- 10000000, // period (100 ns)
+ 100000, // worst case execution time
+ 100000, // typical execution time (unused)
+ 100000, // cached execution time
+ 10000000, // period (100 ns)
RtecScheduler::HIGH_CRITICALITY, // criticality
RtecScheduler::LOW_IMPORTANCE, // importance
0, // quantum (unused)
- 1, // threads
+ 0, // threads
0, // OS priority
0, // Preemption subpriority
0, // Preemption priority
RtecScheduler::OPERATION // info type
},
- // 1 Hz low criticality supplier
- { "low_01_S", // entry point
+ // 1 Hz low criticality supplier (remote dependant: scheduler should warn)
+ { "low_01_S", // entry point
0, // handle
- 0, // worst case execution time
- 0, // typical execution time (unused)
- 0, // cached execution time
- 10000000, // period (100 ns)
+ 100000, // worst case execution time
+ 100000, // typical execution time (unused)
+ 100000, // cached execution time
+ 0, // period (100 ns)
RtecScheduler::LOW_CRITICALITY, // criticality
RtecScheduler::HIGH_IMPORTANCE, // importance
0, // quantum (unused)
- 1, // threads
+ 0, // threads
0, // OS priority
0, // Preemption subpriority
0, // Preemption priority
- RtecScheduler::OPERATION // info type
+ RtecScheduler::REMOTE_DEPENDANT // info type
},
// 20 Hz high criticality consumer
{ "high_20_C", // entry point
@@ -299,7 +299,7 @@ main (int argc, char *argv[])
0, // Preemption priority
RtecScheduler::OPERATION // info type
},
- // 10 Hz low criticality consumer
+ // 1 Hz low criticality consumer
{ "low_01_C", // entry point
0, // handle
0, // worst case execution time
diff --git a/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Runtime.h b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Runtime.h
index 25ea80ad2de..8e783496ce8 100644
--- a/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Runtime.h
+++ b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Runtime.h
@@ -6,37 +6,37 @@
#include "orbsvcs/Scheduler_Factory.h"
static ACE_Scheduler_Factory::POD_RT_Info infos[] = {
-{"high_20_S" , 1, 0, 0, 0, 500000, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 1, 15, 9, 0, (RtecScheduler::Info_Type) 0}
+{"high_20_S" , 1, 5000, 5000, 5000, 500000, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 1, 15, 11, 0, (RtecScheduler::Info_Type) 0}
,
-{"low_20_S" , 2, 0, 0, 0, 500000, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 1, 2, 9, 1, (RtecScheduler::Info_Type) 0}
+{"low_20_S" , 2, 5000, 5000, 5000, 500000, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 1, 2, 8, 1, (RtecScheduler::Info_Type) 0}
,
-{"high_10_S" , 3, 0, 0, 0, 1000000, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 1, 15, 6, 0, (RtecScheduler::Info_Type) 0}
+{"high_10_S" , 3, 10000, 10000, 10000, 1000000, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 1, 15, 8, 0, (RtecScheduler::Info_Type) 0}
,
-{"low_10_S" , 4, 0, 0, 0, 1000000, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 1, 2, 6, 1, (RtecScheduler::Info_Type) 0}
+{"low_10_S" , 4, 10000, 10000, 10000, 1000000, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 1, 2, 5, 1, (RtecScheduler::Info_Type) 0}
,
-{"high_05_S" , 5, 0, 0, 0, 2000000, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 1, 15, 3, 0, (RtecScheduler::Info_Type) 0}
+{"high_05_S" , 5, 20000, 20000, 20000, 2000000, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 1, 15, 5, 0, (RtecScheduler::Info_Type) 0}
,
-{"low_05_S" , 6, 0, 0, 0, 2000000, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 1, 2, 3, 1, (RtecScheduler::Info_Type) 0}
+{"low_05_S" , 6, 20000, 20000, 20000, 2000000, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 1, 2, 2, 1, (RtecScheduler::Info_Type) 0}
,
-{"high_01_S" , 7, 0, 0, 0, 10000000, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 1, 15, 0, 0, (RtecScheduler::Info_Type) 0}
+{"high_01_S" , 7, 100000, 100000, 100000, 10000000, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 15, 2, 0, (RtecScheduler::Info_Type) 0}
,
-{"low_01_S" , 8, 0, 0, 0, 10000000, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 1, 2, 0, 1, (RtecScheduler::Info_Type) 0}
+{"low_01_S" , 8, 100000, 100000, 100000, 0, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 0, 0, 0, (RtecScheduler::Info_Type) 3}
,
-{"high_20_C" , 9, 0, 0, 0, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 15, 10, 0, (RtecScheduler::Info_Type) 0}
+{"high_20_C" , 9, 0, 0, 0, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 15, 9, 0, (RtecScheduler::Info_Type) 0}
,
-{"low_20_C" , 10, 0, 0, 0, 0, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 2, 10, 1, (RtecScheduler::Info_Type) 0}
+{"low_20_C" , 10, 0, 0, 0, 0, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 2, 6, 1, (RtecScheduler::Info_Type) 0}
,
-{"high_10_C" , 11, 0, 0, 0, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 15, 7, 0, (RtecScheduler::Info_Type) 0}
+{"high_10_C" , 11, 0, 0, 0, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 15, 6, 0, (RtecScheduler::Info_Type) 0}
,
-{"low_10_C" , 12, 0, 0, 0, 0, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 2, 7, 1, (RtecScheduler::Info_Type) 0}
+{"low_10_C" , 12, 0, 0, 0, 0, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 2, 3, 1, (RtecScheduler::Info_Type) 0}
,
-{"high_05_C" , 13, 0, 0, 0, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 15, 4, 0, (RtecScheduler::Info_Type) 0}
+{"high_05_C" , 13, 0, 0, 0, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 15, 3, 0, (RtecScheduler::Info_Type) 0}
,
-{"low_05_C" , 14, 0, 0, 0, 0, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 2, 4, 1, (RtecScheduler::Info_Type) 0}
+{"low_05_C" , 14, 0, 0, 0, 0, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 2, 0, 1, (RtecScheduler::Info_Type) 0}
,
-{"high_01_C" , 15, 0, 0, 0, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 15, 1, 0, (RtecScheduler::Info_Type) 0}
+{"high_01_C" , 15, 0, 0, 0, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 15, 0, 0, (RtecScheduler::Info_Type) 0}
,
-{"low_01_C" , 16, 0, 0, 0, 0, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 2, 1, 1, (RtecScheduler::Info_Type) 0}
+{"low_01_C" , 16, 0, 0, 0, 0, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 0, 0, 0, (RtecScheduler::Info_Type) 0}
};