Ejemplo n.º 1
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;
}
Ejemplo n.º 2
0
void _Region_Process_queue(
  Region_Control *the_region
)
{
  Thread_Control *the_thread;
  void           *the_segment;
  /*
   *  Switch from using the memory allocation mutex to using a
   *  dispatching disabled critical section.  We have to do this
   *  because this thread may unblock one or more threads that were
   *  waiting on memory.
   *
   *  NOTE: Be sure to disable dispatching before unlocking the mutex
   *        since we do not want to open a window where a context
   *        switch could occur.
   */
  _Thread_Disable_dispatch();
  _RTEMS_Unlock_allocator();

  /*
   *  NOTE: The following loop is O(n) where n is the number of
   *        threads whose memory request is satisfied.
   */
  for ( ; ; ) {
    the_thread = _Thread_queue_First( &the_region->Wait_queue );

    if ( the_thread == NULL )
      break;

    the_segment = (void **) _Region_Allocate_segment(
      the_region,
      the_thread->Wait.count
    );

    if ( the_segment == NULL )
      break;

    *(void **)the_thread->Wait.return_argument = the_segment;
    the_region->number_of_used_blocks += 1;
    _Thread_queue_Extract( &the_region->Wait_queue, the_thread );
    the_thread->Wait.return_code = RTEMS_SUCCESSFUL;
  }
  _Thread_Enable_dispatch();
}
Ejemplo n.º 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;
}
Ejemplo n.º 4
0
/**
 *  This directive allows a thread to delete a rwlock specified by
 *  the rwlock id.  The rwlock is freed back to the inactive
 *  rwlock chain.
 *
 *  @param[in] rwlock is the rwlock id
 *
 *  @return This method returns 0 if there was not an
 *  error. Otherwise, a status code is returned indicating the
 *  source of the error.
 */
int pthread_rwlock_destroy(
  pthread_rwlock_t *rwlock
)
{
  POSIX_RWLock_Control *the_rwlock = NULL;
  Objects_Locations      location;

  if ( !rwlock )
    return EINVAL;

  the_rwlock = _POSIX_RWLock_Get( rwlock, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:
      /*
       *  If there is at least one thread waiting, then do not delete it.
       */
      if ( _Thread_queue_First( &the_rwlock->RWLock.Wait_queue ) != NULL ) {
        _Objects_Put( &the_rwlock->Object );
        return EBUSY;
      }

      /*
       *  POSIX doesn't require behavior when it is locked.
       */

      _Objects_Close( &_POSIX_RWLock_Information, &the_rwlock->Object );

      _POSIX_RWLock_Free( the_rwlock );

      _Objects_Put( &the_rwlock->Object );
      return 0;

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

  return EINVAL;
}
Ejemplo n.º 5
0
ER ref_mbx(
  T_RMBX *pk_rmbx,
  ID      mbxid
)
{
  register ITRON_Mailbox_Control *the_mailbox;
  Objects_Locations               location;
  Chain_Control                  *pending;

  if ( !pk_rmbx )
    return E_PAR;

  the_mailbox = _ITRON_Mailbox_Get( mbxid, &location );
  switch ( location ) {
#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:
#endif
    case OBJECTS_ERROR:
      return _ITRON_Mailbox_Clarify_get_id_error( mbxid );

    case OBJECTS_LOCAL:

      pending = &the_mailbox->message_queue.Pending_messages;
      if ( _Chain_Is_empty( pending ) )
        pk_rmbx->pk_msg = NULL;
      else
        pk_rmbx->pk_msg = (T_MSG *) pending->first;

      /*
       *  Fill in whether or not there is a waiting task
       */

      if ( !_Thread_queue_First( &the_mailbox->message_queue.Wait_queue ) )
        pk_rmbx->wtsk = FALSE;
      else
        pk_rmbx->wtsk = TRUE;

      break;
  }
  _ITRON_return_errorno( E_OK );
}
Ejemplo n.º 6
0
void _CORE_RWLock_Obtain_for_reading(
  CORE_RWLock_Control                 *the_rwlock,
  Thread_Control                      *executing,
  Objects_Id                           id,
  bool                                 wait,
  Watchdog_Interval                    timeout,
  CORE_RWLock_API_mp_support_callout   api_rwlock_mp_support
)
{
  ISR_Level       level;

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

  _ISR_Disable( level );
    switch ( the_rwlock->current_state ) {
      case CORE_RWLOCK_UNLOCKED:
	the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING;
	the_rwlock->number_of_readers += 1;
	_ISR_Enable( level );
	executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
	return;

      case CORE_RWLOCK_LOCKED_FOR_READING: {
        Thread_Control *waiter;
        waiter = _Thread_queue_First( &the_rwlock->Wait_queue );
        if ( !waiter ) {
	  the_rwlock->number_of_readers += 1;
	  _ISR_Enable( level );
	  executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
          return;
        }
        break;
      }
      case CORE_RWLOCK_LOCKED_FOR_WRITING:
        break;
    }

    /*
     *  If the thread is not willing to wait, then return immediately.
     */

    if ( !wait ) {
      _ISR_Enable( level );
      executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
      return;
    }

    /*
     *  We need to wait to enter this critical section
     */

    _Thread_queue_Enter_critical_section( &the_rwlock->Wait_queue );
    executing->Wait.queue       = &the_rwlock->Wait_queue;
    executing->Wait.id          = id;
    executing->Wait.option      = CORE_RWLOCK_THREAD_WAITING_FOR_READ;
    executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
    _ISR_Enable( level );

    _Thread_queue_Enqueue(
       &the_rwlock->Wait_queue,
       executing,
       STATES_WAITING_FOR_RWLOCK,
       timeout
    );

    /* return to API level so it can dispatch and we block */
}
Ejemplo n.º 7
0
CORE_RWLock_Status _CORE_RWLock_Release(
  CORE_RWLock_Control *the_rwlock,
  Thread_Control      *executing
)
{
  ISR_Level       level;
  Thread_Control *next;

  /*
   *  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.
   */

  _ISR_Disable( level );
    if ( the_rwlock->current_state == CORE_RWLOCK_UNLOCKED){
      _ISR_Enable( level );
      executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
      return CORE_RWLOCK_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 */
	  _ISR_Enable( level );
          return CORE_RWLOCK_SUCCESSFUL;
        }
    }

    /* CORE_RWLOCK_LOCKED_FOR_WRITING or READING with readers */
    executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;

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

  next = _Thread_queue_Dequeue( &the_rwlock->Wait_queue );

  if ( next ) {
    if ( next->Wait.option == CORE_RWLOCK_THREAD_WAITING_FOR_WRITE ) {
      the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING;
      return CORE_RWLOCK_SUCCESSFUL;
    }

    /*
     * Must be CORE_RWLOCK_THREAD_WAITING_FOR_READING
     */
    the_rwlock->number_of_readers += 1;
    the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING;

    /*
     * Now see if more readers can be let go.
     */
    while ( 1 ) {
      next = _Thread_queue_First( &the_rwlock->Wait_queue );
      if ( !next ||
           next->Wait.option == CORE_RWLOCK_THREAD_WAITING_FOR_WRITE )
        return CORE_RWLOCK_SUCCESSFUL;
      the_rwlock->number_of_readers += 1;
      _Thread_queue_Extract( &the_rwlock->Wait_queue, next );
    }
  }

  /* indentation is to match _ISR_Disable at top */

  return CORE_RWLOCK_SUCCESSFUL;
}