Esempio n. 1
0
Status_Control _Thread_queue_Enqueue_sticky(
    Thread_queue_Queue            *queue,
    const Thread_queue_Operations *operations,
    Thread_Control                *the_thread,
    Thread_queue_Context          *queue_context
)
{
    Per_CPU_Control *cpu_self;

    _Thread_Wait_claim( the_thread, queue );

    if ( !_Thread_queue_Path_acquire_critical( queue, the_thread, queue_context ) ) {
        _Thread_queue_Path_release_critical( queue_context );
        _Thread_Wait_restore_default( the_thread );
        _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
        _Thread_Wait_tranquilize( the_thread );
        ( *queue_context->deadlock_callout )( the_thread );
        return _Thread_Wait_get_status( the_thread );
    }

    _Thread_queue_Context_clear_priority_updates( queue_context );
    _Thread_Wait_claim_finalize( the_thread, operations );
    ( *operations->enqueue )( queue, the_thread, queue_context );

    _Thread_queue_Path_release_critical( queue_context );

    the_thread->Wait.return_code = STATUS_SUCCESSFUL;
    _Thread_Wait_flags_set( the_thread, THREAD_QUEUE_INTEND_TO_BLOCK );
    cpu_self = _Thread_Dispatch_disable_critical(
                   &queue_context->Lock_context.Lock_context
               );
    _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );

    if ( cpu_self->thread_dispatch_disable_level != 1 ) {
        _Internal_error(
            INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE
        );
    }

    _Thread_queue_Timeout( the_thread, cpu_self, queue_context );
    _Thread_Priority_update( queue_context );
    _Thread_Priority_and_sticky_update( the_thread, 1 );
    _Thread_Dispatch_enable( cpu_self );

    while (
        _Thread_Wait_flags_get_acquire( the_thread ) == THREAD_QUEUE_INTEND_TO_BLOCK
    ) {
        /* Wait */
    }

    _Thread_Wait_tranquilize( the_thread );
    _Thread_Timer_remove( the_thread );
    return _Thread_Wait_get_status( the_thread );
}
Esempio n. 2
0
static void _Mutex_Queue_release(
  Mutex_Control    *mutex,
  ISR_lock_Context *lock_context
)
{
  _Thread_queue_Queue_release( &mutex->Queue.Queue, lock_context );
}
Esempio n. 3
0
void _Thread_queue_Surrender_sticky(
    Thread_queue_Queue            *queue,
    Thread_queue_Heads            *heads,
    Thread_Control                *previous_owner,
    Thread_queue_Context          *queue_context,
    const Thread_queue_Operations *operations
)
{
    Thread_Control  *new_owner;
    Per_CPU_Control *cpu_self;

    _Assert( heads != NULL );

    _Thread_queue_Context_clear_priority_updates( queue_context );
    new_owner = ( *operations->surrender )(
                    queue,
                    heads,
                    previous_owner,
                    queue_context
                );
    queue->owner = new_owner;
    _Thread_queue_Make_ready_again( new_owner );

    cpu_self = _Thread_Dispatch_disable_critical(
                   &queue_context->Lock_context.Lock_context
               );
    _Thread_queue_Queue_release(
        queue,
        &queue_context->Lock_context.Lock_context
    );
    _Thread_Priority_and_sticky_update( previous_owner, -1 );
    _Thread_Priority_and_sticky_update( new_owner, 0 );
    _Thread_Dispatch_enable( cpu_self );
}
Esempio n. 4
0
static void _Condition_Queue_release(
  Condition_Control *condition,
  ISR_lock_Context  *lock_context
)
{
  _Thread_queue_Queue_release( &condition->Queue.Queue, lock_context );
}
Esempio n. 5
0
static void _Semaphore_Queue_release(
  Semaphore_Control    *sem,
  Thread_queue_Context *queue_context
)
{
  _Thread_queue_Queue_release(
    &sem->Queue.Queue,
    &queue_context->Lock_context.Lock_context
  );
}
Esempio n. 6
0
static void _Mutex_Queue_release(
  Mutex_Control        *mutex,
  Thread_queue_Context *queue_context
)
{
  _Thread_queue_Queue_release(
    &mutex->Queue.Queue,
    &queue_context->Lock_context.Lock_context
  );
}
Esempio n. 7
0
void _Thread_queue_Unblock_critical(
    bool                unblock,
    Thread_queue_Queue *queue,
    Thread_Control     *the_thread,
    ISR_lock_Context   *lock_context
)
{
    if ( unblock ) {
        Per_CPU_Control *cpu_self;

        cpu_self = _Thread_Dispatch_disable_critical( lock_context );
        _Thread_queue_Queue_release( queue, lock_context );

        _Thread_Remove_timer_and_unblock( the_thread, queue );

        _Thread_Dispatch_enable( cpu_self );
    } else {
        _Thread_queue_Queue_release( queue, lock_context );
    }
}
Esempio n. 8
0
void _Thread_queue_Surrender(
    Thread_queue_Queue            *queue,
    Thread_queue_Heads            *heads,
    Thread_Control                *previous_owner,
    Thread_queue_Context          *queue_context,
    const Thread_queue_Operations *operations
)
{
    Thread_Control  *new_owner;
    bool             unblock;
    Per_CPU_Control *cpu_self;

    _Assert( heads != NULL );

    _Thread_queue_Context_clear_priority_updates( queue_context );
    new_owner = ( *operations->surrender )(
                    queue,
                    heads,
                    previous_owner,
                    queue_context
                );
    queue->owner = new_owner;

#if defined(RTEMS_MULTIPROCESSING)
    if ( !_Thread_queue_MP_set_callout( new_owner, queue_context ) )
#endif
    {
        _Thread_Resource_count_increment( new_owner );
    }

    unblock = _Thread_queue_Make_ready_again( new_owner );

    cpu_self = _Thread_Dispatch_disable_critical(
                   &queue_context->Lock_context.Lock_context
               );
    _Thread_queue_Queue_release(
        queue,
        &queue_context->Lock_context.Lock_context
    );

    _Thread_Priority_update( queue_context );

    if ( unblock ) {
        _Thread_Remove_timer_and_unblock( new_owner, queue );
    }

    _Thread_Dispatch_enable( cpu_self );
}
Esempio n. 9
0
void _Thread_queue_Enqueue(
    Thread_queue_Queue            *queue,
    const Thread_queue_Operations *operations,
    Thread_Control                *the_thread,
    Thread_queue_Context          *queue_context
)
{
    Per_CPU_Control *cpu_self;
    bool             success;

    _Assert( queue_context->enqueue_callout != NULL );
    _Assert( (uint8_t) queue_context->timeout_discipline != 0x7f );

#if defined(RTEMS_MULTIPROCESSING)
    if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet ) {
        the_thread = _Thread_MP_Allocate_proxy( queue_context->thread_state );
    }
#endif

    _Thread_Wait_claim( the_thread, queue );

    if ( !_Thread_queue_Path_acquire_critical( queue, the_thread, queue_context ) ) {
        _Thread_queue_Path_release_critical( queue_context );
        _Thread_Wait_restore_default( the_thread );
        _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
        _Thread_Wait_tranquilize( the_thread );
        _Assert( queue_context->deadlock_callout != NULL );
        ( *queue_context->deadlock_callout )( the_thread );
        return;
    }

    _Thread_queue_Context_clear_priority_updates( queue_context );
    _Thread_Wait_claim_finalize( the_thread, operations );
    ( *operations->enqueue )( queue, the_thread, queue_context );

    _Thread_queue_Path_release_critical( queue_context );

    the_thread->Wait.return_code = STATUS_SUCCESSFUL;
    _Thread_Wait_flags_set( the_thread, THREAD_QUEUE_INTEND_TO_BLOCK );
    cpu_self = _Thread_Dispatch_disable_critical(
                   &queue_context->Lock_context.Lock_context
               );
    _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );

    ( *queue_context->enqueue_callout )( queue, the_thread, queue_context );

    /*
     *  Set the blocking state for this thread queue in the thread.
     */
    _Thread_Set_state( the_thread, queue_context->thread_state );

    /*
     *  If the thread wants to timeout, then schedule its timer.
     */
    _Thread_queue_Timeout( the_thread, cpu_self, queue_context );

    /*
     * At this point thread dispatching is disabled, however, we already released
     * the thread queue lock.  Thus, interrupts or threads on other processors
     * may already changed our state with respect to the thread queue object.
     * The request could be satisfied or timed out.  This situation is indicated
     * by the thread wait flags.  Other parties must not modify our thread state
     * as long as we are in the THREAD_QUEUE_INTEND_TO_BLOCK thread wait state,
     * thus we have to cancel the blocking operation ourself if necessary.
     */
    success = _Thread_Wait_flags_try_change_acquire(
                  the_thread,
                  THREAD_QUEUE_INTEND_TO_BLOCK,
                  THREAD_QUEUE_BLOCKED
              );
    if ( !success ) {
        _Thread_Remove_timer_and_unblock( the_thread, queue );
    }

    _Thread_Priority_update( queue_context );
    _Thread_Dispatch_direct( cpu_self );
}
Esempio n. 10
0
void _Thread_queue_Enqueue_critical(
  Thread_queue_Queue            *queue,
  const Thread_queue_Operations *operations,
  Thread_Control                *the_thread,
  States_Control                 state,
  Thread_queue_Context          *queue_context
)
{
  Thread_queue_Path  path;
  Per_CPU_Control   *cpu_self;
  bool               success;

#if defined(RTEMS_MULTIPROCESSING)
  if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet ) {
    the_thread = _Thread_MP_Allocate_proxy( state );
  }
#endif

  _Thread_Wait_claim( the_thread, queue, operations );

  if ( !_Thread_queue_Path_acquire( the_thread, queue, &path ) ) {
    _Thread_Wait_restore_default( the_thread );
    _Thread_queue_Queue_release( queue, &queue_context->Lock_context );
    _Thread_Wait_tranquilize( the_thread );
    ( *queue_context->deadlock_callout )( the_thread );
    return;
  }

  ( *operations->enqueue )( queue, the_thread, &path );

  _Thread_queue_Path_release( &path );

  the_thread->Wait.return_code = STATUS_SUCCESSFUL;
  _Thread_Wait_flags_set( the_thread, THREAD_QUEUE_INTEND_TO_BLOCK );
  cpu_self = _Thread_Dispatch_disable_critical( &queue_context->Lock_context );
  _Thread_queue_Queue_release( queue, &queue_context->Lock_context );

  if (
    cpu_self->thread_dispatch_disable_level
      != queue_context->expected_thread_dispatch_disable_level
  ) {
    _Terminate(
      INTERNAL_ERROR_CORE,
      false,
      INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_FROM_BAD_STATE
    );
  }

  /*
   *  Set the blocking state for this thread queue in the thread.
   */
  _Thread_Set_state( the_thread, state );

  /*
   *  If the thread wants to timeout, then schedule its timer.
   */
  switch ( queue_context->timeout_discipline ) {
    case WATCHDOG_RELATIVE:
      /* A relative timeout of 0 is a special case indefinite (no) timeout */
      if ( queue_context->timeout != 0 ) {
        _Thread_Timer_insert_relative(
          the_thread,
          cpu_self,
          _Thread_Timeout,
          (Watchdog_Interval) queue_context->timeout
        );
      }
      break;
    case WATCHDOG_ABSOLUTE:
      _Thread_Timer_insert_absolute(
        the_thread,
        cpu_self,
        _Thread_Timeout,
        queue_context->timeout
      );
      break;
    default:
      break;
  }

  /*
   * At this point thread dispatching is disabled, however, we already released
   * the thread queue lock.  Thus, interrupts or threads on other processors
   * may already changed our state with respect to the thread queue object.
   * The request could be satisfied or timed out.  This situation is indicated
   * by the thread wait flags.  Other parties must not modify our thread state
   * as long as we are in the THREAD_QUEUE_INTEND_TO_BLOCK thread wait state,
   * thus we have to cancel the blocking operation ourself if necessary.
   */
  success = _Thread_Wait_flags_try_change_acquire(
    the_thread,
    THREAD_QUEUE_INTEND_TO_BLOCK,
    THREAD_QUEUE_BLOCKED
  );
  if ( !success ) {
    _Thread_Remove_timer_and_unblock( the_thread, queue );
  }

  _Thread_Update_priority( path.update_priority );
  _Thread_Dispatch_enable( cpu_self );
}