ER rsm_tsk(
  ID tskid
)
{
  register Thread_Control *the_thread;
  Objects_Locations        location;

  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 ( _Thread_Is_executing( the_thread ) )
        _ITRON_return_errorno( E_OBJ );

      if ( _States_Is_dormant( the_thread->current_state ))
        _ITRON_return_errorno( E_OBJ );

      if ( ! _States_Is_suspended(the_thread->current_state) )
        _ITRON_return_errorno( E_OBJ );

      _Thread_Resume( the_thread, false );
      break;
  }

  _ITRON_return_errorno( E_OK );
}
void _Thread_queue_Process_timeout(
  Thread_Control *the_thread
)
{
  Thread_queue_Control *the_thread_queue = the_thread->Wait.queue;

  /*
   *  If the_thread_queue is not synchronized, then it is either
   *  "nothing happened", "timeout", or "satisfied".   If the_thread
   *  is the executing thread, then it is in the process of blocking
   *  and it is the thread which is responsible for the synchronization
   *  process.
   *
   *  If it is not satisfied, then it is "nothing happened" and
   *  this is the "timeout" transition.  After a request is satisfied,
   *  a timeout is not allowed to occur.
   */

  if ( the_thread_queue->sync_state != THREAD_BLOCKING_OPERATION_SYNCHRONIZED &&
       _Thread_Is_executing( the_thread ) ) {
    if ( the_thread_queue->sync_state != THREAD_BLOCKING_OPERATION_SATISFIED ) {
      the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
      the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_TIMEOUT;
    }
  } else {
    the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
    _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
  }
}
Exemple #3
0
rtems_status_code rtems_rate_monotonic_cancel(
    rtems_id id
)
{
    Rate_monotonic_Control *the_period;
    Objects_Locations       location;

    the_period = _Rate_monotonic_Get( id, &location );
    switch ( location ) {

    case OBJECTS_LOCAL:
        if ( !_Thread_Is_executing( the_period->owner ) ) {
            _Thread_Enable_dispatch();
            return RTEMS_NOT_OWNER_OF_RESOURCE;
        }
        (void) _Watchdog_Remove( &the_period->Timer );
        the_period->state = RATE_MONOTONIC_INACTIVE;
        _Scheduler_Release_job(the_period->owner, 0);
        _Thread_Enable_dispatch();
        return RTEMS_SUCCESSFUL;

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

    return RTEMS_INVALID_ID;
}
Exemple #4
0
bool _Thread_Restart(
  Thread_Control            *the_thread,
  void                      *pointer_argument,
  Thread_Entry_numeric_type  numeric_argument
)
{
  if ( !_States_Is_dormant( the_thread->current_state ) ) {

    _Thread_Set_transient( the_thread );

    _Thread_Reset( the_thread, pointer_argument, numeric_argument );

    _Thread_Load_environment( the_thread );

    _Thread_Ready( the_thread );

    _User_extensions_Thread_restart( the_thread );

    if ( _Thread_Is_executing ( the_thread ) )
      _Thread_Restart_self();

    return true;
  }

  return false;
}
int pthread_kill(
  pthread_t   thread,
  int         sig
)
{
  POSIX_API_Control  *api;
  Thread_Control     *the_thread;
  Objects_Locations  location;

  if ( !sig )
    rtems_set_errno_and_return_minus_one( EINVAL );

  if ( !is_valid_signo(sig) )
    rtems_set_errno_and_return_minus_one( EINVAL );

/* commented out when posix timers added
  if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO )
    rtems_set_errno_and_return_minus_one( ENOSYS );
*/

  the_thread = _POSIX_Threads_Get( thread, &location );
  switch ( location ) {
    case OBJECTS_ERROR:
    case OBJECTS_REMOTE:
      rtems_set_errno_and_return_minus_one( ESRCH );
    case OBJECTS_LOCAL:
      /*
       *  If sig == 0 then just validate arguments
       */

      api = the_thread->API_Extensions[ THREAD_API_POSIX ];

      if ( sig ) {

        if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) {
          _Thread_Enable_dispatch();
          return 0;
        }

        /* XXX critical section */

        api->signals_pending |= signo_to_mask( sig );

        (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL );

        the_thread->do_post_task_switch_extension = TRUE;

        if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) )
          _ISR_Signals_to_thread_executing = TRUE;
      }
      _Thread_Enable_dispatch();
      return 0;
  }

  return POSIX_BOTTOM_REACHED();
}
Exemple #6
0
int pthread_kill(
  pthread_t   thread,
  int         sig
)
{
  POSIX_API_Control  *api;
  Thread_Control     *the_thread;
  Objects_Locations  location;

  if ( !sig )
    rtems_set_errno_and_return_minus_one( EINVAL );

  if ( !is_valid_signo(sig) )
    rtems_set_errno_and_return_minus_one( EINVAL );

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

    case OBJECTS_LOCAL:
      /*
       *  If sig == 0 then just validate arguments
       */

      api = the_thread->API_Extensions[ THREAD_API_POSIX ];

      if ( sig ) {

        if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) {
          _Thread_Enable_dispatch();
          return 0;
        }

        /* XXX critical section */

        api->signals_pending |= signo_to_mask( sig );

        (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL );

        the_thread->do_post_task_switch_extension = true;

        if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) )
          _ISR_Signals_to_thread_executing = true;
      }
      _Thread_Enable_dispatch();
      return 0;

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

  rtems_set_errno_and_return_minus_one( ESRCH );
}
void _Scheduler_simple_Block(
  Thread_Control   *the_thread
)
{
  _Scheduler_simple_Extract(the_thread);

  if ( _Thread_Is_heir( the_thread ) )
    _Scheduler_simple_Schedule();

  if ( _Thread_Is_executing( the_thread ) )
    _Thread_Dispatch_necessary = true;
}
Exemple #8
0
void _Event_Timeout(
  Objects_Id  id,
  void       *ignored
)
{
  Thread_Control    *the_thread;
  Objects_Locations  location;
  ISR_Level          level;

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

    case OBJECTS_LOCAL:

      /*
       *  If the event manager is not synchronized, then it is either
       *  "nothing happened", "timeout", or "satisfied".   If the_thread
       *  is the executing thread, then it is in the process of blocking
       *  and it is the thread which is responsible for the synchronization
       *  process.
       *
       *  If it is not satisfied, then it is "nothing happened" and
       *  this is the "timeout" transition.  After a request is satisfied,
       *  a timeout is not allowed to occur.
       */
      _ISR_Disable( level );
        #if defined(RTEMS_DEBUG)
          if ( !the_thread->Wait.count ) {  /* verify thread is waiting */
            _Thread_Unnest_dispatch();
            _ISR_Enable( level );
            return;
          }
        #endif

        the_thread->Wait.count = 0;
        if ( _Thread_Is_executing( the_thread ) ) {
          if ( _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )
            _Event_Sync_state = THREAD_BLOCKING_OPERATION_TIMEOUT;
        }

        the_thread->Wait.return_code = RTEMS_TIMEOUT;
      _ISR_Enable( level );
      _Thread_Unblock( the_thread );
      _Thread_Unnest_dispatch();
      break;

#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:  /* impossible */
#endif
    case OBJECTS_ERROR:
      break;
  }
}
void _Scheduler_EDF_Block(
  Thread_Control    *the_thread
)
{
  _Scheduler_EDF_Extract( the_thread );

  /* TODO: flash critical section? */

  if ( _Thread_Is_heir( the_thread ) )
    _Scheduler_EDF_Schedule();

  if ( _Thread_Is_executing( the_thread ) )
    _Thread_Dispatch_necessary = true;
}
Exemple #10
0
rtems_status_code rtems_signal_send(
  rtems_id          id,
  rtems_signal_set  signal_set
)
{
  register Thread_Control *the_thread;
  Objects_Locations        location;
  RTEMS_API_Control       *api;
  ASR_Information         *asr;

  if ( !signal_set )
    return RTEMS_INVALID_NUMBER;

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

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

      if ( ! _ASR_Is_null_handler( asr->handler ) ) {
        if ( asr->is_enabled ) {
          _ASR_Post_signals( signal_set, &asr->signals_posted );

          if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) )
            _Thread_Dispatch_necessary = true;
        } else {
          _ASR_Post_signals( signal_set, &asr->signals_pending );
        }
        _Thread_Enable_dispatch();
        return RTEMS_SUCCESSFUL;
      }
      _Thread_Enable_dispatch();
      return RTEMS_NOT_DEFINED;

#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:
      return _Signal_MP_Send_request_packet(
        SIGNAL_MP_SEND_REQUEST,
        id,
        signal_set
      );
#endif

    case OBJECTS_ERROR:
      break;
  }

  return RTEMS_INVALID_ID;
}
void _Scheduler_priority_Block(
  Thread_Control   *the_thread
)
{
  _Scheduler_priority_Ready_queue_extract( the_thread );

  /* TODO: flash critical section? */

  if ( _Thread_Is_heir( the_thread ) )
     _Scheduler_priority_Schedule_body();

  if ( _Thread_Is_executing( the_thread ) )
    _Thread_Dispatch_necessary = true;

}
void _RTEMS_Tasks_Invoke_task_variable_dtor(
  Thread_Control        *the_thread,
  rtems_task_variable_t *tvp
)
{
  void (*dtor)(void *);
  void *value;

  dtor = tvp->dtor;
  if (_Thread_Is_executing(the_thread)) {
    value = *tvp->ptr;
    *tvp->ptr = tvp->gval;
  } else {
    value = tvp->tval;
  }

  if ( dtor )
    (*dtor)(value);

  _Workspace_Free(tvp);
}
void _Thread_Ready(
  Thread_Control *the_thread
)
{
  ISR_Level              level;
  Thread_Control *heir;

  _ISR_Disable( level );

  the_thread->current_state = STATES_READY;

  _Priority_Add_to_bit_map( &the_thread->Priority_map );

  _Chain_Append_unprotected( the_thread->ready, &the_thread->Object.Node );

  _ISR_Flash( level );

 _Thread_Calculate_heir();
/*  Priority_Bit_map_control minor;
  Priority_Bit_map_control major;

  _Bitfield_Find_first_bit( _Priority_Major_bit_map, major );
  _Bitfield_Find_first_bit( _Priority_Bit_map[major], minor );
  Priority_Control My_Pri=(major<< 4) +minor ;
//  My_Pri=My_Pri+0x100;
  Chain_Control *xx;
  *xx=_Thread_Ready_chain[ My_Pri ];

  _Thread_Heir=(Thread_Control *)(xx->first);
 
//  _Thread_Heir = (Thread_Control *)_Thread_Ready_chain[ My_Pri ].first;
*/

  heir = _Thread_Heir;

  if ( !_Thread_Is_executing( heir ) && _Thread_Executing->is_preemptible )
    _Context_Switch_necessary = true;

  _ISR_Enable( level );
}
void _Thread_Suspend(
  Thread_Control   *the_thread
)
{
  ISR_Level      level;
  Chain_Control *ready;

  ready = the_thread->ready;
  _ISR_Disable( level );
  #if defined(RTEMS_ITRON_API)
    the_thread->suspend_count++;
  #endif
  if ( !_States_Is_ready( the_thread->current_state ) ) {
    the_thread->current_state =
       _States_Set( STATES_SUSPENDED, the_thread->current_state );
    _ISR_Enable( level );
    return;
  }

  the_thread->current_state = STATES_SUSPENDED;

  if ( _Chain_Has_only_one_node( ready ) ) {

    _Chain_Initialize_empty( ready );
    _Priority_Remove_from_bit_map( &the_thread->Priority_map );

  } else
    _Chain_Extract_unprotected( &the_thread->Object.Node );

  _ISR_Flash( level );

  if ( _Thread_Is_heir( the_thread ) )
     _Thread_Calculate_heir();

  if ( _Thread_Is_executing( the_thread ) )
    _Context_Switch_necessary = true;

  _ISR_Enable( level );
}
void _Thread_Set_state(
  Thread_Control *the_thread,
  States_Control  state
)
{
  ISR_Level      level;
  Chain_Control *ready;

  ready = the_thread->ready;
  _ISR_Disable( level );
  if ( !_States_Is_ready( the_thread->current_state ) ) {
    the_thread->current_state =
       _States_Set( state, the_thread->current_state );
    _ISR_Enable( level );
    return;
  }

  the_thread->current_state = state;

  if ( _Chain_Has_only_one_node( ready ) ) {

    _Chain_Initialize_empty( ready );
    _Priority_Remove_from_bit_map( &the_thread->Priority_map );

  } else
    _Chain_Extract_unprotected( &the_thread->Object.Node );

  _ISR_Flash( level );

  if ( _Thread_Is_heir( the_thread ) )
     _Thread_Calculate_heir();

  if ( _Thread_Is_executing( the_thread ) )
    _Context_Switch_necessary = TRUE;

  _ISR_Enable( level );
}
rtems_status_code rtems_rate_monotonic_period(
  rtems_id       id,
  rtems_interval length
)
{
  Rate_monotonic_Control              *the_period;
  Objects_Locations                    location;
  rtems_status_code                    return_value;
  rtems_rate_monotonic_period_states   local_state;
  ISR_Level                            level;

  the_period = _Rate_monotonic_Get( id, &location );

  switch ( location ) {
    case OBJECTS_LOCAL:
      if ( !_Thread_Is_executing( the_period->owner ) ) {
        _Thread_Enable_dispatch();
        return RTEMS_NOT_OWNER_OF_RESOURCE;
      }

      if ( length == RTEMS_PERIOD_STATUS ) {
        switch ( the_period->state ) {
          case RATE_MONOTONIC_INACTIVE:
            return_value = RTEMS_NOT_DEFINED;
            break;
          case RATE_MONOTONIC_EXPIRED:
          case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
            return_value = RTEMS_TIMEOUT;
            break;
          case RATE_MONOTONIC_ACTIVE:
          default:              /* unreached -- only to remove warnings */
            return_value = RTEMS_SUCCESSFUL;
            break;
        }
        _Thread_Enable_dispatch();
        return( return_value );
      }

      _ISR_Disable( level );
      if ( the_period->state == RATE_MONOTONIC_INACTIVE ) {
        _ISR_Enable( level );

        the_period->next_length = length;

        /*
         *  Baseline statistics information for the beginning of a period.
         */
        _Rate_monotonic_Initiate_statistics( the_period );

        the_period->state = RATE_MONOTONIC_ACTIVE;
        _Watchdog_Initialize(
          &the_period->Timer,
          _Rate_monotonic_Timeout,
          id,
          NULL
        );

        _Watchdog_Insert_ticks( &the_period->Timer, length );
        _Thread_Enable_dispatch();
        return RTEMS_SUCCESSFUL;
      }

      if ( the_period->state == RATE_MONOTONIC_ACTIVE ) {
        /*
         *  Update statistics from the concluding period.
         */
        _Rate_monotonic_Update_statistics( the_period );

        /*
         *  This tells the _Rate_monotonic_Timeout that this task is
         *  in the process of blocking on the period and that we
         *  may be changing the length of the next period.
         */
        the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING;
        the_period->next_length = length;

        _ISR_Enable( level );

        _Thread_Executing->Wait.id = the_period->Object.id;
        _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );

        /*
         *  Did the watchdog timer expire while we were actually blocking
         *  on it?
         */
        _ISR_Disable( level );
          local_state = the_period->state;
          the_period->state = RATE_MONOTONIC_ACTIVE;
        _ISR_Enable( level );

        /*
         *  If it did, then we want to unblock ourself and continue as
         *  if nothing happen.  The period was reset in the timeout routine.
         */
        if ( local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING )
          _Thread_Clear_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );

        _Thread_Enable_dispatch();
        return RTEMS_SUCCESSFUL;
      }

      if ( the_period->state == RATE_MONOTONIC_EXPIRED ) {
        /*
         *  Update statistics from the concluding period
         */
        _Rate_monotonic_Update_statistics( the_period );

        _ISR_Enable( level );

        the_period->state = RATE_MONOTONIC_ACTIVE;
        the_period->next_length = length;

        _Watchdog_Insert_ticks( &the_period->Timer, length );
        _Scheduler_Release_job(the_period->owner, the_period->next_length);
        _Thread_Enable_dispatch();
        return RTEMS_TIMEOUT;
      }

      /*
       *  These should never happen so just return invalid Id.
       *    - RATE_MONOTONIC_OWNER_IS_BLOCKING:
       *    - RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
       */
#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:            /* should never return this */
#endif
    case OBJECTS_ERROR:
      break;
  }

  return RTEMS_INVALID_ID;
}
Exemple #17
0
/* XXX this routine could probably be cleaned up */
bool _POSIX_signals_Unblock_thread(
  Thread_Control  *the_thread,
  int              signo,
  siginfo_t       *info
)
{
  POSIX_API_Control  *api;
  sigset_t            mask;
  siginfo_t          *the_info = NULL;

  api = the_thread->API_Extensions[ THREAD_API_POSIX ];

  mask = signo_to_mask( signo );

  /*
   *  Is the thread is specifically waiting for a signal?
   */

  if ( _States_Is_interruptible_signal( the_thread->current_state ) ) {

    if ( (the_thread->Wait.option & mask) || (~api->signals_blocked & mask) ) {
      the_thread->Wait.return_code = EINTR;

      the_info = (siginfo_t *) the_thread->Wait.return_argument;

      if ( !info ) {
        the_info->si_signo = signo;
        the_info->si_code = SI_USER;
        the_info->si_value.sival_int = 0;
      } else {
        *the_info = *info;
      }

      _Thread_queue_Extract_with_proxy( the_thread );
      return true;
    }

    /*
     *  This should only be reached via pthread_kill().
     */

    return false;
  }

  /*
   *  Thread is not waiting due to a sigwait.
   */
  if ( ~api->signals_blocked & mask ) {

    /*
     *  The thread is interested in this signal.  We are going
     *  to post it.  We have a few broad cases:
     *    + If it is blocked on an interruptible signal, THEN
     *        we unblock the thread.
     *    + If it is in the ready state AND
     *      we are sending from an ISR AND
     *      it is the interrupted thread AND
     *      it is not blocked, THEN
     *        we need to dispatch at the end of this ISR.
     *    + Any other combination, do nothing.
     */

    the_thread->do_post_task_switch_extension = true;

    if ( _States_Is_interruptible_by_signal( the_thread->current_state ) ) {
      the_thread->Wait.return_code = EINTR;
      /*
       *  In pthread_cond_wait, a thread will be blocking on a thread
       *  queue, but is also interruptible by a POSIX signal.
       */
      if ( _States_Is_waiting_on_thread_queue(the_thread->current_state) )
        _Thread_queue_Extract_with_proxy( the_thread );
      else if ( _States_Is_delaying(the_thread->current_state) ){
	(void) _Watchdog_Remove( &the_thread->Timer );
        _Thread_Unblock( the_thread );
      }

    } else if ( the_thread->current_state == STATES_READY ) {
      if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) )
	_ISR_Signals_to_thread_executing = true;
    }
  }
  return false;
}
Exemple #18
0
void _Event_Surrender(
  Thread_Control *the_thread
)
{
  ISR_Level           level;
  rtems_event_set     pending_events;
  rtems_event_set     event_condition;
  rtems_event_set     seized_events;
  rtems_option        option_set;
  RTEMS_API_Control  *api;

  api = the_thread->API_Extensions[ THREAD_API_RTEMS ];

  option_set = (rtems_option) the_thread->Wait.option;

  _ISR_Disable( level );
  pending_events  = api->pending_events;
  event_condition = (rtems_event_set) the_thread->Wait.count;

  seized_events = _Event_sets_Get( pending_events, event_condition );

  /*
   *  No events were seized in this operation
   */
  if ( _Event_sets_Is_empty( seized_events ) ) {
    _ISR_Enable( level );
    return;
  }

  /*
   *  If we are in an ISR and sending to the current thread, then
   *  we have a critical section issue to deal with.
   */
  if ( _ISR_Is_in_progress() &&
       _Thread_Is_executing( the_thread ) &&
       ((_Event_Sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT) ||
        (_Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED)) ) {
    if ( seized_events == event_condition || _Options_Is_any(option_set) ) {
      api->pending_events = _Event_sets_Clear( pending_events,seized_events );
      the_thread->Wait.count = 0;
      *(rtems_event_set *)the_thread->Wait.return_argument = seized_events;
      _Event_Sync_state = THREAD_BLOCKING_OPERATION_SATISFIED;
    }
    _ISR_Enable( level );
    return;
  }

  /*
   *  Otherwise, this is a normal send to another thread
   */
  if ( _States_Is_waiting_for_event( the_thread->current_state ) ) {
    if ( seized_events == event_condition || _Options_Is_any( option_set ) ) {
      api->pending_events = _Event_sets_Clear( pending_events, seized_events );
      the_thread->Wait.count = 0;
      *(rtems_event_set *)the_thread->Wait.return_argument = seized_events;

      _ISR_Flash( level );

      if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
        _ISR_Enable( level );
        _Thread_Unblock( the_thread );
      } else {
        _Watchdog_Deactivate( &the_thread->Timer );
        _ISR_Enable( level );
        (void) _Watchdog_Remove( &the_thread->Timer );
        _Thread_Unblock( the_thread );
      }
      return;
    }
  }
  _ISR_Enable( level );
}
Exemple #19
0
void _Event_Timeout(
  Objects_Id  id,
  void       *arg
)
{
  Thread_Control                   *the_thread;
  Objects_Locations                 location;
  ISR_Level                         level;
  Thread_blocking_operation_States *sync_state;

  sync_state = arg;

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

    case OBJECTS_LOCAL:

      /*
       *  If the event manager is not synchronized, then it is either
       *  "nothing happened", "timeout", or "satisfied".   If the_thread
       *  is the executing thread, then it is in the process of blocking
       *  and it is the thread which is responsible for the synchronization
       *  process.
       *
       *  If it is not satisfied, then it is "nothing happened" and
       *  this is the "timeout" transition.  After a request is satisfied,
       *  a timeout is not allowed to occur.
       */
      _ISR_Disable( level );
        /*
         * Verify that the thread is still waiting for the event condition.
         * This test is necessary to avoid state corruption if the timeout
         * happens after the event condition is satisfied in
         * _Event_Surrender().  A satisfied event condition is indicated with
         * count set to zero.
         */
        if ( !the_thread->Wait.count ) {
          _ISR_Enable( level );
          _Objects_Put_without_thread_dispatch( &the_thread->Object );
          return;
        }

        the_thread->Wait.count = 0;
        if ( _Thread_Is_executing( the_thread ) ) {
          if ( *sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )
            *sync_state = THREAD_BLOCKING_OPERATION_TIMEOUT;
        }

        the_thread->Wait.return_code = RTEMS_TIMEOUT;
      _ISR_Enable( level );
      _Thread_Unblock( the_thread );
      _Objects_Put_without_thread_dispatch( &the_thread->Object );
      break;

#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:  /* impossible */
#endif
    case OBJECTS_ERROR:
      break;
  }
}
Exemple #20
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
  ISR_lock_Context                  *lock_context
)
{
  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 ) ) {
      _ISR_lock_ISR_enable( lock_context );
      return CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE;
    }
  }

  _Thread_queue_Acquire_critical( &the_mutex->Wait_queue, lock_context );

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

  if ( !the_mutex->nest_count ) {
    _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    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:
          _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
          return CORE_MUTEX_STATUS_SUCCESSFUL;
        #if defined(RTEMS_POSIX_API)
          case CORE_MUTEX_NESTING_IS_ERROR:
            /* should never occur */
            _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
            return CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
        #endif
        case CORE_MUTEX_NESTING_BLOCKS:
          /* Currently no API exercises this behavior. */
          break;
      }
    #else
      _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
      /* 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 ) {
      _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
      return pop_status;
    }

    holder->resource_count--;
  }
  the_mutex->holder = NULL;

  /*
   *  Now we check if another thread was waiting for this mutex.  If so,
   *  transfer the mutex to that thread.
   */
  if ( ( the_thread = _Thread_queue_First_locked( &the_mutex->Wait_queue ) ) ) {
    /*
     * We must extract the thread now since this will restore its default
     * thread lock.  This is necessary to avoid a deadlock in the
     * _Thread_Change_priority() below due to a recursive thread queue lock
     * acquire.
     */
    _Thread_queue_Extract_locked( &the_mutex->Wait_queue, the_thread );

#if defined(RTEMS_MULTIPROCESSING)
    _Thread_Dispatch_disable();

    if ( _Objects_Is_local_id( the_thread->Object.id ) )
#endif
    {
      the_mutex->holder     = the_thread;
      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++;
          _Thread_Raise_priority(
            the_thread,
            the_mutex->Attributes.priority_ceiling
          );
          break;
      }
    }

    _Thread_queue_Unblock_critical(
      &the_mutex->Wait_queue,
      the_thread,
      lock_context
    );

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

      the_mutex->holder     = NULL;
      the_mutex->nest_count = 1;

      ( *api_mutex_mp_support)( the_thread, id );

    }

    _Thread_Dispatch_enable( _Per_CPU_Get() );
#endif
  } else {
    _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
  }

  /*
   *  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 ( !_Thread_Owns_resources( holder ) ) {
    /*
     * Ensure that the holder resource count is visible to all other processors
     * and that we read the latest priority restore hint.
     */
    _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );

    if ( holder->priority_restore_hint ) {
      Per_CPU_Control *cpu_self;

      cpu_self = _Thread_Dispatch_disable();
      _Thread_Restore_priority( holder );
      _Thread_Dispatch_enable( cpu_self );
    }
  }

  return CORE_MUTEX_STATUS_SUCCESSFUL;
}
Exemple #21
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;
}
Exemple #22
0
int pthread_join(
  pthread_t   thread,
  void      **value_ptr
)
{
  register Thread_Control *the_thread;
  POSIX_API_Control       *api;
  Objects_Locations        location;
  void                    *return_pointer;

on_EINTR:
  the_thread = _Thread_Get( thread, &location );
  switch ( location ) {

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

      if ( api->detachstate == PTHREAD_CREATE_DETACHED ) {
        _Thread_Enable_dispatch();
        return EINVAL;
      }

      if ( _Thread_Is_executing( the_thread ) ) {
        _Thread_Enable_dispatch();
        return EDEADLK;
      }

      /*
       *  Put ourself on the threads join list
       */

      if ( the_thread->current_state ==
             (STATES_WAITING_FOR_JOIN_AT_EXIT | STATES_TRANSIENT) ) {
         return_pointer = the_thread->Wait.return_argument;
         _Thread_Clear_state(
           the_thread,
           (STATES_WAITING_FOR_JOIN_AT_EXIT | STATES_TRANSIENT)
         );
      } else {
	_Thread_Executing->Wait.return_argument = &return_pointer;
        _Thread_queue_Enter_critical_section( &api->Join_List );
        _Thread_queue_Enqueue( &api->Join_List, WATCHDOG_NO_TIMEOUT );
      }
      _Thread_Enable_dispatch();

      if ( _Thread_Executing->Wait.return_code == EINTR )
        goto on_EINTR;

      if ( value_ptr )
        *value_ptr = return_pointer;
      return 0;

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

  return ESRCH;
}