Exemple #1
0
void _Thread_queue_Requeue(
  Thread_queue_Control *the_thread_queue,
  Thread_Control       *the_thread
)
{
  /*
   * Just in case the thread really wasn't blocked on a thread queue
   * when we get here.
   */
  if ( !the_thread_queue )
    return;

  /*
   * If queueing by FIFO, there is nothing to do. This only applies to
   * priority blocking discipline.
   */
  if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY ) {
    Thread_queue_Control *tq = the_thread_queue;
    ISR_Level             level;
    ISR_Level             level_ignored;

    _ISR_Disable( level );
    if ( _States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
      _Thread_queue_Enter_critical_section( tq );
      _Thread_queue_Extract_priority_helper( tq, the_thread, true );
      (void) _Thread_queue_Enqueue_priority( tq, the_thread, &level_ignored );
    }
    _ISR_Enable( level );
  }
}
Exemple #2
0
void _CORE_barrier_Wait(
    CORE_barrier_Control                *the_barrier,
    Thread_Control                      *executing,
    Objects_Id                           id,
    bool                                 wait,
    Watchdog_Interval                    timeout,
    CORE_barrier_API_mp_support_callout  api_barrier_mp_support
)
{
    ISR_Level       level;

    executing->Wait.return_code = CORE_BARRIER_STATUS_SUCCESSFUL;
    _ISR_Disable( level );
    the_barrier->number_of_waiting_threads++;
    if ( _CORE_barrier_Is_automatic( &the_barrier->Attributes ) ) {
        if ( the_barrier->number_of_waiting_threads ==
                the_barrier->Attributes.maximum_count) {
            executing->Wait.return_code = CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED;
            _ISR_Enable( level );
            _CORE_barrier_Release( the_barrier, id, api_barrier_mp_support );
            return;
        }
    }

    _Thread_queue_Enter_critical_section( &the_barrier->Wait_queue );
    executing->Wait.queue          = &the_barrier->Wait_queue;
    executing->Wait.id             = id;
    _ISR_Enable( level );

    _Thread_queue_Enqueue( &the_barrier->Wait_queue, timeout );
}
Exemple #3
0
uint32_t   _MPCI_Send_request_packet (
  uint32_t            destination,
  MP_packet_Prefix   *the_packet,
  States_Control      extra_state
)
{
  Thread_Control *executing = _Thread_Executing;

  the_packet->source_tid      = executing->Object.id;
  the_packet->source_priority = executing->current_priority;
  the_packet->to_convert =
     ( the_packet->to_convert - sizeof(MP_packet_Prefix) ) / sizeof(uint32_t);

  executing->Wait.id = the_packet->id;

  executing->Wait.queue = &_MPCI_Remote_blocked_threads;

  _Thread_Disable_dispatch();

    (*_MPCI_table->send_packet)( destination, the_packet );

    _Thread_queue_Enter_critical_section( &_MPCI_Remote_blocked_threads );

    /*
     *  See if we need a default timeout
     */

    if (the_packet->timeout == MPCI_DEFAULT_TIMEOUT)
        the_packet->timeout = _MPCI_table->default_timeout;

    _Thread_queue_Enqueue(
      &_MPCI_Remote_blocked_threads,
      executing,
      the_packet->timeout
    );

    executing->current_state =
      _States_Set( extra_state, executing->current_state );

  _Thread_Enable_dispatch();

  return executing->Wait.return_code;
}
Exemple #4
0
void _Thread_queue_Requeue(
  Thread_queue_Control *the_thread_queue,
  Thread_Control       *the_thread
)
{
  /*
   * Just in case the thread really wasn't blocked on a thread queue
   * when we get here.
   */
  if ( !the_thread_queue )
    return;

  /*
   * If queueing by FIFO, there is nothing to do. This only applies to
   * priority blocking discipline.
   */
  if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY ) {
    Thread_queue_Control *tq = the_thread_queue;
    ISR_Level             level;

    _ISR_Disable( level );
    if ( _States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
      _Thread_queue_Enter_critical_section( tq );

      /* extract the thread */
      _RBTree_Extract(
        &the_thread->Wait.queue->Queues.Priority,
        &the_thread->RBNode
      );

      /* enqueue the thread at the new priority */
      _RBTree_Insert(
        &the_thread_queue->Queues.Priority,
        &the_thread->RBNode,
        _Thread_queue_Compare_priority,
        false
      );
    }
    _ISR_Enable( level );
  }
}
Exemple #5
0
void _CORE_semaphore_Seize(
  CORE_semaphore_Control *the_semaphore,
  Objects_Id              id,
  bool                    wait,
  Watchdog_Interval       timeout
)
{
  Thread_Control *executing;
  ISR_Level       level;

  executing = _Thread_Executing;
  executing->Wait.return_code = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
  _ISR_Disable( level );
  if ( the_semaphore->count != 0 ) {
    the_semaphore->count -= 1;
    _ISR_Enable( level );
    return;
  }

  /*
   *  If the semaphore was not available and the caller was not willing
   *  to block, then return immediately with a status indicating that
   *  the semaphore was not available and the caller never blocked.
   */
  if ( !wait ) {
    _ISR_Enable( level );
    executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
    return;
  }

  /*
   *  If the semaphore is not available and the caller is willing to
   *  block, then we now block the caller with optional timeout.
   */
  _Thread_queue_Enter_critical_section( &the_semaphore->Wait_queue );
  executing->Wait.queue = &the_semaphore->Wait_queue;
  executing->Wait.id    = id;
  _ISR_Enable( level );
  _Thread_queue_Enqueue( &the_semaphore->Wait_queue, timeout );
}
int sigtimedwait(
  const sigset_t         *set,
  siginfo_t              *info,
  const struct timespec  *timeout
)
{
  Thread_Control    *the_thread;
  POSIX_API_Control *api;
  Watchdog_Interval  interval;
  siginfo_t          signal_information;
  siginfo_t         *the_info;
  int                signo;
  ISR_Level          level;

  /*
   *  Error check parameters before disabling interrupts.
   */
  if ( !set )
    rtems_set_errno_and_return_minus_one( EINVAL );

  /*  NOTE: This is very specifically a RELATIVE not ABSOLUTE time
   *        in the Open Group specification.
   */

  interval = 0;
  if ( timeout ) {

    if ( !_Timespec_Is_valid( timeout ) )
      rtems_set_errno_and_return_minus_one( EINVAL );

    interval = _Timespec_To_ticks( timeout );

    if ( !interval )
      rtems_set_errno_and_return_minus_one( EINVAL );
  }

  /*
   *  Initialize local variables.
   */

  the_info = ( info ) ? info : &signal_information;

  the_thread = _Thread_Executing;

  api = the_thread->API_Extensions[ THREAD_API_POSIX ];

  /*
   *  What if they are already pending?
   */

  /* API signals pending? */

  _ISR_Disable( level );
  if ( *set & api->signals_pending ) {
    /* XXX real info later */
    the_info->si_signo = _POSIX_signals_Get_highest( api->signals_pending );
    _POSIX_signals_Clear_signals(
      api,
      the_info->si_signo,
      the_info,
      false,
      false
    );
    _ISR_Enable( level );

    the_info->si_code = SI_USER;
    the_info->si_value.sival_int = 0;
    return the_info->si_signo;
  }

  /* Process pending signals? */

  if ( *set & _POSIX_signals_Pending ) {
    signo = _POSIX_signals_Get_highest( _POSIX_signals_Pending );
    _POSIX_signals_Clear_signals( api, signo, the_info, true, false );
    _ISR_Enable( level );

    the_info->si_signo = signo;
    the_info->si_code = SI_USER;
    the_info->si_value.sival_int = 0;
    return signo;
  }

  the_info->si_signo = -1;

  _Thread_Disable_dispatch();
    the_thread->Wait.queue           = &_POSIX_signals_Wait_queue;
    the_thread->Wait.return_code     = EINTR;
    the_thread->Wait.option          = *set;
    the_thread->Wait.return_argument = the_info;
    _Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue );
    _ISR_Enable( level );
    _Thread_queue_Enqueue( &_POSIX_signals_Wait_queue, interval );
  _Thread_Enable_dispatch();

  /*
   * When the thread is set free by a signal, it is need to eliminate
   * the signal.
   */

  _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info, false, false );
  errno = _Thread_Executing->Wait.return_code;
  return the_info->si_signo;
}
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;
}
Exemple #8
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;
}
Exemple #9
0
void _CORE_message_queue_Seize(
  CORE_message_queue_Control      *the_message_queue,
  Thread_Control                  *executing,
  Objects_Id                       id,
  void                            *buffer,
  size_t                          *size_p,
  bool                             wait,
  Watchdog_Interval                timeout
)
{
  ISR_Level                          level;
  CORE_message_queue_Buffer_control *the_message;

  executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
  _ISR_Disable( level );
  the_message = _CORE_message_queue_Get_pending_message( the_message_queue );
  if ( the_message != NULL ) {
    the_message_queue->number_of_pending_messages -= 1;
    _ISR_Enable( level );

    *size_p = the_message->Contents.size;
    executing->Wait.count =
      _CORE_message_queue_Get_message_priority( the_message );
    _CORE_message_queue_Copy_buffer(
      the_message->Contents.buffer,
      buffer,
      *size_p
    );

    #if !defined(RTEMS_SCORE_COREMSG_ENABLE_BLOCKING_SEND)
      /*
       *  There is not an API with blocking sends enabled.
       *  So return immediately.
       */
      _CORE_message_queue_Free_message_buffer(the_message_queue, the_message);
      return;
    #else
    {
      Thread_Control   *the_thread;

      /*
       *  There could be a thread waiting to send a message.  If there
       *  is not, then we can go ahead and free the buffer.
       *
       *  NOTE: If we note that the queue was not full before this receive,
       *  then we can avoid this dequeue.
       */
      the_thread = _Thread_queue_Dequeue( &the_message_queue->Wait_queue );
      if ( !the_thread ) {
        _CORE_message_queue_Free_message_buffer(
          the_message_queue,
          the_message
        );
        return;
      }

      /*
       *  There was a thread waiting to send a message.  This code
       *  puts the messages in the message queue on behalf of the
       *  waiting task.
       */
      _CORE_message_queue_Set_message_priority(
        the_message,
        the_thread->Wait.count
      );
      the_message->Contents.size = (size_t) the_thread->Wait.option;
      _CORE_message_queue_Copy_buffer(
        the_thread->Wait.return_argument_second.immutable_object,
        the_message->Contents.buffer,
        the_message->Contents.size
      );

      _CORE_message_queue_Insert_message(
         the_message_queue,
         the_message,
         _CORE_message_queue_Get_message_priority( the_message )
      );
      return;
    }
    #endif
  }

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

  _Thread_queue_Enter_critical_section( &the_message_queue->Wait_queue );
  executing->Wait.queue = &the_message_queue->Wait_queue;
  executing->Wait.id = id;
  executing->Wait.return_argument_second.mutable_object = buffer;
  executing->Wait.return_argument = size_p;
  /* Wait.count will be filled in with the message priority */
  _ISR_Enable( level );

  _Thread_queue_Enqueue(
    &the_message_queue->Wait_queue,
    executing,
    STATES_WAITING_FOR_MESSAGE,
    timeout
  );
}
Exemple #10
0
rtems_status_code rtems_region_get_segment(
  rtems_id           id,
  uintptr_t          size,
  rtems_option       option_set,
  rtems_interval     timeout,
  void              **segment
)
{
  Thread_Control     *executing;
  Objects_Locations   location;
  rtems_status_code   return_status;
  Region_Control     *the_region;
  void               *the_segment;

  if ( !segment )
    return RTEMS_INVALID_ADDRESS;

  *segment = NULL;

  if ( size == 0 )
    return RTEMS_INVALID_SIZE;

  _RTEMS_Lock_allocator();

    executing  = _Thread_Get_executing();
    the_region = _Region_Get( id, &location );
    switch ( location ) {

      case OBJECTS_LOCAL:
        if ( size > the_region->maximum_segment_size )
          return_status = RTEMS_INVALID_SIZE;

        else {
          _Region_Debug_Walk( the_region, 1 );

          the_segment = _Region_Allocate_segment( the_region, size );

          _Region_Debug_Walk( the_region, 2 );

          if ( the_segment ) {
            the_region->number_of_used_blocks += 1;
            *segment = the_segment;
            return_status = RTEMS_SUCCESSFUL;
          } else if ( _Options_Is_no_wait( option_set ) ) {
            return_status = RTEMS_UNSATISFIED;
          } else {
            /*
             *  Switch from using the memory allocation mutex to using a
             *  dispatching disabled critical section.  We have to do this
             *  because this thread is going to block.
             */
            /* FIXME: Lock order reversal */
            _Thread_Disable_dispatch();
            _RTEMS_Unlock_allocator();

            executing->Wait.queue           = &the_region->Wait_queue;
            executing->Wait.id              = id;
            executing->Wait.count           = size;
            executing->Wait.return_argument = segment;

            _Thread_queue_Enter_critical_section( &the_region->Wait_queue );

            _Thread_queue_Enqueue(
              &the_region->Wait_queue,
              executing,
              timeout
            );

            _Objects_Put( &the_region->Object );

            return (rtems_status_code) executing->Wait.return_code;
          }
        }
        break;

#if defined(RTEMS_MULTIPROCESSING)
      case OBJECTS_REMOTE:        /* this error cannot be returned */
        break;
#endif

      case OBJECTS_ERROR:
      default:
        return_status = RTEMS_INVALID_ID;
        break;
    }

  _RTEMS_Unlock_allocator();

  return return_status;
}
void _CORE_RWLock_Obtain_for_writing(
  CORE_RWLock_Control                 *the_rwlock,
  Objects_Id                           id,
  bool                                 wait,
  Watchdog_Interval                    timeout,
  CORE_RWLock_API_mp_support_callout   api_rwlock_mp_support
)
{
  ISR_Level       level;
  Thread_Control *executing = _Thread_Executing;

  /*
   *  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 );
    switch ( the_rwlock->current_state ) {
      case CORE_RWLOCK_UNLOCKED:
	the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING;
	_ISR_Enable( level );
	executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
	return;

      case CORE_RWLOCK_LOCKED_FOR_READING:
      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_WRITE;
    executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
    _ISR_Enable( level );

    _Thread_queue_Enqueue_with_handler(
       &the_rwlock->Wait_queue,
       timeout,
       _CORE_RWLock_Timeout
    );


    /* return to API level so it can dispatch and we block */
}
CORE_message_queue_Status _CORE_message_queue_Submit(
  CORE_message_queue_Control                *the_message_queue,
  void                                      *buffer,
  size_t                                     size,
  Objects_Id                                 id,
  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
  CORE_message_queue_Submit_types            submit_type,
  boolean                                    wait,
  Watchdog_Interval                          timeout
)
{
  ISR_Level                            level;
  CORE_message_queue_Buffer_control   *the_message;
  Thread_Control                      *the_thread;

  if ( size > the_message_queue->maximum_message_size ) {
    return CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE;
  }

  /*
   *  Is there a thread currently waiting on this message queue?
   */

  if ( the_message_queue->number_of_pending_messages == 0 ) {
    the_thread = _Thread_queue_Dequeue( &the_message_queue->Wait_queue );
    if ( the_thread ) {
      _CORE_message_queue_Copy_buffer(
        buffer,
        the_thread->Wait.return_argument,
        size
      );
      *(size_t *)the_thread->Wait.return_argument_1 = size;
      the_thread->Wait.count = submit_type;

#if defined(RTEMS_MULTIPROCESSING)
      if ( !_Objects_Is_local_id( the_thread->Object.id ) )
        (*api_message_queue_mp_support) ( the_thread, id );
#endif
      return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
    }
  }

  /*
   *  No one waiting on the message queue at this time, so attempt to
   *  queue the message up for a future receive.
   */

  if ( the_message_queue->number_of_pending_messages <
       the_message_queue->maximum_pending_messages ) {

    the_message =
        _CORE_message_queue_Allocate_message_buffer( the_message_queue );

    /*
     *  NOTE: If the system is consistent, this error should never occur.
     */

    if ( !the_message ) {
      return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED;
    }

    _CORE_message_queue_Copy_buffer(
      buffer,
      the_message->Contents.buffer,
      size
    );
    the_message->Contents.size = size;
    the_message->priority  = submit_type;

    _CORE_message_queue_Insert_message(
       the_message_queue,
       the_message,
       submit_type
    );
    return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
  }

  /*
   *  No message buffers were available so we may need to return an
   *  overflow error or block the sender until the message is placed
   *  on the queue.
   */

  if ( !wait ) {
    return CORE_MESSAGE_QUEUE_STATUS_TOO_MANY;
  }

  /*
   *  Do NOT block on a send if the caller is in an ISR.  It is
   *  deadly to block in an ISR.
   */

  if ( _ISR_Is_in_progress() ) {
    return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED;
  }

  /*
   *  WARNING!! executing should NOT be used prior to this point.
   *  Thus the unusual choice to open a new scope and declare
   *  it as a variable.  Doing this emphasizes how dangerous it
   *  would be to use this variable prior to here.
   */

  {
    Thread_Control  *executing = _Thread_Executing;

    _ISR_Disable( level );
    _Thread_queue_Enter_critical_section( &the_message_queue->Wait_queue );
    executing->Wait.queue              = &the_message_queue->Wait_queue;
    executing->Wait.id                 = id;
    executing->Wait.return_argument    = buffer;
    executing->Wait.option             = size;
    executing->Wait.count              = submit_type;
    _ISR_Enable( level );

    _Thread_queue_Enqueue( &the_message_queue->Wait_queue, timeout );
  }

  return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT;
}
rtems_status_code rtems_region_get_segment(
  Objects_Id         id,
  uint32_t           size,
  rtems_option       option_set,
  rtems_interval     timeout,
  void              **segment
)
{
  register Region_Control *the_region;
  Objects_Locations        location;
  Thread_Control          *executing;
  void                    *the_segment;

  if ( !segment )
    return RTEMS_INVALID_ADDRESS;

  *segment = NULL;

  if ( size == 0 )
    return RTEMS_INVALID_SIZE;

  _RTEMS_Lock_allocator();
  executing  = _Thread_Executing;
  the_region = _Region_Get( id, &location );
  switch ( location ) {
    case OBJECTS_REMOTE:        /* this error cannot be returned */
      _RTEMS_Unlock_allocator();
      return RTEMS_INTERNAL_ERROR;

    case OBJECTS_ERROR:
      _RTEMS_Unlock_allocator();
      return RTEMS_INVALID_ID;

    case OBJECTS_LOCAL:
      if ( size > the_region->maximum_segment_size ) {
        _RTEMS_Unlock_allocator();
        return RTEMS_INVALID_SIZE;
      }

      _Region_Debug_Walk( the_region, 1 );

      the_segment = _Region_Allocate_segment( the_region, size );

      _Region_Debug_Walk( the_region, 2 );

      if ( the_segment ) {
        the_region->number_of_used_blocks += 1;
        _RTEMS_Unlock_allocator();
        *segment = the_segment;
        return RTEMS_SUCCESSFUL;
      }

      if ( _Options_Is_no_wait( option_set ) ) {
        _RTEMS_Unlock_allocator();
        return RTEMS_UNSATISFIED;
      }

      /*
       *  Switch from using the memory allocation mutex to using a
       *  dispatching disabled critical section.  We have to do this
       *  because this thread is going to block.
       */
      _Thread_Disable_dispatch();
      _RTEMS_Unlock_allocator();

      executing->Wait.queue           = &the_region->Wait_queue;
      executing->Wait.id              = id;
      executing->Wait.count           = size;
      executing->Wait.return_argument = segment;

      _Thread_queue_Enter_critical_section( &the_region->Wait_queue );

      _Thread_queue_Enqueue( &the_region->Wait_queue, timeout );

      _Thread_Enable_dispatch();

      return (rtems_status_code) executing->Wait.return_code;
  }

  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
}