diff options
author | cdgill <cdgill@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1998-10-19 03:24:48 +0000 |
---|---|---|
committer | cdgill <cdgill@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1998-10-19 03:24:48 +0000 |
commit | 6b15c6af8646485c6072fe14835b31094bf43d35 (patch) | |
tree | c1239013b4c3806d4247e72db122b304d1f33e34 /TAO | |
parent | 043e6bfff776fee364fcbbde2cbbbfb95e78780d (diff) | |
download | ATCD-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-98c | 15 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.cpp | 31 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp | 8 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Sched/SchedEntry.cpp | 120 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Sched/SchedEntry.h | 119 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Sched/SchedEntry.i | 30 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Sched/Scheduler.h | 1 | ||||
-rw-r--r-- | TAO/orbsvcs/tests/Sched_Conf/README | 42 | ||||
-rw-r--r-- | TAO/orbsvcs/tests/Sched_Conf/Sched_Conf.cpp | 76 | ||||
-rw-r--r-- | TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Runtime.h | 32 |
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} }; |