示例#1
0
int _POSIX_Condition_variables_Signal_support(
    pthread_cond_t            *cond,
    bool                       is_broadcast
)
{
    register POSIX_Condition_variables_Control *the_cond;
    Objects_Locations                           location;
    Thread_Control                             *the_thread;

    the_cond = _POSIX_Condition_variables_Get( cond, &location );
    switch ( location ) {

    case OBJECTS_LOCAL:
        do {
            the_thread = _Thread_queue_Dequeue( &the_cond->Wait_queue );
            if ( !the_thread )
                the_cond->Mutex = POSIX_CONDITION_VARIABLES_NO_MUTEX;
        } while ( is_broadcast && the_thread );

        _Thread_Enable_dispatch();

        return 0;

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

    return EINVAL;
}
示例#2
0
/**
 *  11.4.2 Initializing and Destroying a Condition Variable,
 *         P1003.1c/Draft 10, p. 87
 */
int pthread_cond_destroy(
  pthread_cond_t           *cond
)
{
  POSIX_Condition_variables_Control *the_cond;
  Objects_Locations                  location;

  the_cond = _POSIX_Condition_variables_Get( cond, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:

      if ( _Thread_queue_First( &the_cond->Wait_queue ) ) {
        _Thread_Enable_dispatch();
        return EBUSY;
      }

      _Objects_Close(
        &_POSIX_Condition_variables_Information,
        &the_cond->Object
      );

      _POSIX_Condition_variables_Free( the_cond );
      _Thread_Enable_dispatch();
      return 0;

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

  return EINVAL;
}
示例#3
0
/**
 *  11.4.2 Initializing and Destroying a Condition Variable,
 *         P1003.1c/Draft 10, p. 87
 */
int pthread_cond_destroy(
  pthread_cond_t           *cond
)
{
  POSIX_Condition_variables_Control *the_cond;
  Objects_Locations                  location;

  _Objects_Allocator_lock();
  the_cond = _POSIX_Condition_variables_Get( cond, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:

      if (
        _Thread_queue_First(
          &the_cond->Wait_queue,
          POSIX_CONDITION_VARIABLES_TQ_OPERATIONS
        )
      ) {
        _Objects_Put( &the_cond->Object );
        _Objects_Allocator_unlock();
        return EBUSY;
      }

      _Objects_Close(
        &_POSIX_Condition_variables_Information,
        &the_cond->Object
      );
      _Objects_Put( &the_cond->Object );
      _POSIX_Condition_variables_Free( the_cond );
      _Objects_Allocator_unlock();
      return 0;

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

  _Objects_Allocator_unlock();

  return EINVAL;
}
示例#4
0
int _POSIX_Condition_variables_Wait_support(
  pthread_cond_t            *cond,
  pthread_mutex_t           *mutex,
  const struct timespec     *abstime
)
{
  POSIX_Condition_variables_Control *the_cond;
  Thread_queue_Context               queue_context;
  int                                error;
  int                                mutex_error;
  Per_CPU_Control                   *cpu_self;
  Thread_Control                    *executing;
  Watchdog_Interval                  timeout;
  bool                               already_timedout;
  TOD_Absolute_timeout_conversion_results  status;

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

  the_cond = _POSIX_Condition_variables_Get( cond, &queue_context );

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

  already_timedout = false;

  if ( abstime != NULL ) {
    /*
     *  POSIX requires that blocking calls with timeouts that take
     *  an absolute timeout must ignore issues with the absolute
     *  time provided if the operation would otherwise succeed.
     *  So we check the abstime provided, and hold on to whether it
     *  is valid or not.  If it isn't correct and in the future,
     *  then we do a polling operation and convert the UNSATISFIED
     *  status into the appropriate error.
     */
    _Assert( the_cond->clock );
    status = _TOD_Absolute_timeout_to_ticks(abstime, the_cond->clock, &timeout);
    if ( status == TOD_ABSOLUTE_TIMEOUT_INVALID )
      return EINVAL;

    if ( status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST ||
        status == TOD_ABSOLUTE_TIMEOUT_IS_NOW ) {
      already_timedout = true;
    } else {
      _Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
    }
  } else {
    _Thread_queue_Context_set_no_timeout( &queue_context );
  }

  _POSIX_Condition_variables_Acquire_critical( the_cond, &queue_context );

  if (
    the_cond->mutex != POSIX_CONDITION_VARIABLES_NO_MUTEX
      && the_cond->mutex != *mutex
  ) {
    _POSIX_Condition_variables_Release( the_cond, &queue_context );
    return EINVAL;
  }

  the_cond->mutex = *mutex;

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

  if ( !already_timedout ) {
    _Thread_queue_Context_set_expected_level( &queue_context, 2 );
    _Thread_queue_Enqueue_critical(
      &the_cond->Wait_queue.Queue,
      POSIX_CONDITION_VARIABLES_TQ_OPERATIONS,
      executing,
      STATES_WAITING_FOR_CONDITION_VARIABLE,
      &queue_context
    );
  } else {
    _POSIX_Condition_variables_Release( the_cond, &queue_context );
    executing->Wait.return_code = STATUS_TIMEOUT;
  }

  mutex_error = pthread_mutex_unlock( mutex );
  if ( mutex_error != 0 ) {
    /*
     *  Historically, we ignored the unlock status since the behavior
     *  is undefined by POSIX. But GNU/Linux returns EPERM in this
     *  case, so we follow their lead.
     */
    _Assert( mutex_error == EINVAL || mutex_error == EPERM );
    _Thread_queue_Extract( executing );
    _Thread_Dispatch_enable( cpu_self );
    return EPERM;
  }

  /*
   *  Switch ourself out because we blocked as a result of the
   *  _Thread_queue_Enqueue_critical().
   */

  _Thread_Dispatch_enable( cpu_self );

  error = _POSIX_Get_error_after_wait( executing );

  /*
   *  If the thread is interrupted, while in the thread queue, by
   *  a POSIX signal, then pthread_cond_wait returns spuriously,
   *  according to the POSIX standard. It means that pthread_cond_wait
   *  returns a success status, except for the fact that it was not
   *  woken up a pthread_cond_signal() or a pthread_cond_broadcast().
   */

  if ( error == EINTR ) {
    error = 0;
  }

  /*
   *  When we get here the dispatch disable level is 0.
   */

  mutex_error = pthread_mutex_lock( mutex );
  if ( mutex_error != 0 ) {
    _Assert( mutex_error == EINVAL );
    return EINVAL;
  }

  return error;
}
示例#5
0
int _POSIX_Condition_variables_Wait_support(
  pthread_cond_t            *cond,
  pthread_mutex_t           *mutex,
  Watchdog_Interval          timeout,
  bool                       already_timedout
)
{
  POSIX_Condition_variables_Control          *the_cond;
  POSIX_Mutex_Control                        *the_mutex;
  Objects_Locations                           location;
  int                                         status;
  int                                         mutex_status;
  Thread_Control                             *executing;

  the_mutex = _POSIX_Mutex_Get( mutex, &location );
  if ( !the_mutex ) {
     return EINVAL;
  }

  _Objects_Put_without_thread_dispatch( &the_mutex->Object );

  the_cond = _POSIX_Condition_variables_Get( cond, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:

      if ( the_cond->Mutex && ( the_cond->Mutex != *mutex ) ) {
        _Objects_Put( &the_cond->Object );
        return EINVAL;
      }


      mutex_status = pthread_mutex_unlock( mutex );
      /*
       *  Historically, we ignored the return code since the behavior
       *  is undefined by POSIX. But GNU/Linux returns EPERM in this
       *  case, so we follow their lead.
       */
      if ( mutex_status ) {
        _Objects_Put( &the_cond->Object );
        return EPERM;
      }

      if ( !already_timedout ) {
        the_cond->Mutex = *mutex;

        executing = _Thread_Executing;
        executing->Wait.return_code = 0;
        executing->Wait.id          = *cond;

        _Thread_queue_Enqueue(
          &the_cond->Wait_queue,
          executing,
          STATES_WAITING_FOR_CONDITION_VARIABLE
            | STATES_INTERRUPTIBLE_BY_SIGNAL,
          timeout,
          ETIMEDOUT
        );

        _Objects_Put( &the_cond->Object );

        /*
         *  Switch ourself out because we blocked as a result of the
         *  _Thread_queue_Enqueue.
         */

        /*
         *  If the thread is interrupted, while in the thread queue, by
         *  a POSIX signal, then pthread_cond_wait returns spuriously,
         *  according to the POSIX standard. It means that pthread_cond_wait
         *  returns a success status, except for the fact that it was not
         *  woken up a pthread_cond_signal or a pthread_cond_broadcast.
         */
        status = executing->Wait.return_code;
        if ( status == EINTR )
          status = 0;

      } else {
        _Objects_Put( &the_cond->Object );
        status = ETIMEDOUT;
      }

      /*
       *  When we get here the dispatch disable level is 0.
       */

      mutex_status = pthread_mutex_lock( mutex );
      if ( mutex_status )
        return EINVAL;

      return status;

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

  return EINVAL;
}
示例#6
0
int _POSIX_Condition_variables_Wait_support(
  pthread_cond_t            *cond,
  pthread_mutex_t           *mutex,
  Watchdog_Interval          timeout,
  bool                       already_timedout
)
{
  register POSIX_Condition_variables_Control *the_cond;
  Objects_Locations                           location;
  int                                         status;
  int                                         mutex_status;

  if ( !_POSIX_Mutex_Get( mutex, &location ) ) {
     return EINVAL;
  }

  _Thread_Unnest_dispatch();

  the_cond = _POSIX_Condition_variables_Get( cond, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:

      if ( the_cond->Mutex && ( the_cond->Mutex != *mutex ) ) {
        _Thread_Enable_dispatch();
        return EINVAL;
      }

      (void) pthread_mutex_unlock( mutex );
/* XXX ignore this for now  since behavior is undefined
      if ( mutex_status ) {
        _Thread_Enable_dispatch();
        return EINVAL;
      }
*/

      if ( !already_timedout ) {
        the_cond->Mutex = *mutex;

        _Thread_queue_Enter_critical_section( &the_cond->Wait_queue );
        _Thread_Executing->Wait.return_code = 0;
        _Thread_Executing->Wait.queue       = &the_cond->Wait_queue;
        _Thread_Executing->Wait.id          = *cond;

        _Thread_queue_Enqueue( &the_cond->Wait_queue, timeout );

        _Thread_Enable_dispatch();

        /*
         *  Switch ourself out because we blocked as a result of the
         *  _Thread_queue_Enqueue.
         */

        /*
         *  If the thread is interrupted, while in the thread queue, by
         *  a POSIX signal, then pthread_cond_wait returns spuriously,
         *  according to the POSIX standard. It means that pthread_cond_wait
         *  returns a success status, except for the fact that it was not
         *  woken up a pthread_cond_signal or a pthread_cond_broadcast.
         */
        status = _Thread_Executing->Wait.return_code;
        if ( status == EINTR )
          status = 0;

      } else {
        _Thread_Enable_dispatch();
        status = ETIMEDOUT;
      }

      /*
       *  When we get here the dispatch disable level is 0.
       */

      mutex_status = pthread_mutex_lock( mutex );
      if ( mutex_status )
        return EINVAL;

      return status;

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

  return EINVAL;
}