diff options
author | cdgill <cdgill@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1998-11-09 23:54:14 +0000 |
---|---|---|
committer | cdgill <cdgill@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1998-11-09 23:54:14 +0000 |
commit | 9df5e0df391ee8d80ab36ae86edf720f82374d91 (patch) | |
tree | f5ead0dbc00d73fafe342caeb8ffce75ee08b146 | |
parent | 587806dc9c2d2fa965f01bdd48cf447f1cadedb8 (diff) | |
download | ATCD-9df5e0df391ee8d80ab36ae86edf720f82374d91.tar.gz |
added complete anomaly recording to scheduler
24 files changed, 1580 insertions, 290 deletions
diff --git a/ChangeLog-98b b/ChangeLog-98b index 7ac0cf10d40..c73158e5940 100644 --- a/ChangeLog-98b +++ b/ChangeLog-98b @@ -729,6 +729,13 @@ Fri Oct 23 21:11:03 1998 Douglas C. Schmidt <schmidt@mambo.cs.wustl.edu> * ace/OS.h: Changed a comment to be consistent. Thanks to Serge Kolgan <skolgan@cisco.com> for reporting this. +Fri Oct 23 20:39:00 1998 Chris Gill <cdgill@cs.wustl.edu> + + * Paul Christopher Gill was born Friday October 23, 1998, at + 20:39 CDT, weighing 6 lbs. 7 oz., at 19 3/4 inches in length. + A true hacker in the making, Paul decided to work through the + evening even though it was a Friday night. ;-) + Fri Oct 23 11:37:38 1998 Steve Huston <shuston@riverace.com> * include/makeinclude/platform_aix4.2.GNU: Removed -qinitauto=5F from diff --git a/TAO/orbsvcs/orbsvcs/RtecScheduler.idl b/TAO/orbsvcs/orbsvcs/RtecScheduler.idl index 4b0477c20b3..aeb8e9d6352 100644 --- a/TAO/orbsvcs/orbsvcs/RtecScheduler.idl +++ b/TAO/orbsvcs/orbsvcs/RtecScheduler.idl @@ -169,6 +169,35 @@ module RtecScheduler typedef sequence<Config_Info> Config_Info_Set; + enum Anomaly_Severity + // Defines the type of prioritization strategy + // to be used by a dispatching queue + { + ANOMALY_FATAL, + ANOMALY_ERROR, + ANOMALY_WARNING, + ANOMALY_NONE + }; + + struct Scheduling_Anomaly + // = TITLE + // Describes an anomalous condition encountered during scheduling. + // + // = DESCRIPTION + // The severity and description of an anomolous + // condition encountered during schedule computation + // is described by the following information. + { + // Application-defined string that describes + // the anomalous condition. + string description; + + // Severity of the anomaly + Anomaly_Severity severity; + }; + + typedef sequence<Scheduling_Anomaly> Scheduling_Anomaly_Set; + exception DUPLICATE_NAME {}; // The application is trying to register the same task again. @@ -269,7 +298,8 @@ module RtecScheduler void compute_scheduling (in long minimum_priority, in long maximum_priority, out RT_Info_Set infos, - out Config_Info_Set configs) + out Config_Info_Set configs, + out Scheduling_Anomaly_Set anomalies) raises (UTILIZATION_BOUND_EXCEEDED, INSUFFICIENT_THREAD_PRIORITY_LEVELS, TASK_COUNT_MISMATCH); diff --git a/TAO/orbsvcs/orbsvcs/Runtime_Scheduler.cpp b/TAO/orbsvcs/orbsvcs/Runtime_Scheduler.cpp index a2dc0c1362a..18f2ebdcdff 100644 --- a/TAO/orbsvcs/orbsvcs/Runtime_Scheduler.cpp +++ b/TAO/orbsvcs/orbsvcs/Runtime_Scheduler.cpp @@ -196,7 +196,9 @@ void ACE_Runtime_Scheduler::add_dependency (RtecScheduler::handle_t handle, void ACE_Runtime_Scheduler::compute_scheduling (CORBA::Long minimum_priority, CORBA::Long maximum_priority, RtecScheduler::RT_Info_Set_out infos, - RtecScheduler::Config_Info_Set_out configs, + RtecScheduler::Config_Info_Set_out configs, + RtecScheduler::Scheduling_Anomaly_Set_out anomalies, + CORBA::Environment &_env) TAO_THROW_SPEC ((CORBA::SystemException, RtecScheduler::UTILIZATION_BOUND_EXCEEDED, diff --git a/TAO/orbsvcs/orbsvcs/Runtime_Scheduler.h b/TAO/orbsvcs/orbsvcs/Runtime_Scheduler.h index 81fcc5773eb..3b8200a21bd 100644 --- a/TAO/orbsvcs/orbsvcs/Runtime_Scheduler.h +++ b/TAO/orbsvcs/orbsvcs/Runtime_Scheduler.h @@ -81,6 +81,7 @@ public: CORBA::Long maximum_priority, RtecScheduler::RT_Info_Set_out infos, RtecScheduler::Config_Info_Set_out configs, + RtecScheduler::Scheduling_Anomaly_Set_out anomalies, CORBA::Environment &_env) TAO_THROW_SPEC ((CORBA::SystemException, RtecScheduler::UTILIZATION_BOUND_EXCEEDED, diff --git a/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.cpp b/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.cpp index 0dc1025acee..ec5da0f4ae5 100644 --- a/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.cpp +++ b/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.cpp @@ -113,7 +113,7 @@ ACE_Config_Scheduler::get (RtecScheduler::handle_t handle, { case BaseSchedImplType::SUCCEEDED: { - // IDL memory managment semantics require the we return a copy + // IDL memory managment semantics require that we return a copy. RtecScheduler::RT_Info* copy; ACE_NEW_RETURN (copy, RtecScheduler::RT_Info (*rt_info), 0); return copy; @@ -243,6 +243,7 @@ void ACE_Config_Scheduler::compute_scheduling (CORBA::Long minimum_priority, CORBA::Long maximum_priority, RtecScheduler::RT_Info_Set_out infos, RtecScheduler::Config_Info_Set_out configs, + RtecScheduler::Scheduling_Anomaly_Set_out anomalies, CORBA::Environment &_env) TAO_THROW_SPEC ((CORBA::SystemException, RtecScheduler::UTILIZATION_BOUND_EXCEEDED, @@ -251,35 +252,128 @@ void ACE_Config_Scheduler::compute_scheduling (CORBA::Long minimum_priority, { ACE_UNUSED_ARG (_env); + // Initialize the scheduler implementation. impl->init (minimum_priority, maximum_priority); + // Construct an unbounded set to hold any scheduling anomalies. + ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> anomaly_set; + + // Invoke the imlementation's scheduling method. BaseSchedImplType::status_t schedule_status; - schedule_status = impl->schedule (); - switch (schedule_status) + schedule_status = impl->schedule (anomaly_set); + + // Iterate over the set of anomalies, reporting each one, storing + // it in the set of anomalies to return, and determining the worst + // anomaly severity. + RtecScheduler::Anomaly_Severity severity = RtecScheduler::ANOMALY_NONE; + RtecScheduler::Scheduling_Anomaly **anomaly = 0; + char *anomaly_severity_msg = "NONE"; + CORBA::ULong anomaly_index = 0; + if (anomalies.ptr () == 0) { - // If we succeeded with no warnings, do nothing. - case BaseSchedImplType::SUCCEEDED: - break; + anomalies = + new RtecScheduler::Scheduling_Anomaly_Set (anomaly_set.size ()); + } + anomalies->length (anomaly_set.size ()); + ACE_Unbounded_Set_Iterator<RtecScheduler::Scheduling_Anomaly *> + anomaly_iter (anomaly_set); + for (anomaly_iter.first (), anomaly_index = 0; + anomaly_iter.next (anomaly); + anomaly_iter.advance (), ++anomaly_index) + { + if (0 == *anomaly) + { + // if for some reason we stored a null anomaly pointer, + // just give default values to that entry in the sequence. + anomalies[anomaly_index].severity = RtecScheduler::ANOMALY_NONE; + anomalies[anomaly_index].description = ""; + continue; + } - // Issue a warning if there were unresolved remote dependencies. - case BaseSchedImplType::ST_UNRESOLVED_REMOTE_DEPENDENCIES: + // Keep track of the *worst* anomaly severity + switch ((*anomaly)->severity) + { + case RtecScheduler::ANOMALY_FATAL: + anomaly_severity_msg = "FATAL"; + severity = RtecScheduler::ANOMALY_FATAL; + break; + + case RtecScheduler::ANOMALY_ERROR: + anomaly_severity_msg = "ERROR"; + if (severity != RtecScheduler::ANOMALY_FATAL) + { + severity = RtecScheduler::ANOMALY_ERROR; + } + break; + + case RtecScheduler::ANOMALY_WARNING: + anomaly_severity_msg = "WARNING"; + if ((severity != RtecScheduler::ANOMALY_FATAL) && + (severity != RtecScheduler::ANOMALY_ERROR)) + { + severity = RtecScheduler::ANOMALY_WARNING; + } + break; + + case RtecScheduler::ANOMALY_NONE: + anomaly_severity_msg = "UNKNOWN"; + break; + } + + // Output the anomaly message ACE_DEBUG ((LM_DEBUG, - "Warning: schedule has unresolved " - "remote dependencies\n.")); - break; + "%s: %s\n", + anomaly_severity_msg, + (*anomaly)->description)); - // 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; + // Store the anomaly in the anomaly sequence out parameter + anomalies[anomaly_index] = **anomaly; - // On any other kind of scheduling error, - // abort without generating a schedule. - default: + // Release the anomaly node. + delete (*anomaly); + } + + switch (severity) + { + // On a fatal anomaly abort without generating a schedule. + case RtecScheduler::ANOMALY_FATAL: // TODO: throw something. - ACE_ERROR ((LM_ERROR, "Schedule failed\n")); + ACE_ERROR ((LM_ERROR, "Schedule failed due to FATAL anomaly.\n")); return; + + // Otherwise, make sure we didn't get a fatal return type. + default: + switch (schedule_status) + { + case BaseSchedImplType::ST_BAD_INTERNAL_POINTER : + // TODO: throw something. + ACE_ERROR ((LM_ERROR, + "Schedule failed due to bad internal pointer.\n")); + return; + + case BaseSchedImplType::ST_VIRTUAL_MEMORY_EXHAUSTED : + // TODO: throw something. + ACE_ERROR ((LM_ERROR, + "Schedule failed due to insufficient memory.\n")); + return; + + case BaseSchedImplType::THREAD_COUNT_MISMATCH : + // TODO: throw something. + ACE_ERROR ((LM_ERROR, + "Schedule failed due to thread count mismatch.\n")); + return; + + case BaseSchedImplType::TASK_COUNT_MISMATCH : + // TODO: throw something. + ACE_ERROR ((LM_ERROR, + "Schedule failed due to task count mismatch.\n")); + return; + + // Otherwise, go ahead and generate a schedule. + default: + break; + } + break; } // return the set of scheduled RT_Infos @@ -312,11 +406,13 @@ void ACE_Config_Scheduler::compute_scheduling (CORBA::Long minimum_priority, // return the set of scheduled Config_Infos if (configs.ptr () == 0) { - configs = new RtecScheduler::Config_Info_Set(impl->minimum_priority_queue () + 1); + configs = + new RtecScheduler::Config_Info_Set(impl->minimum_priority_queue () + 1); } configs->length (impl->minimum_priority_queue () + 1); for (RtecScheduler::Preemption_Priority priority = 0; - priority <= (RtecScheduler::Preemption_Priority) impl->minimum_priority_queue (); + priority <= + (RtecScheduler::Preemption_Priority) impl->minimum_priority_queue (); ++priority) { RtecScheduler::Config_Info* config_info = 0; @@ -330,17 +426,18 @@ void ACE_Config_Scheduler::compute_scheduling (CORBA::Long minimum_priority, case BaseSchedImplType::ST_UNKNOWN_TASK: default: ACE_ERROR ((LM_ERROR, - "Config_Scheduler::schedule - lookup_config_info failed\n")); + "Config_Scheduler::schedule - " + "lookup_config_info failed\n")); // TODO: throw something. break; } } - ACE_DEBUG ((LM_DEBUG, "schedule prepared\n")); - - ACE_DEBUG ((LM_DEBUG, "dumping to stdout\n")); - ACE_Scheduler_Factory::dump_schedule (*(infos.ptr()), *(configs.ptr()), 0); - ACE_DEBUG ((LM_DEBUG, "dump done\n")); + ACE_DEBUG ((LM_DEBUG, "Schedule prepared.\n")); + ACE_DEBUG ((LM_DEBUG, "Dumping to stdout.\n")); + ACE_Scheduler_Factory::dump_schedule (*(infos.ptr()), *(configs.ptr()), + *(anomalies.ptr()), 0); + ACE_DEBUG ((LM_DEBUG, "Dump done.\n")); } diff --git a/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.h b/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.h index 866b373dd72..58d2084e31a 100644 --- a/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.h +++ b/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.h @@ -89,6 +89,7 @@ public: CORBA::Long maximum_priority, RtecScheduler::RT_Info_Set_out infos, RtecScheduler::Config_Info_Set_out configs, + RtecScheduler::Scheduling_Anomaly_Set_out anomalies, CORBA::Environment &_env) TAO_THROW_SPEC((CORBA::SystemException, RtecScheduler::UTILIZATION_BOUND_EXCEEDED, diff --git a/TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp b/TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp index 8ba959ee59d..6f71fd94198 100644 --- a/TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp +++ b/TAO/orbsvcs/orbsvcs/Sched/DynSched.cpp @@ -83,10 +83,10 @@ ACE_DynScheduler::status_message (ACE_DynScheduler::status_t status) 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_DEPENDENCIES_ON_TASK : - return "BAD_DEPENDENCIES_ON_TASK"; case ST_BAD_INTERNAL_POINTER : return "BAD_INTERNAL_POINTER"; case ST_VIRTUAL_MEMORY_EXHAUSTED : @@ -95,8 +95,16 @@ ACE_DynScheduler::status_message (ACE_DynScheduler::status_t status) 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). @@ -111,6 +119,8 @@ ACE_DynScheduler::status_message (ACE_DynScheduler::status_t status) 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 : @@ -126,6 +136,66 @@ ACE_DynScheduler::status_message (ACE_DynScheduler::status_t status) 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; + break; + + // 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; + break; + + // Produce a lowest severity anomaly for any unknown status value + default: + return RtecScheduler::ANOMALY_NONE; + break; + } +} + + +// = 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. @@ -193,13 +263,13 @@ ACE_DynScheduler::init (const OS_Priority minimum_priority, ACE_DynScheduler::status_t ACE_DynScheduler::register_task (RT_Info *rt_info, handle_t &handle) { - ACE_DynScheduler::status_t ret; + ACE_DynScheduler::status_t ret = ST_UNKNOWN_TASK; // check the pointer we were passed if (! rt_info) { handle = 0; - return ST_UNKNOWN_TASK; + return ret; } // try to store the new task's information . . . @@ -454,7 +524,7 @@ ACE_DynScheduler::dispatch_configuration (const Preemption_Priority & p_priority ACE_DynScheduler::status_t ACE_DynScheduler::lookup_rt_info (handle_t handle, - RT_Info*& rtinfo) + RT_Info*& rtinfo) { if (handle < 0 || (size_t) handle > rt_info_entries_.size ()) { @@ -616,9 +686,13 @@ ACE_DynScheduler::reset () } ACE_DynScheduler::status_t -ACE_DynScheduler::schedule (void) +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_Guard<LOCK> ace_mon (lock_); @@ -634,137 +708,340 @@ ACE_DynScheduler::schedule (void) tasks (rt_info_entries_.size ()); } - // set up the task entry data structures, check for call cycles + // 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; + } - if (status_ == SUCCEEDED) - { - // 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. - status_ = check_dependency_cycles (); - } + switch (anomaly->severity) + { + case RtecScheduler::ANOMALY_FATAL : + return status_; - if (status_ == SUCCEEDED) - { - // task entries are related, now threads can be found - status_ = identify_threads (); - } + default: + severity = anomaly->severity; + break; + } + } - if ((status_ == SUCCEEDED) || (status_ == ST_UNRESOLVED_REMOTE_DEPENDENCIES)) - { - // invokes the internal thread scheduling method of the strategy - temp_status = schedule_threads (); - if (temp_status != SUCCEEDED) - { - status_ = temp_status; - } - } + // 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; + } - if ((status_ == SUCCEEDED) || (status_ == ST_UNRESOLVED_REMOTE_DEPENDENCIES)) - { - // propagate the dispatch information from the - // threads throughout the call graph - temp_status = propagate_dispatches (); - if (temp_status != SUCCEEDED) - { - status_ = temp_status; - } - } + 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; + } + } - if ((status_ == SUCCEEDED) || (status_ == ST_UNRESOLVED_REMOTE_DEPENDENCIES)) - { - // invokes the internal dispatch scheduling method of the strategy - temp_status = schedule_dispatches (); - if (temp_status != SUCCEEDED) - { - status_ = temp_status; - } - } + // task entries are related, now threads can be found + temp_status = identify_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; + } + } + + // 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; + } + } + + // propagate the dispatch information from the + // threads throughout the call graph + temp_status = propagate_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; + } + } + + // 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; + } + } // calculate utilization, total frame size, critical set - if ((status_ == SUCCEEDED) || (status_ == ST_UNRESOLVED_REMOTE_DEPENDENCIES)) - { - temp_status = calculate_utilization_params (); - if (temp_status != SUCCEEDED) - { - status_ = temp_status; - } - } + 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; + } + } // calculate utilization, total frame size, critical set - if ((status_ == SUCCEEDED) || (status_ == ST_UTILIZATION_BOUND_EXCEEDED) || - (status_ == ST_UNRESOLVED_REMOTE_DEPENDENCIES)) - { - temp_status = store_assigned_info (); - if (temp_status != SUCCEEDED) - { - status_ = temp_status; - } - } + 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; + } - // generate the scheduling timeline over the total frame size - if ((status_ == SUCCEEDED) || (status_ == ST_UTILIZATION_BOUND_EXCEEDED) || - (status_ == ST_UNRESOLVED_REMOTE_DEPENDENCIES)) - { - temp_status = create_timeline (); - if (temp_status != SUCCEEDED) - { - status_ = temp_status; - } - } + 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; + } + } - // store the timeline to a file if one was given - if ((timeline_filename_ != 0) && - ((status_ == SUCCEEDED) || (status_ == ST_UTILIZATION_BOUND_EXCEEDED))) + // 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; + } + } + + temp_status = output_timeline (timeline_filename_, 0); if (temp_status != SUCCEEDED) { - status_ = temp_status; + // 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; + } } } - // if a valid schedule was not generated, clean up from the attempt + // if a valid schedule was generated, mark it as up to date switch (status_) { - // these are statuses that indicate a reasonable schedule was generated + // These are statuses that indicate a reasonable schedule was generated. case SUCCEEDED: - case ST_UTILIZATION_BOUND_EXCEEDED: - case ST_UNRESOLVED_REMOTE_DEPENDENCIES: + 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: - - // (try to) remove the output files - if (timeline_filename_ && ACE_OS::unlink (timeline_filename_) && - errno != ENOENT) - { - ACE_OS::perror ("ACE_DynScheduler::schedule (); " - "unable to remove timeline file"); - } - if (runtime_filename_ && ACE_OS::unlink (runtime_filename_) && - errno != ENOENT) - { - ACE_OS::perror ("ACE_DynScheduler::schedule (); " - "unable to remove schedule file"); - } - if (rt_info_filename_ && ACE_OS::unlink (rt_info_filename_) && - errno != ENOENT) - { - ACE_OS::perror ("ACE_DynScheduler::schedule (); " - "unable to remove rt_info file"); - } - - // free resources and remove "up_to_date" mark - reset (); - break; } @@ -773,10 +1050,13 @@ ACE_DynScheduler::schedule (void) } ACE_DynScheduler::status_t -ACE_DynScheduler::propagate_dispatches () +ACE_DynScheduler::propagate_dispatches ( + ACE_Unbounded_Set<ACE_DynScheduler::Scheduling_Anomaly *> &anomaly_set) { 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 @@ -784,9 +1064,73 @@ ACE_DynScheduler::propagate_dispatches () // the dispatches propagate top down through the call DAG for (i = 0; i < tasks (); ++i) { - if (ordered_task_entries_ [i]->merge_dispatches (*dispatch_entries_) < 0) - { - return ST_UNKNOWN_TASK; + switch (ordered_task_entries_ [i]->merge_dispatches (*dispatch_entries_)) + { + 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) @@ -795,14 +1139,9 @@ ACE_DynScheduler::propagate_dispatches () minimum_frame_size (frame_size_, ordered_task_entries_ [i]->effective_period ()); } - else - { - return ST_UNKNOWN_TASK; - } - } - return SUCCEEDED; + return status; } // propagate the dispatch information from the // threads throughout the call graph @@ -888,7 +1227,7 @@ ACE_DynScheduler::setup_task_entries (void) // bail out if there are no tasks registered if (tasks () <= 0) { - return ST_UNKNOWN_TASK; + return ST_NO_TASKS_REGISTERED; } // clear the decks of any previous scheduling information @@ -930,7 +1269,7 @@ ACE_DynScheduler::setup_task_entries (void) // tie task entry to corresponding rt_info if (! iter.next (info_entry)) { - return ST_UNKNOWN_TASK; + return ST_BAD_INTERNAL_POINTER; } task_entries_ [i].rt_info (*info_entry); @@ -1002,7 +1341,7 @@ ACE_DynScheduler::relate_task_entries_recurse (long &time, Task_Entry &entry) if (! dependency_info) { - return ST_UNKNOWN_TASK; + return ST_BAD_INTERNAL_POINTER; } // obtain a pointer to the Task_Entry from the dependency RT_Info @@ -1011,7 +1350,7 @@ ACE_DynScheduler::relate_task_entries_recurse (long &time, Task_Entry &entry) if (! dependency_entry_ptr) { - return ST_UNKNOWN_TASK; + return ST_BAD_INTERNAL_POINTER; } // relate the entries according to the direction of the dependency @@ -1041,10 +1380,12 @@ ACE_DynScheduler::relate_task_entries_recurse (long &time, Task_Entry &entry) } ACE_DynScheduler::status_t -ACE_DynScheduler::identify_threads (void) +ACE_DynScheduler::identify_threads ( + ACE_Unbounded_Set<ACE_DynScheduler::Scheduling_Anomaly *> &anomaly_set) { u_int i, j; ACE_DynScheduler::status_t result = SUCCEEDED; + Scheduling_Anomaly * anomaly = 0; // walk array of task entries, picking out thread delineators for (i = 0; i < tasks_; i++) @@ -1092,24 +1433,53 @@ ACE_DynScheduler::identify_threads (void) else if (task_entries_ [i].rt_info ()->info_type == RtecScheduler::REMOTE_DEPENDANT) { // Warn about unresolved remote dependencies, mark the task entry - result = ST_UNRESOLVED_REMOTE_DEPENDENCIES; + + 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.", + "\"%s\" has unresolved remote dependencies.\n", (const char*) task_entries_ [i].rt_info ()->entry_point)); + + // 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; + } } else { // Local node that no one calls and has neither rate nor threads is suspect - ACE_ERROR_RETURN ( - (LM_ERROR, - "An operation identified by \"%s\" does not specify a period or\n" - "visible threads, and is not called by any other operation. " - "Are there backwards dependencies?\n", - (const char*) task_entries_ [i].rt_info ()->entry_point), - ST_BAD_DEPENDENCIES_ON_TASK); + 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); + + // 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; + } } } } @@ -1201,8 +1571,10 @@ ACE_DynScheduler::check_dependency_cycles_recurse (Task_Entry &entry) ACE_DynScheduler::status_t -ACE_DynScheduler::schedule_threads (void) +ACE_DynScheduler::schedule_threads (ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> &anomaly_set) { + Scheduling_Anomaly * anomaly = 0; + // make sure there are as many thread delineator // entries in the set as the counter indicates if (threads_ != thread_delineators_->size ()) @@ -1226,7 +1598,7 @@ ACE_DynScheduler::schedule_threads (void) if (! iter.next (dispatch_entry)) { - return ST_UNKNOWN_TASK; + return ST_BAD_INTERNAL_POINTER; } ordered_thread_dispatch_entries_ [i] = *dispatch_entry; @@ -1238,7 +1610,8 @@ ACE_DynScheduler::schedule_threads (void) if (status == SUCCEEDED) { // assign priorities to the thread dispatch entries - status = assign_priorities (ordered_thread_dispatch_entries_, threads_); + status = assign_priorities (ordered_thread_dispatch_entries_, + threads_, anomaly_set); } return status; @@ -1247,7 +1620,7 @@ ACE_DynScheduler::schedule_threads (void) // entries that are threads, calls internal thread scheduling method ACE_DynScheduler::status_t -ACE_DynScheduler::schedule_dispatches (void) +ACE_DynScheduler::schedule_dispatches (ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> &anomaly_set) { dispatch_entry_count_ = dispatch_entries_->size (); @@ -1257,8 +1630,6 @@ ACE_DynScheduler::schedule_dispatches (void) 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 ()) { @@ -1266,7 +1637,7 @@ ACE_DynScheduler::schedule_dispatches (void) if (! iter.next (dispatch_entry)) { - return ST_UNKNOWN_TASK; + return ST_BAD_INTERNAL_POINTER; } ordered_dispatch_entries_ [i] = *dispatch_entry; @@ -1276,7 +1647,8 @@ ACE_DynScheduler::schedule_dispatches (void) 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_); + 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. @@ -1284,22 +1656,19 @@ ACE_DynScheduler::schedule_dispatches (void) 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_UNKNOWN_TASK); - } + { + 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 - // TBD - assign values into a map of priorities and RT_Infos: - // an RT_Info can be dispatched at multiple priorities 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 = @@ -1367,7 +1736,7 @@ ACE_DynScheduler::create_timeline () if (reschedule_queue.dequeue_head (rescheduled_entry) < 0) { - status = ST_UNKNOWN_TASK; + status = ST_BAD_INTERNAL_POINTER; break; } @@ -1382,9 +1751,8 @@ ACE_DynScheduler::create_timeline () break; } - - // schedule additional dispatcheds of the entry - // over the total frame size into the timeline + // 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 (); @@ -1424,10 +1792,9 @@ ACE_DynScheduler::create_timeline () while (reschedule_queue.is_empty () == 0) { - if (reschedule_queue.dequeue_head (rescheduled_entry) < 0) { - status = ST_UNKNOWN_TASK; + status = ST_BAD_INTERNAL_POINTER; break; } status = schedule_timeline_entry (*rescheduled_entry, reschedule_queue); diff --git a/TAO/orbsvcs/orbsvcs/Sched/DynSched.h b/TAO/orbsvcs/orbsvcs/Sched/DynSched.h index a4f7a67cd48..e61d08f3749 100644 --- a/TAO/orbsvcs/orbsvcs/Sched/DynSched.h +++ b/TAO/orbsvcs/orbsvcs/Sched/DynSched.h @@ -34,7 +34,7 @@ class TAO_ORBSVCS_Export ACE_DynScheduler // = TITLE - // dispatch scheduling interface. + // Dispatch scheduling interface. // // = DESCRIPTION // This abstract base class provides the majority of the @@ -59,6 +59,8 @@ public: typedef RtecScheduler::Info_Type Info_Type; typedef RtecScheduler::Dependency_Type Dependency_Type; typedef RtecScheduler::Dispatching_Type Dispatching_Type; + typedef RtecScheduler::Scheduling_Anomaly Scheduling_Anomaly; + typedef RtecScheduler::Anomaly_Severity Anomaly_Severity; typedef ACE_Map_Entry <ACE_CString, RT_Info *> Thread_Map_Entry; typedef ACE_Map_Manager <ACE_CString, RT_Info *, ACE_Null_Mutex> @@ -78,9 +80,13 @@ public: , ST_UNKNOWN_TASK , ST_UNKNOWN_PRIORITY , ST_TASK_ALREADY_REGISTERED + , ST_NO_TASKS_REGISTERED , ST_BAD_DEPENDENCIES_ON_TASK , ST_BAD_INTERNAL_POINTER , ST_VIRTUAL_MEMORY_EXHAUSTED + , TWO_WAY_DISJUNCTION + , TWO_WAY_CONJUNCTION + , UNRECOGNIZED_INFO_TYPE // The following are only used by the runtime Scheduler. , TASK_COUNT_MISMATCH // only used by schedule () @@ -95,6 +101,7 @@ public: , ST_INSUFFICIENT_THREAD_PRIORITY_LEVELS , ST_CYCLE_IN_DEPENDENCIES , ST_UNRESOLVED_REMOTE_DEPENDENCIES + , ST_UNRESOLVED_LOCAL_DEPENDENCIES , ST_INVALID_PRIORITY_ORDERING , UNABLE_TO_OPEN_SCHEDULE_FILE , UNABLE_TO_WRITE_SCHEDULE_FILE @@ -113,6 +120,15 @@ public: // representation of a status_t value. static const char * status_message (status_t status); + // = Utility function for creating an entry for determining + // the severity of an anomaly detected during scheduling. + static Anomaly_Severity anomaly_severity (status_t status); + + // = Utility function for creating an entry for the + // log of anomalies detected during scheduling. + static Scheduling_Anomaly * create_anomaly (status_t status); + + // = Initialize the scheduler. void init (const OS_Priority minimum_priority, const OS_Priority maximum_priority, @@ -174,10 +190,11 @@ public: // Obtains an RT_Info based on its "handle". status_t lookup_config_info (Preemption_Priority priority, - Config_Info* &config_info); + Config_Info* &config_info); // Obtains a Config_Info based on its priority. - status_t schedule (void); + status_t + schedule (ACE_Unbounded_Set<Scheduling_Anomaly *> &anomaly_set); // This sets up the data structures, invokes the internal scheduling method. status_t output_timeline (const char *filename, const char *heading); @@ -245,11 +262,13 @@ protected: ACE_DynScheduler (); - status_t schedule_threads (void); + status_t schedule_threads ( + ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> &anomaly_set); // thread scheduling method: sets up array of pointers to task // entries that are threads, calls internal thread scheduling method - status_t schedule_dispatches (void); + status_t schedule_dispatches ( + ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> &anomaly_set); // dispatch scheduling method: sets up an array of dispatch entries, // calls internal dispatch scheduling method. @@ -279,12 +298,16 @@ protected: // internal sorting method: this orders the dispatches by // static priority and dynamic and static subpriority. - virtual status_t assign_priorities (Dispatch_Entry **dispatches, - u_int count) = 0; + virtual status_t assign_priorities ( + Dispatch_Entry **dispatches, + u_int count, + ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> &anomaly_set) = 0; // = assign priorities to the sorted dispatches - virtual status_t assign_subpriorities (Dispatch_Entry **dispatches, - u_int count) = 0; + virtual status_t assign_subpriorities ( + Dispatch_Entry **dispatches, + u_int count, + ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> &anomaly_set) = 0; // = assign dynamic and static sub-priorities to the sorted dispatches virtual status_t @@ -401,7 +424,8 @@ private: status_t relate_task_entries_recurse (long &time, Task_Entry &entry); // identify thread delimiters - status_t identify_threads (void); + status_t + identify_threads (ACE_Unbounded_Set<Scheduling_Anomaly *> &anomaly_set); // checks for cycles in the dependency graph status_t check_dependency_cycles (void); @@ -421,7 +445,8 @@ private: // update the scheduling parameters for the previous priority level void update_priority_level_params (); - status_t propagate_dispatches (); + status_t + propagate_dispatches (ACE_Unbounded_Set<Scheduling_Anomaly *> &anomaly_set); // propagate the dispatch information from the // threads throughout the call graph diff --git a/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.cpp b/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.cpp index 45fdf921a99..4594dc1a550 100644 --- a/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.cpp +++ b/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.cpp @@ -99,6 +99,7 @@ Task_Entry::Task_Entry () finished_ (-1), is_thread_delineator_ (0), has_unresolved_remote_dependencies_ (0), + has_unresolved_local_dependencies_ (0), calls_ (), callers_ () { @@ -127,10 +128,10 @@ Task_Entry::~Task_Entry () // Merge dispatches according to info type and type of call, // update relevant scheduling characteristics for this entry. -int +Task_Entry::Propagation_Status Task_Entry::merge_dispatches (ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_entries) { - int result = 0; + Task_Entry::Propagation_Status result = SUCCEEDED; switch (info_type ()) { case RtecScheduler::DISJUNCTION: @@ -140,12 +141,14 @@ Task_Entry::merge_dispatches (ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_ent // NOTE: one interpretation of disjunction for two-way calls // is that the caller calls one OR the other, but this // is problematic: how do we map the dispatches for this ? - result = prohibit_dispatches (RtecScheduler::TWO_WAY_CALL); - if (result == 0) - { - result = disjunctive_merge (RtecScheduler::ONE_WAY_CALL, dispatch_entries); - } - + if (prohibit_dispatches (RtecScheduler::TWO_WAY_CALL) < 0) + { + result = TWO_WAY_DISJUNCTION; + } + if (disjunctive_merge (RtecScheduler::ONE_WAY_CALL, dispatch_entries) < 0) + { + result = INTERNAL_ERROR; + } break; case RtecScheduler::CONJUNCTION: @@ -158,12 +161,14 @@ Task_Entry::merge_dispatches (ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_ent // (prohibit for now, as the additional complexity of allowing // conjunctions of two-ways, but not disjunctions does not // buy us anything, anyway). - result = prohibit_dispatches (RtecScheduler::TWO_WAY_CALL); - if (result == 0) - { - result = conjunctive_merge (RtecScheduler::ONE_WAY_CALL, dispatch_entries); - } - + if (prohibit_dispatches (RtecScheduler::TWO_WAY_CALL) < 0) + { + result = TWO_WAY_CONJUNCTION; + } + if (conjunctive_merge (RtecScheduler::ONE_WAY_CALL, dispatch_entries) < 0) + { + result = INTERNAL_ERROR; + } break; case RtecScheduler::OPERATION: @@ -171,28 +176,27 @@ Task_Entry::merge_dispatches (ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_ent // 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) - { - result = conjunctive_merge (RtecScheduler::ONE_WAY_CALL, dispatch_entries); - } - + if (disjunctive_merge (RtecScheduler::TWO_WAY_CALL, dispatch_entries) < 0) + { + result = INTERNAL_ERROR; + } + if (conjunctive_merge (RtecScheduler::ONE_WAY_CALL, dispatch_entries) < 0) + { + result = INTERNAL_ERROR; + } break; - default: // 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; + result = UNRECOGNIZED_INFO_TYPE; break; } return result; } - - // 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 @@ -260,6 +264,22 @@ Task_Entry::disjunctive_merge ( (const char*) this->rt_info ()->entry_point)); } + // Check for and warn about unresolved local + // dependencies in the ONE_WAY call graph. + if ((*link)->dependency_type () == RtecScheduler::ONE_WAY_CALL && + (*link)->caller ().has_unresolved_local_dependencies () && + ! this->has_unresolved_local_dependencies ()) + { + // Propagate the unresolved local dependency + // flag, and issue a debug scheduler warning. + this->has_unresolved_local_dependencies (1); + ACE_DEBUG ( + (LM_DEBUG, + "Warning: an operation identified by " + "\"%s\" has unresolved local dependencies.\n", + (const char*) this->rt_info ()->entry_point)); + } + // Merge the caller's dispatches into the current set. if (merge_frames (dispatch_entries, *this, dispatches_, (*link)->caller ().dispatches_, effective_period_, @@ -320,6 +340,22 @@ Task_Entry::conjunctive_merge ( (const char*) this->rt_info ()->entry_point)); } + // Check for and warn about unresolved local + // dependencies in the ONE_WAY call graph. + if ((*link)->dependency_type () == RtecScheduler::ONE_WAY_CALL && + (*link)->caller ().has_unresolved_local_dependencies () && + ! this->has_unresolved_local_dependencies ()) + { + // Propagate the unresolved local dependency + // flag, and issue a debug scheduler warning. + this->has_unresolved_local_dependencies (1); + ACE_DEBUG ( + (LM_DEBUG, + "Warning: an operation identified by " + "\"%s\" has unresolved local dependencies.\n", + (const char*) this->rt_info ()->entry_point)); + } + frame_size = minimum_frame_size (frame_size, (*link)->caller ().effective_period_); } } diff --git a/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.h b/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.h index 9c6141e14d6..8eb7f33d118 100644 --- a/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.h +++ b/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.h @@ -109,6 +109,13 @@ public: // Info for DFS traversal, topological sort of call graph. enum DFS_Status {NOT_VISITED, VISITED, FINISHED}; + // Status of merging dispatches. + enum Propagation_Status {SUCCEEDED, + TWO_WAY_DISJUNCTION, + TWO_WAY_CONJUNCTION, + INTERNAL_ERROR, + UNRECOGNIZED_INFO_TYPE}; + // Constructor. Task_Entry (); @@ -118,7 +125,7 @@ public: // 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. - int merge_dispatches ( + Propagation_Status merge_dispatches ( ACE_Unbounded_Set <Dispatch_Entry *> &dispatch_entries); // Gets the pointer to the underlying RT_Info. @@ -163,6 +170,12 @@ public: // Gets the flag indicating whether node has unresolved remote dependencies. int has_unresolved_remote_dependencies () const; + // Sets a flag indicating whether node has unresolved local dependencies. + void has_unresolved_local_dependencies (int i); + + // Gets the flag indicating whether node has unresolved local dependencies. + int has_unresolved_local_dependencies () const; + // Gets the set of links to Task Entries which this entry calls. ACE_Unbounded_Set <Task_Entry_Link *> & calls (); @@ -259,6 +272,10 @@ private: // dependencies in the entry's dependency call chain. int has_unresolved_remote_dependencies_; + // Flag indicating whether or not there are unresolved local + // dependencies in the entry's dependency call chain. + int has_unresolved_local_dependencies_; + // Set of links to Task Entries which this entry calls. ACE_Unbounded_Set <Task_Entry_Link *> calls_; diff --git a/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.i b/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.i index f016b0ebeb4..5603dc6537b 100644 --- a/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.i +++ b/TAO/orbsvcs/orbsvcs/Sched/SchedEntry.i @@ -120,6 +120,22 @@ Task_Entry::has_unresolved_remote_dependencies () const } +// Sets a flag indicating whether node has unresolved local dependencies. + +ACE_INLINE void +Task_Entry::has_unresolved_local_dependencies (int i) +{ + has_unresolved_local_dependencies_ = i; +} + +// Gets the flag indicating whether node has unresolved local dependencies. + +ACE_INLINE int +Task_Entry::has_unresolved_local_dependencies () const +{ + return has_unresolved_local_dependencies_; +} + // Gets the set of Task Entries on which this entry depends. ACE_INLINE ACE_Unbounded_Set <Task_Entry_Link *> & diff --git a/TAO/orbsvcs/orbsvcs/Sched/Scheduler.h b/TAO/orbsvcs/orbsvcs/Sched/Scheduler.h index 257329bb4e7..e95db5677c8 100644 --- a/TAO/orbsvcs/orbsvcs/Sched/Scheduler.h +++ b/TAO/orbsvcs/orbsvcs/Sched/Scheduler.h @@ -55,6 +55,7 @@ public: typedef RtecScheduler::Config_Info Config_Info; typedef RtecScheduler::Time Time; typedef RtecScheduler::Dispatching_Type Dispatching_Type; + typedef RtecScheduler::Scheduling_Anomaly Scheduling_Anomaly; // Map some types to simplify re-use. @@ -73,11 +74,13 @@ public: , ST_UNKNOWN_PRIORITY , ST_TASK_ALREADY_REGISTERED , ST_VIRTUAL_MEMORY_EXHAUSTED + , ST_BAD_INTERNAL_POINTER // The following are only used by the runtime Scheduler. , INVALID_MODE , MODE_COUNT_MISMATCH // only used by schedule () , TASK_COUNT_MISMATCH // only used by schedule () + , THREAD_COUNT_MISMATCH // only used by schedule () , INVALID_PRIORITY // only used by schedule (): mismatch of // (off-line, maybe) Scheduler output to // the runtime Scheduler component. @@ -166,7 +169,8 @@ public: // = Computes the schedule. - virtual status_t schedule (void) = 0; + virtual status_t + schedule (ACE_Unbounded_Set<Scheduling_Anomaly *> &anomaly_set) = 0; // This actually generates the files. // = Access a thread priority. diff --git a/TAO/orbsvcs/orbsvcs/Sched/Scheduler_Generic.cpp b/TAO/orbsvcs/orbsvcs/Sched/Scheduler_Generic.cpp index 1d697e30d79..1daaeb423f6 100644 --- a/TAO/orbsvcs/orbsvcs/Sched/Scheduler_Generic.cpp +++ b/TAO/orbsvcs/orbsvcs/Sched/Scheduler_Generic.cpp @@ -217,7 +217,8 @@ Scheduler_Generic::init (const int minimum_priority, Scheduler::status_t -Scheduler_Generic::schedule (void) +Scheduler_Generic::schedule (ACE_Unbounded_Set<Scheduling_Anomaly *> + &anomaly_set) { ACE_Guard<LOCK> ace_mon (lock_); diff --git a/TAO/orbsvcs/orbsvcs/Sched/Scheduler_Generic.h b/TAO/orbsvcs/orbsvcs/Sched/Scheduler_Generic.h index 68c33084cc0..181a4307093 100644 --- a/TAO/orbsvcs/orbsvcs/Sched/Scheduler_Generic.h +++ b/TAO/orbsvcs/orbsvcs/Sched/Scheduler_Generic.h @@ -54,7 +54,8 @@ public: // Obtains a Config_Info based on its priority. // = Computes the schedule. - virtual status_t schedule (void); + virtual status_t + schedule (ACE_Unbounded_Set<Scheduling_Anomaly *> &anomaly_set); // = Access a thread priority. virtual int priority (const handle_t handle, diff --git a/TAO/orbsvcs/orbsvcs/Sched/Strategy_Scheduler.cpp b/TAO/orbsvcs/orbsvcs/Sched/Strategy_Scheduler.cpp index 942586a3115..41f5c1330b3 100644 --- a/TAO/orbsvcs/orbsvcs/Sched/Strategy_Scheduler.cpp +++ b/TAO/orbsvcs/orbsvcs/Sched/Strategy_Scheduler.cpp @@ -67,11 +67,15 @@ ACE_Strategy_Scheduler::sort_dispatches (Dispatch_Entry **dispatches, // by the strategy's comparison operators ACE_DynScheduler::status_t -ACE_Strategy_Scheduler::assign_priorities (Dispatch_Entry **dispatches, - u_int count) +ACE_Strategy_Scheduler::assign_priorities ( + Dispatch_Entry **dispatches, + u_int count, + ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> &anomaly_set) { // start with happy status - ACE_DynScheduler::status_t status = ACE_DynScheduler::SUCCEEDED; + ACE_DynScheduler::status_t status = SUCCEEDED; + + RtecScheduler::Scheduling_Anomaly * anomaly = 0; // start with the highest OS priority in the given range and work downward: // if we run out of values to assign, return an error. @@ -87,7 +91,7 @@ ACE_Strategy_Scheduler::assign_priorities (Dispatch_Entry **dispatches, // store the dispatch configuration for the highest priority level Config_Info *config_ptr; - ACE_NEW_RETURN(config_ptr, Config_Info, ST_VIRTUAL_MEMORY_EXHAUSTED); + ACE_NEW_RETURN (config_ptr, Config_Info, ST_VIRTUAL_MEMORY_EXHAUSTED); config_ptr->preemption_priority = current_scheduler_priority; config_ptr->thread_priority = current_OS_priority; config_ptr->dispatching_type = strategy_.dispatch_type (*(dispatches[0])); @@ -119,10 +123,26 @@ ACE_Strategy_Scheduler::assign_priorities (Dispatch_Entry **dispatches, current_OS_priority, ACE_SCOPE_PROCESS))) { - // if we have run out of priority levels to assign, indicate - // this in the return status, but keep right on assigning the - // minimum OS priority in the range to the remaining tasks. - status = ACE_DynScheduler::ST_INSUFFICIENT_THREAD_PRIORITY_LEVELS; + // If we have run out of priority levels to assign, indicate + // this in the return status, unless a more severe problem is + // already reflected there. Log an anomaly but keep right on + // assigning the minimum OS priority in the range to the remaining + // tasks. + status = (status == SUCCEEDED) + ? ST_INSUFFICIENT_THREAD_PRIORITY_LEVELS + : status; + + // Log the anomaly. + anomaly = + create_anomaly (ST_INSUFFICIENT_THREAD_PRIORITY_LEVELS); + if (anomaly) + { + anomaly_set.insert (anomaly); + } + else + { + return ST_VIRTUAL_MEMORY_EXHAUSTED; + } } else { @@ -149,15 +169,28 @@ ACE_Strategy_Scheduler::assign_priorities (Dispatch_Entry **dispatches, break; - default: // should never reach here: something *bad* has happened + default: // Should never reach here: something *bad* has happened. - ACE_ERROR_RETURN (( + ACE_ERROR (( LM_ERROR, "Priority assignment failure: tasks" " \"%s\" and \"%s\" are out of order.\n", dispatches [i-1]->task_entry ().rt_info ()->entry_point.in (), - dispatches [i]->task_entry ().rt_info ()->entry_point.in ()), - ACE_DynScheduler::ST_INVALID_PRIORITY_ORDERING); + dispatches [i]->task_entry ().rt_info ()->entry_point.in ())); + + status = ACE_DynScheduler::ST_INVALID_PRIORITY_ORDERING; + + // Log the anomaly. + anomaly = + create_anomaly (ST_INVALID_PRIORITY_ORDERING); + if (anomaly) + { + anomaly_set.insert (anomaly); + } + else + { + return ST_VIRTUAL_MEMORY_EXHAUSTED; + } } // set OS priority of the current dispatch entry @@ -173,9 +206,14 @@ ACE_Strategy_Scheduler::assign_priorities (Dispatch_Entry **dispatches, // according to the strategy's priority comparison operator. ACE_DynScheduler::status_t -ACE_Strategy_Scheduler::assign_subpriorities (Dispatch_Entry **dispatches, - u_int count) +ACE_Strategy_Scheduler::assign_subpriorities ( + Dispatch_Entry **dispatches, + u_int count, + ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> &anomaly_set) { + ACE_DynScheduler::status_t status = ACE_DynScheduler::SUCCEEDED; + RtecScheduler::Scheduling_Anomaly * anomaly = 0; + // start subpriority levels and element counts at 1, set level values in // the first entry, increment the static subpriority level, Sub_Priority dynamic_subpriority_level = 0; @@ -252,7 +290,7 @@ ACE_Strategy_Scheduler::assign_subpriorities (Dispatch_Entry **dispatches, case 0: // still at the same dynamic subpriority level - { + { switch (strategy_.static_subpriority_comp (*(dispatches[i-1]), *(dispatches[i]))) { @@ -272,27 +310,52 @@ ACE_Strategy_Scheduler::assign_subpriorities (Dispatch_Entry **dispatches, default: // should never reach here: something *bad* has happened - ACE_ERROR_RETURN (( + ACE_ERROR (( LM_ERROR, "Static subpriority assignment failure: tasks" " \"%s\" and \"%s\" are out of order.\n", dispatches [i-1]->task_entry ().rt_info ()->entry_point.in (), - dispatches [i]->task_entry ().rt_info ()->entry_point.in ()), - ACE_DynScheduler::ST_INVALID_PRIORITY_ORDERING); + dispatches [i]->task_entry ().rt_info ()->entry_point.in ())); + + status = ST_INVALID_PRIORITY_ORDERING; + + // Log the anomaly. + anomaly = + create_anomaly (ST_INVALID_PRIORITY_ORDERING); + if (anomaly) + { + anomaly_set.insert (anomaly); + } + else + { + return ST_VIRTUAL_MEMORY_EXHAUSTED; + } } - break; - } + } default: // should never reach here: something *bad* has happened - ACE_ERROR_RETURN (( + ACE_ERROR (( LM_ERROR, "Dynamic subpriority assignment failure: tasks" " \"%s\" and \"%s\" are out of order.\n", dispatches [i-1]->task_entry ().rt_info ()->entry_point.in (), - dispatches [i]->task_entry ().rt_info ()->entry_point.in ()), - ACE_DynScheduler::ST_INVALID_PRIORITY_ORDERING); + dispatches [i]->task_entry ().rt_info ()->entry_point.in ())); + + status = ACE_DynScheduler::ST_INVALID_PRIORITY_ORDERING; + + // Log the anomaly. + anomaly = + create_anomaly (ST_INVALID_PRIORITY_ORDERING); + if (anomaly) + { + anomaly_set.insert (anomaly); + } + else + { + return ST_VIRTUAL_MEMORY_EXHAUSTED; + } } dispatches [i]->dynamic_subpriority (dynamic_subpriority_level); @@ -302,13 +365,26 @@ ACE_Strategy_Scheduler::assign_subpriorities (Dispatch_Entry **dispatches, default: // should never reach here: something *bad* has happened - ACE_ERROR_RETURN (( + ACE_ERROR (( LM_ERROR, "Priority assignment failure: tasks" " \"%s\" and \"%s\" are out of order.\n", dispatches [i-1]->task_entry ().rt_info ()->entry_point.in (), - dispatches [i]->task_entry ().rt_info ()->entry_point.in ()), - ACE_DynScheduler::ST_INVALID_PRIORITY_ORDERING); + dispatches [i]->task_entry ().rt_info ()->entry_point.in ())); + + status = ACE_DynScheduler::ST_INVALID_PRIORITY_ORDERING; + + // Log the anomaly. + anomaly = + create_anomaly (ST_INVALID_PRIORITY_ORDERING); + if (anomaly) + { + anomaly_set.insert (anomaly); + } + else + { + return ST_VIRTUAL_MEMORY_EXHAUSTED; + } } } @@ -328,7 +404,7 @@ ACE_Strategy_Scheduler::assign_subpriorities (Dispatch_Entry **dispatches, dispatches [i - j]->static_subpriority () - 1); } - return ACE_DynScheduler::SUCCEEDED; + return status; } diff --git a/TAO/orbsvcs/orbsvcs/Sched/Strategy_Scheduler.h b/TAO/orbsvcs/orbsvcs/Sched/Strategy_Scheduler.h index 15abbb9760a..b5d0b87ab03 100644 --- a/TAO/orbsvcs/orbsvcs/Sched/Strategy_Scheduler.h +++ b/TAO/orbsvcs/orbsvcs/Sched/Strategy_Scheduler.h @@ -47,11 +47,15 @@ public: virtual ~ACE_Strategy_Scheduler (); // = virtual dtor - status_t assign_priorities (Dispatch_Entry **dispatches, u_int count); + status_t assign_priorities ( + Dispatch_Entry **dispatches, u_int count, + ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> &anomaly_set); // = assigns priorities to the sorted dispatch schedule, // according to the strategy's priority comparison operator. - status_t assign_subpriorities (Dispatch_Entry **dispatches, u_int count); + status_t assign_subpriorities ( + Dispatch_Entry **dispatches, u_int count, + ACE_Unbounded_Set<RtecScheduler::Scheduling_Anomaly *> &anomaly_set); // = assigns dynamic and static sub-priorities to the sorted dispatch // schedule, according to the strategy's subpriority comparisons. diff --git a/TAO/orbsvcs/orbsvcs/Scheduler_Factory.cpp b/TAO/orbsvcs/orbsvcs/Scheduler_Factory.cpp index 5553cde5589..c9d12bf2d0e 100644 --- a/TAO/orbsvcs/orbsvcs/Scheduler_Factory.cpp +++ b/TAO/orbsvcs/orbsvcs/Scheduler_Factory.cpp @@ -12,7 +12,7 @@ ACE_RCSID(orbsvcs, Scheduler_Factory, "$Id$") -// initialize static class members +// Initialize static class members. RtecScheduler::Scheduler_ptr ACE_Scheduler_Factory::server_ = 0; ACE_Scheduler_Factory::Factory_Status ACE_Scheduler_Factory::status_ = ACE_Scheduler_Factory::UNINITIALIZED; @@ -27,7 +27,7 @@ ACE_Scheduler_Factory::POD_RT_Info* TAO_SF_rt_info = 0; // Helper struct, to encapsulate the singleton static server and // ACE_TSS objects. We can't use ACE_Singleton directly, because -// construction of ACE_Runbtime_Scheduler takes arguments. +// construction of ACE_Runtime_Scheduler takes arguments. struct ACE_Scheduler_Factory_Data { ACE_Runtime_Scheduler scheduler_; @@ -176,22 +176,29 @@ ACE_Scheduler_Factory::server (void) } static char header[] = -"// This file was automatically generated by Scheduler_Factory\n" -"// before editing the file please consider generating it again\n" +"// $Id $\n\n" +"// This file was automatically generated by the Scheduler_Factory.\n" +"// Before editing the file please consider generating it again.\n" "\n" "#include \"orbsvcs/Scheduler_Factory.h\"\n" "\n"; static char footer[] = "\n" -"// This sets up Scheduler_Factory to use the runtime version\n" +"// This sets up Scheduler_Factory to use the runtime version.\n" "int scheduler_factory_setup = \n" " ACE_Scheduler_Factory::use_runtime (configs_size, configs, infos_size, infos);\n" "\n" "// EOF\n"; +static char start_anomalies_found[] = +"\n// The following scheduling anomalies were detected:\n"; + +static char start_anomalies_none[] = +"\n// There were no scheduling anomalies.\n"; + static char start_infos[] = -"static ACE_Scheduler_Factory::POD_RT_Info infos[] = {\n"; +"\n\nstatic ACE_Scheduler_Factory::POD_RT_Info infos[] = {\n"; static char end_infos[] = "};\n\n" @@ -201,7 +208,6 @@ static char end_infos_empty[] = "};\n\n" "static int infos_size = 0;\n\n"; - static char start_configs[] = "\nstatic ACE_Scheduler_Factory::POD_Config_Info configs[] = {\n"; @@ -216,6 +222,7 @@ static char end_configs_empty[] = int ACE_Scheduler_Factory::dump_schedule (const RtecScheduler::RT_Info_Set& infos, const RtecScheduler::Config_Info_Set& configs, + const RtecScheduler::Scheduling_Anomaly_Set& anomalies, const char* file_name, const char* rt_info_format, const char* config_info_format) @@ -223,7 +230,7 @@ int ACE_Scheduler_Factory::dump_schedule u_int i; char entry_point [BUFSIZ]; - // default format for printing RT_Info output + // Default format for printing RT_Info output. if (rt_info_format == 0) { rt_info_format = "{%20s, %10d, %10d, %10d, " @@ -234,7 +241,7 @@ int ACE_Scheduler_Factory::dump_schedule "(RtecScheduler::Info_Type) %d }"; } - // default format for printing Config_Info output + // Default format for printing Config_Info output. if (config_info_format == 0) { config_info_format = " { %10d, %10d, " @@ -252,20 +259,51 @@ int ACE_Scheduler_Factory::dump_schedule } ACE_OS::fprintf(file, header); - // print out operation QoS info + // Indicate anomalies encountered during scheduling. + + ACE_OS::fprintf(file, (anomalies.length () > 0 + ? start_anomalies_found + : start_anomalies_none)); + + for (i = 0; i < anomalies.length (); ++i) + { + const RtecScheduler::Scheduling_Anomaly& anomaly = anomalies[i]; + switch (anomaly.severity) + { + case RtecScheduler::ANOMALY_FATAL: + ACE_OS::fprintf(file, "FATAL: "); + break; + + case RtecScheduler::ANOMALY_ERROR: + ACE_OS::fprintf(file, "ERROR: "); + break; + + case RtecScheduler::ANOMALY_WARNING: + ACE_OS::fprintf(file, "// WARNING: "); + break; + + default: + ACE_OS::fprintf(file, "// UNKNOWN: "); + break; + } + + ACE_OS::fprintf (file, "%s\n", anomaly.description); + } + + // Print out operation QoS info. ACE_OS::fprintf(file, start_infos); for (i = 0; i < infos.length (); ++i) { if (i != 0) { - // Finish previous line + // Finish previous line. ACE_OS::fprintf(file, ",\n"); } const RtecScheduler::RT_Info& info = infos[i]; // Put quotes around the entry point name, exactly as it is stored. - ACE_OS::sprintf (entry_point, "\"%s\"", (const char*) info.entry_point); + ACE_OS::sprintf (entry_point, "\"%s\"", (const char*) info.entry_point); // @@ TODO Eventually the TimeT structure will be a 64-bit // unsigned int, we will have to change this dump method then. @@ -286,7 +324,7 @@ int ACE_Scheduler_Factory::dump_schedule info.preemption_priority, info.info_type); } - // finish last line. + // Finish last line. ACE_OS::fprintf(file, "\n"); if (infos.length () > 0) @@ -298,13 +336,13 @@ int ACE_Scheduler_Factory::dump_schedule ACE_OS::fprintf(file, end_infos_empty); } - // print out queue configuration info + // Print out queue configuration info. ACE_OS::fprintf(file, start_configs); for (i = 0; i < configs.length (); ++i) { if (i != 0) { - // Finish previous line + // Finish previous line. ACE_OS::fprintf(file, ",\n"); } const RtecScheduler::Config_Info& config = configs[i]; @@ -314,7 +352,7 @@ int ACE_Scheduler_Factory::dump_schedule config.thread_priority, config.dispatching_type); } - // finish last line. + // Finish last line. ACE_OS::fprintf(file, "\n"); if (configs.length () > 0) @@ -378,7 +416,7 @@ ACE_Scheduler_Factory::set_preemption_priority ace_scheduler_factory_data->preemption_priority_-> #if defined (HPUX) && !defined (__GNUG__) - // aCC can't handle the typedef + // aCC can't handle the typedef. operator RtecScheduler_Preemption_Priority & () = preemption_priority; #else operator RtecScheduler::Preemption_Priority & () = preemption_priority; diff --git a/TAO/orbsvcs/orbsvcs/Scheduler_Factory.h b/TAO/orbsvcs/orbsvcs/Scheduler_Factory.h index 95707b4370c..688f4360dd0 100644 --- a/TAO/orbsvcs/orbsvcs/Scheduler_Factory.h +++ b/TAO/orbsvcs/orbsvcs/Scheduler_Factory.h @@ -73,6 +73,19 @@ public: RtecScheduler::Dispatching_Type dispatching_type; }; + struct POD_Scheduling_Anomaly + // = TITLE + // Plain Old Data for scheduling anomaly information. + // + // = DESCRIPTION + // This class provide us with a plain old data version of + // scheduling anomalies, which is used to generate error + // and warning lines in the runtime scheduling header output. + { + const char* description; + RtecScheduler::Anomaly_Severity severity; + }; + static int use_config (CosNaming::NamingContext_ptr naming); // Setup the variables needed for a config run, using the // NamingContext to locate a Scheduler. @@ -101,6 +114,7 @@ public: static int dump_schedule (const RtecScheduler::RT_Info_Set& infos, const RtecScheduler::Config_Info_Set& configs, + const RtecScheduler::Scheduling_Anomaly_Set& anomalies, const char* file_name = 0, const char* rt_info_format = 0, const char* config_info_format = 0); diff --git a/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf.cpp b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf.cpp index ff3e11e5422..bd4877561d0 100644 --- a/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf.cpp +++ b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf.cpp @@ -177,7 +177,7 @@ main (int argc, char *argv[]) 100000, // worst case execution time 100000, // typical execution time (unused) 100000, // cached execution time - 0, // period (100 ns) + 10000000, // period (100 ns) RtecScheduler::LOW_CRITICALITY, // criticality RtecScheduler::HIGH_IMPORTANCE, // importance 0, // quantum (unused) @@ -185,7 +185,7 @@ main (int argc, char *argv[]) 0, // OS priority 0, // Preemption subpriority 0, // Preemption priority - RtecScheduler::REMOTE_DEPENDANT // info type + RtecScheduler::OPERATION // info type }, // 20 Hz high criticality consumer { "high_20_C", // entry point @@ -394,6 +394,7 @@ main (int argc, char *argv[]) RtecScheduler::RT_Info_Set_var infos; RtecScheduler::Config_Info_Set_var configs; + RtecScheduler::Scheduling_Anomaly_Set_var anomalies; #if defined (__SUNPRO_CC) // Sun C++ 4.2 warns with the code below: @@ -408,25 +409,27 @@ main (int argc, char *argv[]) RtecScheduler::RT_Info_Set_out infos_out (infos); RtecScheduler::Config_Info_Set_out configs_out (configs); + RtecScheduler::Scheduling_Anomaly_Set_out anomalies_out (anomalies); ACE_Scheduler_Factory::server ()->compute_scheduling (ACE_Sched_Params::priority_min (ACE_SCHED_FIFO, ACE_SCOPE_THREAD), ACE_Sched_Params::priority_max (ACE_SCHED_FIFO, ACE_SCOPE_THREAD), - infos_out, configs_out, TAO_TRY_ENV); + infos_out, configs_out, anomalies_out, TAO_TRY_ENV); #else /* ! __SUNPRO_CC */ ACE_Scheduler_Factory::server ()->compute_scheduling (ACE_Sched_Params::priority_min (ACE_SCHED_FIFO, ACE_SCOPE_THREAD), ACE_Sched_Params::priority_max (ACE_SCHED_FIFO, ACE_SCOPE_THREAD), - infos.out (), configs.out (), TAO_TRY_ENV); + infos.out (), configs.out (), anomalies.out (), TAO_TRY_ENV); #endif /* ! __SUNPRO_CC */ TAO_CHECK_ENV; ACE_Scheduler_Factory::dump_schedule (infos.in (), configs.in (), + anomalies.in (), "Sched_Conf_Runtime.h", format_string); } diff --git a/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf.dsw b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf.dsw index bfa6054e898..829c4735f1e 100644 --- a/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf.dsw +++ b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf.dsw @@ -15,6 +15,18 @@ Package=<4> ###############################################################################
+Project: "Sched_Conf_Anomalies"=.\Sched_Conf_Anomalies.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
Project: "Sched_Conf_Runtime"=.\Sched_Conf_Runtime.dsp - Package Owner=<4>
Package=<5>
diff --git a/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Anomalies.cpp b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Anomalies.cpp new file mode 100644 index 00000000000..891892f6cec --- /dev/null +++ b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Anomalies.cpp @@ -0,0 +1,385 @@ +// $Id$ + +// This program performa a simple scheduler configuration run, +// and dumps the results of one scheduling into a C++ header file. + +#include "ace/Sched_Params.h" +#include "ace/Get_Opt.h" +#include "tao/corba.h" + +#include "orbsvcs/CosNamingC.h" +#include "orbsvcs/Scheduler_Factory.h" +#include "orbsvcs/Naming/Naming_Utils.h" + +ACE_RCSID(Sched_Conf, Sched_Conf_Anomalies, "$Id$") + +const char* service_name = "ScheduleService"; + +const char* format_string = "{%-12s, %d, %d, %d, %d, %8d, " + "(RtecScheduler::Criticality) %d, " + "(RtecScheduler::Importance) %d, " + "%d, %d, %3d, %d, %d, " + "(RtecScheduler::Info_Type) %d}\n"; + +int +parse_args (int argc, char *argv []) +{ + ACE_Get_Opt get_opt (argc, argv, "n:"); + int opt; + + while ((opt = get_opt ()) != EOF) + { + switch (opt) + { + case 'n': + service_name = get_opt.optarg; + break; + case '?': + default: + ACE_DEBUG ((LM_DEBUG, + "Usage: %s " + "-n service_name " + "\n", + argv[0])); + return -1; + } + } + + return 0; +} + +int +main (int argc, char *argv[]) +{ + if (parse_args (argc, argv) != 0) + { + return 1; + } + + // create initial data for supplier and consumer operations + const int operation_count = 8; + ACE_Scheduler_Factory::POD_RT_Info config_infos[operation_count] = { + // good supplier (no unresolved dependencies) + { "good_supplier", // entry point + 0, // handle + 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 + 0, // quantum (unused) + 1, // threads + 0, // OS priority + 0, // Preemption subpriority + 0, // Preemption priority + RtecScheduler::OPERATION // info type + }, + // good consumer (no unresolved dependencies) + { "good_consumer", // entry point + 1, // handle + 5000, // worst case execution time + 5000, // typical execution time (unused) + 5000, // cached execution time + 0, // period (100 ns) + RtecScheduler::HIGH_CRITICALITY, // criticality + RtecScheduler::LOW_IMPORTANCE, // importance + 0, // quantum (unused) + 0, // threads + 0, // OS priority + 0, // Preemption subpriority + 0, // Preemption priority + RtecScheduler::OPERATION // info type + }, + // supplier with unresolved remote dependencies + { "unresolved_remote_supplier", // entry point + 2, // handle + 5000, // worst case execution time + 5000, // typical execution time (unused) + 5000, // cached execution time + 0, // period (100 ns) + RtecScheduler::HIGH_CRITICALITY, // criticality + RtecScheduler::LOW_IMPORTANCE, // importance + 0, // quantum (unused) + 0, // threads + 0, // OS priority + 0, // Preemption subpriority + 0, // Preemption priority + RtecScheduler::REMOTE_DEPENDANT // info type + }, + // consumer with unresolved remote dependencies + { "unresolved_remote_consumer", // entry point + 3, // handle + 5000, // worst case execution time + 5000, // typical execution time (unused) + 5000, // cached execution time + 0, // period (100 ns) + RtecScheduler::HIGH_CRITICALITY, // criticality + RtecScheduler::LOW_IMPORTANCE, // importance + 0, // quantum (unused) + 0, // threads + 0, // OS priority + 0, // Preemption subpriority + 0, // Preemption priority + RtecScheduler::OPERATION // info type + }, + // supplier with unresolved local dependencies + { "unresolved_local_supplier", // entry point + 4, // handle + 5000, // worst case execution time + 5000, // typical execution time (unused) + 5000, // cached execution time + 0, // period (100 ns) + RtecScheduler::HIGH_CRITICALITY, // criticality + RtecScheduler::LOW_IMPORTANCE, // importance + 0, // quantum (unused) + 0, // threads + 0, // OS priority + 0, // Preemption subpriority + 0, // Preemption priority + RtecScheduler::OPERATION // info type + }, + // consumer with unresolved local dependencies + { "unresolved_local_consumer", // entry point + 5, // handle + 5000, // worst case execution time + 5000, // typical execution time (unused) + 5000, // cached execution time + 0, // period (100 ns) + RtecScheduler::HIGH_CRITICALITY, // criticality + RtecScheduler::LOW_IMPORTANCE, // importance + 0, // quantum (unused) + 0, // threads + 0, // OS priority + 0, // Preemption subpriority + 0, // Preemption priority + RtecScheduler::OPERATION // info type + }, + // consumer with unresolved local and remote dependencies + { "both_unresolved_consumer_1", // entry point + 6, // handle + 5000, // worst case execution time + 5000, // typical execution time (unused) + 5000, // cached execution time + 0, // period (100 ns) + RtecScheduler::HIGH_CRITICALITY, // criticality + RtecScheduler::LOW_IMPORTANCE, // importance + 0, // quantum (unused) + 0, // threads + 0, // OS priority + 0, // Preemption subpriority + 0, // Preemption priority + RtecScheduler::OPERATION // info type + }, + // another consumer with unresolved + // local and remote dependencies + { "both_unresolved_consumer_2", // entry point + 7, // handle + 5000, // worst case execution time + 5000, // typical execution time (unused) + 5000, // cached execution time + 0, // period (100 ns) + RtecScheduler::HIGH_CRITICALITY, // criticality + RtecScheduler::LOW_IMPORTANCE, // importance + 0, // quantum (unused) + 0, // threads + 0, // OS priority + 0, // Preemption subpriority + 0, // Preemption priority + RtecScheduler::OPERATION // info type + } + }; + + + TAO_TRY + { + // Initialize ORB. + CORBA::ORB_var orb = + CORBA::ORB_init (argc, argv, "internet", TAO_TRY_ENV); + TAO_CHECK_ENV; + + CORBA::Object_var poa_object = + orb->resolve_initial_references("RootPOA"); + if (CORBA::is_nil(poa_object.in ())) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize the POA.\n"), + 1); + + PortableServer::POA_var root_poa = + PortableServer::POA::_narrow (poa_object.in(), TAO_TRY_ENV); + TAO_CHECK_ENV; + + PortableServer::POAManager_var poa_manager = + root_poa->the_POAManager (TAO_TRY_ENV); + TAO_CHECK_ENV; + + // Initialize the naming services + TAO_Naming_Client my_name_client; + if (my_name_client.init (orb.in ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to initialize " + "the TAO_Naming_Client. \n"), + -1); + + if (ACE_Scheduler_Factory::use_config (my_name_client.get_context (), + service_name) < 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to bind to the scheduling service.\n"), + 1); + } + // create and initialize RT_Infos in the scheduler, + // make second half of array depend on first half. + for (int i = 0; i < operation_count; ++i) + { + // create the RT_Info + config_infos[i].handle = + ACE_Scheduler_Factory::server ()->create (config_infos[i].entry_point, + TAO_TRY_ENV); + + // initialize the RT_Info + ACE_Scheduler_Factory::server ()-> + set (config_infos[i].handle, + (RtecScheduler::Criticality) config_infos[i].criticality, + config_infos[i].worst_case_execution_time, + config_infos[i].typical_execution_time, + config_infos[i].cached_execution_time, + config_infos[i].period, + (RtecScheduler::Importance) config_infos[i].importance, + config_infos[i].quantum, + config_infos[i].threads, + (RtecScheduler::Info_Type) config_infos[i].info_type, + TAO_TRY_ENV); + } + + + // register dependency of good consumer on good supplier + ACE_Scheduler_Factory::server ()-> + add_dependency (config_infos[1].handle, + config_infos[0].handle, + 1, // number of calls + RtecScheduler::ONE_WAY_CALL, // type of dependency + TAO_TRY_ENV); + + // register dependency of consumer that will have unresolved remote + // dependencies on supplier with unresolved remote dependencies + ACE_Scheduler_Factory::server ()-> + add_dependency (config_infos[3].handle, + config_infos[2].handle, + 1, // number of calls + RtecScheduler::ONE_WAY_CALL, // type of dependency + TAO_TRY_ENV); + + + // register dependency of consumer that will have unresolved local + // dependencies on supplier with unresolved local dependencies + ACE_Scheduler_Factory::server ()-> + add_dependency (config_infos[5].handle, + config_infos[4].handle, + 1, // number of calls + RtecScheduler::ONE_WAY_CALL, // type of dependency + TAO_TRY_ENV); + + + // register dependencies on each supplier of first consumer that will + // have both unresolved local and unresolved remote dependencies. + ACE_Scheduler_Factory::server ()-> + add_dependency (config_infos[6].handle, + config_infos[0].handle, + 1, // number of calls + RtecScheduler::ONE_WAY_CALL, // type of dependency + TAO_TRY_ENV); + ACE_Scheduler_Factory::server ()-> + add_dependency (config_infos[6].handle, + config_infos[2].handle, + 1, // number of calls + RtecScheduler::ONE_WAY_CALL, // type of dependency + TAO_TRY_ENV); + ACE_Scheduler_Factory::server ()-> + add_dependency (config_infos[6].handle, + config_infos[4].handle, + 1, // number of calls + RtecScheduler::ONE_WAY_CALL, // type of dependency + TAO_TRY_ENV); + + + // Register dependencies on each of the other consumers by second + // consumer that will have both unresolved local and unresolved remote + // dependencies. + ACE_Scheduler_Factory::server ()-> + add_dependency (config_infos[7].handle, + config_infos[1].handle, + 1, // number of calls + RtecScheduler::ONE_WAY_CALL, // type of dependency + TAO_TRY_ENV); + ACE_Scheduler_Factory::server ()-> + add_dependency (config_infos[7].handle, + config_infos[3].handle, + 1, // number of calls + RtecScheduler::ONE_WAY_CALL, // type of dependency + TAO_TRY_ENV); + ACE_Scheduler_Factory::server ()-> + add_dependency (config_infos[7].handle, + config_infos[5].handle, + 1, // number of calls + RtecScheduler::ONE_WAY_CALL, // type of dependency + TAO_TRY_ENV); + ACE_Scheduler_Factory::server ()-> + add_dependency (config_infos[7].handle, + config_infos[6].handle, + 1, // number of calls + RtecScheduler::ONE_WAY_CALL, // type of dependency + TAO_TRY_ENV); + + + RtecScheduler::RT_Info_Set_var infos; + RtecScheduler::Config_Info_Set_var configs; + RtecScheduler::Scheduling_Anomaly_Set_var anomalies; + +#if defined (__SUNPRO_CC) + // Sun C++ 4.2 warns with the code below: + // Warning (Anachronism): Temporary used for non-const + // reference, now obsolete. + // Note: Type "CC -migration" for more on anachronisms. + // Warning (Anachronism): The copy constructor for argument + // infos of type RtecScheduler::RT_Info_Set_out should take + // const RtecScheduler::RT_Info_Set_out&. + // But, this code is not CORBA conformant, because users should + // not define instances of _out types. + + RtecScheduler::RT_Info_Set_out infos_out (infos); + RtecScheduler::Config_Info_Set_out configs_out (configs); + RtecScheduler::Scheduling_Anomaly_Set_out anomalies_out (anomalies); + ACE_Scheduler_Factory::server ()->compute_scheduling + (ACE_Sched_Params::priority_min (ACE_SCHED_FIFO, + ACE_SCOPE_THREAD), + ACE_Sched_Params::priority_max (ACE_SCHED_FIFO, + ACE_SCOPE_THREAD), + infos_out, configs_out, anomalies_out, TAO_TRY_ENV); +#else /* ! __SUNPRO_CC */ + ACE_Scheduler_Factory::server ()->compute_scheduling + (ACE_Sched_Params::priority_min (ACE_SCHED_FIFO, + ACE_SCOPE_THREAD), + ACE_Sched_Params::priority_max (ACE_SCHED_FIFO, + ACE_SCOPE_THREAD), + infos.out (), configs.out (), anomalies.out (), TAO_TRY_ENV); +#endif /* ! __SUNPRO_CC */ + + TAO_CHECK_ENV; + + ACE_Scheduler_Factory::dump_schedule (infos.in (), + configs.in (), + anomalies.in (), + "Sched_Conf_Anomalies_Runtime.h", + format_string); + } + TAO_CATCH (CORBA::SystemException, sys_ex) + { + TAO_TRY_ENV.print_exception ("SYS_EX"); + } + TAO_ENDTRY; + + return 0; +} + + diff --git a/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Anomalies.dsp b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Anomalies.dsp new file mode 100644 index 00000000000..f7e9d6bad1d --- /dev/null +++ b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Anomalies.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="Sched_Conf_Anomalies" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Sched_Conf_Anomalies - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Sched_Conf_Anomalies.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Sched_Conf_Anomalies.mak" CFG="Sched_Conf_Anomalies - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Sched_Conf_Anomalies - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Sched_Conf_Anomalies - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Sched_Conf_Anomalies - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "Sched_Conf_Anomalies - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Sched_Conf_Anomalies___Win32_Debug"
+# PROP BASE Intermediate_Dir "Sched_Conf_Anomalies___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\\" /I "..\..\..\\" /I "..\..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D TAO_ORBSVCS_HAS_DLL=1 /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 orbsvcsd.lib TAOd.lib aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\orbsvcs" /libpath:"..\..\..\tao" /libpath:"..\..\..\..\ace"
+
+!ENDIF
+
+# Begin Target
+
+# Name "Sched_Conf_Anomalies - Win32 Release"
+# Name "Sched_Conf_Anomalies - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\Sched_Conf_Anomalies.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Anomalies_Runtime.h b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Anomalies_Runtime.h new file mode 100644 index 00000000000..806c0754f76 --- /dev/null +++ b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Anomalies_Runtime.h @@ -0,0 +1,47 @@ +// $Id $ + +// This file was automatically generated by the Scheduler_Factory. +// Before editing the file please consider generating it again. + +#include "orbsvcs/Scheduler_Factory.h" + + +// The following scheduling anomalies were detected: +// WARNING: ST_UNRESOLVED_REMOTE_DEPENDENCIES +ERROR: ST_UNRESOLVED_LOCAL_DEPENDENCIES + + +static ACE_Scheduler_Factory::POD_RT_Info infos[] = { +{"good_supplier", 1, 5000, 5000, 5000, 500000, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 1, 15, 0, 0, (RtecScheduler::Info_Type) 0} +, +{"good_consumer", 2, 5000, 5000, 5000, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 15, 1, 0, (RtecScheduler::Info_Type) 0} +, +{"unresolved_remote_supplier", 3, 5000, 5000, 5000, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 0, 0, 0, (RtecScheduler::Info_Type) 3} +, +{"unresolved_remote_consumer", 4, 5000, 5000, 5000, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 0, 0, 0, (RtecScheduler::Info_Type) 0} +, +{"unresolved_local_supplier", 5, 5000, 5000, 5000, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 0, 0, 0, (RtecScheduler::Info_Type) 0} +, +{"unresolved_local_consumer", 6, 5000, 5000, 5000, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 0, 0, 0, (RtecScheduler::Info_Type) 0} +, +{"both_unresolved_consumer_1", 7, 5000, 5000, 5000, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 0, 0, 0, (RtecScheduler::Info_Type) 0} +, +{"both_unresolved_consumer_2", 8, 5000, 5000, 5000, 0, (RtecScheduler::Criticality) 3, (RtecScheduler::Importance) 1, 0, 0, 0, 0, 0, (RtecScheduler::Info_Type) 0} + +}; + +static int infos_size = sizeof(infos)/sizeof(infos[0]); + + +static ACE_Scheduler_Factory::POD_Config_Info configs[] = { + { 0, 15, (RtecScheduler::Dispatching_Type) 2 } +}; + +static int configs_size = sizeof(configs)/sizeof(configs[0]); + + +// This sets up Scheduler_Factory to use the runtime version. +int scheduler_factory_setup = + ACE_Scheduler_Factory::use_runtime (configs_size, configs, infos_size, infos); + +// EOF diff --git a/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Runtime.h b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Runtime.h index 6f0721b2376..6bdeaec9e4d 100644 --- a/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Runtime.h +++ b/TAO/orbsvcs/tests/Sched_Conf/Sched_Conf_Runtime.h @@ -1,42 +1,46 @@ -// $Id$ +// $Id $ -// This file was automatically generated by Scheduler_Factory -// before editing the file please consider generating it again +// This file was automatically generated by the Scheduler_Factory. +// Before editing the file please consider generating it again. #include "orbsvcs/Scheduler_Factory.h" + +// There were no scheduling anomalies. + + static ACE_Scheduler_Factory::POD_RT_Info infos[] = { {"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, 5000, 5000, 5000, 500000, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 1, 2, 8, 1, (RtecScheduler::Info_Type) 0} +{"low_20_S" , 2, 5000, 5000, 5000, 500000, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 1, 2, 11, 1, (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, 10000, 10000, 10000, 1000000, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 1, 2, 5, 1, (RtecScheduler::Info_Type) 0} +{"low_10_S" , 4, 10000, 10000, 10000, 1000000, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 1, 2, 8, 1, (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, 20000, 20000, 20000, 2000000, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 1, 2, 2, 1, (RtecScheduler::Info_Type) 0} +{"low_05_S" , 6, 20000, 20000, 20000, 2000000, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 1, 2, 5, 1, (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, 100000, 100000, 100000, 0, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 0, 0, 0, (RtecScheduler::Info_Type) 3} +{"low_01_S" , 8, 100000, 100000, 100000, 10000000, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 2, 2, 1, (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, 6, 1, (RtecScheduler::Info_Type) 0} +{"low_20_C" , 10, 0, 0, 0, 0, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 2, 9, 1, (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, 3, 1, (RtecScheduler::Info_Type) 0} +{"low_10_C" , 12, 0, 0, 0, 0, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 2, 6, 1, (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, 0, 1, (RtecScheduler::Info_Type) 0} +{"low_05_C" , 14, 0, 0, 0, 0, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 2, 3, 1, (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, 0, 0, 0, (RtecScheduler::Info_Type) 0} +{"low_01_C" , 16, 0, 0, 0, 0, (RtecScheduler::Criticality) 1, (RtecScheduler::Importance) 3, 0, 0, 2, 0, 1, (RtecScheduler::Info_Type) 0} }; @@ -51,8 +55,8 @@ static ACE_Scheduler_Factory::POD_Config_Info configs[] = { static int configs_size = sizeof(configs)/sizeof(configs[0]); -// This sets up Scheduler_Factory to use the runtime version -int scheduler_factory_setup = +// This sets up Scheduler_Factory to use the runtime version. +int scheduler_factory_setup = ACE_Scheduler_Factory::use_runtime (configs_size, configs, infos_size, infos); // EOF |