summaryrefslogtreecommitdiff
path: root/TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp')
-rw-r--r--TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp2393
1 files changed, 0 insertions, 2393 deletions
diff --git a/TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp b/TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp
deleted file mode 100644
index 99f78f2acaa..00000000000
--- a/TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp
+++ /dev/null
@@ -1,2393 +0,0 @@
-// $Id$
-//
-// ============================================================================
-//
-// = LIBRARY
-// sched
-//
-// = FILENAME
-// DynSched.cpp
-//
-// = CREATION DATE
-// 23 January 1997
-//
-// = AUTHOR
-// Chris Gill
-//
-// ============================================================================
-
-#include "DynSched.h"
-#include "ace/Sched_Params.h"
-#include "math.h"
-
-#if ! defined (__ACE_INLINE__)
-#include "DynSched.i"
-#endif /* __ACE_INLINE__ */
-
-ACE_RCSID(Sched, DynSched, "$Id$")
-
-//////////////////////
-// Helper functions //
-//////////////////////
-
-// compare the DFS finish times of two task entries, order higher time *first*
-extern "C" int compare_entry_finish_times (const void *first, const void *second)
-{
- // sort blank entries to the end
- if (! first)
- {
- return (second) ? 1 : 0;
- }
- else if (! second)
- {
- return -1;
- }
-
- const Task_Entry *first_entry =
- * ACE_static_cast (const Task_Entry *const *, first);
- const Task_Entry *second_entry =
- * ACE_static_cast (const Task_Entry *const *, second);
-
- // sort blank entries to the end
- if (! first_entry)
- {
- return (second_entry) ? 1 : 0;
- }
- else if (! second_entry)
- {
- return -1;
- }
-
- if (first_entry->finished () > second_entry->finished ())
- {
- return -1;
- }
- else if (first_entry->finished () < second_entry->finished ())
- {
- return 1;
- }
-
- return 0;
-}
-
-//////////////////////////////////////////
-// class ACE_DynScheduler member functions //
-//////////////////////////////////////////
-
-const char *
-ACE_DynScheduler::status_message (ACE_DynScheduler::status_t status)
-{
- switch (status)
- {
- case NOT_SCHEDULED :
- return "NOT_SCHEDULED";
- case SUCCEEDED :
- return "SUCCEEDED";
- case ST_NO_TASKS_REGISTERED :
- return "ST_NO_TASKS_REGISTERED";
- case ST_TASK_ALREADY_REGISTERED :
- return "TASK_ALREADY_REGISTERED";
- case ST_BAD_INTERNAL_POINTER :
- return "BAD_INTERNAL_POINTER";
- case ST_VIRTUAL_MEMORY_EXHAUSTED :
- return "VIRTUAL_MEMORY_EXHAUSTED";
- case ST_UNKNOWN_TASK :
- return "UNKNOWN_TASK";
- case TASK_COUNT_MISMATCH :
- return "TASK_COUNT_MISMATCH";
- case THREAD_COUNT_MISMATCH :
- return "THREAD_COUNT_MISMATCH";
- case INVALID_PRIORITY :
- return "INVALID_PRIORITY";
- case TWO_WAY_DISJUNCTION :
- return "TWO_WAY_DISJUNCTION (IGNORED)";
- case TWO_WAY_CONJUNCTION :
- return "TWO_WAY_CONJUNCTION (IGNORED)";
- case UNRECOGNIZED_INFO_TYPE :
- return "UNRECOGNIZED_INFO_TYPE (IGNORED)";
-
- // The following are only used during scheduling (in the case of
- // off-line scheduling, they are only used prior to runtime).
- // To save a little code space (280 bytes on g++ 2.7.2/Solaris 2.5.1),
- // we could conditionally compile them so that they're not in the
- // runtime version.
- case ST_UTILIZATION_BOUND_EXCEEDED :
- return "UTILIZATION_BOUND_EXCEEDED";
- case ST_INSUFFICIENT_THREAD_PRIORITY_LEVELS :
- return "INSUFFICIENT_THREAD_PRIORITY_LEVELS";
- case ST_CYCLE_IN_DEPENDENCIES :
- return "CYCLE_IN_DEPENDENCIES";
- case ST_UNRESOLVED_REMOTE_DEPENDENCIES :
- return "ST_UNRESOLVED_REMOTE_DEPENDENCIES";
- case ST_UNRESOLVED_LOCAL_DEPENDENCIES :
- return "ST_UNRESOLVED_LOCAL_DEPENDENCIES";
- case ST_INVALID_PRIORITY_ORDERING :
- return "INVALID_PRIORITY_ORDERING";
- case UNABLE_TO_OPEN_SCHEDULE_FILE :
- return "UNABLE_TO_OPEN_SCHEDULE_FILE";
- case UNABLE_TO_WRITE_SCHEDULE_FILE :
- return "UNABLE_TO_WRITE_SCHEDULE_FILE";
- // End of config-only status values.
-
- default:
- break;
- }
-
- return "UNKNOWN STATUS";
-}
-
-// = Utility function for creating an entry for determining
-// the severity of an anomaly detected during scheduling.
-ACE_DynScheduler::Anomaly_Severity
-ACE_DynScheduler::anomaly_severity (ACE_DynScheduler::status_t status)
-{
- // Determine severity of the anomaly
- switch (status)
- {
- // Fatal anomalies reflect unrecoverable internal scheduler errors
- case ST_BAD_INTERNAL_POINTER :
- case ST_VIRTUAL_MEMORY_EXHAUSTED :
- case THREAD_COUNT_MISMATCH :
- case TASK_COUNT_MISMATCH :
- return RtecScheduler::ANOMALY_FATAL;
-
- // Errors reflect severe problems with given scheduling information
- case UNABLE_TO_OPEN_SCHEDULE_FILE :
- case UNABLE_TO_WRITE_SCHEDULE_FILE :
- case NOT_SCHEDULED :
- case ST_UNRESOLVED_LOCAL_DEPENDENCIES :
- case ST_UNKNOWN_TASK :
- case ST_CYCLE_IN_DEPENDENCIES :
- case ST_INVALID_PRIORITY_ORDERING :
- return RtecScheduler::ANOMALY_ERROR;
-
- // Warnings reflect serious problems with given scheduling information
- case ST_TASK_ALREADY_REGISTERED :
- case ST_UNRESOLVED_REMOTE_DEPENDENCIES :
- case ST_UTILIZATION_BOUND_EXCEEDED :
- case ST_INSUFFICIENT_THREAD_PRIORITY_LEVELS :
- case TWO_WAY_DISJUNCTION :
- case TWO_WAY_CONJUNCTION :
- case UNRECOGNIZED_INFO_TYPE :
- case ST_NO_TASKS_REGISTERED :
- return RtecScheduler::ANOMALY_WARNING;
-
- // Produce a lowest severity anomaly for any unknown status value
- default:
- return RtecScheduler::ANOMALY_NONE;
- }
-}
-
-
-// = Utility function for creating an entry for the
-// log of anomalies detected during scheduling.
-ACE_DynScheduler::Scheduling_Anomaly *
-ACE_DynScheduler::create_anomaly (ACE_DynScheduler::status_t status)
-{
- ACE_DynScheduler::Scheduling_Anomaly * anomaly;
- ACE_NEW_RETURN (anomaly, ACE_DynScheduler::Scheduling_Anomaly, 0);
-
- anomaly->severity = anomaly_severity (status);
- anomaly->description = status_message (status);
-
- return anomaly;
-}
-
-
-ACE_DynScheduler::ACE_DynScheduler ()
- // Set the minimum and maximum priority to those for the current platform.
- // This shouldn't be necessary, but UPSingleProcessorOrb::initialize_reactors
- // creates threads before the Event Channel calls Scheduler::init ().
- : minimum_priority_ (ACE_Sched_Params::priority_min (ACE_SCHED_FIFO,
- ACE_SCOPE_PROCESS))
- , maximum_priority_ (ACE_Sched_Params::priority_max (ACE_SCHED_FIFO,
- ACE_SCOPE_PROCESS))
- , task_entries_ (0)
- , ordered_task_entries_ (0)
- , thread_delineators_ (0)
- , ordered_thread_dispatch_entries_ (0)
- , dispatch_entries_ (0)
- , config_info_entries_ (0)
- , expanded_dispatches_ (0)
- , ordered_dispatch_entries_ (0)
- , dispatch_entry_count_ (0)
- , threads_ (0)
- , timeline_ (0)
- , lock_ ()
- , rt_info_entries_ ()
- , handles_ (0)
- , runtime_filename_ (0)
- , rt_info_filename_ (0)
- , timeline_filename_ (0)
- , tasks_ (0)
- , status_ (NOT_SCHEDULED)
- , output_level_ (0)
- , frame_size_ (1)
- , critical_set_frame_size_ (0)
- , utilization_ (0.0)
- , critical_set_utilization_ (0.0)
- , minimum_priority_queue_ (0)
- , minimum_guaranteed_priority_queue_ (-1)
- , up_to_date_ (0)
- , min_dispatch_id_ (0)
- , max_dispatch_id_ (0)
-{
-}
-
-
-ACE_DynScheduler::~ACE_DynScheduler ()
-{
- // release all resources used for the most recent schedule
- reset ();
-}
-
-
-void
-ACE_DynScheduler::init (const OS_Priority minimum_priority,
- const OS_Priority maximum_priority,
- const char *runtime_filename,
- const char *rt_info_filename,
- const char *timeline_filename)
-{
- minimum_priority_ = minimum_priority;
- maximum_priority_ = maximum_priority;
- runtime_filename_ = runtime_filename;
- rt_info_filename_ = rt_info_filename;
- timeline_filename_ = timeline_filename;
-}
- // = initializes the scheduler.
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::register_task (RT_Info *rt_info, handle_t &handle)
-{
- ACE_DynScheduler::status_t ret = ST_UNKNOWN_TASK;
-
- // check the pointer we were passed
- if (! rt_info)
- {
- handle = 0;
- return ret;
- }
-
- // try to store the new task's information . . .
- switch (rt_info_entries_.insert (rt_info))
- {
- case 0 : // successfully inserted
- {
- rt_info->handle = (handle = ++handles_);
- ret = SUCCEEDED;
-
- // zero out the task entry ACT used by the scheduler
- rt_info->volatile_token = 0;
-
- // make sure the schedule is reset when a new task is registered
- reset ();
-
- if (output_level () >= 5)
- {
- ACE_OS::printf ("registered task \"%s\" with RT_Info at %X\n",
- (const char*)(rt_info->entry_point),
- (void *) rt_info);
- }
- }
- break;
-
- case 1 : // the entry had already been inserted
- handle = 0;
- ret = ST_TASK_ALREADY_REGISTERED;
- break;
-
- default :
- // case -1 : insert failed, probably because virtual memory exhaused
- handle = 0;
- ret = ST_VIRTUAL_MEMORY_EXHAUSTED;
- break;
- }
-
- return ret;
-}
- // = registers a task.
-
-
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::get_rt_info (Object_Name name,
- RT_Info* &rtinfo)
-{
- handle_t handle;
-
- // This makes a copy. We can optimize this with our own string
- // class.
- ACE_CString lookup (name);
- // Search the map for the <name>. If found, return the RT_Info.
- if (info_collection_.find (lookup, rtinfo) >= 0)
- {
- // If we find it, return.
- return SUCCEEDED;
- }
- else
- // Otherwise, make one, bind it, and register it.
- {
- rtinfo = new RT_Info;
- rtinfo->info_type = RtecScheduler::OPERATION;
- rtinfo->entry_point = name;
- // Bind the rtinfo to the name.
- if (info_collection_.bind (lookup, rtinfo) != 0)
- {
- delete rtinfo;
- rtinfo = 0;
- return FAILED; // Error!
- }
- else
- {
- // Register the task
- status_t result = this->register_task (rtinfo, handle);
- if (result == SUCCEEDED)
- {
- rtinfo->handle = handle;
- return ST_UNKNOWN_TASK; // Didn't find it, but made one!
- }
- else
- {
- rtinfo->handle = 0;
- return FAILED;
- }
- }
- }
-}
-
-
-
-
-int ACE_DynScheduler::priority (
- const RtecScheduler::handle_t handle,
- RtecScheduler::OS_Priority &priority,
- RtecScheduler::Preemption_Subpriority_t &subpriority,
- RtecScheduler::Preemption_Priority_t &preemption_prio)
-{
- // look up the RT_Info that has the given handle
- RT_Info *rt_info = 0;
- if (lookup_rt_info (handle, rt_info) == SUCCEEDED)
- {
- // copy the priority values from the RT_Info
- priority = rt_info->priority;
- subpriority = rt_info->preemption_subpriority;
- preemption_prio = rt_info->preemption_priority;
-
- return 0;
- }
- else
-
- {
- // RT_Info not found: assign default priority values
- priority = minimum_priority_;
- subpriority = ACE_Scheduler_MIN_SUB_PRIORITY;
- preemption_prio = ACE_Scheduler_MAX_PREEMPTION_PRIORITY;
-
- if (output_level () >= 3)
- {
- ACE_OS::printf ("preemption_prio %d: min %d, pri %d, min_pri %d\n",
- preemption_prio, minimum_priority_queue (),
- priority, minimum_priority_);
- }
-
- return -1;
- }
-}
- // "priority" is the OS thread priority that was assigned to the Task that
- // was assigned "handle". "subpriority" combines the dynamic and static
- // subpriorities of the Task that was assigned handle. "preemption_prio"
- // is a platform-independent priority queue number, ranging from a
- // highest priority value of 0 to the lowest priority value, which is
- // returned by "minimum_priority_queue ()". The current and deadline times
- // supplied are used to compute the operation's dynamic subpriority
- // Returns 0 on success, or -1 if an invalid handle was supplied.
-
-
-int ACE_DynScheduler::number_of_dependencies(RT_Info* rt_info)
-{
- return rt_info->dependencies.length();
-}
-
-int ACE_DynScheduler::number_of_dependencies(RT_Info& rt_info)
-{
- return rt_info.dependencies.length();
-}
-
-int ACE_DynScheduler::add_dependency(RT_Info* rt_info,
- Dependency_Info& d)
-{
- RT_Info *temp_info = 0; // temporary pointer to the caller's RT_Info
-
- switch (d.dependency_type)
- {
- case RtecScheduler::TWO_WAY_CALL:
-
- temp_info = rt_info;
- break;
-
- case RtecScheduler::ONE_WAY_CALL:
-
- // swap the handles and point to the caller instead of the called operation
- if (lookup_rt_info (d.rt_info, temp_info) != SUCCEEDED)
- {
- ACE_ERROR ((LM_ERROR, "cannot find %d to add dependency\n", d.rt_info));
- return -1;
- }
-
- d.rt_info = rt_info->handle;
- break;
-
- default:
-
- ACE_ERROR ((LM_ERROR, "unrecognized dependency type %d for %s\n",
- d.dependency_type, rt_info->entry_point.in ()));
- return -1;
- }
-
- ACE_DEBUG ((LM_DEBUG, "Sched (%t) adding %s dependency to caller: %s\n",
- (const char *) ((d.dependency_type == RtecScheduler::TWO_WAY_CALL)
- ? "TWO_WAY" : "ONE_WAY"),
- (const char*)temp_info->entry_point.in ()));
-
- RtecScheduler::Dependency_Set& set = temp_info->dependencies;
- int l = set.length();
- set.length(l + 1);
- set[l] = d;
- return 0;
-}
-
-void ACE_DynScheduler::export(RT_Info* info, FILE* file)
-{
- export(*info, file);
-}
-
-void ACE_DynScheduler::export(RT_Info& info, FILE* file)
-{
- (void) ACE_OS::fprintf (file,
- "%s\n%d\n%ld\n%ld\n%ld\n%ld\n%d\n%d\n%ld\n%u\n"
- "# begin calls\n%d\n",
- info.entry_point.in (),
- info.handle,
- ACE_U64_TO_U32 (info.worst_case_execution_time),
- ACE_U64_TO_U32 (info.typical_execution_time),
- ACE_U64_TO_U32 (info.cached_execution_time),
- info.period,
- info.criticality,
- info.importance,
- ACE_U64_TO_U32 (info.quantum),
- info.threads,
- number_of_dependencies(info));
-
- for (int i = 0; i < number_of_dependencies(info); ++i)
- {
- RT_Info tmp;
- (void) ACE_OS::fprintf (file, "%s, %d\n",
- (const char*)tmp.entry_point,
- info.dependencies[i].number_of_calls);
-
- }
-
- (void) ACE_OS::fprintf (file, "# end calls\n%d\n%d\n\n",
- info.priority,
- info.preemption_subpriority);
-
-
-}
-
-
-int
-ACE_DynScheduler::dispatch_configuration (const Preemption_Priority & p_priority,
- OS_Priority & priority,
- Dispatching_Type & d_type)
-{
- // look up the stored configuration info for the given priority level
- Config_Info *config_info;
- if (lookup_config_info (p_priority, config_info) != SUCCEEDED)
- {
- ACE_ERROR_RETURN ((LM_ERROR,
- "Config info for priority %lu could not be found\n",
- p_priority),
- -1);
- }
-
- priority = config_info->thread_priority;
- d_type = config_info->dispatching_type;
-
- return 0;
-}
- // provide the thread priority and queue type for the given priority level
-
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::lookup_rt_info (handle_t handle,
- RT_Info*& rtinfo)
-{
- if (handle < 0 || (size_t) handle > rt_info_entries_.size ())
- {
- return ST_UNKNOWN_TASK;
- }
-
- RT_Info** entry;
- ACE_Unbounded_Set_Iterator <RT_Info *> i (rt_info_entries_);
- while (i.next (entry) != 0)
- {
- i.advance ();
- RT_Info* info_ptr = *entry;
- if (info_ptr->handle == handle)
- {
- rtinfo = info_ptr;
- return SUCCEEDED;
- }
- }
-
- return ST_UNKNOWN_TASK;
-}
- // obtains an RT_Info based on its "handle".
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::lookup_config_info (Preemption_Priority priority,
- Config_Info* &config_info)
-{
- if (config_info_entries_ == 0)
- {
- return NOT_SCHEDULED;
- }
-
- if (priority < 0 || (size_t) priority > config_info_entries_->size ())
- {
- return ST_UNKNOWN_PRIORITY;
- }
-
- Config_Info** entry;
- ACE_Unbounded_Set_Iterator <Config_Info *> i (*config_info_entries_);
- while (i.next (entry) != 0)
- {
- i.advance ();
- Config_Info* config_ptr = *entry;
- if (config_ptr->preemption_priority == priority)
- {
- config_info = config_ptr;
- return SUCCEEDED;
- }
- }
-
- return ST_UNKNOWN_PRIORITY;
-}
- // Obtains a Config_Info based on its priority.
-
-
-void
-ACE_DynScheduler::reset ()
-{
- // if the schedule is up to date, free resources
- // and mark schedule as not being up to date
- if (up_to_date_)
- {
- delete [] task_entries_;
- task_entries_ = 0;
-
- delete [] ordered_task_entries_;
- ordered_task_entries_ = 0;
-
- delete thread_delineators_;
- thread_delineators_ = 0;
-
- delete [] ordered_thread_dispatch_entries_;
- ordered_thread_dispatch_entries_ = 0;
-
- if (dispatch_entries_)
- {
- // free all the dispatch entries in the list, then the list itself
- ACE_Unbounded_Set_Iterator <Dispatch_Entry *> iter (*dispatch_entries_);
- Dispatch_Entry **entry = 0;
- for (iter.first (); ! iter.done (); iter.advance (), entry = 0)
- {
- if ((iter.next (entry) != 0) && (entry) && (*entry))
- {
- delete (*entry);
- }
- }
- delete dispatch_entries_;
- dispatch_entries_ = 0;
- }
-
- if (config_info_entries_)
- {
- // free all the config info entries in the list, then the list itself
- ACE_Unbounded_Set_Iterator <Config_Info *> iter (*config_info_entries_);
- Config_Info **entry = 0;
- for (iter.first (); ! iter.done (); iter.advance (), entry = 0)
- {
- if ((iter.next (entry) != 0) && (entry) && (*entry))
- {
- delete (*entry);
- }
- }
- delete config_info_entries_;
- config_info_entries_ = 0;
- }
-
-
- if (expanded_dispatches_)
- {
- // free all the dispatch entries in the list, then the list itself
- ACE_Unbounded_Set_Iterator <Dispatch_Entry *> expanded_iter (*expanded_dispatches_);
- Dispatch_Entry **expanded_entry = 0;
- for (expanded_iter.first (); ! expanded_iter.done ();
- expanded_iter.advance (), expanded_entry = 0)
- {
- if ((expanded_iter.next (expanded_entry) != 0) &&
- (expanded_entry) && (*expanded_entry))
- {
- delete (*expanded_entry);
- }
- }
- delete expanded_dispatches_;
- expanded_dispatches_ = 0;
- }
-
- delete [] ordered_dispatch_entries_;
- ordered_dispatch_entries_ = 0;
-
- dispatch_entry_count_ = 0;
- threads_ = 0;
-
- status_ = NOT_SCHEDULED;
-
- frame_size_ = 1;
- critical_set_frame_size_ = 0;
- utilization_ = 0.0;
- critical_set_utilization_ = 0.0;
- minimum_priority_queue_ = 0;
- minimum_guaranteed_priority_queue_ = -1;
-
- if (timeline_)
- {
- // iterate over and delete the set of timeline entries
- ACE_Ordered_MultiSet_Iterator <TimeLine_Entry_Link> t_iter (*timeline_);
- TimeLine_Entry_Link *t_entry = 0;
- for (t_iter.first (); ! t_iter.done (); t_iter.advance (), t_entry = 0)
- {
- if ((t_iter.next (t_entry) != 0) && (t_entry))
- {
- delete &(t_entry->entry ());
- }
- }
- delete timeline_;
- timeline_ = 0;
- }
-
- up_to_date_ = 0;
- }
-}
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::schedule (
- ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> &anomaly_set)
-{
- RtecScheduler::Anomaly_Severity severity = RtecScheduler::ANOMALY_NONE;
- RtecScheduler::Anomaly_Severity temp_severity = RtecScheduler::ANOMALY_NONE;
- status_t temp_status = SUCCEEDED;
- Scheduling_Anomaly *anomaly = 0;
- ACE_CString unresolved_locals (""), unresolved_remotes ("");
-
- ACE_Guard<LOCK> ace_mon (lock_);
-
- if (up_to_date_)
- {
- // do nothing if the RT_Infos have not changed
- // since the last valid schedule was generated
- return SUCCEEDED;
- }
- else
- {
- // save the total number of registered RT_Infos
- tasks (rt_info_entries_.size ());
- }
-
- // set up the task entry data structures
- status_ = setup_task_entries ();
- if (status_ != SUCCEEDED)
- {
- // Create an anomaly, add it to anomaly set
- anomaly = create_anomaly (status_);
- if (anomaly)
- {
- anomaly_set.insert (anomaly);
- }
- else
- {
- return ST_VIRTUAL_MEMORY_EXHAUSTED;
- }
-
- switch (anomaly->severity)
- {
- case RtecScheduler::ANOMALY_FATAL :
- return status_;
-
- default:
- severity = anomaly->severity;
- break;
- }
- }
-
- // check for cycles in the dependency graph: as a side effect, leaves
- // the ordered_task_entries_ pointer array sorted in topological order,
- // which is used by propagate_dispatches () to ensure that dispatches
- // are propagated top down in the call graph.
- temp_status = check_dependency_cycles ();
- if (temp_status != SUCCEEDED)
- {
- // Create an anomaly, add it to anomaly set
- anomaly = create_anomaly (temp_status);
- if (anomaly)
- {
- anomaly_set.insert (anomaly);
- }
- else
- {
- return ST_VIRTUAL_MEMORY_EXHAUSTED;
- }
-
- switch (anomaly->severity)
- {
- case RtecScheduler::ANOMALY_FATAL :
- status_ = temp_status;
- return status_;
-
- case RtecScheduler::ANOMALY_ERROR :
- severity = anomaly->severity;
- status_ = temp_status;
- break;
-
- case RtecScheduler::ANOMALY_WARNING :
- if (severity == RtecScheduler::ANOMALY_NONE)
- {
- severity = anomaly->severity;
- status_ = temp_status;
- }
- break;
-
- default:
- break;
- }
- }
-
- // task entries are related, now threads can be found
- temp_status = identify_threads (unresolved_locals,
- unresolved_remotes);
- if (temp_status != SUCCEEDED)
- {
- temp_severity = anomaly_severity (temp_status);
- switch (temp_severity)
- {
- case RtecScheduler::ANOMALY_FATAL :
- status_ = temp_status;
- return status_;
-
- case RtecScheduler::ANOMALY_ERROR :
- severity = temp_severity;
- status_ = temp_status;
- break;
-
- case RtecScheduler::ANOMALY_WARNING :
- if (severity == RtecScheduler::ANOMALY_NONE)
- {
- severity = temp_severity;
- status_ = temp_status;
- }
- break;
-
- default:
- break;
- }
- }
-
- // invoke the internal thread scheduling method of the strategy
- temp_status = schedule_threads (anomaly_set);
- if (temp_status != SUCCEEDED)
- {
- temp_severity = anomaly_severity (temp_status);
- switch (temp_severity)
- {
- case RtecScheduler::ANOMALY_FATAL :
- status_ = temp_status;
- return status_;
-
- case RtecScheduler::ANOMALY_ERROR :
- severity = temp_severity;
- status_ = temp_status;
- break;
-
- case RtecScheduler::ANOMALY_WARNING :
- if (severity == RtecScheduler::ANOMALY_NONE)
- {
- severity = temp_severity;
- status_ = temp_status;
- }
- break;
-
- default:
- break;
- }
- }
-
- // propagate the dispatch information from the
- // threads throughout the call graph
- temp_status = propagate_dispatches (anomaly_set,
- unresolved_locals,
- unresolved_remotes);
- if (temp_status != SUCCEEDED)
- {
- temp_severity = anomaly_severity (temp_status);
- switch (temp_severity)
- {
- case RtecScheduler::ANOMALY_FATAL :
- status_ = temp_status;
- return status_;
-
- case RtecScheduler::ANOMALY_ERROR :
- severity = temp_severity;
- status_ = temp_status;
- break;
-
- case RtecScheduler::ANOMALY_WARNING :
- if (severity == RtecScheduler::ANOMALY_NONE)
- {
- severity = temp_severity;
- status_ = temp_status;
- }
- break;
-
- default:
- break;
- }
- }
-
- // log anomalies for unresolved local dependencies
- if (unresolved_locals.length () > 0)
- {
- // Create an anomaly, add it to anomaly set
- anomaly = create_anomaly (ST_UNRESOLVED_LOCAL_DEPENDENCIES);
- if (anomaly)
- {
- anomaly_set.insert (anomaly);
- }
- else
- {
- return ST_VIRTUAL_MEMORY_EXHAUSTED;
- }
-
- ACE_NEW_RETURN (anomaly, ACE_DynScheduler::Scheduling_Anomaly,
- ST_VIRTUAL_MEMORY_EXHAUSTED);
-
- ACE_CString temp_str ("The following entry points have "
- "unresolved local dependencies:\n");
- temp_str += unresolved_locals;
-
- anomaly->severity =
- anomaly_severity (ST_UNRESOLVED_LOCAL_DEPENDENCIES);
- anomaly->description = temp_str.c_str ();
- anomaly_set.insert (anomaly);
- }
-
- // log anomalies for unresolved remote dependencies
- if (unresolved_remotes.length () > 0)
- {
- // Create an anomaly, add it to anomaly set
- anomaly = create_anomaly (ST_UNRESOLVED_REMOTE_DEPENDENCIES);
- if (anomaly)
- {
- anomaly_set.insert (anomaly);
- }
- else
- {
- return ST_VIRTUAL_MEMORY_EXHAUSTED;
- }
-
- ACE_NEW_RETURN (anomaly, ACE_DynScheduler::Scheduling_Anomaly,
- ST_VIRTUAL_MEMORY_EXHAUSTED);
-
- ACE_CString temp_str ("The following entry points have "
- "unresolved remote dependencies:\n");
- temp_str += unresolved_remotes;
-
- anomaly->severity =
- anomaly_severity (ST_UNRESOLVED_REMOTE_DEPENDENCIES);
- anomaly->description = temp_str.c_str ();
- anomaly_set.insert (anomaly);
- }
-
- // invoke the internal dispatch scheduling method of the strategy
- temp_status = schedule_dispatches (anomaly_set);
- if (temp_status != SUCCEEDED)
- {
- temp_severity = anomaly_severity (temp_status);
- switch (temp_severity)
- {
- case RtecScheduler::ANOMALY_FATAL :
- status_ = temp_status;
- return status_;
-
- case RtecScheduler::ANOMALY_ERROR :
- severity = temp_severity;
- status_ = temp_status;
- break;
-
- case RtecScheduler::ANOMALY_WARNING :
- if (severity == RtecScheduler::ANOMALY_NONE)
- {
- severity = temp_severity;
- status_ = temp_status;
- }
- break;
-
- default:
- break;
- }
- }
-
- // calculate utilization, total frame size, critical set
- temp_status = calculate_utilization_params ();
- if (temp_status != SUCCEEDED)
- {
- // Create an anomaly, add it to anomaly set
- anomaly = create_anomaly (temp_status);
- if (anomaly)
- {
- anomaly_set.insert (anomaly);
- }
- else
- {
- return ST_VIRTUAL_MEMORY_EXHAUSTED;
- }
-
- switch (anomaly->severity)
- {
- case RtecScheduler::ANOMALY_FATAL :
- status_ = temp_status;
- return status_;
-
- case RtecScheduler::ANOMALY_ERROR :
- severity = anomaly->severity;
- status_ = temp_status;
- break;
-
- case RtecScheduler::ANOMALY_WARNING :
- if (severity == RtecScheduler::ANOMALY_NONE)
- {
- severity = anomaly->severity;
- status_ = temp_status;
- }
- break;
-
- default:
- break;
- }
- }
-
- // calculate utilization, total frame size, critical set
- temp_status = store_assigned_info ();
- if (temp_status != SUCCEEDED)
- {
- // Create an anomaly, add it to anomaly set
- anomaly = create_anomaly (temp_status);
- if (anomaly)
- {
- anomaly_set.insert (anomaly);
- }
- else
- {
- return ST_VIRTUAL_MEMORY_EXHAUSTED;
- }
-
- switch (anomaly->severity)
- {
- case RtecScheduler::ANOMALY_FATAL :
- status_ = temp_status;
- return status_;
-
- case RtecScheduler::ANOMALY_ERROR :
- severity = anomaly->severity;
- status_ = temp_status;
- break;
-
- case RtecScheduler::ANOMALY_WARNING :
- if (severity == RtecScheduler::ANOMALY_NONE)
- {
- severity = anomaly->severity;
- status_ = temp_status;
- }
- break;
-
- default:
- break;
- }
- }
-
- // generate, store the timeline to a file if file was given
- if (timeline_filename_ != 0)
- {
- // generate the scheduling timeline over the total frame size
- temp_status = create_timeline ();
- if (temp_status != SUCCEEDED)
- {
- // Create an anomaly, add it to anomaly set
- anomaly = create_anomaly (temp_status);
- if (anomaly)
- {
- anomaly_set.insert (anomaly);
- }
- else
- {
- return ST_VIRTUAL_MEMORY_EXHAUSTED;
- }
-
- switch (anomaly->severity)
- {
- case RtecScheduler::ANOMALY_FATAL :
- status_ = temp_status;
- return status_;
-
- case RtecScheduler::ANOMALY_ERROR :
- severity = anomaly->severity;
- status_ = temp_status;
- break;
-
- case RtecScheduler::ANOMALY_WARNING :
- if (severity == RtecScheduler::ANOMALY_NONE)
- {
- severity = anomaly->severity;
- status_ = temp_status;
- }
- break;
-
- default:
- break;
- }
- }
-
-
- temp_status = output_timeline (timeline_filename_, 0);
- if (temp_status != SUCCEEDED)
- {
- // Create an anomaly, add it to anomaly set
- anomaly = create_anomaly (temp_status);
- if (anomaly)
- {
- anomaly_set.insert (anomaly);
- }
- else
- {
- return ST_VIRTUAL_MEMORY_EXHAUSTED;
- }
-
- switch (anomaly->severity)
- {
- case RtecScheduler::ANOMALY_FATAL :
- status_ = temp_status;
- return status_;
-
- case RtecScheduler::ANOMALY_ERROR :
- severity = anomaly->severity;
- status_ = temp_status;
- break;
-
- case RtecScheduler::ANOMALY_WARNING :
- if (severity == RtecScheduler::ANOMALY_NONE)
- {
- severity = anomaly->severity;
- status_ = temp_status;
- }
- break;
-
- default:
- break;
- }
- }
- }
-
- // if a valid schedule was generated, mark it as up to date
- switch (status_)
- {
- // These are statuses that indicate a reasonable schedule was generated.
- case SUCCEEDED:
- case ST_TASK_ALREADY_REGISTERED :
- case ST_UNRESOLVED_REMOTE_DEPENDENCIES :
- case ST_UTILIZATION_BOUND_EXCEEDED :
- case ST_INSUFFICIENT_THREAD_PRIORITY_LEVELS :
-
- // if we made it here, the schedule is done
- up_to_date_ = 1;
-
- break;
-
- default:
- break;
- }
-
-
- return status_;
-}
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::propagate_dispatches (
- ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> &anomaly_set,
- ACE_CString & unresolved_locals,
- ACE_CString & unresolved_remotes)
-{
- u_long i;
- frame_size_ = 1;
- status_t status = SUCCEEDED;
- Scheduling_Anomaly * anomaly = 0;
-
- // iterate through the ordered_task_entries_ array in order
- // from highest DFS finishing time to lowest, so that every
- // calling dispatch is accessed before those it calls:
- // the dispatches propagate top down through the call DAG
- for (i = 0; i < tasks (); ++i)
- {
- switch (ordered_task_entries_ [i]->merge_dispatches (*dispatch_entries_,
- unresolved_locals,
- unresolved_remotes))
- {
- case Task_Entry::INTERNAL_ERROR :
- // Create an anomaly, add it to anomaly set
- anomaly = create_anomaly (ST_BAD_INTERNAL_POINTER);
- if (anomaly)
- {
- anomaly_set.insert (anomaly);
- }
- else
- {
- return ST_VIRTUAL_MEMORY_EXHAUSTED;
- }
-
- return ST_BAD_INTERNAL_POINTER;
-
- case Task_Entry::TWO_WAY_DISJUNCTION :
- if (status == SUCCEEDED)
- {
- status = TWO_WAY_DISJUNCTION;
- }
- anomaly = create_anomaly (TWO_WAY_DISJUNCTION);
- if (anomaly)
- {
- anomaly_set.insert (anomaly);
- }
- else
- {
- return ST_VIRTUAL_MEMORY_EXHAUSTED;
- }
- break;
-
- case Task_Entry::TWO_WAY_CONJUNCTION :
- if (status == SUCCEEDED)
- {
- status = TWO_WAY_CONJUNCTION;
- }
- anomaly = create_anomaly (TWO_WAY_CONJUNCTION);
- if (anomaly)
- {
- anomaly_set.insert (anomaly);
- }
- else
- {
- return ST_VIRTUAL_MEMORY_EXHAUSTED;
- }
- break;
-
- case Task_Entry::UNRECOGNIZED_INFO_TYPE :
- if (status == SUCCEEDED)
- {
- status = UNRECOGNIZED_INFO_TYPE;
- }
- anomaly = create_anomaly (UNRECOGNIZED_INFO_TYPE);
- if (anomaly)
- {
- anomaly_set.insert (anomaly);
- }
- else
- {
- return ST_VIRTUAL_MEMORY_EXHAUSTED;
- }
- break;
-
- case Task_Entry::SUCCEEDED :
- default:
- break;
- }
-
- if (ordered_task_entries_ [i]->effective_period () > 0)
- {
- frame_size_ =
- minimum_frame_size (frame_size_,
- ordered_task_entries_ [i]->effective_period ());
- }
- }
-
- return status;
-}
-// propagate the dispatch information from the
-// threads throughout the call graph
-
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::calculate_utilization_params (void)
-{
- critical_set_frame_size_ = 0;
- utilization_ = 0.0;
- critical_set_utilization_ = 0.0;
-
- minimum_priority_queue_ =
- ordered_dispatch_entries_ [0]->priority ();
-
- minimum_guaranteed_priority_queue_ = -1;
-
- // iterate through ordered task entries, calculating frame size, utilization
- for (u_int i = 0; i < dispatch_entry_count_; ++i)
- {
- // if we've just finished examining another priority level
- if (minimum_priority_queue_ != ordered_dispatch_entries_ [i]->priority ())
- {
- // update parameters for the previous priority level
- update_priority_level_params ();
-
- // update the minimum priority queue
- minimum_priority_queue_ = ordered_dispatch_entries_ [i]->priority ();
- }
-
- // Only consider computation times of dispatches of
- // OPERATION and REMOTE_DEPENDANT descriptors.
- if (((ordered_dispatch_entries_ [i]->task_entry ().info_type () ==
- RtecScheduler::OPERATION) ||
- (ordered_dispatch_entries_ [i]->task_entry ().info_type () ==
- RtecScheduler::REMOTE_DEPENDANT)) &&
- (ordered_dispatch_entries_ [i]->task_entry ().effective_period () > 0))
- {
- utilization_ +=
- ACE_static_cast (double,
- ACE_UINT64_DBLCAST_ADAPTER (ordered_dispatch_entries_ [i]->
- task_entry ().rt_info ()->worst_case_execution_time)) /
- ACE_static_cast (double, ordered_dispatch_entries_ [i]->
- task_entry ().effective_period ());
- }
- }
-
- // update parameters for the lowest priority level
- update_priority_level_params ();
-
- // if the critical set is schedulable, return success
- return (1.0 - critical_set_utilization_ > DBL_EPSILON)
- ? SUCCEEDED : ST_UTILIZATION_BOUND_EXCEEDED;
-}
-
-
-
-void
-ACE_DynScheduler::update_priority_level_params ()
-{
- // if we've just finished examining a critical priority level
- if (minimum_priority_queue_ <= minimum_critical_priority ())
- {
- // update the information about the critical set
- critical_set_frame_size_ = frame_size_;
- critical_set_utilization_ = utilization_;
- }
-
- // if the lowest priority level considered is schedulable
- if (1.0 - utilization_ > DBL_EPSILON)
- {
- // the minimum guaranteed priority queue is the minimum considered so far
- minimum_guaranteed_priority_queue_ = minimum_priority_queue_;
- }
-}
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::setup_task_entries (void)
-{
- // store number of tasks, based on registrations
- tasks (rt_info_entries_.size ());
-
- // bail out if there are no tasks registered
- if (tasks () <= 0)
- {
- return ST_NO_TASKS_REGISTERED;
- }
-
- // clear the decks of any previous scheduling information
- reset ();
-
- // allocate new table of task entries (wrappers for rt_infos)
- ACE_NEW_RETURN (task_entries_, Task_Entry [tasks ()],
- ST_VIRTUAL_MEMORY_EXHAUSTED);
-
- // allocate new table of pointers to task entries (for sorting)
- ACE_NEW_RETURN (ordered_task_entries_, Task_Entry *[tasks ()],
- ST_VIRTUAL_MEMORY_EXHAUSTED);
- ACE_OS::memset (ordered_task_entries_, 0,
- sizeof (Task_Entry *) * tasks ());
-
- // allocate new unbounded set for pointers to
- // task entries that delineate threads
- ACE_NEW_RETURN (thread_delineators_, ACE_Unbounded_Set <Dispatch_Entry *>,
- ST_VIRTUAL_MEMORY_EXHAUSTED);
-
- // allocate new unbounded set for pointers to dispatch entries
- ACE_NEW_RETURN (dispatch_entries_,
- ACE_Unbounded_Set <Dispatch_Entry *>,
- ST_VIRTUAL_MEMORY_EXHAUSTED);
-
- // allocate new unbounded set for pointers to config info entries
- ACE_NEW_RETURN (config_info_entries_,
- ACE_Unbounded_Set <Config_Info *>,
- ST_VIRTUAL_MEMORY_EXHAUSTED);
-
-
- // set up links between rt_info_entries_, task_entries_,
- // and ordered_task_entries_ tables
- ACE_Unbounded_Set_Iterator <RT_Info *> iter (rt_info_entries_);
- for (u_int i = 0; i < tasks (); ++i, iter.advance ())
- {
- RT_Info** info_entry;
-
- // tie task entry to corresponding rt_info
- if (! iter.next (info_entry))
- {
- return ST_BAD_INTERNAL_POINTER;
- }
- task_entries_ [i].rt_info (*info_entry);
-
- // tie rt_info to corresponding task entry
- task_entries_ [i].rt_info ()->volatile_token = (u_long) &(task_entries_ [i]);
-
- // tie ordered task entry pointer to corresponding task entry
- ordered_task_entries_ [i] = &(task_entries_ [i]);
- }
-
- // set up bidirectional links between task entries
- return relate_task_entries ();
-}
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::relate_task_entries (void)
-{
- status_t status = SUCCEEDED;
-
- // do DFS traversal of the entire RT_Info handle dependency DAG, replicating
- // the handle dependency DAG as a calls DAG of pointers between task
- // entries (and creating its transpose, the callers DAG). This is done
- // to avoid the O(n) cost of handle lookups in the RT_Infos for further
- // traversal of the graph during schedule sorting. One useful side effect
- // of this traversal is that is produces a topological ordering of dependencies
- // in the traversal finishing times, which can be used to detect call cycles.
- long time = 0;
-
- for (u_int i = 0; i < tasks (); ++i)
- {
- if ((status = relate_task_entries_recurse (time, task_entries_[i]))
- != SUCCEEDED)
- {
- break;
- }
- }
-
- return status;
-}
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::relate_task_entries_recurse (long &time, Task_Entry &entry)
-{
-
- // may have entered at a non-root node previously, so this does
- // not necessarily indicate a cycle in the dependency graph
- if (entry.dfs_status () != Task_Entry::NOT_VISITED)
- {
- return SUCCEEDED;
- }
-
- // when a node is discovered, mark it as visited, increment "time" and
- // store as the entry's discovery time. This is not currently used in
- // the scheduling algorithms, but is left in for possible future use
- // as it shows full parenthetization of entry discovery/finishing.
- entry.dfs_status (Task_Entry::VISITED);
- entry.discovered (++time);
-
- u_int dependency_count = number_of_dependencies (*entry.rt_info ());
- if (dependency_count > 0)
- {
- // traverse dependencies of underlying RT_Info
- for (u_int i = 0; i < dependency_count; ++i)
- {
- // obtain a pointer to the corresponding Task_Entry for each dependency
-
- RT_Info* dependency_info = 0;
- lookup_rt_info(entry.rt_info ()->dependencies[i].rt_info, dependency_info);
-
- if (! dependency_info)
- {
- return ST_BAD_INTERNAL_POINTER;
- }
-
- // obtain a pointer to the Task_Entry from the dependency RT_Info
- Task_Entry *dependency_entry_ptr =
- (Task_Entry *) dependency_info->volatile_token;
-
- if (! dependency_entry_ptr)
- {
- return ST_BAD_INTERNAL_POINTER;
- }
-
- // relate the entries according to the direction of the dependency
- Task_Entry_Link *link;
- ACE_NEW_RETURN (link,
- Task_Entry_Link (entry,
- *dependency_entry_ptr,
- entry.rt_info ()->dependencies[i].number_of_calls,
- entry.rt_info ()->dependencies[i].dependency_type),
- ST_VIRTUAL_MEMORY_EXHAUSTED);
-
- dependency_entry_ptr->callers ().insert (link);
- entry.calls ().insert (link);
-
- // depth first recursion on the newly identified entry
- relate_task_entries_recurse (time, *dependency_entry_ptr);
- }
- }
-
- // when a node is finished, mark it as finished, increment "time" and
- // store as the entry's finish time. This produces a topological ordering
- // based on dependencies, which is used to check for call cycles.
- entry.dfs_status (Task_Entry::FINISHED);
- entry.finished (++time);
-
- return SUCCEEDED;
-}
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::identify_threads (ACE_CString & unresolved_locals,
- ACE_CString & unresolved_remotes)
-{
- u_int i, j;
- ACE_DynScheduler::status_t result = SUCCEEDED;
- char string_buffer [BUFSIZ];
-
- // walk array of task entries, picking out thread delineators
- for (i = 0; i < tasks_; i++)
- {
- // if entry has exposed threads or no callers, it may be a thread
- if ((task_entries_ [i].rt_info ()->threads > 0) ||
- (task_entries_ [i].callers ().is_empty ()))
- {
- // if its period is valued, it's a thread delineator
- if (task_entries_ [i].rt_info ()->period > 0)
- {
- task_entries_ [i].effective_period (task_entries_ [i].rt_info ()->period);
- task_entries_ [i].is_thread_delineator (1);
-
- // create a Dispatch_Entry for each thread of the delimiting Task_Entry
- u_int thread_count = (task_entries_ [i].rt_info ()->threads > 0)
- ? task_entries_ [i].rt_info ()->threads : 1;
- // Just use low 32 bits of effective_period. This will
- // have to change when CosTimeBase.idl is finalized.
- const TimeBase::TimeT zero = 0;
- for (j = 0; j < thread_count; j++)
- {
- Dispatch_Entry *dispatch_ptr;
- const TimeBase::TimeT effective_period =
- task_entries_ [i].effective_period ();
- ACE_NEW_RETURN(dispatch_ptr,
- Dispatch_Entry (zero,
- effective_period,
- task_entries_ [i].rt_info ()->preemption_priority,
- task_entries_ [i].rt_info ()->priority,
- task_entries_ [i]),
- ST_VIRTUAL_MEMORY_EXHAUSTED);
-
- if ((task_entries_ [i].dispatches ().insert (Dispatch_Entry_Link (*dispatch_ptr)) < 0) ||
- (dispatch_entries_->insert (dispatch_ptr) < 0) ||
- (thread_delineators_->insert (dispatch_ptr) < 0))
- {
- return ST_VIRTUAL_MEMORY_EXHAUSTED;
- }
-
- // increase the count of thread dispatches
- ++ threads_;
- }
- }
- else if (task_entries_ [i].rt_info ()->info_type == RtecScheduler::REMOTE_DEPENDANT)
- {
- // Warn about unresolved remote dependencies, mark the task entry
-
- result = (result == SUCCEEDED)
- ? ST_UNRESOLVED_REMOTE_DEPENDENCIES
- : result;
-
- task_entries_ [i].has_unresolved_remote_dependencies (1);
-
- ACE_DEBUG (
- (LM_DEBUG,
- "Warning: an operation identified by "
- "\"%s\" has unresolved remote dependencies.\n",
- (const char*) task_entries_ [i].rt_info ()->entry_point));
-
- // Record entry point in list of unresolved remote dependencies
- ACE_OS::sprintf (string_buffer, "// %s\n",
- (const char*) task_entries_ [i].rt_info ()->
- entry_point);
- unresolved_remotes +=
- ACE_CString (string_buffer);
- }
- else
- {
- // Local node that no one calls and has neither rate nor threads is suspect
- ACE_DEBUG (
- (LM_DEBUG,
- "Error: operation \"%s\" does not specify a period or\n"
- "visible threads, and is not called by any other operation.\n"
- "Are there backwards dependencies.\n",
- (const char*) task_entries_ [i].rt_info ()->entry_point));
-
- result = ST_UNRESOLVED_LOCAL_DEPENDENCIES;
-
- task_entries_ [i].has_unresolved_local_dependencies (1);
-
- // Record entry point in list of unresolved local dependencies
- ACE_OS::sprintf (string_buffer, "// %s\n",
- (const char*) task_entries_ [i].rt_info ()->
- entry_point);
- unresolved_locals +=
- ACE_CString (string_buffer);
- }
- }
- }
-
- return result;
-}
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::check_dependency_cycles (void)
-{
- status_t return_status = SUCCEEDED;
-
- // sort the pointers to entries in order of descending finish time
- ::qsort ((void *) ordered_task_entries_,
- tasks (),
- sizeof (Task_Entry *),
- compare_entry_finish_times);
-
- // set all the dfs_status indicators to NOT_VISITED
- u_int i;
- for (i = 0; i < tasks (); ++i)
- {
- ordered_task_entries_ [i]->dfs_status (Task_Entry::NOT_VISITED);
- }
-
- // recurse on each entry, saving most recent status if it is not SUCCEEDED
- for (i = 0; i < tasks (); ++i)
- {
- status_t status =
- check_dependency_cycles_recurse (*ordered_task_entries_ [i]);
-
- if (status != SUCCEEDED)
- {
- return_status = status;
- }
- }
-
- return return_status;
-}
- // uses strongly connected components algorithm: consider entries
- // in order of finishing time from dependency DAG traversal,
- // but traverse transpose graph: any entry that has a dependant
- // that was not previously visited in this traversal is part
- // of a dependency cycle
-
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::check_dependency_cycles_recurse (Task_Entry &entry)
-{
- status_t return_status = SUCCEEDED;
-
- // halt DFS recursion on callers graph if entry has already been visited
- if (entry.dfs_status () != Task_Entry::NOT_VISITED)
- {
- return return_status;
- }
-
- // mark the entry as visited
- entry.dfs_status (Task_Entry::VISITED);
-
- // check all the calling operations: if there is one that has not already been
- // visited, mark the return status indicating there is a cycle, print
- // an error message to that effect, and recurse on that dependant
- Task_Entry_Link **calling_entry_link;
- ACE_Unbounded_Set_Iterator <Task_Entry_Link *> i (entry.callers ());
- while (i.next (calling_entry_link) != 0)
- {
- i.advance ();
- if ((*calling_entry_link)->caller ().dfs_status () == Task_Entry::NOT_VISITED)
- {
- // indicate the two tasks are in (the same) dependency cycle
- ACE_ERROR ((LM_ERROR,
- "Tasks \"%s\" and \"%s\" are part of a call cycle.\n",
- (*calling_entry_link)->caller ().rt_info ()->entry_point.in (),
- entry.rt_info ()->entry_point.in ()));
-
- // set return status, ignore status returned by recursive call:
- // we already know there are cycles in the dependencies
- return_status = ST_CYCLE_IN_DEPENDENCIES;
- check_dependency_cycles_recurse ((*calling_entry_link)->caller ());
- }
- }
-
- // mark the entry as finished
- entry.dfs_status (Task_Entry::FINISHED);
-
- return return_status;
-}
-
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::schedule_threads (ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> &anomaly_set)
-{
- // make sure there are as many thread delineator
- // entries in the set as the counter indicates
- if (threads_ != thread_delineators_->size ())
- {
- return THREAD_COUNT_MISMATCH;
- }
-
- // allocate an array of pointers to the thread delineators
- ACE_NEW_RETURN (ordered_thread_dispatch_entries_,
- Dispatch_Entry * [threads_],
- ST_VIRTUAL_MEMORY_EXHAUSTED);
- ACE_OS::memset (ordered_thread_dispatch_entries_, 0,
- sizeof (Dispatch_Entry *) * threads_);
-
-
- // copy pointers to the thread delineators from the set to the array
- ACE_Unbounded_Set_Iterator <Dispatch_Entry *> iter (*thread_delineators_);
- for (u_int i = 0; i < threads_; ++i, iter.advance ())
- {
- Dispatch_Entry** dispatch_entry;
-
- if (! iter.next (dispatch_entry))
- {
- return ST_BAD_INTERNAL_POINTER;
- }
-
- ordered_thread_dispatch_entries_ [i] = *dispatch_entry;
- }
-
- // sort the thread dispatch entries into priority order
- status_t status = sort_dispatches (ordered_thread_dispatch_entries_, threads_);
-
- if (status == SUCCEEDED)
- {
- // assign priorities to the thread dispatch entries
- status = assign_priorities (ordered_thread_dispatch_entries_,
- threads_, anomaly_set);
- }
-
- return status;
-}
- // thread scheduling method: sets up array of pointers to task
- // entries that are threads, calls internal thread scheduling method
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::schedule_dispatches (ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> &anomaly_set)
-{
- dispatch_entry_count_ = dispatch_entries_->size ();
-
- ACE_NEW_RETURN (ordered_dispatch_entries_,
- Dispatch_Entry * [dispatch_entry_count_],
- ST_VIRTUAL_MEMORY_EXHAUSTED);
- ACE_OS::memset (ordered_dispatch_entries_, 0,
- sizeof (Dispatch_Entry *) * dispatch_entry_count_);
-
- ACE_Unbounded_Set_Iterator <Dispatch_Entry *> iter (*dispatch_entries_);
- for (u_int i = 0; i < dispatch_entry_count_; ++i, iter.advance ())
- {
- Dispatch_Entry** dispatch_entry;
-
- if (! iter.next (dispatch_entry))
- {
- return ST_BAD_INTERNAL_POINTER;
- }
-
- ordered_dispatch_entries_ [i] = *dispatch_entry;
- }
-
- // sort the entries in order of priority and subpriority
- sort_dispatches (ordered_dispatch_entries_, dispatch_entry_count_);
-
- // assign dynamic and static subpriorities to the thread dispatch entries
- return assign_subpriorities (ordered_dispatch_entries_,
- dispatch_entry_count_, anomaly_set);
-}
- // dispatch scheduling method: sets up an array of dispatch entries,
- // calls internal dispatch scheduling method.
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::store_assigned_info (void)
-{
- for (u_int i = 0; i < dispatch_entry_count_; ++i)
- {
- if ((! ordered_dispatch_entries_) || (! (ordered_dispatch_entries_[i])) ||
- (! (ordered_dispatch_entries_[i]->task_entry ().rt_info ())))
- {
- ACE_ERROR_RETURN ((LM_ERROR,
- "ACE_DynScheduler::store_assigned_info () could not store "
- "priority information (error in internal representation)"),
- ST_BAD_INTERNAL_POINTER);
- }
-
- // set OS priority and Scheduler preemption priority and static
- // preemption subpriority in underlying RT_Info
- ordered_dispatch_entries_ [i]->task_entry ().rt_info ()->priority =
- ordered_dispatch_entries_ [i]->OS_priority ();
- ordered_dispatch_entries_ [i]->task_entry ().rt_info ()->preemption_priority =
- ordered_dispatch_entries_ [i]->priority ();
- ordered_dispatch_entries_ [i]->task_entry ().rt_info ()->preemption_subpriority =
- ordered_dispatch_entries_ [i]->static_subpriority ();
- }
-
- return SUCCEEDED;
-}
- // = store assigned information back into the RT_Infos
-
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::create_timeline ()
-{
- // queue of previously scheduled entries that need to be rescheduled
- ACE_Unbounded_Queue <Dispatch_Entry *> reschedule_queue;
-
- status_t status = SUCCEEDED;
-
- ACE_NEW_RETURN(timeline_, ACE_Ordered_MultiSet <TimeLine_Entry_Link>,
- ST_VIRTUAL_MEMORY_EXHAUSTED);
-
- ACE_NEW_RETURN(expanded_dispatches_, ACE_Unbounded_Set <Dispatch_Entry *>,
- ST_VIRTUAL_MEMORY_EXHAUSTED);
-
- // start with the id of the first entry in the array
- min_dispatch_id_ = ordered_dispatch_entries_[0]->dispatch_id ();
- max_dispatch_id_ = ordered_dispatch_entries_[0]->dispatch_id ();
-
- for (u_long i = 0; i < dispatch_entry_count_; ++i)
- {
- // update the minimal and maximal id values for the schedule
- if (ordered_dispatch_entries_[i]->dispatch_id () < min_dispatch_id_)
- {
- min_dispatch_id_ = ordered_dispatch_entries_[i]->dispatch_id ();
- }
- if (ordered_dispatch_entries_[i]->dispatch_id () > max_dispatch_id_)
- {
- max_dispatch_id_ = ordered_dispatch_entries_[i]->dispatch_id ();
- }
-
- // only put OPERATION and REMOTE_DEPENDANT dispatches into the timeline.
- if ((ordered_dispatch_entries_[i]->task_entry().info_type () !=
- RtecScheduler::OPERATION) &&
- (ordered_dispatch_entries_[i]->task_entry().info_type () !=
- RtecScheduler::REMOTE_DEPENDANT))
- {
- continue;
- }
-
- // schedule the current dispatch entry into the timeline
- status = schedule_timeline_entry (*(ordered_dispatch_entries_[i]),
- reschedule_queue);
- if (status != SUCCEEDED)
- {
- break;
- }
-
- // iterate through the set of dispatch entries that need to be rescheduled
- Dispatch_Entry *rescheduled_entry;
- while (reschedule_queue.is_empty () == 0)
- {
-
- if (reschedule_queue.dequeue_head (rescheduled_entry) < 0)
- {
- status = ST_BAD_INTERNAL_POINTER;
- break;
- }
-
- status = schedule_timeline_entry (*rescheduled_entry, reschedule_queue);
- if (status != SUCCEEDED)
- {
- break;
- }
- }
- if (status != SUCCEEDED)
- {
- break;
- }
-
- // Schedule additional dispatches of the entry
- // over the total frame size into the timeline.
- u_long current_frame_offset = 0;
- u_long task_period =
- ordered_dispatch_entries_[i]->task_entry ().effective_period ();
- for (current_frame_offset = task_period;
- current_frame_offset < frame_size_;
- current_frame_offset += task_period)
- {
- Dispatch_Entry *new_dispatch_entry;
-
- // create a new dispatch entry at the current sub-frame offset
- // Just use low 32 bits of arrival and deadline. This will
- // have to change when CosTimeBase.idl is finalized.
- const TimeBase::TimeT arrival =
- ordered_dispatch_entries_[i]->arrival () + current_frame_offset;
- const TimeBase::TimeT deadline=
- ordered_dispatch_entries_[i]->deadline () + current_frame_offset;
-
- ACE_NEW_RETURN (
- new_dispatch_entry,
- Dispatch_Entry (arrival,
- deadline,
- ordered_dispatch_entries_[i]->priority (),
- ordered_dispatch_entries_[i]->OS_priority (),
- ordered_dispatch_entries_[i]->task_entry (),
- ordered_dispatch_entries_[i]),
- ST_VIRTUAL_MEMORY_EXHAUSTED);
-
- // add the new dispatch entry to the set of expanded dispatches
- expanded_dispatches_->insert (new_dispatch_entry);
-
- // schedule the new dispatch entry into the timeline
- status = schedule_timeline_entry (*new_dispatch_entry, reschedule_queue);
- if (status != SUCCEEDED)
- {
- break;
- }
-
- while (reschedule_queue.is_empty () == 0)
- {
- if (reschedule_queue.dequeue_head (rescheduled_entry) < 0)
- {
- status = ST_BAD_INTERNAL_POINTER;
- break;
- }
- status = schedule_timeline_entry (*rescheduled_entry, reschedule_queue);
- if (status != SUCCEEDED)
- {
- break;
- }
- }
- if (status != SUCCEEDED)
- {
- break;
- }
- }
-
- if (status != SUCCEEDED)
- {
- break;
- }
- }
-
- return status;
-}
- // Create a timeline.
-
-
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::output_dispatch_priorities (const char *filename)
-{
- status_t status = UNABLE_TO_OPEN_SCHEDULE_FILE;
-
- // open the file
- FILE *file = ACE_OS::fopen (filename, "w");
- if (file)
- {
- status = output_dispatch_priorities (file);
- fclose (file);
- }
-
- return status;
-}
-
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::output_dispatch_priorities (FILE *file)
-{
-
- u_long dispatch_count = 0;
- u_long i = 0;
- for (i = 0; i < dispatch_entry_count_; ++i)
- {
- dispatch_count += frame_size_ / ordered_dispatch_entries_[i]->task_entry ().effective_period ();
- }
-
- if (ACE_OS::fprintf (
- file, "\n\nSCHEDULING RESULTS:\n\n"
- "Number of dispatches: %3u\n"
- "Number of threads: %3u\n"
- "Number of tasks: %3u\n"
- "Scheduler Status: [%d] %s\n"
- "Total Frame Size: %lu nsec (%lf Hz)\n"
- "Critical Set Frame Size: %lu nsec (%lf Hz)\n"
- "Utilization: %lf\n"
- "Critical Set Utilization: %lf\n"
- "Minimum Priority Queue: %3ld\n"
- "Minimum Guaranteed Priority Queue: %3ld\n"
- "Minimum Critical Priority: %3ld\n\n\n"
-
- "DISPATCH PRIORITIES:\n\n"
- " (critical \n"
- " instant) \n"
- " dispatch dynamic static \n"
- "operation ID priority subpriority subpriority\n"
- "--------- -------- -------- ----------- -----------\n",
- dispatch_count, threads_, tasks_, status_,
- status_message(status_), frame_size_, (double) (10000000.0 / ((double) frame_size_)),
- critical_set_frame_size_, (double) (10000000.0 / ((double) critical_set_frame_size_)),
- utilization_, critical_set_utilization_, minimum_priority_queue_,
- minimum_guaranteed_priority_queue_, minimum_critical_priority ()) < 0)
-
- {
- return UNABLE_TO_WRITE_SCHEDULE_FILE;
- }
-
- for (i = 0; i < dispatch_entry_count_; ++i)
- {
- if (ACE_OS::fprintf (file, "%-11s %8lu %8lu %11lu %11lu\n",
- ordered_dispatch_entries_[i]->task_entry ().rt_info ()->entry_point.in (),
- ordered_dispatch_entries_[i]->dispatch_id (),
- ordered_dispatch_entries_[i]->priority (),
- ordered_dispatch_entries_[i]->dynamic_subpriority (),
- ordered_dispatch_entries_[i]->static_subpriority ()) < 0)
- {
- return UNABLE_TO_WRITE_SCHEDULE_FILE;
- }
- }
-
- return SUCCEEDED;
-}
-
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::output_dispatch_timeline (const char *filename)
-{
- status_t status = UNABLE_TO_OPEN_SCHEDULE_FILE;
-
- // open the file
- FILE *file = ACE_OS::fopen (filename, "w");
- if (file)
- {
- status = output_dispatch_timeline (file);
- fclose (file);
- }
-
- return status;
-}
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::output_dispatch_timeline (FILE *file)
-{
- if (ACE_OS::fprintf (
- file, "\n\nDISPATCH TIMELINE:\n\n"
- " dispatch arrival deadline start stop execution latency laxity\n"
- "operation ID (nsec) (nsec) (nsec) (nsec) time (nsec) (nsec) (nsec)\n"
- "--------- ----------- ------- -------- ----- ------ ----------- ------- ------\n") < 0)
- {
- return UNABLE_TO_WRITE_SCHEDULE_FILE;
- }
-
- // iterate through timeline, picking out entries whose prev_ pointer
- // is null (i.e. those representing the start of a dispatch), find end
- // of dispatch, output the operation, dispatch, priority, and time info
- ACE_Ordered_MultiSet_Iterator <TimeLine_Entry_Link> iter (*timeline_);
- for (iter.first (); iter.done () == 0; iter.advance ())
- {
- TimeLine_Entry_Link *link;
- if ((iter.next (link) == 0) || (! link))
- {
- return ST_BAD_INTERNAL_POINTER;
- }
-
- // for each timeline entry that starts a dispatch
- if (link->entry ().prev () == 0)
- {
- // find the last time slice for the dispatch
- TimeLine_Entry *last_entry = &(link->entry ());
- while (last_entry->next ())
- {
- last_entry = last_entry->next ();
- }
-
- Time tmp = last_entry->stop () - link->entry ().arrival () -
- link->entry ().dispatch_entry ().task_entry ().rt_info ()->
- worst_case_execution_time;
- if (link->entry ().dispatch_entry ().original_dispatch ())
- {
- if (ACE_OS::fprintf (
- file, "%-11s [%4lu] %4lu %7lu %8lu %8lu %10lu %11lu %10ld %10ld\n",
- link->entry ().dispatch_entry ().task_entry ().rt_info ()->
- entry_point.in (),
- link->entry ().dispatch_entry ().original_dispatch ()->dispatch_id (),
- link->entry ().dispatch_entry ().dispatch_id (),
- ACE_U64_TO_U32 (link->entry ().arrival ()),
- ACE_U64_TO_U32 (link->entry ().deadline ()),
- ACE_U64_TO_U32 (link->entry ().start ()),
- ACE_U64_TO_U32 (last_entry->stop ()),
- ACE_U64_TO_U32 (link->entry ().dispatch_entry ().task_entry ().
- rt_info ()->worst_case_execution_time),
- ACE_U64_TO_U32 (tmp),
- ACE_U64_TO_U32 (link->entry ().deadline () -
- last_entry->stop ())) < 0)
-
- {
- return UNABLE_TO_WRITE_SCHEDULE_FILE;
- }
- }
- else
- {
- if (ACE_OS::fprintf (
- file, "%-11s %11lu %7lu %8lu %8lu %10lu %11lu %10ld %10ld\n",
- link->entry ().dispatch_entry ().task_entry ().rt_info ()->
- entry_point.in (),
- link->entry ().dispatch_entry ().dispatch_id (),
- ACE_U64_TO_U32 (link->entry ().arrival ()),
- ACE_U64_TO_U32 (link->entry ().deadline ()),
- ACE_U64_TO_U32 (link->entry ().start ()),
- ACE_U64_TO_U32 (last_entry->stop ()),
- ACE_U64_TO_U32 (link->entry ().dispatch_entry ().task_entry ().
- rt_info ()->worst_case_execution_time),
- ACE_U64_TO_U32 (tmp),
- ACE_U64_TO_U32 (link->entry ().deadline () -
- last_entry->stop ())) < 0)
-
- {
- return UNABLE_TO_WRITE_SCHEDULE_FILE;
- }
- }
- }
- }
-
- return SUCCEEDED;
-}
- // this prints the entire set of timeline outputs to the specified file
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::output_preemption_timeline (const char *filename)
-{
- status_t status = UNABLE_TO_OPEN_SCHEDULE_FILE;
-
- // open the file
- FILE *file = ACE_OS::fopen (filename, "w");
- if (file)
- {
- status = output_preemption_timeline (file);
- fclose (file);
- }
-
- return status;
-}
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::output_preemption_timeline (FILE *file)
-{
- if (ACE_OS::fprintf (
- file, "\n\nPREEMPTION TIMELINE:\n\n"
- " dispatch start stop \n"
- "operation ID (nsec) (nsec)\n"
- "--------- ----------- ------ ------\n") < 0)
- {
- return UNABLE_TO_WRITE_SCHEDULE_FILE;
- }
-
- ACE_Ordered_MultiSet_Iterator <TimeLine_Entry_Link> iter (*timeline_);
-
- TimeLine_Entry_Link *link;
- for (iter.first (); iter.done () == 0; iter.advance ())
- {
- if ((iter.next (link) == 0) || (! link))
- {
- return ST_BAD_INTERNAL_POINTER;
- }
-
- if (link->entry ().dispatch_entry ().original_dispatch ())
- {
- if (ACE_OS::fprintf (
- file, "%-9s [%4lu] %4lu %8lu %8lu\n",
- link->entry ().dispatch_entry ().task_entry ().rt_info ()->
- entry_point.in (),
- link->entry ().dispatch_entry ().original_dispatch ()->dispatch_id (),
- link->entry ().dispatch_entry ().dispatch_id (),
- ACE_U64_TO_U32 (link->entry ().start ()),
- ACE_U64_TO_U32 (link->entry ().stop ())) < 0)
- {
- return UNABLE_TO_WRITE_SCHEDULE_FILE;
- }
- }
- else
- {
- if (ACE_OS::fprintf (
- file, "%-9s %11lu %8lu %8lu\n",
- link->entry ().dispatch_entry ().task_entry ().rt_info ()->
- entry_point.in (),
- link->entry ().dispatch_entry ().dispatch_id (),
- ACE_U64_TO_U32 (link->entry ().start ()),
- ACE_U64_TO_U32 (link->entry ().stop ())) < 0)
- {
- return UNABLE_TO_WRITE_SCHEDULE_FILE;
- }
- }
- }
-
- return SUCCEEDED;
-}
-
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::output_viewer_timeline (const char *filename)
-{
- status_t status = UNABLE_TO_OPEN_SCHEDULE_FILE;
-
- // open the file
- FILE *file = ACE_OS::fopen (filename, "w");
- if (file)
- {
- status = output_dispatch_timeline (file);
- fclose (file);
- }
-
- return status;
-}
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::output_viewer_timeline (FILE *file)
-{
- if (ACE_OS::fprintf (
- file, "\n\nVIEWER TIMELINE:\n\n"
- " arrival deadline completion execution \n"
- "operation utilization overhead (nsec) (nsec) time (nsec) time (nsec)\n"
- "--------- ----------- -------- ------- -------- ----------- -----------\n") < 0)
- {
- return UNABLE_TO_WRITE_SCHEDULE_FILE;
- }
-
- // iterate through timeline, picking out dispatches in chronological
- // order of operation completion time
- int entries_remain = 1;
- Time accumulated_execution = 0;
- Time current_accumulated_execution = 0;
- Time last_completion = 0;
- Time current_completion = 0;
- TimeLine_Entry *current_entry = 0;
- TimeLine_Entry *current_last_entry = 0;
-
- while (entries_remain)
- {
- last_completion = current_completion;
-
- accumulated_execution = 0;
- current_accumulated_execution = 0;
- current_completion = 0;
- current_entry = 0;
- current_last_entry = 0;
-
- ACE_Ordered_MultiSet_Iterator <TimeLine_Entry_Link> iter (*timeline_);
- for (iter.first (); iter.done () == 0; iter.advance ())
- {
- TimeLine_Entry_Link *link;
- if ((iter.next (link) == 0) || (! link))
- {
- return ST_BAD_INTERNAL_POINTER;
- }
-
- accumulated_execution += link->entry ().stop () -
- link->entry ().start ();
-
- // for each timeline entry that starts a dispatch
- if (link->entry ().prev () == 0)
- {
- // find the last time slice for the dispatch
- TimeLine_Entry *last_entry = &(link->entry ());
- while (last_entry->next ())
- {
- last_entry = last_entry->next ();
- }
-
- if ((last_entry->stop () > last_completion) &&
- ((last_entry->stop () < current_completion) ||
- (current_completion == 0)))
- {
- current_completion = last_entry->stop ();
- current_entry = &(link->entry ());
- current_last_entry = last_entry;
- }
- }
-
- // save the accumulated execution if we're at
- // the last entry for the current dispatch
- if (current_last_entry == &(link->entry ()))
- {
- current_accumulated_execution = accumulated_execution;
- }
- }
-
- // if we found another entry, print it (otherwise we're done)
- if (current_entry)
- {
- if (ACE_OS::fprintf (
- file, "%-11s %9lf %9lf %8lu %8lu %11lu %11u\n",
- current_entry->dispatch_entry ().task_entry ().rt_info ()->
- entry_point.in (),
- ACE_static_cast (
- double,
- ACE_UINT64_DBLCAST_ADAPTER(current_accumulated_execution)) /
- ACE_static_cast (
- double,
- ACE_UINT64_DBLCAST_ADAPTER(current_completion)),
- 0.0,
- ACE_U64_TO_U32 (current_entry->arrival ()),
- ACE_U64_TO_U32 (current_entry->deadline ()),
- ACE_U64_TO_U32 (current_last_entry->stop ()),
- ACE_U64_TO_U32 (current_entry->dispatch_entry ().task_entry ().
- rt_info ()->worst_case_execution_time)) < 0)
- {
- return UNABLE_TO_WRITE_SCHEDULE_FILE;
- }
- }
- else
- {
- entries_remain = 0;
- }
- }
-
- return SUCCEEDED;
-}
-
-
-ACE_DynScheduler::status_t
-ACE_DynScheduler::output_timeline (const char *filename, const char *heading)
-{
- status_t status = SUCCEEDED;
- FILE *file = 0;
-
- // bail out if we're not up to date or there is no timeline
- if ((! up_to_date_) || (! timeline_))
- {
- status = NOT_SCHEDULED;
- }
-
- if (status == SUCCEEDED)
- {
- // open the file
- file = ACE_OS::fopen (filename, "w");
- if (! file)
- {
- status = UNABLE_TO_OPEN_SCHEDULE_FILE;
- }
- }
-
- if ((status == SUCCEEDED) && (heading))
- {
- if (ACE_OS::fprintf (file, "%s\n\n", heading) < 0)
- {
- status = UNABLE_TO_WRITE_SCHEDULE_FILE;
- }
- }
-
- if (status == SUCCEEDED)
- {
- status = output_dispatch_priorities (file);
- }
-
- if (status == SUCCEEDED)
- {
- status = output_dispatch_timeline (file);
- }
-
- if (status == SUCCEEDED)
- {
- status = output_preemption_timeline (file);
- }
-
- if (status == SUCCEEDED)
- {
- status = output_viewer_timeline (file);
- }
-
- if (file)
- {
- fclose (file);
- }
-
- return status;
-}
- // this prints the entire set of timeline outputs to the specified file
-
-#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
-template class ACE_Map_Entry<ACE_CString, RtecScheduler::RT_Info *>;
-template class ACE_Map_Manager<ACE_CString, RtecScheduler::RT_Info *, ACE_SYNCH_MUTEX>;
-template class ACE_Map_Iterator_Base<ACE_CString, RtecScheduler::RT_Info *, ACE_SYNCH_MUTEX>;
-template class ACE_Map_Iterator<ACE_CString, RtecScheduler::RT_Info *, ACE_SYNCH_MUTEX>;
-template class ACE_Map_Reverse_Iterator<ACE_CString, RtecScheduler::RT_Info *, ACE_SYNCH_MUTEX>;
-template class ACE_DNode<Dispatch_Entry_Link>;
-template class ACE_DNode<Dispatch_Proxy_Iterator *>;
-template class ACE_DNode<TimeLine_Entry_Link>;
-template class ACE_Node<RtecScheduler::RT_Info *>;
-template class ACE_Node<Task_Entry_Link *>;
-template class ACE_Ordered_MultiSet<Dispatch_Entry_Link>;
-template class ACE_Ordered_MultiSet<Dispatch_Proxy_Iterator *>;
-template class ACE_Ordered_MultiSet<TimeLine_Entry_Link>;
-template class ACE_Ordered_MultiSet_Iterator<Dispatch_Entry_Link>;
-template class ACE_Ordered_MultiSet_Iterator<Dispatch_Proxy_Iterator *>;
-template class ACE_Ordered_MultiSet_Iterator<TimeLine_Entry_Link>;
-template class ACE_Unbounded_Queue<Dispatch_Entry *>;
-template class ACE_Unbounded_Queue_Iterator<Dispatch_Entry *>;
-template class ACE_Unbounded_Set<RtecScheduler::RT_Info *>;
-template class ACE_Unbounded_Set<Task_Entry_Link *>;
-template class ACE_Unbounded_Set_Iterator<RtecScheduler::RT_Info *>;
-template class ACE_Unbounded_Set_Iterator<Task_Entry_Link *>;
-template class ACE_Node<RtecScheduler::Config_Info *>;
-template class ACE_Unbounded_Set<RtecScheduler::Config_Info *>;
-template class ACE_Unbounded_Set_Iterator<RtecScheduler::Config_Info *>;
-template class ACE_Node<RtecScheduler::Scheduling_Anomaly *>;
-template class ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *>;
-template class ACE_Unbounded_Set_Iterator<RtecScheduler::Scheduling_Anomaly *>;
-#elif defined(ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
-#pragma instantiate ACE_Map_Entry<ACE_CString, RtecScheduler::RT_Info *>
-#pragma instantiate ACE_Map_Manager<ACE_CString, RtecScheduler::RT_Info *, ACE_SYNCH_MUTEX>
-#pragma instantiate ACE_Map_Iterator_Base<ACE_CString, RtecScheduler::RT_Info *, ACE_SYNCH_MUTEX>
-#pragma instantiate ACE_Map_Iterator<ACE_CString, RtecScheduler::RT_Info *, ACE_SYNCH_MUTEX>
-#pragma instantiate ACE_Map_Reverse_Iterator<ACE_CString, RtecScheduler::RT_Info *, ACE_SYNCH_MUTEX>
-#pragma instantiate ACE_DNode<Dispatch_Entry_Link>
-#pragma instantiate ACE_DNode<Dispatch_Proxy_Iterator *>
-#pragma instantiate ACE_DNode<TimeLine_Entry_Link>
-#pragma instantiate ACE_Node<RtecScheduler::RT_Info *>
-#pragma instantiate ACE_Node<Task_Entry_Link *>
-#pragma instantiate ACE_Ordered_MultiSet<Dispatch_Entry_Link>
-#pragma instantiate ACE_Ordered_MultiSet<Dispatch_Proxy_Iterator *>
-#pragma instantiate ACE_Ordered_MultiSet<TimeLine_Entry_Link>
-#pragma instantiate ACE_Ordered_MultiSet_Iterator<Dispatch_Entry_Link>
-#pragma instantiate ACE_Ordered_MultiSet_Iterator<Dispatch_Proxy_Iterator *>
-#pragma instantiate ACE_Ordered_MultiSet_Iterator<TimeLine_Entry_Link>
-#pragma instantiate ACE_Unbounded_Queue<Dispatch_Entry *>
-#pragma instantiate ACE_Unbounded_Queue_Iterator<Dispatch_Entry *>
-#pragma instantiate ACE_Unbounded_Set<RtecScheduler::RT_Info *>
-#pragma instantiate ACE_Unbounded_Set<Task_Entry_Link *>
-#pragma instantiate ACE_Unbounded_Set_Iterator<RtecScheduler::RT_Info *>
-#pragma instantiate ACE_Unbounded_Set_Iterator<Task_Entry_Link *>
-#pragma instantiate ACE_Node<RtecScheduler::Config_Info *>
-#pragma instantiate ACE_Unbounded_Set<RtecScheduler::Config_Info *>
-#pragma instantiate ACE_Unbounded_Set_Iterator<RtecScheduler::Config_Info *>
-#pragma instantiate ACE_Node<RtecScheduler::Scheduling_Anomaly *>
-#pragma instantiate ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *>
-#pragma instantiate ACE_Unbounded_Set_Iterator<RtecScheduler::Scheduling_Anomaly *>
-#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
-
-
-
-
-// EOF