Beispiel #1
0
static void test_case_change_priority(
  Thread_Control *executing,
  Scheduler_SMP_Node *node,
  Scheduler_SMP_Node_state start_state,
  Priority_Control prio,
  bool prepend_it,
  Scheduler_SMP_Node_state new_state
)
{
  switch (start_state) {
    case SCHEDULER_SMP_NODE_SCHEDULED:
      _Thread_Change_priority(executing, 1, true);
      break;
    case SCHEDULER_SMP_NODE_READY:
      _Thread_Change_priority(executing, 4, true);
      break;
    default:
      rtems_test_assert(0);
      break;
  }
  rtems_test_assert(node->state == start_state);

  _Thread_Change_priority(executing, prio, prepend_it);
  rtems_test_assert(node->state == new_state);
}
void _Scheduler_CBS_Release_job(
  Thread_Control    *the_thread,
  uint32_t           deadline
)
{
  Priority_Control new_priority;
  Scheduler_CBS_Per_thread *sched_info =
    (Scheduler_CBS_Per_thread *) the_thread->scheduler_info;
  Scheduler_CBS_Server *serv_info =
    (Scheduler_CBS_Server *) sched_info->cbs_server;

  if (deadline) {
    /* Initializing or shifting deadline. */
    if (serv_info)
      new_priority = (_Watchdog_Ticks_since_boot + serv_info->parameters.deadline)
        & ~SCHEDULER_EDF_PRIO_MSB;
    else
      new_priority = (_Watchdog_Ticks_since_boot + deadline)
        & ~SCHEDULER_EDF_PRIO_MSB;
  }
  else {
    /* Switch back to background priority. */
    new_priority = the_thread->Start.initial_priority;
  }

  /* Budget replenishment for the next job. */
  if (serv_info)
    the_thread->cpu_time_budget = serv_info->parameters.budget;

  the_thread->real_priority = new_priority;
  _Thread_Change_priority(the_thread, new_priority, true);
}
Beispiel #3
0
static void test_unblock_op(void)
{
  rtems_status_code sc;
  rtems_id task_id;
  Thread_Control *executing;
  Scheduler_SMP_Node *executing_node;
  Thread_Control *other;
  size_t i;

  task_id = start_task(3);

  _Thread_Disable_dispatch();

  executing = _Thread_Executing;
  executing_node = _Scheduler_SMP_Thread_get_node(executing);

  other = get_thread_by_id(task_id);

  for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
    test_case_unblock_op(
      executing,
      executing_node,
      other,
      states[i]
    );
  }

  _Thread_Change_priority(executing, 1, true);
  rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);

  _Thread_Enable_dispatch();

  sc = rtems_task_delete(task_id);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
}
Beispiel #4
0
void _Scheduler_CBS_Budget_callout(
  Thread_Control *the_thread
)
{
  Priority_Control          new_priority;
  Scheduler_CBS_Per_thread *sched_info;
  Scheduler_CBS_Server_id   server_id;

  /* Put violating task to background until the end of period. */
  new_priority = the_thread->Start.initial_priority;
  if ( the_thread->real_priority != new_priority )
    the_thread->real_priority = new_priority;
  if ( the_thread->current_priority != new_priority )
    _Thread_Change_priority(the_thread, new_priority, true);

  /* Invoke callback function if any. */
  sched_info = (Scheduler_CBS_Per_thread *) the_thread->scheduler_info;
  if ( sched_info->cbs_server->cbs_budget_overrun ) {
    _Scheduler_CBS_Get_server_id(
        sched_info->cbs_server->task_id,
        &server_id
    );
    sched_info->cbs_server->cbs_budget_overrun( server_id );
  }
}
Beispiel #5
0
  static inline CORE_mutex_Status _CORE_mutex_Pop_priority(
    CORE_mutex_Control *mutex,
    Thread_Control *holder
  )
  {
    /*
     *  Check whether the holder release the mutex in LIFO order if not return
     *  error code.
     */
    if ( _Chain_First( holder->lock_mutex ) != &mutex->queue.lock_queue ) {
      mutex->nest_count++;

      return CORE_MUTEX_RELEASE_NOT_ORDER;
    }

    /*
     *  This pops the first node from the list.
     */
    _Chain_Get_first_unprotected( &holder->lock_mutex );

    if ( mutex->queue.priority_before != holder->current_priority )
      _Thread_Change_priority( holder, mutex->queue.priority_before, true );

    return CORE_MUTEX_STATUS_SUCCESSFUL;
  }
Beispiel #6
0
/*
 *  _POSIX_Threads_Sporadic_budget_TSR
 */
void _POSIX_Threads_Sporadic_budget_TSR(
    Objects_Id      id RTEMS_UNUSED,
    void           *argument
)
{
    uint32_t            ticks;
    Thread_Control     *the_thread;
    POSIX_API_Control  *api;

    the_thread = argument;

    api = the_thread->API_Extensions[ THREAD_API_POSIX ];

    /* ticks is guaranteed to be at least one */
    ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_init_budget );

    the_thread->cpu_time_budget = ticks;

    _Thread_Change_priority(
        the_thread,
        _POSIX_Priority_To_core( api->schedparam.sched_priority ),
        NULL,
        _POSIX_Threads_Sporadic_budget_TSR_filter,
        true
    );

    /* ticks is guaranteed to be at least one */
    ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period );

    _Watchdog_Insert_ticks( &api->Sporadic_timer, ticks );
}
Beispiel #7
0
CORE_mutex_Status _CORE_mutex_Initialize(
  CORE_mutex_Control           *the_mutex,
  Thread_Control               *executing,
  const CORE_mutex_Attributes  *the_mutex_attributes,
  bool                          initially_locked
)
{

/* Add this to the RTEMS environment later ?????????
  rtems_assert( initial_lock == CORE_MUTEX_LOCKED ||
                initial_lock == CORE_MUTEX_UNLOCKED );
 */

  the_mutex->Attributes    = *the_mutex_attributes;

  if ( initially_locked ) {
    the_mutex->nest_count = 1;
    the_mutex->holder     = executing;
    if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
         _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
      Priority_Control ceiling = the_mutex->Attributes.priority_ceiling;

      /*
       * The mutex initialization is only protected by the allocator lock in
       * general.  Disable thread dispatching before the priority check to
       * prevent interference with priority inheritance.
       */
      _Thread_Disable_dispatch();

      if ( executing->current_priority < ceiling ) {
        _Thread_Enable_dispatch();
        return CORE_MUTEX_STATUS_CEILING_VIOLATED;
      }

#ifdef __RTEMS_STRICT_ORDER_MUTEX__
       _Chain_Prepend_unprotected( &executing->lock_mutex,
                                   &the_mutex->queue.lock_queue );
       the_mutex->queue.priority_before = executing->current_priority;
#endif

      executing->resource_count++;

      _Thread_Change_priority( executing, ceiling, false );
      _Thread_Enable_dispatch();
    }
  } else {
    the_mutex->nest_count = 0;
    the_mutex->holder     = NULL;
  }

  _Thread_queue_Initialize(
    &the_mutex->Wait_queue,
    _CORE_mutex_Is_fifo( the_mutex_attributes ) ?
      THREAD_QUEUE_DISCIPLINE_FIFO : THREAD_QUEUE_DISCIPLINE_PRIORITY,
    STATES_WAITING_FOR_MUTEX,
    CORE_MUTEX_TIMEOUT
  );

  return CORE_MUTEX_STATUS_SUCCESSFUL;
}
void _CORE_mutex_Seize_interrupt_blocking(
  CORE_mutex_Control  *the_mutex,
  Watchdog_Interval    timeout
)
{
  Thread_Control   *executing;

  executing = _Thread_Executing;
  if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ) {
    if ( _Scheduler_Is_priority_higher_than(
         executing->current_priority,
         the_mutex->holder->current_priority)) {
      _Thread_Change_priority(
        the_mutex->holder,
        executing->current_priority,
        false
      );
    }
  }

  the_mutex->blocked_count++;
  _Thread_queue_Enqueue( &the_mutex->Wait_queue, timeout );

  _Thread_Enable_dispatch();
}
rtems_status_code rtems_task_set_priority(
  rtems_id             id,
  rtems_task_priority  new_priority,
  rtems_task_priority *old_priority_p
)
{
  Thread_Control          *the_thread;
  ISR_lock_Context         lock_context;
  const Scheduler_Control *scheduler;
  Priority_Control         old_priority;
  rtems_status_code        status;

  if ( old_priority_p == NULL ) {
    return RTEMS_INVALID_ADDRESS;
  }

  the_thread = _Thread_Get( id, &lock_context );

  if ( the_thread == NULL ) {
#if defined(RTEMS_MULTIPROCESSING)
    return _RTEMS_tasks_MP_Set_priority( id, new_priority, old_priority_p );
#else
    return RTEMS_INVALID_ID;
#endif
  }

  if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
    RTEMS_tasks_Set_priority_context  context;
    Per_CPU_Control                  *cpu_self;

    cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
    _ISR_lock_ISR_enable( &lock_context );

    context.new_priority = new_priority;
    _Thread_Change_priority(
      the_thread,
      0,
      &context,
      _RTEMS_tasks_Set_priority_filter,
      false
    );

    _Thread_Dispatch_enable( cpu_self );
    scheduler = context.scheduler;
    old_priority = context.old_priority;
    status = context.status;
  } else {
    _Thread_State_acquire_critical( the_thread, &lock_context );
    scheduler = _Scheduler_Get_own( the_thread );
    old_priority = _Thread_Get_priority( the_thread );
    _Thread_State_release( the_thread, &lock_context );
    status = RTEMS_SUCCESSFUL;
  }

  *old_priority_p = _RTEMS_Priority_From_core( scheduler, old_priority );
  return status;
}
Beispiel #10
0
static void test_case_change_priority_op(
  Thread_Control *executing,
  Scheduler_SMP_Node *executing_node,
  Thread_Control *other,
  Scheduler_SMP_Node_state start_state,
  Priority_Control prio,
  bool prepend_it,
  Scheduler_SMP_Node_state new_state
)
{
  Thread_Control *needs_help;

  switch (start_state) {
    case SCHEDULER_SMP_NODE_SCHEDULED:
      _Thread_Change_priority(executing, 1, true);
      break;
    case SCHEDULER_SMP_NODE_READY:
      _Thread_Change_priority(executing, 4, true);
      break;
    default:
      rtems_test_assert(0);
      break;
  }
  rtems_test_assert(executing_node->state == start_state);

  needs_help = change_priority_op(executing, prio, prepend_it);
  rtems_test_assert(executing_node->state == new_state);

  if (start_state != new_state) {
    switch (start_state) {
      case SCHEDULER_SMP_NODE_SCHEDULED:
        rtems_test_assert(needs_help == executing);
        break;
      case SCHEDULER_SMP_NODE_READY:
        rtems_test_assert(needs_help == other);
        break;
      default:
        rtems_test_assert(0);
        break;
    }
  } else {
    rtems_test_assert(needs_help == NULL);
  }
}
Beispiel #11
0
void _Thread_Restore_priority( Thread_Control *the_thread )
{
  _Thread_Change_priority(
    the_thread,
    0,
    NULL,
    _Thread_Restore_priority_filter,
    true
  );
}
Beispiel #12
0
static void test_case_unblock_op(
  Thread_Control *executing,
  Scheduler_SMP_Node *executing_node,
  Thread_Control *other,
  Scheduler_SMP_Node_state new_state
)
{
  Thread_Control *needs_help;

  switch (new_state) {
    case SCHEDULER_SMP_NODE_SCHEDULED:
      _Thread_Change_priority(executing, 2, false);
      rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED);
      break;
    case SCHEDULER_SMP_NODE_READY:
      _Thread_Change_priority(executing, 4, false);
      rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_READY);
      break;
    default:
      rtems_test_assert(0);
      break;
  }

  block_op(executing);
  rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_BLOCKED);

  needs_help = unblock_op(executing);
  rtems_test_assert(executing_node->state == new_state);

  switch (new_state) {
    case SCHEDULER_SMP_NODE_SCHEDULED:
      rtems_test_assert(needs_help == other);
      break;
    case SCHEDULER_SMP_NODE_READY:
      rtems_test_assert(needs_help == executing);
      break;
    default:
      rtems_test_assert(0);
      break;
  }
}
Beispiel #13
0
void _Thread_Raise_priority(
  Thread_Control   *the_thread,
  Priority_Control  new_priority
)
{
  _Thread_Change_priority(
    the_thread,
    new_priority,
    NULL,
    _Thread_Raise_priority_filter,
    false
  );
}
Beispiel #14
0
void _Thread_Inherit_priority(
  Thread_Control *inheritor,
  Thread_Control *ancestor
)
{
  _Thread_Change_priority(
    inheritor,
    PRIORITY_PSEUDO_ISR,
    ancestor,
    _Thread_Inherit_priority_filter,
    false
  );
}
static void _Thread_Raise_real_priority(
  Thread_Control   *the_thread,
  Priority_Control  priority
)
{
  _Thread_Change_priority(
    the_thread,
    priority,
    NULL,
    _Thread_Raise_real_priority_filter,
    false
  );
}
Beispiel #16
0
static void test(void)
{
  rtems_status_code sc;
  rtems_id task_id;
  Thread_Control *executing;
  Scheduler_SMP_Node *node;
  size_t i;
  size_t j;
  size_t k;

  sc = rtems_task_create(
    rtems_build_name('T', 'A', 'S', 'K'),
    3,
    RTEMS_MINIMUM_STACK_SIZE,
    RTEMS_DEFAULT_MODES,
    RTEMS_DEFAULT_ATTRIBUTES,
    &task_id
  );
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);

  sc = rtems_task_start(task_id, task, 0);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);

  _Thread_Disable_dispatch();

  executing = _Thread_Executing;
  node = _Scheduler_SMP_Node_get( executing );

  for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
    for (j = 0; j < RTEMS_ARRAY_SIZE(priorities); ++j) {
      for (k = 0; k < RTEMS_ARRAY_SIZE(prepend_it); ++k) {
        test_case(
          executing,
          node,
          states[i],
          priorities[j],
          prepend_it[k],
          states[j]
        );
      }
    }
  }

  _Thread_Change_priority(executing, 1, true);
  rtems_test_assert(node->state == SCHEDULER_SMP_NODE_SCHEDULED);

  _Thread_Enable_dispatch();

  sc = rtems_task_delete(task_id);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
}
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;
}
Beispiel #18
0
/*
 *  _POSIX_Threads_Sporadic_budget_TSR
 */
void _POSIX_Threads_Sporadic_budget_TSR(
  Objects_Id      id __attribute__((unused)),
  void           *argument
)
{
  uint32_t            ticks;
  uint32_t            new_priority;
  Thread_Control     *the_thread;
  POSIX_API_Control  *api;

  the_thread = argument;

  api = the_thread->API_Extensions[ THREAD_API_POSIX ];

  /* ticks is guaranteed to be at least one */
  ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_init_budget );

  the_thread->cpu_time_budget = ticks;

  new_priority = _POSIX_Priority_To_core( api->schedparam.sched_priority );
  the_thread->real_priority = new_priority;

  /*
   *  If holding a resource, then do not change it.
   */
  #if 0
    printk( "TSR %d %d %d\n", the_thread->resource_count,
        the_thread->current_priority, new_priority );
  #endif
  if ( the_thread->resource_count == 0 ) {
    /*
     *  If this would make them less important, then do not change it.
     */
    if ( the_thread->current_priority > new_priority ) {
      _Thread_Change_priority( the_thread, new_priority, true );
      #if 0
        printk( "raise priority\n" );
      #endif
    }
  }

  /* ticks is guaranteed to be at least one */
  ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period );

  _Watchdog_Insert_ticks( &api->Sporadic_timer, ticks );
}
Beispiel #19
0
void _Scheduler_EDF_Release_job(
  Thread_Control    *the_thread,
  uint32_t           deadline
)
{
  Priority_Control new_priority;

  if (deadline) {
    /* Initializing or shifting deadline. */
    new_priority = (_Watchdog_Ticks_since_boot + deadline)
                   & ~SCHEDULER_EDF_PRIO_MSB;
  }
  else {
    /* Switch back to background priority. */
    new_priority = the_thread->Start.initial_priority;
  }

  the_thread->real_priority = new_priority;
  _Thread_Change_priority(the_thread, new_priority, true);
}
ER chg_pri(
  ID  tskid,
  PRI tskpri
)
{
  register Thread_Control *the_thread;
  Objects_Locations        location;
  Priority_Control         new_priority;

  the_thread = _ITRON_Task_Get( tskid, &location );
  switch ( location ) {
#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:
#endif
    case OBJECTS_ERROR:
      return _ITRON_Task_Clarify_get_id_error( tskid );

    case OBJECTS_LOCAL:
      if (_States_Is_dormant( the_thread->current_state ))
        _ITRON_return_errorno( E_OBJ );

      if (( tskpri <= 0 ) || ( tskpri >= PRIORITY_MAXIMUM-1 ))
        _ITRON_return_errorno( E_PAR );

      new_priority = _ITRON_Task_Priority_to_Core( tskpri );
      the_thread->real_priority = new_priority;

      /*
       * The priority should not be changed until later if priority
       * inheratance has occured.
       */

      if ( the_thread->resource_count == 0 ||
           the_thread->current_priority > new_priority )
        _Thread_Change_priority( the_thread, new_priority, false );

      break;
  }

  _ITRON_return_errorno( E_OK );
}
Beispiel #21
0
static void test_change_priority(void)
{
  rtems_status_code sc;
  rtems_id task_id;
  Thread_Control *executing;
  Scheduler_SMP_Node *node;
  size_t i;
  size_t j;
  size_t k;

  task_id = start_task(3);

  _Thread_Disable_dispatch();

  executing = _Thread_Executing;
  node = _Scheduler_SMP_Thread_get_node( executing );

  for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) {
    for (j = 0; j < RTEMS_ARRAY_SIZE(priorities); ++j) {
      for (k = 0; k < RTEMS_ARRAY_SIZE(prepend_it); ++k) {
        test_case_change_priority(
          executing,
          node,
          states[i],
          priorities[j],
          prepend_it[k],
          states[j]
        );
      }
    }
  }

  _Thread_Change_priority(executing, 1, true);
  rtems_test_assert(node->state == SCHEDULER_SMP_NODE_SCHEDULED);

  _Thread_Enable_dispatch();

  sc = rtems_task_delete(task_id);
  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
}
Beispiel #22
0
/*
 *  _POSIX_Threads_Sporadic_budget_callout
 */
void _POSIX_Threads_Sporadic_budget_callout(
  Thread_Control *the_thread
)
{
  POSIX_API_Control *api;
  uint32_t           new_priority;

  api = the_thread->API_Extensions[ THREAD_API_POSIX ];

  /*
   *  This will prevent the thread from consuming its entire "budget"
   *  while at low priority.
   */
  the_thread->cpu_time_budget = 0xFFFFFFFF; /* XXX should be based on MAX_U32 */

  new_priority = _POSIX_Priority_To_core(api->schedparam.sched_ss_low_priority);
  the_thread->real_priority = new_priority;

  /*
   *  If holding a resource, then do not change it.
   */
  #if 0
    printk( "callout %d %d %d\n", the_thread->resource_count,
	the_thread->current_priority, new_priority );
  #endif
  if ( the_thread->resource_count == 0 ) {
    /*
     *  Make sure we are actually lowering it. If they have lowered it
     *  to logically lower than sched_ss_low_priority, then we do not want to
     *  change it.
     */
    if ( the_thread->current_priority < new_priority ) {
      _Thread_Change_priority( the_thread, new_priority, true );
      #if 0
        printk( "lower priority\n" );
      #endif
    }
  }
}
Beispiel #23
0
/*
 *  _POSIX_Threads_Sporadic_budget_callout
 */
void _POSIX_Threads_Sporadic_budget_callout(
    Thread_Control *the_thread
)
{
    POSIX_API_Control *api;

    api = the_thread->API_Extensions[ THREAD_API_POSIX ];

    /*
     *  This will prevent the thread from consuming its entire "budget"
     *  while at low priority.
     */
    the_thread->cpu_time_budget = UINT32_MAX;

    _Thread_Change_priority(
        the_thread,
        _POSIX_Priority_To_core( api->schedparam.sched_ss_low_priority ),
        NULL,
        _POSIX_Threads_Sporadic_budget_callout_filter,
        true
    );
}
Beispiel #24
0
static void _Thread_Request_life_change(
  Thread_Control    *the_thread,
  Thread_Control    *executing,
  Priority_Control   priority,
  Thread_Life_state  additional_life_state
)
{
  Thread_Life_state previous_life_state;
  Per_CPU_Control *cpu;
  ISR_Level level;
  const Scheduler_Control *scheduler;

  cpu = _Thread_Action_ISR_disable_and_acquire( the_thread, &level );
  previous_life_state = the_thread->Life.state;
  the_thread->Life.state = previous_life_state | additional_life_state;
  _Thread_Action_release_and_ISR_enable( cpu, level );

  scheduler = _Scheduler_Get( the_thread );
  if ( the_thread == executing ) {
    Priority_Control unused;

    _Thread_Set_priority( the_thread, priority, &unused, true );
    _Thread_Start_life_change_for_executing( executing );
  } else if ( previous_life_state == THREAD_LIFE_NORMAL ) {
    _Thread_Start_life_change( the_thread, scheduler, priority );
  } else {
    _Thread_Clear_state( the_thread, STATES_SUSPENDED );

    if ( _Thread_Is_life_terminating( additional_life_state ) ) {
      _Thread_Change_priority(
        the_thread,
        priority,
        NULL,
        _Thread_Raise_real_priority_filter,
        false
      );
    }
  }
}
Beispiel #25
0
static void _Thread_Start_life_change(
  Thread_Control          *the_thread,
  const Scheduler_Control *scheduler,
  Priority_Control         priority
)
{
  the_thread->is_preemptible   = the_thread->Start.is_preemptible;
  the_thread->budget_algorithm = the_thread->Start.budget_algorithm;
  the_thread->budget_callout   = the_thread->Start.budget_callout;

  _Thread_Set_state( the_thread, STATES_RESTARTING );
  _Thread_queue_Extract_with_proxy( the_thread );
  _Watchdog_Remove_ticks( &the_thread->Timer );
  _Thread_Change_priority(
    the_thread,
    priority,
    NULL,
    _Thread_Raise_real_priority_filter,
    false
  );
  _Thread_Add_life_change_action( the_thread );
  _Thread_Ready( the_thread );
}
Beispiel #26
0
CORE_mutex_Status _CORE_mutex_Surrender(
  CORE_mutex_Control                *the_mutex,
#if defined(RTEMS_MULTIPROCESSING)
  Objects_Id                         id,
  CORE_mutex_API_mp_support_callout  api_mutex_mp_support
#else
  Objects_Id                         id __attribute__((unused)),
  CORE_mutex_API_mp_support_callout  api_mutex_mp_support __attribute__((unused))
#endif
)
{
  Thread_Control *the_thread;
  Thread_Control *holder;

  holder = the_mutex->holder;

  /*
   *  The following code allows a thread (or ISR) other than the thread
   *  which acquired the mutex to release that mutex.  This is only
   *  allowed when the mutex in quetion is FIFO or simple Priority
   *  discipline.  But Priority Ceiling or Priority Inheritance mutexes
   *  must be released by the thread which acquired them.
   */

  if ( the_mutex->Attributes.only_owner_release ) {
    if ( !_Thread_Is_executing( holder ) )
      return CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE;
  }

  /* XXX already unlocked -- not right status */

  if ( !the_mutex->nest_count )
    return CORE_MUTEX_STATUS_SUCCESSFUL;

  the_mutex->nest_count--;

  if ( the_mutex->nest_count != 0 ) {
    /*
     *  All error checking is on the locking side, so if the lock was
     *  allowed to acquired multiple times, then we should just deal with
     *  that.  The RTEMS_DEBUG is just a validation.
     */
    #if defined(RTEMS_DEBUG)
      switch ( the_mutex->Attributes.lock_nesting_behavior ) {
        case CORE_MUTEX_NESTING_ACQUIRES:
          return CORE_MUTEX_STATUS_SUCCESSFUL;
        #if defined(RTEMS_POSIX_API)
          case CORE_MUTEX_NESTING_IS_ERROR:
            /* should never occur */
            return CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
        #endif
        case CORE_MUTEX_NESTING_BLOCKS:
          /* Currently no API exercises this behavior. */
          break;
      }
    #else
      /* must be CORE_MUTEX_NESTING_ACQUIRES or we wouldn't be here */
      return CORE_MUTEX_STATUS_SUCCESSFUL;
    #endif
  }

  /*
   *  Formally release the mutex before possibly transferring it to a
   *  blocked thread.
   */
  if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
       _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
    CORE_mutex_Status pop_status =
      _CORE_mutex_Pop_priority( the_mutex, holder );

    if ( pop_status != CORE_MUTEX_STATUS_SUCCESSFUL )
      return pop_status;

    holder->resource_count--;

    /*
     *  Whether or not someone is waiting for the mutex, an
     *  inherited priority must be lowered if this is the last
     *  mutex (i.e. resource) this task has.
     */
    if ( holder->resource_count == 0 &&
         holder->real_priority != holder->current_priority ) {
      _Thread_Change_priority( holder, holder->real_priority, true );
    }
  }
  the_mutex->holder    = NULL;
  the_mutex->holder_id = 0;

  /*
   *  Now we check if another thread was waiting for this mutex.  If so,
   *  transfer the mutex to that thread.
   */
  if ( ( the_thread = _Thread_queue_Dequeue( &the_mutex->Wait_queue ) ) ) {

#if defined(RTEMS_MULTIPROCESSING)
    if ( !_Objects_Is_local_id( the_thread->Object.id ) ) {

      the_mutex->holder     = NULL;
      the_mutex->holder_id  = the_thread->Object.id;
      the_mutex->nest_count = 1;

      ( *api_mutex_mp_support)( the_thread, id );

    } else
#endif
    {

      the_mutex->holder     = the_thread;
      the_mutex->holder_id  = the_thread->Object.id;
      the_mutex->nest_count = 1;

      switch ( the_mutex->Attributes.discipline ) {
        case CORE_MUTEX_DISCIPLINES_FIFO:
        case CORE_MUTEX_DISCIPLINES_PRIORITY:
          break;
        case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
          _CORE_mutex_Push_priority( the_mutex, the_thread );
          the_thread->resource_count++;
          break;
        case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
          _CORE_mutex_Push_priority( the_mutex, the_thread );
          the_thread->resource_count++;
          if (the_mutex->Attributes.priority_ceiling <
              the_thread->current_priority){
              _Thread_Change_priority(
                the_thread,
                the_mutex->Attributes.priority_ceiling,
                false
              );
          }
          break;
      }
    }
  } else
    the_mutex->lock = CORE_MUTEX_UNLOCKED;

  return CORE_MUTEX_STATUS_SUCCESSFUL;
}
Beispiel #27
0
void _Scheduler_CBS_Unblock(
  Scheduler_Control *scheduler,
  Thread_Control    *the_thread
)
{
  Scheduler_CBS_Per_thread *sched_info;
  Scheduler_CBS_Server *serv_info;
  Priority_Control new_priority;

  _Scheduler_EDF_Enqueue( scheduler, the_thread );
  /* TODO: flash critical section? */

  sched_info = (Scheduler_CBS_Per_thread *) the_thread->scheduler_info;
  serv_info = (Scheduler_CBS_Server *) sched_info->cbs_server;

  /*
   * Late unblock rule for deadline-driven tasks. The remaining time to
   * deadline must be sufficient to serve the remaining computation time
   * without increased utilization of this task. It might cause a deadline
   * miss of another task.
   */
  if (serv_info) {
    time_t deadline = serv_info->parameters.deadline;
    time_t budget = serv_info->parameters.budget;
    time_t deadline_left = the_thread->cpu_time_budget;
    time_t budget_left = the_thread->real_priority -
                           _Watchdog_Ticks_since_boot;

    if ( deadline*budget_left > budget*deadline_left ) {
      /* Put late unblocked task to background until the end of period. */
      new_priority = the_thread->Start.initial_priority;
      if ( the_thread->real_priority != new_priority )
        the_thread->real_priority = new_priority;
      if ( the_thread->current_priority != new_priority )
        _Thread_Change_priority(the_thread, new_priority, true);
    }
  }

  /*
   *  If the thread that was unblocked is more important than the heir,
   *  then we have a new heir.  This may or may not result in a
   *  context switch.
   *
   *  Normal case:
   *    If the current thread is preemptible, then we need to do
   *    a context switch.
   *  Pseudo-ISR case:
   *    Even if the thread isn't preemptible, if the new heir is
   *    a pseudo-ISR system task, we need to do a context switch.
   */
  if (
    _Scheduler_Is_priority_higher_than(
       scheduler,
       the_thread->current_priority,
       _Thread_Heir->current_priority
    )
  ) {
    _Thread_Heir = the_thread;
    if ( _Thread_Executing->is_preemptible ||
         the_thread->current_priority == 0 )
      _Thread_Dispatch_necessary = true;
  }
}
Beispiel #28
0
int pthread_setschedparam(
  pthread_t           thread,
  int                 policy,
  struct sched_param *param
)
{
  register Thread_Control             *the_thread;
  POSIX_API_Control                   *api;
  Thread_CPU_budget_algorithms         budget_algorithm;
  Thread_CPU_budget_algorithm_callout  budget_callout;
  Objects_Locations                    location;
  int                                  rc;

  /*
   *  Check all the parameters
   */
  if ( !param )
    return EINVAL;

  rc = _POSIX_Thread_Translate_sched_param(
    policy,
    param,
    &budget_algorithm,
    &budget_callout
  );
  if ( rc )
    return rc;

  /*
   *  Actually change the scheduling policy and parameters
   */
  the_thread = _Thread_Get( thread, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:
      api = the_thread->API_Extensions[ THREAD_API_POSIX ];

      if ( api->schedpolicy == SCHED_SPORADIC )
        (void) _Watchdog_Remove( &api->Sporadic_timer );

      api->schedpolicy = policy;
      api->schedparam  = *param;
      the_thread->budget_algorithm = budget_algorithm;
      the_thread->budget_callout   = budget_callout;

      switch ( api->schedpolicy ) {
        case SCHED_OTHER:
        case SCHED_FIFO:
        case SCHED_RR:
          the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice;

          the_thread->real_priority =
            _POSIX_Priority_To_core( api->schedparam.sched_priority );

          _Thread_Change_priority(
             the_thread,
             the_thread->real_priority,
             true
          );
          break;

        case SCHED_SPORADIC:
          api->ss_high_priority = api->schedparam.sched_priority;
          _Watchdog_Remove( &api->Sporadic_timer );
          _POSIX_Threads_Sporadic_budget_TSR( 0, the_thread );
          break;
      }

      _Thread_Enable_dispatch();
      return 0;

#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:
#endif
    case OBJECTS_ERROR:
      break;
  }

  return ESRCH;
}
Beispiel #29
0
static void test_case_yield_op(
  Thread_Control *executing,
  Scheduler_SMP_Node *executing_node,
  Thread_Control *other,
  Scheduler_SMP_Node_state start_state,
  Scheduler_SMP_Node_state new_state
)
{
  Thread_Control *needs_help;

  _Thread_Change_priority(executing, 4, false);
  _Thread_Change_priority(other, 4, false);

  switch (start_state) {
    case SCHEDULER_SMP_NODE_SCHEDULED:
      switch (new_state) {
        case SCHEDULER_SMP_NODE_SCHEDULED:
          _Thread_Change_priority(executing, 2, false);
          _Thread_Change_priority(other, 3, false);
          break;
        case SCHEDULER_SMP_NODE_READY:
          _Thread_Change_priority(executing, 2, false);
          _Thread_Change_priority(other, 2, false);
          break;
        default:
          rtems_test_assert(0);
          break;
      }
      break;
    case SCHEDULER_SMP_NODE_READY:
      switch (new_state) {
        case SCHEDULER_SMP_NODE_SCHEDULED:
          rtems_test_assert(0);
          break;
        case SCHEDULER_SMP_NODE_READY:
          _Thread_Change_priority(executing, 3, false);
          _Thread_Change_priority(other, 2, false);
          break;
        default:
          rtems_test_assert(0);
          break;
      }
      break;
    default:
      rtems_test_assert(0);
      break;
  }
  rtems_test_assert(executing_node->state == start_state);

  needs_help = yield_op(executing);
  rtems_test_assert(executing_node->state == new_state);

  if (start_state != new_state) {
    switch (start_state) {
      case SCHEDULER_SMP_NODE_SCHEDULED:
        rtems_test_assert(needs_help == executing);
        break;
      case SCHEDULER_SMP_NODE_READY:
        rtems_test_assert(needs_help == other);
        break;
      default:
        rtems_test_assert(0);
        break;
    }
  } else {
    rtems_test_assert(needs_help == NULL);
  }
}