rtems_status_code rtems_semaphore_delete( rtems_id id ) { register Semaphore_Control *the_semaphore; Objects_Locations location; the_semaphore = _Semaphore_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) { if ( _CORE_mutex_Is_locked( &the_semaphore->Core_control.mutex ) && !_Attributes_Is_simple_binary_semaphore( the_semaphore->attribute_set ) ) { _Thread_Enable_dispatch(); return RTEMS_RESOURCE_IN_USE; } _CORE_mutex_Flush( &the_semaphore->Core_control.mutex, SEMAPHORE_MP_OBJECT_WAS_DELETED, CORE_MUTEX_WAS_DELETED ); } else { _CORE_semaphore_Flush( &the_semaphore->Core_control.semaphore, SEMAPHORE_MP_OBJECT_WAS_DELETED, CORE_SEMAPHORE_WAS_DELETED ); } _Objects_Close( &_Semaphore_Information, &the_semaphore->Object ); _Semaphore_Free( the_semaphore ); #if defined(RTEMS_MULTIPROCESSING) if ( _Attributes_Is_global( the_semaphore->attribute_set ) ) { _Objects_MP_Close( &_Semaphore_Information, the_semaphore->Object.id ); _Semaphore_MP_Send_process_packet( SEMAPHORE_MP_ANNOUNCE_DELETE, the_semaphore->Object.id, 0, /* Not used */ 0 /* Not used */ ); } #endif _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: _Thread_Dispatch(); return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; #endif case OBJECTS_ERROR: break; } return RTEMS_INVALID_ID; }
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; }
rtems_status_code rtems_semaphore_create( rtems_name name, uint32_t count, rtems_attribute attribute_set, rtems_task_priority priority_ceiling, rtems_id *id ) { register 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 ) ) return RTEMS_NOT_DEFINED; } else #endif 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_Is_inherit_priority( attribute_set ) && _Attributes_Is_priority_ceiling( attribute_set ) ) return RTEMS_NOT_DEFINED; if ( !_Attributes_Is_counting_semaphore( attribute_set ) && ( count > 1 ) ) return RTEMS_INVALID_NUMBER; _Thread_Disable_dispatch(); /* prevents deletion */ the_semaphore = _Semaphore_Allocate(); if ( !the_semaphore ) { _Thread_Enable_dispatch(); 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 ); _Thread_Enable_dispatch(); 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 ); } 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 = 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, &the_mutex_attr, (count == 1) ? CORE_MUTEX_UNLOCKED : CORE_MUTEX_LOCKED ); if ( mutex_status == CORE_MUTEX_STATUS_CEILING_VIOLATED ) { _Semaphore_Free( the_semaphore ); _Thread_Enable_dispatch(); 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 _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; }
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; }