Пример #1
0
void _Mutex_recursive_Release( struct _Mutex_recursive_Control *_mutex )
{
  Mutex_recursive_Control *mutex;
  Thread_queue_Context     queue_context;
  ISR_Level                level;
  Thread_Control          *executing;
  unsigned int             nest_level;

  mutex = _Mutex_recursive_Get( _mutex );
  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_ISR_disable( &queue_context, level );
  executing = _Mutex_Queue_acquire_critical( &mutex->Mutex, &queue_context );

  _Assert( mutex->Mutex.Queue.Queue.owner == executing );

  nest_level = mutex->nest_level;

  if ( __predict_true( nest_level == 0 ) ) {
    _Mutex_Release_critical( &mutex->Mutex, executing, level, &queue_context );
  } else {
    mutex->nest_level = nest_level - 1;

    _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
  }
}
Пример #2
0
void _Mutex_recursive_Acquire( struct _Mutex_recursive_Control *_mutex )
{
  Mutex_recursive_Control *mutex;
  Thread_queue_Context     queue_context;
  Thread_Control          *executing;
  Thread_Control          *owner;

  mutex = _Mutex_recursive_Get( _mutex );
  _Thread_queue_Context_initialize( &queue_context );
  executing = _Mutex_Queue_acquire( &mutex->Mutex, &queue_context );

  owner = mutex->Mutex.Queue.Queue.owner;

  if ( __predict_true( owner == NULL ) ) {
    mutex->Mutex.Queue.Queue.owner = executing;
    ++executing->resource_count;
    _Mutex_Queue_release( &mutex->Mutex, &queue_context );
  } else if ( owner == executing ) {
    ++mutex->nest_level;
    _Mutex_Queue_release( &mutex->Mutex, &queue_context );
  } else {
    _Thread_queue_Context_set_no_timeout( &queue_context );
    _Mutex_Acquire_slow( &mutex->Mutex, owner, executing, &queue_context );
  }
}
Пример #3
0
void _Thread_queue_Extract( Thread_Control *the_thread )
{
    Thread_queue_Context  queue_context;
    Thread_queue_Queue   *queue;

    _Thread_queue_Context_initialize( &queue_context );
    _Thread_Wait_acquire( the_thread, &queue_context );

    queue = the_thread->Wait.queue;

    if ( queue != NULL ) {
        bool unblock;

        _Thread_Wait_remove_request( the_thread, &queue_context.Lock_context );
        _Thread_queue_Context_set_MP_callout(
            &queue_context,
            _Thread_queue_MP_callout_do_nothing
        );
        unblock = _Thread_queue_Extract_locked(
                      queue,
                      the_thread->Wait.operations,
                      the_thread,
                      &queue_context
                  );
        _Thread_queue_Unblock_critical(
            unblock,
            queue,
            the_thread,
            &queue_context.Lock_context.Lock_context
        );
    } else {
        _Thread_Wait_release( the_thread, &queue_context );
    }
}
Пример #4
0
int _Mutex_Try_acquire( struct _Mutex_Control *_mutex )
{
  Mutex_Control        *mutex;
  Thread_queue_Context  queue_context;
  Thread_Control       *executing;
  Thread_Control       *owner;
  int                   eno;

  mutex = _Mutex_Get( _mutex );
  _Thread_queue_Context_initialize( &queue_context );
  executing = _Mutex_Queue_acquire( mutex, &queue_context );

  owner = mutex->Queue.Queue.owner;

  if ( __predict_true( owner == NULL ) ) {
    mutex->Queue.Queue.owner = executing;
    ++executing->resource_count;
    eno = 0;
  } else {
    eno = EBUSY;
  }

  _Mutex_Queue_release( mutex, &queue_context );

  return eno;
}
Пример #5
0
Thread_Control *_Thread_queue_Do_dequeue(
    Thread_queue_Control          *the_thread_queue,
    const Thread_queue_Operations *operations
#if defined(RTEMS_MULTIPROCESSING)
    ,
    Thread_queue_MP_callout        mp_callout
#endif
)
{
    Thread_queue_Context  queue_context;
    Thread_Control       *the_thread;

    _Thread_queue_Context_initialize( &queue_context );
    _Thread_queue_Context_set_MP_callout( &queue_context, mp_callout );
    _Thread_queue_Acquire( the_thread_queue, &queue_context );

    the_thread = _Thread_queue_First_locked( the_thread_queue, operations );

    if ( the_thread != NULL ) {
        _Thread_queue_Extract_critical(
            &the_thread_queue->Queue,
            operations,
            the_thread,
            &queue_context
        );
    } else {
        _Thread_queue_Release( the_thread_queue, &queue_context );
    }

    return the_thread;
}
Пример #6
0
void _Semaphore_Post( struct _Semaphore_Control *_sem )
{
  Semaphore_Control    *sem;
  Thread_queue_Context  queue_context;
  Thread_queue_Heads   *heads;

  sem = _Semaphore_Get( _sem );
  _Thread_queue_Context_initialize( &queue_context );
  _Semaphore_Queue_acquire( sem, &queue_context );

  heads = sem->Queue.Queue.heads;
  if ( heads == NULL ) {
    _Assert( sem->count < UINT_MAX );
    ++sem->count;
    _Semaphore_Queue_release( sem, &queue_context );
  } else {
    const Thread_queue_Operations *operations;
    Thread_Control *first;

    operations = SEMAPHORE_TQ_OPERATIONS;
    first = ( *operations->first )( heads );

    _Thread_queue_Extract_critical(
      &sem->Queue.Queue,
      operations,
      first,
      &queue_context
    );
  }
}
Пример #7
0
void _Semaphore_Wait( struct _Semaphore_Control *_sem )
{
  Semaphore_Control    *sem ;
  Thread_queue_Context  queue_context;
  Thread_Control       *executing;
  unsigned int          count;

  sem = _Semaphore_Get( _sem );
  _Thread_queue_Context_initialize( &queue_context );
  executing = _Semaphore_Queue_acquire( sem, &queue_context );

  count = sem->count;
  if ( count > 0 ) {
    sem->count = count - 1;
    _Semaphore_Queue_release( sem, &queue_context );
  } else {
    _Thread_queue_Context_set_expected_level( &queue_context, 1 );
    _Thread_queue_Context_set_no_timeout( &queue_context );
    _Thread_queue_Enqueue_critical(
      &sem->Queue.Queue,
      SEMAPHORE_TQ_OPERATIONS,
      executing,
      STATES_WAITING_FOR_SYS_LOCK_SEMAPHORE,
      &queue_context
    );
  }
}
Пример #8
0
int _Mutex_recursive_Try_acquire( struct _Mutex_recursive_Control *_mutex )
{
  Mutex_recursive_Control *mutex;
  Thread_queue_Context     queue_context;
  ISR_Level                level;
  Thread_Control          *executing;
  Thread_Control          *owner;
  int                      eno;

  mutex = _Mutex_recursive_Get( _mutex );
  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_ISR_disable( &queue_context, level );
  executing = _Mutex_Queue_acquire_critical( &mutex->Mutex, &queue_context );

  owner = mutex->Mutex.Queue.Queue.owner;

  if ( __predict_true( owner == NULL ) ) {
    mutex->Mutex.Queue.Queue.owner = executing;
    _Thread_Resource_count_increment( executing );
    eno = 0;
  } else if ( owner == executing ) {
    ++mutex->nest_level;
    eno = 0;
  } else {
    eno = EBUSY;
  }

  _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );

  return eno;
}
Пример #9
0
void _Mutex_recursive_Acquire( struct _Mutex_recursive_Control *_mutex )
{
  Mutex_recursive_Control *mutex;
  Thread_queue_Context     queue_context;
  ISR_Level             level;
  Thread_Control          *executing;
  Thread_Control          *owner;

  mutex = _Mutex_recursive_Get( _mutex );
  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_ISR_disable( &queue_context, level );
  executing = _Mutex_Queue_acquire_critical( &mutex->Mutex, &queue_context );

  owner = mutex->Mutex.Queue.Queue.owner;

  if ( __predict_true( owner == NULL ) ) {
    mutex->Mutex.Queue.Queue.owner = executing;
    _Thread_Resource_count_increment( executing );
    _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
  } else if ( owner == executing ) {
    ++mutex->nest_level;
    _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
  } else {
    _Thread_queue_Context_set_no_timeout( &queue_context );
    _Mutex_Acquire_slow( &mutex->Mutex, owner, executing, level, &queue_context );
  }
}
Пример #10
0
static int _POSIX_Threads_Join( pthread_t thread, void **value_ptr )
{
  Thread_Control       *the_thread;
  Thread_queue_Context  queue_context;
  Per_CPU_Control      *cpu_self;
  Thread_Control       *executing;
  void                 *value;

  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_set_expected_level( &queue_context, 1 );
  the_thread = _Thread_Get( thread, &queue_context.Lock_context );

  if ( the_thread == NULL ) {
    return ESRCH;
  }

  cpu_self = _Per_CPU_Get();
  executing = _Per_CPU_Get_executing( cpu_self );

  if ( executing == the_thread ) {
    _ISR_lock_ISR_enable( &queue_context.Lock_context );
    return EDEADLK;
  }

  _Thread_State_acquire_critical( the_thread, &queue_context.Lock_context );

  if ( !_Thread_Is_joinable( the_thread ) ) {
    _Thread_State_release( the_thread, &queue_context.Lock_context );
    return EINVAL;
  }

  if ( _States_Is_waiting_for_join_at_exit( the_thread->current_state ) ) {
    value = the_thread->Life.exit_value;
    _Thread_Clear_state_locked( the_thread, STATES_WAITING_FOR_JOIN_AT_EXIT );
    _Thread_Dispatch_disable_with_CPU( cpu_self, &queue_context.Lock_context );
    _Thread_State_release( the_thread, &queue_context.Lock_context );
    _Thread_Dispatch_enable( cpu_self );
  } else {
    _Thread_Join(
      the_thread,
      STATES_INTERRUPTIBLE_BY_SIGNAL | STATES_WAITING_FOR_JOIN,
      executing,
      &queue_context
    );

    if ( _POSIX_Get_error_after_wait( executing ) != 0 ) {
      _Assert( _POSIX_Get_error_after_wait( executing ) == EINTR );
      return EINTR;
    }

    value = executing->Wait.return_argument;
  }

  if ( value_ptr != NULL ) {
    *value_ptr = value;
  }

  return 0;
}
Пример #11
0
rtems_status_code rtems_task_set_scheduler(
  rtems_id            task_id,
  rtems_id            scheduler_id,
  rtems_task_priority priority
)
{
  const Scheduler_Control *scheduler;
  Thread_Control          *the_thread;
  Thread_queue_Context     queue_context;
  ISR_lock_Context         state_context;
  Per_CPU_Control         *cpu_self;
  bool                     valid;
  Priority_Control         core_priority;
  Status_Control           status;

  if ( !_Scheduler_Get_by_id( scheduler_id, &scheduler ) ) {
    return RTEMS_INVALID_ID;
  }

  core_priority = _RTEMS_Priority_To_core( scheduler, priority, &valid );
  if ( !valid ) {
    return RTEMS_INVALID_PRIORITY;
  }

  _Thread_queue_Context_initialize( &queue_context );
  the_thread = _Thread_Get( task_id, &queue_context.Lock_context.Lock_context );

  if ( the_thread == NULL ) {
#if defined(RTEMS_MULTIPROCESSING)
    if ( _Thread_MP_Is_remote( task_id ) ) {
      return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
    }
#endif

    return RTEMS_INVALID_ID;
  }

  cpu_self = _Thread_Dispatch_disable_critical(
    &queue_context.Lock_context.Lock_context
  );

  _Thread_Wait_acquire_critical( the_thread, &queue_context );
  _Thread_State_acquire_critical( the_thread, &state_context );

  status = _Scheduler_Set( scheduler, the_thread, core_priority );

  _Thread_State_release_critical( the_thread, &state_context );
  _Thread_Wait_release( the_thread, &queue_context );
  _Thread_Dispatch_enable( cpu_self );
  return _Status_Get( status );
}
Пример #12
0
Status_Control _CORE_RWLock_Surrender( CORE_RWLock_Control *the_rwlock )
{
  Thread_queue_Context queue_context;

  /*
   *  If unlocked, then OK to read.
   *  Otherwise, we have to block.
   *  If locked for reading and no waiters, then OK to read.
   *  If any thread is waiting, then we wait.
   */

  _Thread_queue_Context_initialize( &queue_context );
  _CORE_RWLock_Acquire( the_rwlock, &queue_context );

  if ( the_rwlock->current_state == CORE_RWLOCK_UNLOCKED){
    /* This is an error at the caller site */
    _CORE_RWLock_Release( the_rwlock, &queue_context );
    return STATUS_SUCCESSFUL;
  }

  if ( the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_READING ) {
    the_rwlock->number_of_readers -= 1;

    if ( the_rwlock->number_of_readers != 0 ) {
      /* must be unlocked again */
      _CORE_RWLock_Release( the_rwlock, &queue_context );
      return STATUS_SUCCESSFUL;
    }
  }

  _Assert(
    the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_WRITING
      || ( the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_READING
        && the_rwlock->number_of_readers == 0 )
  );

  /*
   * Implicitly transition to "unlocked" and find another thread interested
   * in obtaining this rwlock.
   */
  the_rwlock->current_state = CORE_RWLOCK_UNLOCKED;

  _Thread_queue_Flush_critical(
    &the_rwlock->Queue.Queue,
    CORE_RWLOCK_TQ_OPERATIONS,
    _CORE_RWLock_Flush_filter,
    &queue_context
  );
  return STATUS_SUCCESSFUL;
}
Пример #13
0
void _Mutex_Release( struct _Mutex_Control *_mutex )
{
  Mutex_Control        *mutex;
  Thread_queue_Context  queue_context;
  Thread_Control       *executing;

  mutex = _Mutex_Get( _mutex );
  _Thread_queue_Context_initialize( &queue_context );
  executing = _Mutex_Queue_acquire( mutex, &queue_context );

  _Assert( mutex->Queue.Queue.owner == executing );

  _Mutex_Release_critical( mutex, executing, &queue_context );
}
Пример #14
0
int _Mutex_recursive_Acquire_timed(
  struct _Mutex_recursive_Control *_mutex,
  const struct timespec           *abstime
)
{
  Mutex_recursive_Control *mutex;
  Thread_queue_Context     queue_context;
  ISR_Level                level;
  Thread_Control          *executing;
  Thread_Control          *owner;

  mutex = _Mutex_recursive_Get( _mutex );
  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_ISR_disable( &queue_context, level );
  executing = _Mutex_Queue_acquire_critical( &mutex->Mutex, &queue_context );

  owner = mutex->Mutex.Queue.Queue.owner;

  if ( __predict_true( owner == NULL ) ) {
    mutex->Mutex.Queue.Queue.owner = executing;
    _Thread_Resource_count_increment( executing );
    _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );

    return 0;
  } else if ( owner == executing ) {
    ++mutex->nest_level;
    _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );

    return 0;
  } else {
    Watchdog_Interval ticks;

    switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
      case TOD_ABSOLUTE_TIMEOUT_INVALID:
        _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
        return EINVAL;
      case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
      case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
        _Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
        return ETIMEDOUT;
      default:
        break;
    }

    _Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
    _Mutex_Acquire_slow( &mutex->Mutex, owner, executing, level, &queue_context );

    return STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
  }
}
Пример #15
0
int pthread_setschedparam(
  pthread_t           thread,
  int                 policy,
  struct sched_param *param
)
{
  Thread_CPU_budget_algorithms         budget_algorithm;
  Thread_CPU_budget_algorithm_callout  budget_callout;
  Thread_Control                      *the_thread;
  Per_CPU_Control                     *cpu_self;
  Thread_queue_Context                 queue_context;
  int                                  error;

  if ( param == NULL ) {
    return EINVAL;
  }

  error = _POSIX_Thread_Translate_sched_param(
    policy,
    param,
    &budget_algorithm,
    &budget_callout
  );
  if ( error != 0 ) {
    return error;
  }

  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_clear_priority_updates( &queue_context );
  the_thread = _Thread_Get( thread, &queue_context.Lock_context.Lock_context );

  if ( the_thread == NULL ) {
    return ESRCH;
  }

  _Thread_Wait_acquire_critical( the_thread, &queue_context );
  error = _POSIX_Set_sched_param(
    the_thread,
    policy,
    param,
    budget_algorithm,
    budget_callout,
    &queue_context
  );
  cpu_self = _Thread_queue_Dispatch_disable( &queue_context );
  _Thread_Wait_release( the_thread, &queue_context );
  _Thread_Priority_update( &queue_context );
  _Thread_Dispatch_enable( cpu_self );
  return error;
}
Пример #16
0
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;
  Thread_queue_Context     queue_context;
  const Scheduler_Control *scheduler;
  Priority_Control         old_priority;
  rtems_status_code        status;

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

  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_clear_priority_updates( &queue_context );
  the_thread = _Thread_Get( id, &queue_context.Lock_context.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
  }

  _Thread_Wait_acquire_critical( the_thread, &queue_context );

  scheduler = _Thread_Scheduler_get_home( the_thread );
  old_priority = _Thread_Get_priority( the_thread );

  if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
    status = _RTEMS_tasks_Set_priority(
      the_thread,
      scheduler,
      new_priority,
      &queue_context
    );
  } else {
    _Thread_Wait_release( the_thread, &queue_context );
    status = RTEMS_SUCCESSFUL;
  }

  *old_priority_p = _RTEMS_Priority_From_core( scheduler, old_priority );
  return status;
}
Пример #17
0
void _Thread_Close( Thread_Control *the_thread, Thread_Control *executing )
{
  Thread_queue_Context queue_context;

  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_set_expected_level( &queue_context, 2 );
  _Thread_queue_Context_set_no_timeout( &queue_context );
  _Thread_State_acquire( the_thread, &queue_context.Lock_context.Lock_context );
  _Thread_Join(
    the_thread,
    STATES_WAITING_FOR_JOIN,
    executing,
    &queue_context
  );
  _Thread_Cancel( the_thread, executing, NULL );
}
Пример #18
0
void _Thread_Restart_self(
  Thread_Control                 *executing,
  const Thread_Entry_information *entry,
  ISR_lock_Context               *lock_context
)
{
  Per_CPU_Control      *cpu_self;
  Thread_queue_Context  queue_context;

  _Assert(
    _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE
  );
  _Assert(
    executing->current_state == STATES_READY
      || executing->current_state == STATES_SUSPENDED
  );

  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_clear_priority_updates( &queue_context );
  _Thread_State_acquire_critical( executing, lock_context );

  executing->Start.Entry = *entry;
  _Thread_Change_life_locked(
    executing,
    0,
    THREAD_LIFE_RESTARTING,
    THREAD_LIFE_PROTECTED | THREAD_LIFE_CHANGE_DEFERRED
  );

  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
  _Thread_State_release( executing, lock_context );

  _Thread_Wait_acquire_default( executing, lock_context );
  _Thread_Priority_change(
    executing,
    &executing->Real_priority,
    executing->Start.initial_priority,
    false,
    &queue_context
  );
  _Thread_Wait_release_default( executing, lock_context );

  _Thread_Priority_update( &queue_context );
  _Thread_Dispatch_enable( cpu_self );
  RTEMS_UNREACHABLE();
}
Пример #19
0
int sem_post( sem_t *_sem )
{
  Sem_Control          *sem;
  ISR_Level             level;
  Thread_queue_Context  queue_context;
  Thread_queue_Heads   *heads;
  unsigned int          count;

  POSIX_SEMAPHORE_VALIDATE_OBJECT( _sem );

  sem = _Sem_Get( &_sem->_Semaphore );
  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_ISR_disable( &queue_context, level );
  _Sem_Queue_acquire_critical( sem, &queue_context );

  heads = sem->Queue.Queue.heads;
  count = sem->count;

  if ( __predict_true( heads == NULL && count < SEM_VALUE_MAX ) ) {
    sem->count = count + 1;
    _Sem_Queue_release( sem, level, &queue_context );
    return 0;
  }

  if ( __predict_true( heads != NULL ) ) {
    const Thread_queue_Operations *operations;
    Thread_Control *first;

    _Thread_queue_Context_set_ISR_level( &queue_context, level );
    operations = SEMAPHORE_TQ_OPERATIONS;
    first = ( *operations->first )( heads );

    _Thread_queue_Extract_critical(
      &sem->Queue.Queue,
      operations,
      first,
      &queue_context
    );
    return 0;
  }

  _Sem_Queue_release( sem, level, &queue_context );
  rtems_set_errno_and_return_minus_one( EOVERFLOW );
}
Пример #20
0
static void _Thread_Wake_up_joining_threads( Thread_Control *the_thread )
{
  Thread_Join_context join_context;

#if defined(RTEMS_POSIX_API)
  join_context.exit_value = the_thread->Life.exit_value;
#endif

  _Thread_queue_Context_initialize( &join_context.Base );
  _Thread_queue_Acquire( &the_thread->Join_queue, &join_context.Base );
  _Thread_queue_Flush_critical(
    &the_thread->Join_queue.Queue,
    THREAD_JOIN_TQ_OPERATIONS,
#if defined(RTEMS_POSIX_API)
    _Thread_Join_flush_filter,
#else
    _Thread_queue_Flush_default_filter,
#endif
    &join_context.Base
  );
}
Пример #21
0
void _API_Mutex_Lock( API_Mutex_Control *the_mutex )
{
  Thread_Life_state    previous_thread_life_state;
  Thread_queue_Context queue_context;

  previous_thread_life_state =
    _Thread_Set_life_protection( THREAD_LIFE_PROTECTED );

  _Thread_queue_Context_initialize( &queue_context );
  _ISR_lock_ISR_disable( &queue_context.Lock_context );
  _Thread_queue_Context_set_no_timeout( &queue_context );
  _CORE_recursive_mutex_Seize(
    &the_mutex->Mutex,
    _Thread_Executing,
    true,
    _CORE_recursive_mutex_Seize_nested,
    &queue_context
  );

  if ( the_mutex->Mutex.nest_level == 0 ) {
    the_mutex->previous_thread_life_state = previous_thread_life_state;
  }
}
Пример #22
0
int pthread_rwlock_timedwrlock(
  pthread_rwlock_t      *rwlock,
  const struct timespec *abstime
)
{
  POSIX_RWLock_Control *the_rwlock;
  Thread_queue_Context  queue_context;
  Status_Control        status;

  the_rwlock = _POSIX_RWLock_Get( rwlock );
  POSIX_RWLOCK_VALIDATE_OBJECT( the_rwlock );

  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
    &queue_context,
    abstime
  );
  status = _CORE_RWLock_Seize_for_writing(
    &the_rwlock->RWLock,
    true,
    &queue_context
  );
  return _POSIX_Get_error( status );
}
Пример #23
0
static void _Thread_Raise_real_priority(
  Thread_Control   *the_thread,
  Priority_Control  priority
)
{
  Thread_queue_Context queue_context;

  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_clear_priority_updates( &queue_context );
  _Thread_Wait_acquire( the_thread, &queue_context );

  if ( priority < the_thread->Real_priority.priority ) {
    _Thread_Priority_change(
      the_thread,
      &the_thread->Real_priority,
      priority,
      false,
      &queue_context
    );
  }

  _Thread_Wait_release( the_thread, &queue_context );
  _Thread_Priority_update( &queue_context );
}
Пример #24
0
static bool _Thread_queue_Path_acquire(
  Thread_Control     *the_thread,
  Thread_queue_Queue *queue,
  Thread_queue_Path  *path
)
{
  Thread_Control     *owner;

#if defined(RTEMS_SMP)
  Thread_queue_Link  *link;
  Thread_queue_Queue *target;

  /*
   * For an overview please look at the non-SMP part below.  We basically do
   * the same on SMP configurations.  The fact that we may have more than one
   * executing thread and each thread queue has its own SMP lock makes the task
   * a bit more difficult.  We have to avoid deadlocks at SMP lock level, since
   * this would result in an unrecoverable deadlock of the overall system.
   */

  _Chain_Initialize_empty( &path->Links );

  owner = queue->owner;

  if ( owner == NULL ) {
    return true;
  }

  if ( owner == the_thread ) {
    return false;
  }

  _RBTree_Initialize_node( &path->Start.Registry_node );
  _Chain_Initialize_node( &path->Start.Path_node );
  _Thread_queue_Context_initialize( &path->Start.Queue_context );
  link = &path->Start;

  do {
    _Chain_Append_unprotected( &path->Links, &link->Path_node );
    link->owner = owner;

    _Thread_Wait_acquire_default_critical(
      owner,
      &link->Queue_context.Lock_context
    );

    target = owner->Wait.queue;
    link->Queue_context.Wait.queue = target;

    if ( target != NULL ) {
      if ( _Thread_queue_Link_add( link, queue, target ) ) {
        _Thread_queue_Gate_add(
          &owner->Wait.Lock.Pending_requests,
          &link->Queue_context.Wait.Gate
        );
        _Thread_Wait_release_default_critical(
          owner,
          &link->Queue_context.Lock_context
        );
        _Thread_Wait_acquire_queue_critical( target, &link->Queue_context );

        if ( link->Queue_context.Wait.queue == NULL ) {
          _Thread_queue_Link_remove( link );
          _Thread_Wait_release_queue_critical( target, &link->Queue_context );
          _Thread_Wait_acquire_default_critical(
            owner,
            &link->Queue_context.Lock_context
          );
          _Thread_Wait_remove_request_locked( owner, &link->Queue_context );
          _Assert( owner->Wait.queue == NULL );
          return true;
        }
      } else {
        link->Queue_context.Wait.queue = NULL;
        _Thread_queue_Path_release( path );
        return false;
      }
    } else {
      return true;
    }

    link = &owner->Wait.Link;
    queue = target;
    owner = queue->owner;
  } while ( owner != NULL );
#else
  do {
    owner = queue->owner;

    if ( owner == NULL ) {
      return true;
    }

    if ( owner == the_thread ) {
      return false;
    }

    queue = owner->Wait.queue;
  } while ( queue != NULL );
#endif

  return true;
}
Пример #25
0
rtems_status_code rtems_region_get_segment(
  rtems_id           id,
  uintptr_t          size,
  rtems_option       option_set,
  rtems_interval     timeout,
  void              **segment
)
{
  rtems_status_code  status;
  Region_Control    *the_region;

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

  *segment = NULL;

  if ( size == 0 ) {
    return RTEMS_INVALID_SIZE;
  }

  the_region = _Region_Get_and_lock( id );

  if ( the_region == NULL ) {
    return RTEMS_INVALID_ID;
  }

  if ( size > the_region->maximum_segment_size ) {
    status = RTEMS_INVALID_SIZE;
  } else {
    void *the_segment;

    the_segment = _Region_Allocate_segment( the_region, size );

    if ( the_segment != NULL ) {
      *segment = the_segment;
      status = RTEMS_SUCCESSFUL;
    } else if ( _Options_Is_no_wait( option_set ) ) {
      status = RTEMS_UNSATISFIED;
    } else {
      Thread_queue_Context  queue_context;
      Thread_Control       *executing;

      _Thread_queue_Context_initialize( &queue_context );
      _Thread_queue_Acquire( &the_region->Wait_queue, &queue_context );

      executing  = _Thread_Executing;
      executing->Wait.count           = size;
      executing->Wait.return_argument = segment;

      /* FIXME: This is a home grown condition variable */
      _Thread_queue_Context_set_thread_state(
        &queue_context,
        STATES_WAITING_FOR_SEGMENT
      );
      _Thread_queue_Context_set_timeout_ticks( &queue_context, timeout );
      _Thread_queue_Context_set_enqueue_callout(
        &queue_context,
        _Region_Enqueue_callout
      );
      _Thread_queue_Enqueue(
        &the_region->Wait_queue.Queue,
        the_region->wait_operations,
        executing,
        &queue_context
      );
      return _Status_Get_after_wait( executing );
    }
  }

  _Region_Unlock( the_region );
  return status;
}
Пример #26
0
static void _POSIX_signals_Action_handler(
  Thread_Control   *executing,
  Thread_Action    *action,
  ISR_lock_Context *lock_context
)
{
  POSIX_API_Control *api;
  int                signo;
  uint32_t           hold_errno;

  (void) action;
  _Thread_State_release( executing, lock_context );

  api = executing->API_Extensions[ THREAD_API_POSIX ];

  /*
   *  We need to ensure that if the signal handler executes a call
   *  which overwrites the unblocking status, we restore it.
   */
  hold_errno = executing->Wait.return_code;

  /*
   * api may be NULL in case of a thread close in progress
   */
  if ( !api )
    return;

  /*
   *  In case the executing thread is blocked or about to block on something
   *  that uses the thread wait information, then this is a kernel bug.
   */
  _Assert(
    ( _Thread_Wait_flags_get( executing )
      & ( THREAD_WAIT_STATE_BLOCKED | THREAD_WAIT_STATE_INTEND_TO_BLOCK ) ) == 0
  );

  /*
   *  If we invoke any user code, there is the possibility that
   *  a new signal has been posted that we should process so we
   *  restart the loop if a signal handler was invoked.
   *
   *  The first thing done is to check there are any signals to be
   *  processed at all.  No point in doing this loop otherwise.
   */
  while (1) {
    Thread_queue_Context queue_context;

    _Thread_queue_Context_initialize( &queue_context );
    _POSIX_signals_Acquire( &queue_context );
      if ( !(api->signals_unblocked &
            (api->signals_pending | _POSIX_signals_Pending)) ) {
       _POSIX_signals_Release( &queue_context );
       break;
     }
    _POSIX_signals_Release( &queue_context );

    for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
      _POSIX_signals_Check_signal( api, signo, false );
      _POSIX_signals_Check_signal( api, signo, true );
    }
    /* Unfortunately - nothing like __SIGFIRSTNOTRT in newlib signal .h */

    for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) {
      _POSIX_signals_Check_signal( api, signo, false );
      _POSIX_signals_Check_signal( api, signo, true );
    }
  }

  executing->Wait.return_code = hold_errno;
}