diff options
author | cdgill <cdgill@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-05-02 16:54:18 +0000 |
---|---|---|
committer | cdgill <cdgill@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-05-02 16:54:18 +0000 |
commit | 53dfae5554064554dddac2c44fedde902dde668f (patch) | |
tree | be3657202253b1eae77f5ca7e256dbe88cd66d2a | |
parent | ee5c1771fdab8989cbbb81521047bc756e33b30c (diff) | |
download | ATCD-53dfae5554064554dddac2c44fedde902dde668f.tar.gz |
first draft of reconfig scheduler, does not compile
-rw-r--r-- | TAO/ChangeLog-99c | 6 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Sched/Reconfig_Scheduler.cpp | 317 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Sched/Reconfig_Scheduler.h | 178 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Sched/Reconfig_Scheduler.i | 5 | ||||
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Scheduler_Factory.h | 23 |
5 files changed, 527 insertions, 2 deletions
diff --git a/TAO/ChangeLog-99c b/TAO/ChangeLog-99c index 5bbf33ecec3..4a05f3987a5 100644 --- a/TAO/ChangeLog-99c +++ b/TAO/ChangeLog-99c @@ -1,3 +1,9 @@ +Sun May 02 11:55:00 1999 Chris Gill <cdgill@cs.wustl.edu> + + * orbsvcs\orbsvcs\Sched\Reconfig_Scheduler.{cpp, h, i} (new) + orbsvcs\orbsvcs\Scheduler_Factory.h: Very early draft + of the reconfigurable scheduler implementation. + Sun May 02 08:15:50 1999 David L. Levine <levine@cs.wustl.edu> * tao/Context.cpp: removed ACE_Unbounded_Queue<char *> diff --git a/TAO/orbsvcs/orbsvcs/Sched/Reconfig_Scheduler.cpp b/TAO/orbsvcs/orbsvcs/Sched/Reconfig_Scheduler.cpp new file mode 100644 index 00000000000..67bc6df6310 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Sched/Reconfig_Scheduler.cpp @@ -0,0 +1,317 @@ +// $Id$ + +#include "orbsvcs/Time_Utilities.h" +#include "orbsvcs/Reconfig_Scheduler.h" + +#if defined (__ACE_INLINE__) +#include "orbsvcs/Reconfig_Scheduler.i" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(orbsvcs, Reconfig_Scheduler, "$Id$") + +// Constructor. Initialize the scheduler from the POD_Config_Info, POD_RT_Info, +// and POD_Dependency arrays, plus stability flag. + +ACE_Reconfig_Scheduler:: +ACE_Reconfig_Scheduler (int config_count, + ACE_Scheduler_Factory::POD_Config_Info config_info[], + int entry_count, + ACE_Scheduler_Factory::POD_RT_Info rt_info[]) + : config_count_ (config_count), + config_info_ (config_info), + entry_count_ (entry_count), + rt_info_ (rt_info), + dependency_count_ (dependency_count), + dependency_info_ (dependency_info), + is_stable_ (is_stable) +{ +CDG - TBD - after all the other methods are done, make sure +the infrastructure they need is appropriately initialized here. +} + +// Create an RT_Info. If the RT_Info already exists, is handle is simply +// returned. If it does not exist, a new RT_Info is created and inserted +// into the schedule, and the handle of the new RT_Info is returned. + +RtecScheduler::handle_t +ACE_Reconfig_Scheduler::create (const char *entry_point, + CORBA::Environment &) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::DUPLICATE_NAME)) +{ +CDG - TBD rework this to be very efficient. + + // Just make sure it's there and return its handle. + for (int i = 0; i < entry_count_; ++i) + if (ACE_OS::strcmp (entry_point, + rt_info_[i].entry_point) == 0) + return i + 1; + + // TODO: throw an exception or print an error. + return -1; +} + +// Lookup a handle for an RT_Info, and return its handle, or an error +// value if it's not present. + +RtecScheduler::handle_t +ACE_Reconfig_Scheduler::lookup (const char * entry_point, + CORBA::Environment &TAO_IN_ENV) + TAO_THROW_SPEC ((CORBA::SystemException)) +{ + return create (entry_point, TAO_IN_ENV); +} + + +// Return a pointer to the RT_Info corresponding to the passed handle. + +RtecScheduler::RT_Info * +ACE_Reconfig_Scheduler::get (RtecScheduler::handle_t handle, + CORBA::Environment &ACE_TRY_ENV) + TAO_THROW_SPEC((CORBA::SystemException, + RtecScheduler::UNKNOWN_TASK)) +{ +CDG - TBD - redo this + + if (handle <= 0 || handle > entry_count_) + ACE_THROW_RETURN (RtecScheduler::UNKNOWN_TASK (), + 0); + // Note: there is no memory leak here, according to the CORBA spec, + // we are supposed to allocate an structure and return it, the + // caller owns it from then on. + + // Allocate a new RT_Info + RtecScheduler::RT_Info* info; + ACE_NEW_THROW_EX (info, + RtecScheduler::RT_Info, + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (0); + + + info->entry_point = rt_info_[handle - 1].entry_point; + info->handle = rt_info_[handle - 1].handle; + info->worst_case_execution_time = rt_info_[handle - 1].worst_case_execution_time; + info->typical_execution_time = rt_info_[handle - 1].typical_execution_time; + info->cached_execution_time = rt_info_[handle - 1].cached_execution_time; + info->period = rt_info_[handle - 1].period; + info->criticality = RtecScheduler::Criticality_t(rt_info_[handle - 1].criticality); + info->importance = RtecScheduler::Importance_t(rt_info_[handle - 1].importance); + info->quantum = rt_info_[handle - 1].quantum; + info->threads = rt_info_[handle - 1].threads; + info->priority = rt_info_[handle - 1].priority; + info->preemption_subpriority = rt_info_[handle - 1].static_subpriority; + info->preemption_priority = rt_info_[handle - 1].preemption_priority; + info->info_type = RtecScheduler::Info_Type_t(rt_info_[handle - 1].info_type); + + return info; +} + + +// Set characteristics of the RT_Info corresponding to the passed handle. + +void +ACE_Reconfig_Scheduler::set (RtecScheduler::handle_t handle, + RtecScheduler::Criticality_t criticality, + RtecScheduler::Time time, + RtecScheduler::Time typical_time, + RtecScheduler::Time cached_time, + RtecScheduler::Period_t period, + RtecScheduler::Importance_t importance, + RtecScheduler::Quantum_t quantum, + CORBA::Long threads, + RtecScheduler::Info_Type_t info_type, + CORBA::Environment &TAO_IN_ENV) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::UNKNOWN_TASK)) +{ +CDG - TBD - redo this - should actually update, and sset flags accordingly + + // We compare the values with the ones stored and print a message on + // any differences. + if (handle <= 0 || handle > entry_count_) + { + ACE_DEBUG ((LM_DEBUG, "Unknown task: no entry for handle %d\n", + handle)); + TAO_THROW (RtecScheduler::UNKNOWN_TASK()); + // NOTREACHED + } + if (rt_info_[handle - 1].worst_case_execution_time != time + || rt_info_[handle - 1].typical_execution_time != typical_time + || rt_info_[handle - 1].cached_execution_time != cached_time + || rt_info_[handle - 1].period != period + || rt_info_[handle - 1].criticality != criticality + || rt_info_[handle - 1].importance != importance + || rt_info_[handle - 1].quantum != quantum + || rt_info_[handle - 1].info_type != info_type + || rt_info_[handle - 1].threads != threads) + ACE_ERROR ((LM_ERROR, + "invalid data for RT_Info: %s\n", + (const char*)rt_info_[handle - 1].entry_point)); + // TODO: throw something here. +} + + +// Returns the priority and subpriority values assigned to an RT_Info, +// based on its handle. + +void +ACE_Reconfig_Scheduler::priority (RtecScheduler::handle_t handle, + RtecScheduler::OS_Priority& o_priority, + RtecScheduler::Preemption_Subpriority_t& subpriority, + RtecScheduler::Preemption_Priority_t& p_priority, + CORBA::Environment &TAO_IN_ENV) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::UNKNOWN_TASK, + RtecScheduler::NOT_SCHEDULED)) +{ +CDG - TBD - redo this + + if (handle <= 0 || handle > entry_count_) + TAO_THROW (RtecScheduler::UNKNOWN_TASK ()); + // NOTREACHED + + o_priority = rt_info_[handle - 1].priority; + subpriority = rt_info_[handle - 1].static_subpriority; + p_priority = rt_info_[handle - 1].preemption_priority; +} + + +// Returns the priority and subpriority values assigned to an RT_Info, +// based on its entry point name. + +void +ACE_Reconfig_Scheduler::entry_point_priority (const char * entry_point, + RtecScheduler::OS_Priority& priority, + RtecScheduler::Preemption_Subpriority_t& subpriority, + RtecScheduler::Preemption_Priority_t& p_priority, + CORBA::Environment &TAO_IN_ENV) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::UNKNOWN_TASK, + RtecScheduler::NOT_SCHEDULED)) +{ +CDG - TBD - redo this + + RtecScheduler::handle_t handle = lookup (entry_point, TAO_IN_ENV); + if (handle < -1) + // The exception was thrown or is in TAO_IN_ENV already. + return; + this->priority (handle, + priority, + subpriority, + p_priority, + TAO_IN_ENV); +} + + +// This method registers a dependency between two RT_Infos. + +void +ACE_Reconfig_Scheduler::add_dependency (RtecScheduler::handle_t handle, + RtecScheduler::handle_t /* dependency */, + CORBA::Long /* number_of_calls */, + RtecScheduler::Dependency_Type_t /* dependency_type */, + CORBA::Environment &TAO_IN_ENV) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::UNKNOWN_TASK)) +{ + if (handle <= 0 || handle > entry_count_) + TAO_THROW (RtecScheduler::UNKNOWN_TASK ()); + // NOTREACHED + +CDG - TBD - redo this + +#if 0 + // Just check that the information is consistent. + RtecScheduler::Dependency_Set& deps = rt_info_[handle - 1]->dependencies; + for (CORBA::ULong i = 0; i < deps.length (); ++i) + { + if (deps[i].rt_info == dependency + && deps[i].number_of_calls == number_of_calls + && deps[i].dependency_type == dependency_type) + { + return; + } + } + ACE_ERROR ((LM_ERROR, "unmatched dependency on %s\n", + (const char*)rt_info_[handle - 1]->entry_point)); +#endif +} + + +// If information has been added or changed since the last stable +// schedule was computed, this method causes scheduling information +// to be computed for all registered RT_Infos. If the schedule is +// already stable, this is a no-op + +void +ACE_Reconfig_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 &) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::UTILIZATION_BOUND_EXCEEDED, + RtecScheduler::INSUFFICIENT_THREAD_PRIORITY_LEVELS, + RtecScheduler::TASK_COUNT_MISMATCH)) +{ +CDG - TBD - redo this + + // TODO: Right now just do nothing, later we could validate the + // priorities (without recomputing). + // TODO: fill up the infos. + return; +} + + +// Provides the thread priority and queue type for the given priority +// level. + +void +ACE_Reconfig_Scheduler::dispatch_configuration (RtecScheduler::Preemption_Priority_t p_priority, + RtecScheduler::OS_Priority& priority, + RtecScheduler::Dispatching_Type_t & d_type, + CORBA::Environment &TAO_IN_ENV) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::NOT_SCHEDULED, + RtecScheduler::UNKNOWN_PRIORITY_LEVEL)) +{ + // Throw an exception if a valid schedule has not been loaded + if (config_count_ <= 0 + || config_info_ [p_priority].preemption_priority != p_priority) + { + TAO_THROW (RtecScheduler::NOT_SCHEDULED ()); + ACE_NOTREACHED (return); + } + // throw an exception if an invalid priority was passed + else if (p_priority < 0 || p_priority >= config_count_) + { + TAO_THROW (RtecScheduler::UNKNOWN_PRIORITY_LEVEL()); + ACE_NOTREACHED (return); + } + else + { + priority = config_info_ [p_priority].thread_priority; + d_type = config_info_ [p_priority].dispatching_type; + return; + } +} + + +// Returns the last priority number assigned to an operation in the +// schedule. The number returned is one less than the total number +// of scheduled priorities. All scheduled priorities range from 0 +// to the number returned, inclusive. + +RtecScheduler::Preemption_Priority_t +ACE_Reconfig_Scheduler::last_scheduled_priority (CORBA::Environment &TAO_IN_ENV) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::NOT_SCHEDULED)) +{ + // throw an exception if a valid schedule has not been loaded + if (config_count_ <= 0) + TAO_THROW_RETURN (RtecScheduler::NOT_SCHEDULED(), + (RtecScheduler::Preemption_Priority_t) -1); + else + return (RtecScheduler::Preemption_Priority_t) (config_count_ - 1); +} diff --git a/TAO/orbsvcs/orbsvcs/Sched/Reconfig_Scheduler.h b/TAO/orbsvcs/orbsvcs/Sched/Reconfig_Scheduler.h new file mode 100644 index 00000000000..d2e2c1064a1 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Sched/Reconfig_Scheduler.h @@ -0,0 +1,178 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// orbsvcs +// +// = FILENAME +// Reconfig_Scheduler.h +// +// = AUTHOR +// Chris Gill <cdgill@cs.wustl.edu> +// +// ============================================================================ + +#ifndef ACE_RECONFIG_SCHEDULER_H +#define ACE_RECONFIG_SCHEDULER_H + +#include "orbsvcs/Scheduler_Factory.h" +#include "orbsvcs/RtecSchedulerS.h" + +class TAO_ORBSVCS_Export ACE_Reconfig_Scheduler : public POA_RtecScheduler::Scheduler +{ + // = TITLE + // A servant for RtecScheduler::Scheduler that can be initialized + // and run solely with precomputed scheduling information, but is also + // designed to perform efficient recomputation of scheduling info + // in the face of run-time changes to RT_Infos in the schedule. + // + // = DESCRIPTION + // This class implements the TAO scheduling service. It has + // the ability to accept and use precomputed scheduling information + // with deterministic performance once the schedule is fully configured. + // It also provides efficient and flexible lookup and computation + // during schedule configuration, so that it can be used during + // both schedule configuration and run-time phases of operation. + // +public: + ACE_Reconfig_Scheduler (int config_count, + ACE_Scheduler_Factory::POD_Config_Info config_info[], + int entry_count, + ACE_Scheduler_Factory::POD_RT_Info rt_info[], + int dependency_count, + ACE_Scheduler_Factory::POD_Dependency_Info dependency_info[], + int is_stable); + // Constructor. Initialize the scheduler from the POD_Config_Info, POD_RT_Info, + // and POD_Dependency arrays, plus stability flag. + + + virtual RtecScheduler::handle_t create (const char * entry_point, + CORBA::Environment &_env) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::DUPLICATE_NAME)); + // Create an RT_Info. If the RT_Info already exists, is handle is simply + // returned. If it does not exist, a new RT_Info is created and inserted + // into the schedule, and the handle of the new RT_Info is returned. + + virtual RtecScheduler::handle_t lookup (const char * entry_point, + CORBA::Environment &_env) + TAO_THROW_SPEC((CORBA::SystemException)); + // Lookup a handle for an RT_Info, and return its handle, or an error + // value if it's not present. + + virtual RtecScheduler::RT_Info* get (RtecScheduler::handle_t handle, + CORBA::Environment &_env) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::UNKNOWN_TASK)); + // Return a pointer to the RT_Info corresponding to the passed handle. + + virtual void set (RtecScheduler::handle_t handle, + RtecScheduler::Criticality_t criticality, + RtecScheduler::Time time, + RtecScheduler::Time typical_time, + RtecScheduler::Time cached_time, + RtecScheduler::Period_t period, + RtecScheduler::Importance_t importance, + RtecScheduler::Quantum_t quantum, + CORBA::Long threads, + RtecScheduler::Info_Type_t info_type, + CORBA::Environment &_env) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::UNKNOWN_TASK)); + // Set characteristics of the RT_Info corresponding to the passed handle. + + virtual void priority (RtecScheduler::handle_t handle, + RtecScheduler::OS_Priority& o_priority, + RtecScheduler::Preemption_Subpriority_t& p_subpriority, + RtecScheduler::Preemption_Priority_t& p_priority, + CORBA::Environment &_env) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::UNKNOWN_TASK, + RtecScheduler::NOT_SCHEDULED)); + // Returns the priority and subpriority values assigned to an RT_Info, + // based on its handle. + + virtual void entry_point_priority (const char * entry_point, + RtecScheduler::OS_Priority& o_priority, + RtecScheduler::Preemption_Subpriority_t& p_subpriority, + RtecScheduler::Preemption_Priority_t& p_priority, + CORBA::Environment &_env) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::UNKNOWN_TASK, + RtecScheduler::NOT_SCHEDULED)); + // Returns the priority and subpriority values assigned to an RT_Info, + // based on its entry point name. + + virtual void add_dependency (RtecScheduler::handle_t handle, + RtecScheduler::handle_t dependency, + CORBA::Long number_of_calls, + RtecScheduler::Dependency_Type_t dependency_type, + CORBA::Environment &_env) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::UNKNOWN_TASK)); + // This method registers a dependency between two RT_Infos. + + virtual void 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, + RtecScheduler::INSUFFICIENT_THREAD_PRIORITY_LEVELS, + RtecScheduler::TASK_COUNT_MISMATCH)); + // If information has been added or changed since the last stable + // schedule was computed, this method causes scheduling information + // to be computed for all registered RT_Infos. If the schedule is + // already stable, this is a no-op + + virtual void dispatch_configuration (RtecScheduler::Preemption_Priority_t p_priority, + RtecScheduler::OS_Priority& o_priority, + RtecScheduler::Dispatching_Type_t & d_type, + CORBA::Environment &_env) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::NOT_SCHEDULED, + RtecScheduler::UNKNOWN_PRIORITY_LEVEL)); + // Provides the thread priority and queue type for the given priority level. + + virtual RtecScheduler::Preemption_Priority_t last_scheduled_priority (CORBA::Environment &_env) + TAO_THROW_SPEC ((CORBA::SystemException, + RtecScheduler::NOT_SCHEDULED)); + // Returns the last priority number assigned to an operation in the + // schedule. The number returned is one less than the total number + // of scheduled priorities. All scheduled priorities range from 0 + // to the number returned, inclusive. + +private: + + int config_count_; + // The number of elements in the config array. + + ACE_Scheduler_Factory::POD_Config_Info* config_info_; + // The array of precomputed queue configuration structures. + + int entry_count_; + // The number of elements in the RT_Info array. + + ACE_Scheduler_Factory::POD_RT_Info* rt_info_; + // The array of precomputed RT_Info structures. + + int dependency_count_; + // The number of elements in the Dependency_Info array. + + ACE_Scheduler_Factory::POD_Dependency_Info dependency_info_; + // The array of precomputed dependency information. + + int is_stable_; + // Flag indicating whether a stable schedule has been computed + // since the last addition or modification of information. +}; + +#if defined (__ACE_INLINE__) +#include "orbsvcs/Reconfig_Scheduler.i" +#endif /* __ACE_INLINE__ */ + +#endif /* ACE_RECONFIG_SCHEDULER_H */ diff --git a/TAO/orbsvcs/orbsvcs/Sched/Reconfig_Scheduler.i b/TAO/orbsvcs/orbsvcs/Sched/Reconfig_Scheduler.i new file mode 100644 index 00000000000..a21ea7f9897 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Sched/Reconfig_Scheduler.i @@ -0,0 +1,5 @@ +// ============================================================================ +// +// $Id$ +// +// ============================================================================ diff --git a/TAO/orbsvcs/orbsvcs/Scheduler_Factory.h b/TAO/orbsvcs/orbsvcs/Scheduler_Factory.h index 5f08c90a8f1..b9f9f1e86ec 100644 --- a/TAO/orbsvcs/orbsvcs/Scheduler_Factory.h +++ b/TAO/orbsvcs/orbsvcs/Scheduler_Factory.h @@ -45,10 +45,12 @@ public: // // = DESCRIPTION // This type enumerates the possible states of the factory: - // uninitialized, or in a config or runtime mode of operation. + // uninitialized, or in a configuration, runtime, or + // reconfigurable mode of operation. UNINITIALIZED, CONFIG, + RECONFIG, RUNTIME }; @@ -59,7 +61,7 @@ public: // // = DESCRIPTION // This class provide us with a plain old data version of - // RT_Info, this is useful for implementing static arrays or of + // RT_Info, this is useful for implementing arrays of // those. const char *entry_point; @@ -78,6 +80,23 @@ public: CORBA::Long info_type; }; + + struct POD_Dependency_Info + { + // = TITLE + // Plain Old Data for RT_Info Dependencies. + // + // = DESCRIPTION + // This class provide us with a plain old data version of + // dependencies between RT_Infos. This is useful for implementing + // arrays of those. + + RtecScheduler::handle_t info_that_depends; + RtecScheduler::handle_t info_depended_on; + RtecScheduler::Dependency_Type_t dependency_type; + CORBA::Long number_of_calls; + }; + struct POD_Config_Info { // = TITLE |