Example #1
0
static int shm_mmap(
  rtems_libio_t *iop,
  void** addr,
  size_t len,
  int prot,
  off_t off
)
{
  POSIX_Shm_Control *shm = iop_to_shm( iop );

  _Objects_Allocator_lock();

  *addr = (*shm->shm_object.ops->object_mmap)( &shm->shm_object, len, prot, off);
  if ( *addr != NULL ) {
    /* Keep a reference in the shared memory to prevent its removal. */
    ++shm->reference_count;

    /* Update atime */
    _POSIX_Shm_Update_atime(shm);
  } else {
    _Objects_Allocator_unlock();
    rtems_set_errno_and_return_minus_one( ENOMEM );
  }

  _Objects_Allocator_unlock();

  return 0;
}
Example #2
0
int sem_unlink(
  const char *name
)
{
  int                      status;
  POSIX_Semaphore_Control *the_semaphore;
  Objects_Id               the_semaphore_id;
  size_t                   name_len;

  _Objects_Allocator_lock();
  _Thread_Disable_dispatch();

  status = _POSIX_Semaphore_Name_to_id( name, &the_semaphore_id, &name_len );
  if ( status != 0 ) {
    _Thread_Enable_dispatch();
    _Objects_Allocator_unlock();
    rtems_set_errno_and_return_minus_one( status );
  }

  the_semaphore = (POSIX_Semaphore_Control *) _Objects_Get_local_object(
    &_POSIX_Semaphore_Information,
    _Objects_Get_index( the_semaphore_id )
  );

  the_semaphore->linked = false;
  _POSIX_Semaphore_Namespace_remove( the_semaphore );
  _POSIX_Semaphore_Delete( the_semaphore );

  _Thread_Enable_dispatch();
  _Objects_Allocator_unlock();

  return 0;
}
Example #3
0
rtems_status_code rtems_port_delete(
  rtems_id id
)
{
  Dual_ported_memory_Control          *the_port;
  Objects_Locations                    location;

  _Objects_Allocator_lock();
  the_port = _Dual_ported_memory_Get( id, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:
      _Objects_Close( &_Dual_ported_memory_Information, &the_port->Object );
      _Objects_Put( &the_port->Object );
      _Dual_ported_memory_Free( the_port );
      _Objects_Allocator_unlock();
      return RTEMS_SUCCESSFUL;

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

  _Objects_Allocator_unlock();

  return RTEMS_INVALID_ID;
}
Example #4
0
rtems_status_code rtems_timer_create(
  rtems_name  name,
  rtems_id   *id
)
{
  Timer_Control *the_timer;

  if ( !rtems_is_name_valid( name ) )
    return RTEMS_INVALID_NAME;

  if ( !id )
    return RTEMS_INVALID_ADDRESS;

  the_timer = _Timer_Allocate();

  if ( !the_timer ) {
    _Objects_Allocator_unlock();
    return RTEMS_TOO_MANY;
  }

  the_timer->the_class = TIMER_DORMANT;
  _Watchdog_Preinitialize( &the_timer->Ticker, _Per_CPU_Get_snapshot() );

  _Objects_Open(
    &_Timer_Information,
    &the_timer->Object,
    (Objects_Name) name
  );

  *id = the_timer->Object.id;
  _Objects_Allocator_unlock();
  return RTEMS_SUCCESSFUL;
}
Example #5
0
int mq_unlink(
  const char *name
)
{
  POSIX_Message_queue_Control *the_mq;
  Objects_Get_by_name_error    error;
  Thread_queue_Context         queue_context;

  _Objects_Allocator_lock();

  the_mq = _POSIX_Message_queue_Get_by_name( name, NULL, &error );
  if ( the_mq == NULL ) {
    _Objects_Allocator_unlock();
    rtems_set_errno_and_return_minus_one( _POSIX_Get_by_name_error( error ) );
  }

  _POSIX_Message_queue_Namespace_remove( the_mq );

  _CORE_message_queue_Acquire( &the_mq->Message_queue, &queue_context );

  the_mq->linked = false;
  _POSIX_Message_queue_Delete( the_mq, &queue_context );

  _Objects_Allocator_unlock();
  return 0;
}
Example #6
0
/*
 *  This method will set the object name based upon the user string.
 *  If the object class uses 32-bit names, then only the first 4 bytes
 *  of the string will be used.
 */
rtems_status_code rtems_object_set_name(
  rtems_id       id,
  const char    *name
)
{
  Objects_Information *information;
  Objects_Control     *the_object;
  Objects_Id           tmpId;

  if ( !name )
    return RTEMS_INVALID_ADDRESS;

  tmpId = (id == OBJECTS_ID_OF_SELF) ? rtems_task_self() : id;

  information  = _Objects_Get_information_id( tmpId );
  if ( !information )
    return RTEMS_INVALID_ID;

  _Objects_Allocator_lock();
  the_object = _Objects_Get_no_protection( tmpId, information );

  if ( the_object == NULL ) {
    _Objects_Allocator_unlock();
    return RTEMS_INVALID_ID;
  }

  _Objects_Set_name( information, the_object, name );
  _Objects_Allocator_unlock();
  return RTEMS_SUCCESSFUL;
}
Example #7
0
/*
 *  17.1.3 Thread-Specific Data Key Deletion, P1003.1c/Draft 10, p. 167
 */
int pthread_key_delete(
  pthread_key_t  key
)
{
  POSIX_Keys_Control *the_key;
  Objects_Locations   location;

  _Objects_Allocator_lock();
  the_key = _POSIX_Keys_Get( key, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:
      _POSIX_Keys_Free_memory( the_key );

      /*
       *  NOTE:  The destructor is not called and it is the responsibility
       *         of the application to free the memory.
       */
      _POSIX_Keys_Free( the_key );
      _Objects_Put(&the_key->Object);
      _Objects_Allocator_unlock();
      return 0;

#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:   /* should never happen */
#endif
    case OBJECTS_ERROR:
      break;
  }

  _Objects_Allocator_unlock();

  return EINVAL;
}
Example #8
0
int mq_close(
    mqd_t  mqdes
)
{
    POSIX_Message_queue_Control *the_mq;
    Thread_queue_Context         queue_context;

    _Objects_Allocator_lock();
    the_mq = _POSIX_Message_queue_Get( mqdes, &queue_context );

    if ( the_mq == NULL ) {
        _Objects_Allocator_unlock();
        rtems_set_errno_and_return_minus_one( EBADF );
    }

    _CORE_message_queue_Acquire_critical(
        &the_mq->Message_queue,
        &queue_context
    );

    if ( the_mq->open_count == 0 ) {
        _CORE_message_queue_Release( &the_mq->Message_queue, &queue_context );
        _Objects_Allocator_unlock();
        rtems_set_errno_and_return_minus_one( EBADF );
    }

    the_mq->open_count -= 1;
    _POSIX_Message_queue_Delete( the_mq, &queue_context );

    _Objects_Allocator_unlock();
    return 0;
}
Example #9
0
rtems_status_code rtems_message_queue_delete(
  rtems_id id
)
{
  Message_queue_Control          *the_message_queue;
  Objects_Locations               location;

  _Objects_Allocator_lock();
  the_message_queue = _Message_queue_Get( id, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:
      _Objects_Close( &_Message_queue_Information,
                      &the_message_queue->Object );

      _CORE_message_queue_Close(
        &the_message_queue->message_queue,
        _Message_queue_MP_Send_object_was_deleted,
        id
      );

#if defined(RTEMS_MULTIPROCESSING)
      if ( _Attributes_Is_global( the_message_queue->attribute_set ) ) {
        _Objects_MP_Close(
          &_Message_queue_Information,
          the_message_queue->Object.id
        );

        _Message_queue_MP_Send_process_packet(
          MESSAGE_QUEUE_MP_ANNOUNCE_DELETE,
          the_message_queue->Object.id,
          0,                                 /* Not used */
          0
        );
      }
#endif
      _Objects_Put( &the_message_queue->Object );
      _Message_queue_Free( the_message_queue );
      _Objects_Allocator_unlock();
      return RTEMS_SUCCESSFUL;

#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:
      _Objects_Allocator_unlock();
      return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
#endif

    case OBJECTS_ERROR:
      break;
  }

  _Objects_Allocator_unlock();

  return RTEMS_INVALID_ID;
}
Example #10
0
rtems_status_code rtems_region_create(
  rtems_name          name,
  void               *starting_address,
  uintptr_t           length,
  uintptr_t           page_size,
  rtems_attribute     attribute_set,
  rtems_id           *id
)
{
  rtems_status_code  return_status;
  Region_Control    *the_region;

  if ( !rtems_is_name_valid( name ) )
    return RTEMS_INVALID_NAME;

  if ( !starting_address )
    return RTEMS_INVALID_ADDRESS;

  if ( !id )
    return RTEMS_INVALID_ADDRESS;

  the_region = _Region_Allocate();

    if ( !the_region )
      return_status = RTEMS_TOO_MANY;

    else {
      _Thread_queue_Initialize( &the_region->Wait_queue );

      if ( _Attributes_Is_priority( attribute_set ) ) {
        the_region->wait_operations = &_Thread_queue_Operations_priority;
      } else {
        the_region->wait_operations = &_Thread_queue_Operations_FIFO;
      }

      the_region->maximum_segment_size = _Heap_Initialize(
        &the_region->Memory, starting_address, length, page_size
      );

      if ( !the_region->maximum_segment_size ) {
        _Region_Free( the_region );
        return_status = RTEMS_INVALID_SIZE;
      } else {
        the_region->attribute_set = attribute_set;

        _Objects_Open(
          &_Region_Information,
          &the_region->Object,
          (Objects_Name) name
        );

        *id = the_region->Object.id;
        return_status = RTEMS_SUCCESSFUL;
      }
    }

  _Objects_Allocator_unlock();

  return return_status;
}
Example #11
0
int sem_init(
  sem_t         *sem,
  int            pshared,
  unsigned int   value
)
{
  int                        status;
  POSIX_Semaphore_Control   *the_semaphore;

  if ( !sem )
    rtems_set_errno_and_return_minus_one( EINVAL );

  _Objects_Allocator_lock();
  status = _POSIX_Semaphore_Create_support(
    NULL,
    0,
    pshared,
    value,
    &the_semaphore
  );
  _Objects_Allocator_unlock();

  if ( status != -1 )
    *sem = the_semaphore->Object.id;

  return status;
}
Example #12
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;
}
Example #13
0
static int shm_ftruncate( rtems_libio_t *iop, off_t length )
{
  int err;
  POSIX_Shm_Control *shm = iop_to_shm( iop );

  _Objects_Allocator_lock();

  err = (*shm->shm_object.ops->object_resize)( &shm->shm_object, length );

  if ( err != 0 ) {
    _Objects_Allocator_unlock();
    rtems_set_errno_and_return_minus_one( err );
  }

  _POSIX_Shm_Update_mtime_ctime( shm );

  _Objects_Allocator_unlock();
  return 0;
}
Example #14
0
/*
 *  15.2.2 Open a Message Queue, P1003.1b-1993, p. 272
 */
mqd_t mq_open(
  const char *name,
  int         oflag,
  ...
  /* mode_t mode, */
  /* struct mq_attr  attr */
)
{
  POSIX_Message_queue_Control *the_mq;
  size_t                       name_len;
  Objects_Get_by_name_error    error;
  mqd_t                        status;

  _Objects_Allocator_lock();
  the_mq = _POSIX_Message_queue_Get_by_name( name, &name_len, &error );

  /*
   *  If the name to id translation worked, then the message queue exists
   *  and we can just return a pointer to the id.  Otherwise we may
   *  need to check to see if this is a "message queue does not exist"
   *  or some other miscellaneous error on the name.
   */
  if ( the_mq == NULL ) {
    va_list               ap;
    const struct mq_attr *attr;

    /*
     * Unless provided a valid name that did not already exist
     * and we are willing to create then it is an error.
     */

    if ( error != OBJECTS_GET_BY_NAME_NO_OBJECT || ( oflag & O_CREAT ) == 0 ) {
      _Objects_Allocator_unlock();
      rtems_set_errno_and_return_value(
        _POSIX_Get_by_name_error( error ),
        MQ_OPEN_FAILED
      );
    }

    va_start( ap, oflag );
    va_arg( ap, mode_t );
    attr = va_arg( ap, const struct mq_attr * );
    va_end( ap );

    if ( attr == NULL ) {
      attr = &_POSIX_Message_queue_Default_attributes;
    }

    /*
     *  At this point, the message queue does not exist and everything has been
     *  checked. We should go ahead and create a message queue.
     */

    status = _POSIX_Message_queue_Create( name, name_len, oflag, attr );
  } else {
Example #15
0
rtems_status_code rtems_rate_monotonic_create(
  rtems_name  name,
  rtems_id   *id
)
{
  Rate_monotonic_Control *the_period;

  if ( !rtems_is_name_valid( name ) )
    return RTEMS_INVALID_NAME;

  if ( !id )
    return RTEMS_INVALID_ADDRESS;

  the_period = _Rate_monotonic_Allocate();

  if ( !the_period ) {
    _Objects_Allocator_unlock();
    return RTEMS_TOO_MANY;
  }

  _ISR_lock_Initialize( &the_period->Lock, "Rate Monotonic Period" );
  _Priority_Node_initialize( &the_period->Priority, 0 );
  _Priority_Node_set_inactive( &the_period->Priority );

  the_period->owner = _Thread_Get_executing();
  the_period->state = RATE_MONOTONIC_INACTIVE;

  _Watchdog_Preinitialize( &the_period->Timer, _Per_CPU_Get_by_index( 0 ) );
  _Watchdog_Initialize( &the_period->Timer, _Rate_monotonic_Timeout );

  _Rate_monotonic_Reset_statistics( the_period );

  _Objects_Open(
    &_Rate_monotonic_Information,
    &the_period->Object,
    (Objects_Name) name
  );

  *id = the_period->Object.id;
  _Objects_Allocator_unlock();
  return RTEMS_SUCCESSFUL;
}
Example #16
0
/**
 *  This directive allows a thread to delete a barrier specified by
 *  the barrier id.  The barrier is freed back to the inactive
 *  barrier chain.
 *
 *  @param[in] barrier is the barrier 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_barrier_destroy(
  pthread_barrier_t *barrier
)
{
  POSIX_Barrier_Control *the_barrier = NULL;
  Objects_Locations      location;

  if ( !barrier )
    return EINVAL;

  _Objects_Allocator_lock();
  the_barrier = _POSIX_Barrier_Get( barrier, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:
      if ( the_barrier->Barrier.number_of_waiting_threads != 0 ) {
        _Objects_Put( &the_barrier->Object );
        return EBUSY;
      }

      _Objects_Close( &_POSIX_Barrier_Information, &the_barrier->Object );
      _Objects_Put( &the_barrier->Object );

      _POSIX_Barrier_Free( the_barrier );
      _Objects_Allocator_unlock();
      return 0;

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

  _Objects_Allocator_unlock();

  return EINVAL;
}
Example #17
0
int timer_delete(
  timer_t timerid
)
{
 /*
  * IDEA: This function must probably stop the timer first and then delete it
  *
  *       It will have to do a call to rtems_timer_cancel and then another
  *       call to rtems_timer_delete.
  *       The call to rtems_timer_delete will be probably unnecessary,
  *       because rtems_timer_delete stops the timer before deleting it.
  */
  POSIX_Timer_Control *ptimer;
  ISR_lock_Context     lock_context;

  _Objects_Allocator_lock();

  ptimer = _POSIX_Timer_Get( timerid, &lock_context );
  if ( ptimer != NULL ) {
    Per_CPU_Control *cpu;

    _Objects_Close( &_POSIX_Timer_Information, &ptimer->Object );
    cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
    ptimer->state = POSIX_TIMER_STATE_FREE;
    _Watchdog_Remove(
      &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_MONOTONIC ],
      &ptimer->Timer
    );
    _POSIX_Timer_Release( cpu, &lock_context );
    _POSIX_Timer_Free( ptimer );
    _Objects_Allocator_unlock();
    return 0;
  }

  _Objects_Allocator_unlock();

  rtems_set_errno_and_return_minus_one( EINVAL );
}
Example #18
0
int pthread_rwlock_destroy(
  pthread_rwlock_t *rwlock
)
{
  POSIX_RWLock_Control *the_rwlock;
  ISR_lock_Context      lock_context;

  _Objects_Allocator_lock();
  the_rwlock = _POSIX_RWLock_Get( rwlock, &lock_context );

  if ( the_rwlock == NULL ) {
    _Objects_Allocator_unlock();
    return EINVAL;
  }

  _CORE_RWLock_Acquire_critical( &the_rwlock->RWLock, &lock_context );

  /*
   *  If there is at least one thread waiting, then do not delete it.
   */

  if ( !_Thread_queue_Is_empty( &the_rwlock->RWLock.Wait_queue.Queue ) ) {
    _CORE_RWLock_Release( &the_rwlock->RWLock, &lock_context );
    _Objects_Allocator_unlock();
    return EBUSY;
  }

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

  _Objects_Close( &_POSIX_RWLock_Information, &the_rwlock->Object );
  _CORE_RWLock_Release( &the_rwlock->RWLock, &lock_context );
  _POSIX_RWLock_Free( the_rwlock );
  _Objects_Allocator_unlock();
  return 0;
}
Example #19
0
int pthread_spin_init(
  pthread_spinlock_t  *spinlock,
  int                  pshared
)
{
  POSIX_Spinlock_Control   *the_spinlock;
  CORE_spinlock_Attributes  attributes;

  if ( !spinlock )
    return EINVAL;

  switch ( pshared ) {
    case PTHREAD_PROCESS_PRIVATE:    /* only supported values */
      break;
    case PTHREAD_PROCESS_SHARED:
    default:
      return EINVAL;
  }

  the_spinlock = _POSIX_Spinlock_Allocate();

  if ( !the_spinlock ) {
    _Objects_Allocator_unlock();
    return EAGAIN;
  }

  _CORE_spinlock_Initialize_attributes( &attributes );

  _CORE_spinlock_Initialize( &the_spinlock->Spinlock, &attributes );

  _Objects_Open_u32( &_POSIX_Spinlock_Information, &the_spinlock->Object, 0 );

  *spinlock = the_spinlock->Object.id;

  _Objects_Allocator_unlock();
  return 0;
}
Example #20
0
/* read() is unspecified for shared memory objects */
static ssize_t shm_read( rtems_libio_t *iop, void *buffer, size_t count )
{
  ssize_t bytes_read;
  POSIX_Shm_Control *shm = iop_to_shm( iop );

  _Objects_Allocator_lock();
  bytes_read = (*shm->shm_object.ops->object_read)(
      &shm->shm_object,
      buffer,
      count
  );
  _POSIX_Shm_Update_atime( shm );

  _Objects_Allocator_unlock();
  return bytes_read;
}
Example #21
0
rtems_status_code rtems_region_delete(
  rtems_id id
)
{
  Objects_Locations   location;
  rtems_status_code   return_status;
  Region_Control     *the_region;

  _Objects_Allocator_lock();

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

      case OBJECTS_LOCAL:
        _Region_Debug_Walk( the_region, 5 );
        if ( the_region->number_of_used_blocks != 0 )
          return_status = RTEMS_RESOURCE_IN_USE;
        else {
          _Objects_Close( &_Region_Information, &the_region->Object );
          _Region_Free( the_region );
          return_status = RTEMS_SUCCESSFUL;
        }
        break;

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

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

  _Objects_Allocator_unlock();

  return return_status;
}
Example #22
0
rtems_status_code rtems_extension_delete(
  rtems_id id
)
{
  rtems_status_code  status;
  Extension_Control *the_extension;

  _Objects_Allocator_lock();

  the_extension = _Extension_Get( id );

  if ( the_extension != NULL ) {
    _Objects_Close( &_Extension_Information, &the_extension->Object );
    _User_extensions_Remove_set( &the_extension->Extension );
    _Extension_Free( the_extension );
    status = RTEMS_SUCCESSFUL;
  } else {
    status = RTEMS_INVALID_ID;
  }

  _Objects_Allocator_unlock();
  return status;
}
Example #23
0
int pthread_mutex_init(
  pthread_mutex_t           *mutex,
  const pthread_mutexattr_t *attr
)
{
  POSIX_Mutex_Control          *the_mutex;
  CORE_mutex_Attributes        *the_mutex_attr;
  const pthread_mutexattr_t    *the_attr;
  CORE_mutex_Disciplines        the_discipline;

  if ( attr ) the_attr = attr;
  else        the_attr = &_POSIX_Mutex_Default_attributes;

  /* Check for NULL mutex */
  if ( !mutex )
    return EINVAL;

  /*
   *  This code should eventually be removed.
   *
   *  Although the POSIX specification says:
   *
   *  "Attempting to initialize an already initialized mutex results
   *  in undefined behavior."
   *
   *  Trying to keep the caller from doing the create when *mutex
   *  is actually a valid ID causes grief.  All it takes is the wrong
   *  value in an uninitialized variable to make this fail.  As best
   *  I can tell, RTEMS was the only pthread implementation to choose
   *  this option for "undefined behavior" and doing so has created
   *  portability problems.  In particular, Rosimildo DaSilva
   *  <*****@*****.**> saw seemingly random failures in the
   *  RTEMS port of omniORB2 when this code was enabled.
   *
   *  Joel Sherrill <*****@*****.**>     14 May 1999
   *  NOTE: Be careful to avoid infinite recursion on call to this
   *        routine in _POSIX_Mutex_Get.
   */
  #if 0
  {
    POSIX_Mutex_Control *mutex_in_use;
    Objects_Locations    location;

    if ( *mutex != PTHREAD_MUTEX_INITIALIZER ) {

      /* EBUSY if *mutex is a valid id */

      mutex_in_use = _POSIX_Mutex_Get( mutex, &location );
      switch ( location ) {
        case OBJECTS_LOCAL:
          _Objects_Put( &mutex_in_use->Object );
          return EBUSY;
        #if defined(RTEMS_MULTIPROCESSING)
          case OBJECTS_REMOTE:
        #endif
        case OBJECTS_ERROR:
          break;
      }
    }
  }
  #endif

  if ( !the_attr->is_initialized )
    return EINVAL;

  /*
   *  We only support process private mutexes.
   */
  if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED )
    return ENOSYS;

  if ( the_attr->process_shared != PTHREAD_PROCESS_PRIVATE )
    return EINVAL;

  /*
   *  Determine the discipline of the mutex
   */
  switch ( the_attr->protocol ) {
    case PTHREAD_PRIO_NONE:
      the_discipline = CORE_MUTEX_DISCIPLINES_FIFO;
      break;
    case PTHREAD_PRIO_INHERIT:
      the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
      break;
    case PTHREAD_PRIO_PROTECT:
      the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
      break;
    default:
      return EINVAL;
  }

  /*
   *  Validate the priority ceiling field -- should always be valid.
   */
  if ( !_POSIX_Priority_Is_valid( the_attr->prio_ceiling ) )
    return EINVAL;

#if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES)
  /*
   *  Validate the mutex type and set appropriate SuperCore mutex
   *  attributes.
   */
  switch ( the_attr->type ) {
    case PTHREAD_MUTEX_NORMAL:
    case PTHREAD_MUTEX_RECURSIVE:
    case PTHREAD_MUTEX_ERRORCHECK:
    case PTHREAD_MUTEX_DEFAULT:
      break;

    default:
      return EINVAL;
  }
#endif

  the_mutex = _POSIX_Mutex_Allocate();

  if ( !the_mutex ) {
    _Objects_Allocator_unlock();
    return EAGAIN;
  }

  the_mutex->process_shared = the_attr->process_shared;

  the_mutex_attr = &the_mutex->Mutex.Attributes;

  if ( the_attr->type == PTHREAD_MUTEX_RECURSIVE )
    the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
  else
    the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_IS_ERROR;
  the_mutex_attr->only_owner_release = true;
  the_mutex_attr->priority_ceiling =
    _POSIX_Priority_To_core( the_attr->prio_ceiling );
  the_mutex_attr->discipline = the_discipline;

  /*
   *  Must be initialized to unlocked.
   */
  _CORE_mutex_Initialize( &the_mutex->Mutex, NULL, the_mutex_attr, false );

  _Objects_Open_u32( &_POSIX_Mutex_Information, &the_mutex->Object, 0 );

  *mutex = the_mutex->Object.id;

  _Objects_Allocator_unlock();
  return 0;
}
Example #24
0
rtems_status_code rtems_region_create(
  rtems_name          name,
  void               *starting_address,
  uintptr_t           length,
  uintptr_t           page_size,
  rtems_attribute     attribute_set,
  rtems_id           *id
)
{
  rtems_status_code  return_status;
  Region_Control    *the_region;

  if ( !rtems_is_name_valid( name ) )
    return RTEMS_INVALID_NAME;

  if ( !starting_address )
    return RTEMS_INVALID_ADDRESS;

  if ( !id )
    return RTEMS_INVALID_ADDRESS;

  the_region = _Region_Allocate();

    if ( !the_region )
      return_status = RTEMS_TOO_MANY;

    else {

      the_region->maximum_segment_size = _Heap_Initialize(
        &the_region->Memory, starting_address, length, page_size
      );

      if ( !the_region->maximum_segment_size ) {
        _Region_Free( the_region );
        return_status = RTEMS_INVALID_SIZE;
      }

      else {

        the_region->starting_address      = starting_address;
        the_region->length                = length;
        the_region->page_size             = page_size;
        the_region->attribute_set         = attribute_set;
        the_region->number_of_used_blocks = 0;

        _Thread_queue_Initialize(
          &the_region->Wait_queue,
          _Attributes_Is_priority( attribute_set ) ?
             THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,
          STATES_WAITING_FOR_SEGMENT,
          RTEMS_TIMEOUT
        );

        _Objects_Open(
          &_Region_Information,
          &the_region->Object,
          (Objects_Name) name
        );

        *id = the_region->Object.id;
        return_status = RTEMS_SUCCESSFUL;
      }
    }

  _Objects_Allocator_unlock();

  return return_status;
}
Example #25
0
int pthread_rwlock_init(
  pthread_rwlock_t           *rwlock,
  const pthread_rwlockattr_t *attr
)
{
  POSIX_RWLock_Control        *the_rwlock;
  CORE_RWLock_Attributes       the_attributes;
  pthread_rwlockattr_t         default_attr;
  const pthread_rwlockattr_t  *the_attr;

  /*
   *  Error check parameters
   */
  if ( !rwlock )
    return EINVAL;

  /*
   * If the user passed in NULL, use the default attributes
   */
  if ( attr ) {
    the_attr = attr;
  } else {
    (void) pthread_rwlockattr_init( &default_attr );
    the_attr = &default_attr;
  }

  /*
   * Now start error checking the attributes that we are going to use
   */
  if ( !the_attr->is_initialized )
    return EINVAL;

  switch ( the_attr->process_shared ) {
    case PTHREAD_PROCESS_PRIVATE:    /* only supported values */
      break;
    case PTHREAD_PROCESS_SHARED:
    default:
      return EINVAL;
  }

  /*
   * Convert from POSIX attributes to Core RWLock attributes
   * 
   * NOTE: Currently there are no core rwlock attributes
   */
  _CORE_RWLock_Initialize_attributes( &the_attributes );

  the_rwlock = _POSIX_RWLock_Allocate();

  if ( !the_rwlock ) {
    _Objects_Allocator_unlock();
    return EAGAIN;
  }

  _CORE_RWLock_Initialize( &the_rwlock->RWLock, &the_attributes );

  _Objects_Open_u32(
    &_POSIX_RWLock_Information,
    &the_rwlock->Object,
    0
  );

  *rwlock = the_rwlock->Object.id;

  _Objects_Allocator_unlock();
  return 0;
}
Example #26
0
rtems_status_code rtems_semaphore_create(
  rtems_name           name,
  uint32_t             count,
  rtems_attribute      attribute_set,
  rtems_task_priority  priority_ceiling,
  rtems_id            *id
)
{
  Semaphore_Control          *the_semaphore;
  CORE_mutex_Attributes       the_mutex_attr;
  CORE_semaphore_Attributes   the_semaphore_attr;
  CORE_mutex_Status           mutex_status;

  if ( !rtems_is_name_valid( name ) )
    return RTEMS_INVALID_NAME;

  if ( !id )
    return RTEMS_INVALID_ADDRESS;

#if defined(RTEMS_MULTIPROCESSING)
  if ( _Attributes_Is_global( attribute_set ) ) {

    if ( !_System_state_Is_multiprocessing )
      return RTEMS_MP_NOT_CONFIGURED;

    if ( _Attributes_Is_inherit_priority( attribute_set ) ||
         _Attributes_Is_priority_ceiling( attribute_set ) ||
         _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) )
      return RTEMS_NOT_DEFINED;

  } else
#endif

  if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) &&
       !( _Attributes_Is_binary_semaphore( attribute_set ) &&
         !_Attributes_Is_priority( attribute_set ) ) ) {
    return RTEMS_NOT_DEFINED;
  }

  if ( _Attributes_Is_inherit_priority( attribute_set ) ||
              _Attributes_Is_priority_ceiling( attribute_set ) ) {

    if ( ! (_Attributes_Is_binary_semaphore( attribute_set ) &&
            _Attributes_Is_priority( attribute_set ) ) )
      return RTEMS_NOT_DEFINED;

  }

  if ( !_Attributes_Has_at_most_one_protocol( attribute_set ) )
    return RTEMS_NOT_DEFINED;

  if ( !_Attributes_Is_counting_semaphore( attribute_set ) && ( count > 1 ) )
    return RTEMS_INVALID_NUMBER;

#if !defined(RTEMS_SMP)
  /*
   * On uni-processor configurations the Multiprocessor Resource Sharing
   * Protocol is equivalent to the Priority Ceiling Protocol.
   */
  if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) {
    attribute_set |= RTEMS_PRIORITY_CEILING | RTEMS_PRIORITY;
  }
#endif

  the_semaphore = _Semaphore_Allocate();

  if ( !the_semaphore ) {
    _Objects_Allocator_unlock();
    return RTEMS_TOO_MANY;
  }

#if defined(RTEMS_MULTIPROCESSING)
  if ( _Attributes_Is_global( attribute_set ) &&
       ! ( _Objects_MP_Allocate_and_open( &_Semaphore_Information, name,
                            the_semaphore->Object.id, false ) ) ) {
    _Semaphore_Free( the_semaphore );
    _Objects_Allocator_unlock();
    return RTEMS_TOO_MANY;
  }
#endif

  the_semaphore->attribute_set = attribute_set;

  /*
   *  Initialize it as a counting semaphore.
   */
  if ( _Attributes_Is_counting_semaphore( attribute_set ) ) {
    /*
     *  This effectively disables limit checking.
     */
    the_semaphore_attr.maximum_count = 0xFFFFFFFF;

    if ( _Attributes_Is_priority( attribute_set ) )
      the_semaphore_attr.discipline = CORE_SEMAPHORE_DISCIPLINES_PRIORITY;
    else
      the_semaphore_attr.discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO;

    /*
     *  The following are just to make Purify happy.
     */
    the_mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
    the_mutex_attr.priority_ceiling = PRIORITY_MINIMUM;

    _CORE_semaphore_Initialize(
      &the_semaphore->Core_control.semaphore,
      &the_semaphore_attr,
      count
    );
#if defined(RTEMS_SMP)
  } else if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) {
    MRSP_Status mrsp_status = _MRSP_Initialize(
      &the_semaphore->Core_control.mrsp,
      priority_ceiling,
      _Thread_Get_executing(),
      count != 1
    );

    if ( mrsp_status != MRSP_SUCCESSFUL ) {
      _Semaphore_Free( the_semaphore );
      _Objects_Allocator_unlock();

      return _Semaphore_Translate_MRSP_status_code( mrsp_status );
    }
#endif
  } else {
    /*
     *  It is either simple binary semaphore or a more powerful mutex
     *  style binary semaphore.  This is the mutex style.
     */
    if ( _Attributes_Is_priority( attribute_set ) )
      the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY;
    else
      the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_FIFO;

    if ( _Attributes_Is_binary_semaphore( attribute_set ) ) {
      the_mutex_attr.priority_ceiling      = _RTEMS_tasks_Priority_to_Core(
                                               priority_ceiling
                                             );
      the_mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
      the_mutex_attr.only_owner_release    = false;

      if ( the_mutex_attr.discipline == CORE_MUTEX_DISCIPLINES_PRIORITY ) {
        if ( _Attributes_Is_inherit_priority( attribute_set ) ) {
          the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
          the_mutex_attr.only_owner_release = true;
        } else if ( _Attributes_Is_priority_ceiling( attribute_set ) ) {
          the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
          the_mutex_attr.only_owner_release = true;
        }
      }
    } else /* must be simple binary semaphore */ {
      the_mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_BLOCKS;
      the_mutex_attr.only_owner_release = false;
    }

    mutex_status = _CORE_mutex_Initialize(
      &the_semaphore->Core_control.mutex,
      _Thread_Get_executing(),
      &the_mutex_attr,
      count != 1
    );

    if ( mutex_status == CORE_MUTEX_STATUS_CEILING_VIOLATED ) {
      _Semaphore_Free( the_semaphore );
      _Objects_Allocator_unlock();
      return RTEMS_INVALID_PRIORITY;
    }
  }

  /*
   *  Whether we initialized it as a mutex or counting semaphore, it is
   *  now ready to be "offered" for use as a Classic API Semaphore.
   */
  _Objects_Open(
    &_Semaphore_Information,
    &the_semaphore->Object,
    (Objects_Name) name
  );

  *id = the_semaphore->Object.id;

#if defined(RTEMS_MULTIPROCESSING)
  if ( _Attributes_Is_global( attribute_set ) )
    _Semaphore_MP_Send_process_packet(
      SEMAPHORE_MP_ANNOUNCE_CREATE,
      the_semaphore->Object.id,
      name,
      0                          /* Not used */
    );
#endif
  _Objects_Allocator_unlock();
  return RTEMS_SUCCESSFUL;
}
Example #27
0
int shm_open( const char *name, int oflag, mode_t mode )
{
  int err = 0;
  int fd;
  rtems_libio_t *iop;
  POSIX_Shm_Control *shm;
  size_t len;
  Objects_Get_by_name_error obj_err;
  unsigned int flags;

  if ( shm_check_oflag( oflag ) != 0 ) {
    return -1;
  }

  iop = rtems_libio_allocate();
  if ( iop == NULL ) {
    rtems_set_errno_and_return_minus_one( EMFILE );
  }

  _Objects_Allocator_lock();
  shm = _POSIX_Shm_Get_by_name( name, &len, &obj_err );

  if ( shm == NULL ) {
    switch ( obj_err ) {
      case OBJECTS_GET_BY_NAME_INVALID_NAME:
        err = EINVAL;
        break;

      case OBJECTS_GET_BY_NAME_NAME_TOO_LONG:
        err = ENAMETOOLONG;
        break;

      case OBJECTS_GET_BY_NAME_NO_OBJECT:
      default:
        shm = shm_allocate(name, len, oflag, mode, &err);
        break;
    }
  } else { /* shm exists */
    if ( ( oflag & ( O_EXCL | O_CREAT ) ) == ( O_EXCL | O_CREAT ) ) {
      /* Request to create failed. */
      err = EEXIST;
    } else if ( !shm_access_ok( shm, oflag ) ) {
      err = EACCES;
    } else {
      ++shm->reference_count;
    }
  }
  _Objects_Allocator_unlock();
  if ( err != 0 ) {
    rtems_libio_free( iop );
    rtems_set_errno_and_return_minus_one( err );
  }

  if ( oflag & O_TRUNC ) {
    err = shm_ftruncate( iop, 0 );
    (void) err; /* ignore truncate error */
  }

  fd = rtems_libio_iop_to_descriptor( iop );
  iop->data0 = fd;
  iop->data1 = shm;
  iop->pathinfo.node_access = shm;
  iop->pathinfo.handlers = &shm_handlers;
  iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry;
  rtems_filesystem_location_add_to_mt_entry( &iop->pathinfo );

  flags = LIBIO_FLAGS_CLOSE_ON_EXEC;
  if ( oflag & O_RDONLY ) {
    flags |= LIBIO_FLAGS_READ;
  } else {
    flags |= LIBIO_FLAGS_READ_WRITE;
  }

  rtems_libio_iop_flags_initialize( iop, flags );

  return fd;
}
Example #28
0
rtems_status_code rtems_semaphore_delete(
  rtems_id   id
)
{
  Semaphore_Control    *the_semaphore;
  Thread_queue_Context  queue_context;
  Status_Control        status;

  _Objects_Allocator_lock();
  the_semaphore = _Semaphore_Get( id, &queue_context );

  if ( the_semaphore == NULL ) {
    _Objects_Allocator_unlock();

#if defined(RTEMS_MULTIPROCESSING)
    if ( _Semaphore_MP_Is_remote( id ) ) {
      return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
    }
#endif

    return RTEMS_INVALID_ID;
  }

  _Thread_queue_Acquire_critical(
    &the_semaphore->Core_control.Wait_queue,
    &queue_context.Lock_context
  );

  switch ( the_semaphore->variant ) {
    case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY:
    case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
    case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
      if (
        _CORE_mutex_Is_locked(
          &the_semaphore->Core_control.Mutex.Recursive.Mutex
        )
      ) {
        status = STATUS_RESOURCE_IN_USE;
      } else {
        status = STATUS_SUCCESSFUL;
      }

      break;
#if defined(RTEMS_SMP)
    case SEMAPHORE_VARIANT_MRSP:
      status = _MRSP_Can_destroy( &the_semaphore->Core_control.MRSP );
      break;
#endif
    default:
      _Assert(
        the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
          || the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING
      );
      status = STATUS_SUCCESSFUL;
      break;
  }

  if ( status != STATUS_SUCCESSFUL ) {
    _Thread_queue_Release(
      &the_semaphore->Core_control.Wait_queue,
      &queue_context.Lock_context
    );
    _Objects_Allocator_unlock();
    return _Status_Get( status );
  }

  _Objects_Close( &_Semaphore_Information, &the_semaphore->Object );

  switch ( the_semaphore->variant ) {
#if defined(RTEMS_SMP)
    case SEMAPHORE_VARIANT_MRSP:
      _MRSP_Destroy( &the_semaphore->Core_control.MRSP, &queue_context );
      break;
#endif
    default:
      _Assert(
        the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY
          || the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING
          || the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL
          || the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
          || the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING
      );
      _Thread_queue_Flush_critical(
        &the_semaphore->Core_control.Wait_queue.Queue,
        _Semaphore_Get_operations( the_semaphore ),
        _Thread_queue_Flush_status_object_was_deleted,
        &queue_context
      );
      _Thread_queue_Destroy( &the_semaphore->Core_control.Wait_queue );
      break;
  }

#if defined(RTEMS_MULTIPROCESSING)
  if ( the_semaphore->is_global ) {

    _Objects_MP_Close( &_Semaphore_Information, id );

    _Semaphore_MP_Send_process_packet(
      SEMAPHORE_MP_ANNOUNCE_DELETE,
      id,
      0,                         /* Not used */
      0                          /* Not used */
    );
  }
#endif

  _Semaphore_Free( the_semaphore );
  _Objects_Allocator_unlock();
  return RTEMS_SUCCESSFUL;
}
Example #29
0
rtems_status_code rtems_task_create(
  rtems_name           name,
  rtems_task_priority  initial_priority,
  size_t               stack_size,
  rtems_mode           initial_modes,
  rtems_attribute      attribute_set,
  rtems_id            *id
)
{
  Thread_Control          *the_thread;
  bool                     is_fp;
#if defined(RTEMS_MULTIPROCESSING)
  Objects_MP_Control      *the_global_object = NULL;
  bool                     is_global;
#endif
  bool                     status;
  rtems_attribute          the_attribute_set;
  Priority_Control         core_priority;
  RTEMS_API_Control       *api;
  ASR_Information         *asr;


  if ( !id )
   return RTEMS_INVALID_ADDRESS;

  if ( !rtems_is_name_valid( name ) )
    return RTEMS_INVALID_NAME;

  /*
   *  Core Thread Initialize insures we get the minimum amount of
   *  stack space.
   */

  /*
   *  Fix the attribute set to match the attributes which
   *  this processor (1) requires and (2) is able to support.
   *  First add in the required flags for attribute_set
   *  Typically this might include FP if the platform
   *  or application required all tasks to be fp aware.
   *  Then turn off the requested bits which are not supported.
   */

  the_attribute_set = _Attributes_Set( attribute_set, ATTRIBUTES_REQUIRED );
  the_attribute_set =
    _Attributes_Clear( the_attribute_set, ATTRIBUTES_NOT_SUPPORTED );

  if ( _Attributes_Is_floating_point( the_attribute_set ) )
    is_fp = true;
  else
    is_fp = false;

  /*
   *  Validate the RTEMS API priority and convert it to the core priority range.
   */

  if ( !_Attributes_Is_system_task( the_attribute_set ) ) {
    if ( !_RTEMS_tasks_Priority_is_valid( initial_priority ) )
      return RTEMS_INVALID_PRIORITY;
  }

  core_priority = _RTEMS_tasks_Priority_to_Core( initial_priority );

#if defined(RTEMS_MULTIPROCESSING)
  if ( _Attributes_Is_global( the_attribute_set ) ) {

    is_global = true;

    if ( !_System_state_Is_multiprocessing )
      return RTEMS_MP_NOT_CONFIGURED;

  } else
    is_global = false;
#endif

  /*
   *  Make sure system is MP if this task is global
   */

  /*
   *  Allocate the thread control block and -- if the task is global --
   *  allocate a global object control block.
   *
   *  NOTE:  This routine does not use the combined allocate and open
   *         global object routine because this results in a lack of
   *         control over when memory is allocated and can be freed in
   *         the event of an error.
   */

  the_thread = _RTEMS_tasks_Allocate();

  if ( !the_thread ) {
    _Objects_Allocator_unlock();
    return RTEMS_TOO_MANY;
  }

#if defined(RTEMS_MULTIPROCESSING)
  if ( is_global ) {
    the_global_object = _Objects_MP_Allocate_global_object();

    if ( _Objects_MP_Is_null_global_object( the_global_object ) ) {
      _RTEMS_tasks_Free( the_thread );
      _Objects_Allocator_unlock();
      return RTEMS_TOO_MANY;
    }
  }
#endif

  /*
   *  Initialize the core thread for this task.
   */

  status = _Thread_Initialize(
    &_RTEMS_tasks_Information,
    the_thread,
    _Scheduler_Get_by_CPU_index( _SMP_Get_current_processor() ),
    NULL,
    stack_size,
    is_fp,
    core_priority,
    _Modes_Is_preempt(initial_modes)   ? true : false,
    _Modes_Is_timeslice(initial_modes) ?
      THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE :
      THREAD_CPU_BUDGET_ALGORITHM_NONE,
    NULL,        /* no budget algorithm callout */
    _Modes_Get_interrupt_level(initial_modes),
    (Objects_Name) name
  );

  if ( !status ) {
#if defined(RTEMS_MULTIPROCESSING)
    if ( is_global )
      _Objects_MP_Free_global_object( the_global_object );
#endif
    _RTEMS_tasks_Free( the_thread );
    _Objects_Allocator_unlock();
    return RTEMS_UNSATISFIED;
  }

  api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
  asr = &api->Signal;

  asr->is_enabled = _Modes_Is_asr_disabled(initial_modes) ? false : true;

  *id = the_thread->Object.id;

#if defined(RTEMS_MULTIPROCESSING)
  the_thread->is_global = is_global;
  if ( is_global ) {

    _Objects_MP_Open(
      &_RTEMS_tasks_Information.Objects,
      the_global_object,
      name,
      the_thread->Object.id
    );

    _RTEMS_tasks_MP_Send_process_packet(
      RTEMS_TASKS_MP_ANNOUNCE_CREATE,
      the_thread->Object.id,
      name
    );

   }
#endif

  _Objects_Allocator_unlock();
  return RTEMS_SUCCESSFUL;
}