コード例 #1
0
epos_status_code epos_task_set_priority(
  epos_id             id,
  epos_task_priority  new_priority,
  epos_task_priority *old_priority
)
{ 
  register Thread_Control *the_thread;
  Objects_Locations               location;

  if ( new_priority != RTEMS_CURRENT_PRIORITY &&
       !_RTEMS_tasks_Priority_is_valid( new_priority ) )
    return RTEMS_INVALID_PRIORITY;

  if ( !old_priority )
    return RTEMS_INVALID_ADDRESS;

  the_thread = _Thread_Get( id, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:
      /* XXX need helper to "convert" from core priority */
      *old_priority = the_thread->current_priority;
      if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
        the_thread->real_priority = new_priority;
        if ( the_thread->resource_count == 0 ||
             the_thread->current_priority > new_priority )
          _Thread_Change_priority( the_thread, new_priority, false );
      }
      _Thread_Enable_dispatch();
      return RTEMS_SUCCESSFUL;

#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:
      _Thread_Executing->Wait.return_argument = old_priority;
      return _RTEMS_tasks_MP_Send_request_packet(
          RTEMS_TASKS_MP_SET_PRIORITY_REQUEST,
          id,
          new_priority,
          0,          /* Not used */
          0           /* Not used */
      );
#endif

    case OBJECTS_ERROR:
      break;
  }

  return RTEMS_INVALID_ID;
}
コード例 #2
0
ファイル: taskcreate.c プロジェクト: goetzpf/rtems
rtems_status_code rtems_task_create(
  rtems_name           name,
  rtems_task_priority  initial_priority,
  size_t               stack_size,
  rtems_mode           initial_modes,
  rtems_attribute      attribute_set,
  rtems_id            *id
)
{
  Thread_Control          *the_thread;
  bool                     is_fp;
#if defined(RTEMS_MULTIPROCESSING)
  Objects_MP_Control      *the_global_object = NULL;
  bool                     is_global;
#endif
  bool                     status;
  rtems_attribute          the_attribute_set;
  Priority_Control         core_priority;
  RTEMS_API_Control       *api;
  ASR_Information         *asr;


  if ( !id )
   return RTEMS_INVALID_ADDRESS;

  if ( !rtems_is_name_valid( name ) )
    return RTEMS_INVALID_NAME;

  /*
   *  Core Thread Initialize insures we get the minimum amount of
   *  stack space.
   */

  /*
   *  Fix the attribute set to match the attributes which
   *  this processor (1) requires and (2) is able to support.
   *  First add in the required flags for attribute_set
   *  Typically this might include FP if the platform
   *  or application required all tasks to be fp aware.
   *  Then turn off the requested bits which are not supported.
   */

  the_attribute_set = _Attributes_Set( attribute_set, ATTRIBUTES_REQUIRED );
  the_attribute_set =
    _Attributes_Clear( the_attribute_set, ATTRIBUTES_NOT_SUPPORTED );

  if ( _Attributes_Is_floating_point( the_attribute_set ) )
    is_fp = true;
  else
    is_fp = false;

  /*
   *  Validate the RTEMS API priority and convert it to the core priority range.
   */

  if ( !_Attributes_Is_system_task( the_attribute_set ) ) {
    if ( !_RTEMS_tasks_Priority_is_valid( initial_priority ) )
      return RTEMS_INVALID_PRIORITY;
  }

  core_priority = _RTEMS_tasks_Priority_to_Core( initial_priority );

#if defined(RTEMS_MULTIPROCESSING)
  if ( _Attributes_Is_global( the_attribute_set ) ) {

    is_global = true;

    if ( !_System_state_Is_multiprocessing )
      return RTEMS_MP_NOT_CONFIGURED;

  } else
    is_global = false;
#endif

  /*
   *  Make sure system is MP if this task is global
   */

  /*
   *  Allocate the thread control block and -- if the task is global --
   *  allocate a global object control block.
   *
   *  NOTE:  This routine does not use the combined allocate and open
   *         global object routine because this results in a lack of
   *         control over when memory is allocated and can be freed in
   *         the event of an error.
   */

  the_thread = _RTEMS_tasks_Allocate();

  if ( !the_thread ) {
    _Objects_Allocator_unlock();
    return RTEMS_TOO_MANY;
  }

#if defined(RTEMS_MULTIPROCESSING)
  if ( is_global ) {
    the_global_object = _Objects_MP_Allocate_global_object();

    if ( _Objects_MP_Is_null_global_object( the_global_object ) ) {
      _RTEMS_tasks_Free( the_thread );
      _Objects_Allocator_unlock();
      return RTEMS_TOO_MANY;
    }
  }
#endif

  /*
   *  Initialize the core thread for this task.
   */

  status = _Thread_Initialize(
    &_RTEMS_tasks_Information,
    the_thread,
    _Scheduler_Get_by_CPU_index( _SMP_Get_current_processor() ),
    NULL,
    stack_size,
    is_fp,
    core_priority,
    _Modes_Is_preempt(initial_modes)   ? true : false,
    _Modes_Is_timeslice(initial_modes) ?
      THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE :
      THREAD_CPU_BUDGET_ALGORITHM_NONE,
    NULL,        /* no budget algorithm callout */
    _Modes_Get_interrupt_level(initial_modes),
    (Objects_Name) name
  );

  if ( !status ) {
#if defined(RTEMS_MULTIPROCESSING)
    if ( is_global )
      _Objects_MP_Free_global_object( the_global_object );
#endif
    _RTEMS_tasks_Free( the_thread );
    _Objects_Allocator_unlock();
    return RTEMS_UNSATISFIED;
  }

  api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
  asr = &api->Signal;

  asr->is_enabled = _Modes_Is_asr_disabled(initial_modes) ? false : true;

  *id = the_thread->Object.id;

#if defined(RTEMS_MULTIPROCESSING)
  the_thread->is_global = is_global;
  if ( is_global ) {

    _Objects_MP_Open(
      &_RTEMS_tasks_Information.Objects,
      the_global_object,
      name,
      the_thread->Object.id
    );

    _RTEMS_tasks_MP_Send_process_packet(
      RTEMS_TASKS_MP_ANNOUNCE_CREATE,
      the_thread->Object.id,
      name
    );

   }
#endif

  _Objects_Allocator_unlock();
  return RTEMS_SUCCESSFUL;
}
コード例 #3
0
ファイル: timerserver.c プロジェクト: epicsdeb/rtems
/**
 *  @brief rtems_timer_initiate_server
 *
 *  This directive creates and starts the server for task-based timers.
 *  It must be invoked before any task-based timers can be initiated.
 *
 *  @param[in] priority is the timer server priority
 *  @param[in] stack_size is the stack size in bytes
 *  @param[in] attribute_set is the timer server attributes
 *
 *  @return This method returns RTEMS_SUCCESSFUL if successful and an
 *          error code otherwise.
 */
rtems_status_code rtems_timer_initiate_server(
  uint32_t             priority,
  uint32_t             stack_size,
  rtems_attribute      attribute_set
)
{
  rtems_id              id;
  rtems_status_code     status;
  rtems_task_priority   _priority;
  static bool           initialized = false;
  bool                  tmpInitialized;
  Timer_server_Control *ts = &_Timer_server_Default;

  /*
   *  Make sure the requested priority is valid.  The if is
   *  structured so we check it is invalid before looking for
   *  a specific invalid value as the default.
   */
  _priority = priority;
  if ( !_RTEMS_tasks_Priority_is_valid( priority ) ) {
    if ( priority != RTEMS_TIMER_SERVER_DEFAULT_PRIORITY )
      return RTEMS_INVALID_PRIORITY;
    _priority = 0;
  }

  /*
   *  Just to make sure this is only called once.
   */
  _Thread_Disable_dispatch();
    tmpInitialized  = initialized;
    initialized = true;
  _Thread_Enable_dispatch();

  if ( tmpInitialized )
    return RTEMS_INCORRECT_STATE;

  /*
   *  Create the Timer Server with the name the name of "TIME".  The attribute
   *  RTEMS_SYSTEM_TASK allows us to set a priority to 0 which will makes it
   *  higher than any other task in the system.  It can be viewed as a low
   *  priority interrupt.  It is also always NO_PREEMPT so it looks like
   *  an interrupt to other tasks.
   *
   *  We allow the user to override the default priority because the Timer
   *  Server can invoke TSRs which must adhere to language run-time or
   *  other library rules.  For example, if using a TSR written in Ada the
   *  Server should run at the same priority as the priority Ada task.
   *  Otherwise, the priority ceiling for the mutex used to protect the
   *  GNAT run-time is violated.
   */
  status = rtems_task_create(
    _Objects_Build_name('T','I','M','E'),           /* "TIME" */
    _priority,            /* create with priority 1 since 0 is illegal */
    stack_size,           /* let user specify stack size */
    RTEMS_NO_PREEMPT,     /* no preempt is like an interrupt */
                          /* user may want floating point but we need */
                          /*   system task specified for 0 priority */
    attribute_set | RTEMS_SYSTEM_TASK,
    &id                   /* get the id back */
  );
  if (status) {
    initialized = false;
    return status;
  }

  /*
   *  Do all the data structure initialization before starting the
   *  Timer Server so we do not have to have a critical section.
   */

  /*
   *  We work with the TCB pointer, not the ID, so we need to convert
   *  to a TCB pointer from here out.
   */
  ts->thread = (Thread_Control *)_Objects_Get_local_object(
    &_RTEMS_tasks_Information,
    _Objects_Get_index(id)
  );

  /*
   *  Initialize the timer lists that the server will manage.
   */
  _Chain_Initialize_empty( &ts->Interval_watchdogs.Chain );
  _Chain_Initialize_empty( &ts->TOD_watchdogs.Chain );

  /*
   *  Initialize the timers that will be used to control when the
   *  Timer Server wakes up and services the task-based timers.
   */
  _Watchdog_Initialize(
    &ts->Interval_watchdogs.System_watchdog,
    _Thread_Delay_ended,
    id,
    NULL
  );
  _Watchdog_Initialize(
    &ts->TOD_watchdogs.System_watchdog,
    _Thread_Delay_ended,
    id,
    NULL
  );

  /*
   *  Initialize the pointer to the timer schedule method so applications that
   *  do not use the Timer Server do not have to pull it in.
   */
  ts->schedule_operation = _Timer_server_Schedule_operation_method;

  ts->Interval_watchdogs.last_snapshot = _Watchdog_Ticks_since_boot;
  ts->TOD_watchdogs.last_snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch();

  ts->insert_chain = NULL;
  ts->active = false;

  /*
   * The default timer server is now available.
   */
  _Timer_server = ts;

  /*
   *  Start the timer server
   */
  status = rtems_task_start(
    id,
    _Timer_server_Body,
    (rtems_task_argument) ts
  );

  #if defined(RTEMS_DEBUG)
    /*
     *  One would expect a call to rtems_task_delete() here to clean up
     *  but there is actually no way (in normal circumstances) that the
     *  start can fail.  The id and starting address are known to be
     *  be good.  If this service fails, something is weirdly wrong on the
     *  target such as a stray write in an ISR or incorrect memory layout.
     */
    if (status) {
      initialized = false;
    }
  #endif

  return status;
}