int pthread_cond_init( pthread_cond_t *cond, const pthread_condattr_t *attr ) { POSIX_Condition_variables_Control *the_cond; const pthread_condattr_t *the_attr; if ( attr ) the_attr = attr; else the_attr = &_POSIX_Condition_variables_Default_attributes; /* * Be careful about attributes when global!!! */ if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED ) return EINVAL; if ( !the_attr->is_initialized ) return EINVAL; _Thread_Disable_dispatch(); the_cond = _POSIX_Condition_variables_Allocate(); if ( !the_cond ) { _Thread_Enable_dispatch(); return ENOMEM; } the_cond->process_shared = the_attr->process_shared; the_cond->Mutex = POSIX_CONDITION_VARIABLES_NO_MUTEX; _Thread_queue_Initialize( &the_cond->Wait_queue, THREAD_QUEUE_DISCIPLINE_FIFO, STATES_WAITING_FOR_CONDITION_VARIABLE | STATES_INTERRUPTIBLE_BY_SIGNAL, ETIMEDOUT ); _Objects_Open_u32( &_POSIX_Condition_variables_Information, &the_cond->Object, 0 ); *cond = the_cond->Object.id; _Thread_Enable_dispatch(); return 0; }
void _API_Mutex_Allocate( API_Mutex_Control **the_mutex ) { API_Mutex_Control *mutex; mutex = (API_Mutex_Control *) _Objects_Allocate_unprotected( &_API_Mutex_Information ); _Assert( mutex != NULL ); _CORE_recursive_mutex_Initialize( &mutex->Mutex ); _Objects_Open_u32( &_API_Mutex_Information, &mutex->Object, 1 ); *the_mutex = mutex; }
void _API_Mutex_Allocate( API_Mutex_Control **the_mutex ) { API_Mutex_Control *mutex; CORE_mutex_Attributes attr = { CORE_MUTEX_NESTING_IS_ERROR, false, CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT, 0 }; mutex = (API_Mutex_Control *) _Objects_Allocate( &_API_Mutex_Information ); _CORE_mutex_Initialize( &mutex->Mutex, &attr, CORE_MUTEX_UNLOCKED ); _Objects_Open_u32( &_API_Mutex_Information, &mutex->Object, 1 ); *the_mutex = mutex; }
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; } _Thread_Disable_dispatch(); /* prevents deletion */ the_spinlock = _POSIX_Spinlock_Allocate(); if ( !the_spinlock ) { _Thread_Enable_dispatch(); 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; _Thread_Enable_dispatch(); return 0; }
void _API_Mutex_Allocate( API_Mutex_Control **the_mutex ) { API_Mutex_Control *mutex; CORE_mutex_Attributes attr = { CORE_MUTEX_NESTING_ACQUIRES, true, CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT, 0 }; mutex = (API_Mutex_Control *) _Objects_Allocate_unprotected( &_API_Mutex_Information ); _Assert( mutex != NULL ); _CORE_mutex_Initialize( &mutex->Mutex, NULL, &attr, false ); _Objects_Open_u32( &_API_Mutex_Information, &mutex->Object, 1 ); *the_mutex = mutex; }
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 ); /* * Enter dispatching critical section to allocate and initialize RWLock */ _Thread_Disable_dispatch(); /* prevents deletion */ the_rwlock = _POSIX_RWLock_Allocate(); if ( !the_rwlock ) { _Thread_Enable_dispatch(); 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; _Thread_Enable_dispatch(); return 0; }
int pthread_key_create( pthread_key_t *key, void (*destructor)( void * ) ) { POSIX_Keys_Control *the_key; void *table; uint32_t the_api; uint32_t bytes_to_allocate; _Thread_Disable_dispatch(); the_key = _POSIX_Keys_Allocate(); if ( !the_key ) { _Thread_Enable_dispatch(); return EAGAIN; } the_key->destructor = destructor; /* * This is a bit more complex than one might initially expect because * APIs are optional. * * NOTE: Currently RTEMS Classic API tasks are always enabled. */ for ( the_api = 1; the_api <= OBJECTS_APIS_LAST; the_api++ ) { the_key->Values[ the_api ] = NULL; #if defined(RTEMS_DEBUG) /* * Since the removal of ITRON, this cannot occur. */ if ( !_Objects_Information_table[ the_api ] ) continue; /* * Currently all managers are installed if the API is installed. * This would be a horrible implementation error. */ if (_Objects_Information_table[ the_api ][ 1 ] == NULL ) _Internal_error_Occurred( INTERNAL_ERROR_CORE, true, INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY ); #endif bytes_to_allocate = sizeof( void * ) * (_Objects_Information_table[ the_api ][ 1 ]->maximum + 1); table = _Workspace_Allocate( bytes_to_allocate ); if ( !table ) { _POSIX_Keys_Free_memory( the_key ); _POSIX_Keys_Free( the_key ); _Thread_Enable_dispatch(); return ENOMEM; } the_key->Values[ the_api ] = table; memset( table, '\0', bytes_to_allocate ); } _Objects_Open_u32( &_POSIX_Keys_Information, &the_key->Object, 0 ); *key = the_key->Object.id; _Thread_Enable_dispatch(); return 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; }
int pthread_barrier_init( pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count ) { POSIX_Barrier_Control *the_barrier; CORE_barrier_Attributes the_attributes; pthread_barrierattr_t my_attr; const pthread_barrierattr_t *the_attr; /* * Error check parameters */ if ( !barrier ) return EINVAL; if ( count == 0 ) return EINVAL; /* * If the user passed in NULL, use the default attributes */ if ( attr ) { the_attr = attr; } else { (void) pthread_barrierattr_init( &my_attr ); the_attr = &my_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 Barrier attributes */ the_attributes.discipline = CORE_BARRIER_AUTOMATIC_RELEASE; the_attributes.maximum_count = count; /* * Enter dispatching critical section to allocate and initialize barrier */ _Thread_Disable_dispatch(); /* prevents deletion */ the_barrier = _POSIX_Barrier_Allocate(); if ( !the_barrier ) { _Thread_Enable_dispatch(); return EAGAIN; } _CORE_barrier_Initialize( &the_barrier->Barrier, &the_attributes ); _Objects_Open_u32( &_POSIX_Barrier_Information, &the_barrier->Object, 0 ); /* * Exit the critical section and return the user an operational barrier */ *barrier = the_barrier->Object.id; _Thread_Enable_dispatch(); return 0; }