void _MPCI_Handler_initialization( uint32_t timeout_status ) { CORE_semaphore_Attributes attributes; MPCI_Control *users_mpci_table; users_mpci_table = _Configuration_MP_table->User_mpci_table; if ( _System_state_Is_multiprocessing && !users_mpci_table ) _Internal_error_Occurred( INTERNAL_ERROR_CORE, true, INTERNAL_ERROR_NO_MPCI ); _MPCI_table = users_mpci_table; if ( !_System_state_Is_multiprocessing ) return; /* * Register the MP Process Packet routine. */ _MPCI_Register_packet_processor( MP_PACKET_MPCI_INTERNAL, _MPCI_Internal_packets_Process_packet ); /* * Create the counting semaphore used by the MPCI Receive Server. */ attributes.discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO; _CORE_semaphore_Initialize( &_MPCI_Semaphore, &attributes, /* the_semaphore_attributes */ 0 /* initial_value */ ); _Thread_queue_Initialize( &_MPCI_Remote_blocked_threads, THREAD_QUEUE_DISCIPLINE_FIFO, STATES_WAITING_FOR_RPC_REPLY, timeout_status ); }
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; }
/* * _POSIX_Semaphore_Create_support * * This routine does the actual creation and initialization of * a poxix semaphore. It is a support routine for sem_init and * sem_open. */ int _POSIX_Semaphore_Create_support( const char *name_arg, size_t name_len, int pshared, unsigned int value, POSIX_Semaphore_Control **the_sem ) { POSIX_Semaphore_Control *the_semaphore; CORE_semaphore_Attributes *the_sem_attr; char *name; /* Sharing semaphores among processes is not currently supported */ if (pshared != 0) rtems_set_errno_and_return_minus_one( ENOSYS ); the_semaphore = _POSIX_Semaphore_Allocate_unprotected(); if ( !the_semaphore ) { rtems_set_errno_and_return_minus_one( ENOSPC ); } /* * Make a copy of the user's string for name just in case it was * dynamically constructed. */ if ( name_arg != NULL ) { name = _Workspace_String_duplicate( name_arg, name_len ); if ( !name ) { _POSIX_Semaphore_Free( the_semaphore ); rtems_set_errno_and_return_minus_one( ENOMEM ); } } else { name = NULL; } the_semaphore->process_shared = pshared; if ( name ) { the_semaphore->named = true; the_semaphore->open_count = 1; the_semaphore->linked = true; } else { the_semaphore->named = false; the_semaphore->open_count = 0; the_semaphore->linked = false; } the_sem_attr = &the_semaphore->Semaphore.Attributes; /* * POSIX does not appear to specify what the discipline for * blocking tasks on this semaphore should be. It could somehow * be derived from the current scheduling policy. One * thing is certain, no matter what we decide, it won't be * the same as all other POSIX implementations. :) */ the_sem_attr->discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO; /* * This effectively disables limit checking. */ the_sem_attr->maximum_count = 0xFFFFFFFF; _CORE_semaphore_Initialize( &the_semaphore->Semaphore, the_sem_attr, value ); /* * Make the semaphore available for use. */ _Objects_Open_string( &_POSIX_Semaphore_Information, &the_semaphore->Object, name ); *the_sem = the_semaphore; 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; }