⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dynsched.cpp

📁 这是广泛使用的通信开源项目,对于大容量,高并发的通讯要求完全能够胜任,他广泛可用于网络游戏医学图像网关的高qos要求.更详细的内容可阅读相应的材料
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// DynSched.cpp,v 1.49 2004/01/01 06:27:17 bala Exp
//
// ============================================================================
//
// = LIBRARY
//    sched
//
// = FILENAME
//    DynSched.cpp
//
// = CREATION DATE
//    23 January 1997
//
// = AUTHOR
//    Chris Gill
//
// ============================================================================

#include "DynSched.h"
#include "ace/Basic_Types.h"
#include "ace/Sched_Params.h"
#include "ace/OS_NS_stdio.h"
#include "ace/Null_Mutex.h"

#if ! defined (__ACE_INLINE__)
#include "DynSched.i"
#endif /* __ACE_INLINE__ */

ACE_RCSID(Sched, DynSched, "DynSched.cpp,v 1.49 2004/01/01 06:27:17 bala Exp")

//////////////////////
// Helper functions //
//////////////////////

// compare the DFS finish times of two task entries, order higher time *first*
#if defined (ACE_HAS_WINCE)
int _cdecl compare_entry_finish_times (const void *first, const void *second)
#else
extern "C" int compare_entry_finish_times (const void *first, const void *second)
#endif  // ACE_HAS_WINCE
{
  // sort blank entries to the end
  if (! first)
  {
    return (second) ? 1 : 0;
  }
  else if (! second)
  {
    return -1;
  }

  const Task_Entry *first_entry =
          * ACE_static_cast (const Task_Entry *const *, first);
  const Task_Entry *second_entry =
          * ACE_static_cast (const Task_Entry *const *, second);

  // sort blank entries to the end
  if (! first_entry)
  {
    return (second_entry) ? 1 : 0;
  }
  else if (! second_entry)
  {
    return -1;
  }

  if (first_entry->finished () > second_entry->finished ())
  {
    return -1;
  }
  else if (first_entry->finished () < second_entry->finished ())
  {
    return 1;
  }

  return 0;
}

//////////////////////////////////////////
// class ACE_DynScheduler member functions //
//////////////////////////////////////////

const char *
ACE_DynScheduler::status_message (ACE_DynScheduler::status_t status)
{
  switch (status)
  {
    case NOT_SCHEDULED :
      return "NOT_SCHEDULED";
    case SUCCEEDED :
      return "SUCCEEDED";
    case ST_NO_TASKS_REGISTERED :
      return "ST_NO_TASKS_REGISTERED";
    case ST_TASK_ALREADY_REGISTERED :
      return "TASK_ALREADY_REGISTERED";
    case ST_BAD_INTERNAL_POINTER :
      return "BAD_INTERNAL_POINTER";
    case ST_VIRTUAL_MEMORY_EXHAUSTED :
      return "VIRTUAL_MEMORY_EXHAUSTED";
    case ST_UNKNOWN_TASK :
      return "UNKNOWN_TASK";
    case TASK_COUNT_MISMATCH :
      return "TASK_COUNT_MISMATCH";
    case THREAD_COUNT_MISMATCH :
      return "THREAD_COUNT_MISMATCH";
    case INVALID_PRIORITY :
      return "INVALID_PRIORITY";
    case TWO_WAY_DISJUNCTION :
      return "TWO_WAY_DISJUNCTION (IGNORED)";
    case TWO_WAY_CONJUNCTION :
      return "TWO_WAY_CONJUNCTION (IGNORED)";
    case UNRECOGNIZED_INFO_TYPE :
      return "UNRECOGNIZED_INFO_TYPE (IGNORED)";

    // The following are only used during scheduling (in the case of
    // off-line scheduling, they are only used prior to runtime).
    // To save a little code space (280 bytes on g++ 2.7.2/Solaris 2.5.1),
    // we could conditionally compile them so that they're not in the
    // runtime version.
    case ST_UTILIZATION_BOUND_EXCEEDED :
      return "UTILIZATION_BOUND_EXCEEDED";
    case ST_INSUFFICIENT_THREAD_PRIORITY_LEVELS :
      return "INSUFFICIENT_THREAD_PRIORITY_LEVELS";
    case ST_CYCLE_IN_DEPENDENCIES :
      return "CYCLE_IN_DEPENDENCIES";
    case ST_UNRESOLVED_REMOTE_DEPENDENCIES :
      return "ST_UNRESOLVED_REMOTE_DEPENDENCIES";
    case ST_UNRESOLVED_LOCAL_DEPENDENCIES :
      return "ST_UNRESOLVED_LOCAL_DEPENDENCIES";
    case ST_INVALID_PRIORITY_ORDERING :
      return "INVALID_PRIORITY_ORDERING";
    case UNABLE_TO_OPEN_SCHEDULE_FILE :
      return "UNABLE_TO_OPEN_SCHEDULE_FILE";
    case UNABLE_TO_WRITE_SCHEDULE_FILE :
      return "UNABLE_TO_WRITE_SCHEDULE_FILE";
    // End of config-only status values.

    default:
      break;
  }

  return "UNKNOWN STATUS";
}

// = Utility function for creating an entry for determining
//   the severity of an anomaly detected during scheduling.
ACE_DynScheduler::Anomaly_Severity
ACE_DynScheduler::anomaly_severity (ACE_DynScheduler::status_t status)
{
  // Determine severity of the anomaly
  switch (status)
  {
    // Fatal anomalies reflect unrecoverable internal scheduler errors
    case ST_BAD_INTERNAL_POINTER :
    case ST_VIRTUAL_MEMORY_EXHAUSTED :
    case THREAD_COUNT_MISMATCH :
    case TASK_COUNT_MISMATCH :
      return RtecScheduler::ANOMALY_FATAL;

    // Errors reflect severe problems with given scheduling information
    case UNABLE_TO_OPEN_SCHEDULE_FILE :
    case UNABLE_TO_WRITE_SCHEDULE_FILE :
    case NOT_SCHEDULED :
    case ST_UNRESOLVED_LOCAL_DEPENDENCIES :
    case ST_UNKNOWN_TASK :
    case ST_CYCLE_IN_DEPENDENCIES :
    case ST_INVALID_PRIORITY_ORDERING :
      return RtecScheduler::ANOMALY_ERROR;

    // Warnings reflect serious problems with given scheduling information
    case ST_TASK_ALREADY_REGISTERED :
    case ST_UNRESOLVED_REMOTE_DEPENDENCIES :
    case ST_UTILIZATION_BOUND_EXCEEDED :
    case ST_INSUFFICIENT_THREAD_PRIORITY_LEVELS :
    case TWO_WAY_DISJUNCTION :
    case TWO_WAY_CONJUNCTION :
    case UNRECOGNIZED_INFO_TYPE :
    case ST_NO_TASKS_REGISTERED :
      return RtecScheduler::ANOMALY_WARNING;

    // Produce a lowest severity anomaly for any unknown status value
    default:
      return RtecScheduler::ANOMALY_NONE;
  }
}


// = Utility function for creating an entry for the
//   log of anomalies detected during scheduling.
ACE_DynScheduler::Scheduling_Anomaly *
ACE_DynScheduler::create_anomaly (ACE_DynScheduler::status_t status)
{
  ACE_DynScheduler::Scheduling_Anomaly * anomaly;
  ACE_NEW_RETURN (anomaly, ACE_DynScheduler::Scheduling_Anomaly, 0);

  anomaly->severity = anomaly_severity (status);
  anomaly->description = status_message (status);

  return anomaly;
}


ACE_DynScheduler::ACE_DynScheduler ()
  // Set the minimum and maximum priority to those for the current platform.
  // This shouldn't be necessary, but UPSingleProcessorOrb::initialize_reactors
  // creates threads before the Event Channel calls Scheduler::init ().
  : minimum_priority_ (ACE_Sched_Params::priority_min (ACE_SCHED_FIFO,
                                                       ACE_SCOPE_PROCESS))
  , maximum_priority_ (ACE_Sched_Params::priority_max (ACE_SCHED_FIFO,
                                                       ACE_SCOPE_PROCESS))
  , task_entries_ (0)
  , ordered_task_entries_ (0)
  , thread_delineators_ (0)
  , ordered_thread_dispatch_entries_ (0)
  , dispatch_entries_ (0)
  , config_info_entries_ (0)
  , expanded_dispatches_ (0)
  , ordered_dispatch_entries_ (0)
  , dispatch_entry_count_ (0)
  , threads_ (0)
  , timeline_ (0)
  , lock_ ()
  , rt_info_entries_ ()
  , handles_ (0)
  , runtime_filename_ (0)
  , rt_info_filename_ (0)
  , timeline_filename_ (0)
  , tasks_ (0)
  , status_ (NOT_SCHEDULED)
  , output_level_ (0)
  , frame_size_ (1)
  , critical_set_frame_size_ (0)
  , utilization_ (0.0)
  , critical_set_utilization_ (0.0)
  , minimum_priority_queue_ (0)
  , minimum_guaranteed_priority_queue_ (-1)
  , up_to_date_ (0)
  , min_dispatch_id_ (0)
  , max_dispatch_id_ (0)
{
}


ACE_DynScheduler::~ACE_DynScheduler ()
{
  // release all resources used for the most recent schedule
  reset ();
}


void
ACE_DynScheduler::init (const OS_Priority minimum_priority,
                     const OS_Priority maximum_priority,
                     const char *runtime_filename,
                     const char *rt_info_filename,
                     const char *timeline_filename)
{
  minimum_priority_ = minimum_priority;
  maximum_priority_ = maximum_priority;
  runtime_filename_ = runtime_filename;
  rt_info_filename_ = rt_info_filename;
  timeline_filename_ = timeline_filename;
}
  // = initializes the scheduler.

ACE_DynScheduler::status_t
ACE_DynScheduler::register_task (RT_Info *rt_info, handle_t &handle)
{
  ACE_DynScheduler::status_t ret = ST_UNKNOWN_TASK;

  // check the pointer we were passed
  if (! rt_info)
  {
    handle = 0;
    return ret;
  }

  // try to store the new task's information . . .
  switch (rt_info_entries_.insert (rt_info))
    {
      case 0 : // successfully inserted
        {
          rt_info->handle = (handle = ++handles_);
          ret = SUCCEEDED;

          // zero out the task entry ACT used by the scheduler
          rt_info->volatile_token = 0;

          // make sure the schedule is reset when a new task is registered
          reset ();

          if (output_level () >= 5)
            {
              ACE_OS::printf ("registered task \"%s\" with RT_Info at %p\n",
                              (const char*)(rt_info->entry_point), rt_info);
            }
        }
        break;

      case 1 : // the entry had already been inserted
        handle = 0;
        ret = ST_TASK_ALREADY_REGISTERED;
        break;

      default :
        // case -1 : insert failed, probably because virtual memory exhaused
        handle = 0;
        ret = ST_VIRTUAL_MEMORY_EXHAUSTED;
        break;
    }

  return ret;
}
  // = registers a task.



ACE_DynScheduler::status_t
ACE_DynScheduler::get_rt_info (Object_Name name,
                               RT_Info* &rtinfo)
{
  handle_t handle;

  // This makes a copy.  We can optimize this with our own string
  // class.
  ACE_CString lookup (name);
  // Search the map for the <name>.  If found, return the RT_Info.
  if (info_collection_.find (lookup, rtinfo) >= 0)
    {
      // If we find it, return.
      return SUCCEEDED;
    }
  else
    // Otherwise, make one, bind it, and register it.
    {
      rtinfo = new RT_Info;
      rtinfo->info_type = RtecScheduler::OPERATION;
      rtinfo->entry_point = CORBA::string_dup(name);
      // Bind the rtinfo to the name.
      if (info_collection_.bind (lookup, rtinfo) != 0)
        {
          delete rtinfo;
          rtinfo = 0;
          return FAILED; // Error!
        }
      else
        {
          // Register the task
          status_t result = this->register_task (rtinfo, handle);
          if (result == SUCCEEDED)
            {
              rtinfo->handle = handle;
              return ST_UNKNOWN_TASK; // Didn't find it, but made one!
            }
          else
            {
              rtinfo->handle = 0;
              return FAILED;
            }
        }
    }
}




int ACE_DynScheduler::priority (
  const RtecScheduler::handle_t handle,
  RtecScheduler::OS_Priority &priority,
  RtecScheduler::Preemption_Subpriority_t &subpriority,
  RtecScheduler::Preemption_Priority_t &preemption_prio)
{
  // look up the RT_Info that has the given handle
  RT_Info *rt_info = 0;
  if (lookup_rt_info (handle, rt_info) == SUCCEEDED)
  {
    // copy the priority values from the RT_Info
    priority = rt_info->priority;
    subpriority = rt_info->preemption_subpriority;
    preemption_prio = rt_info->preemption_priority;

    return 0;
  }
  else

  {
    // RT_Info not found: assign default priority values
    priority = minimum_priority_;
    subpriority = ACE_Scheduler_MIN_SUB_PRIORITY;
    preemption_prio = ACE_Scheduler_MAX_PREEMPTION_PRIORITY;

    if (output_level () >= 3)
    {
      ACE_OS::printf ("preemption_prio %d: min %d, pri %d, min_pri %d\n",
                      preemption_prio, minimum_priority_queue (),
                      priority, minimum_priority_);
    }

    return -1;
  }
}
  // "priority" is the OS thread priority that was assigned to the Task that
  // was assigned "handle".  "subpriority" combines the dynamic and static
  // subpriorities of the Task that was assigned handle.  "preemption_prio"
  // is a platform-independent priority queue number, ranging from a
  // highest priority value of 0 to the lowest priority value, which is
  // returned by "minimum_priority_queue ()".  The current and deadline times
  // supplied are used to compute the operation's dynamic subpriority
  // Returns 0 on success, or -1 if an invalid handle was supplied.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -