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; }
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; }
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; }
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; }
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; }
/* * 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; }
/* * 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; }
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; }
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; }
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; }
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; }
/** * 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; }
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; }
/* * 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 {
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; }
/** * 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; }
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 ); }
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; }
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; }
/* 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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }