CORE_mutex_Status _CORE_mutex_Initialize( CORE_mutex_Control *the_mutex, Thread_Control *executing, const CORE_mutex_Attributes *the_mutex_attributes, bool initially_locked ) { /* Add this to the RTEMS environment later ????????? rtems_assert( initial_lock == CORE_MUTEX_LOCKED || initial_lock == CORE_MUTEX_UNLOCKED ); */ the_mutex->Attributes = *the_mutex_attributes; if ( initially_locked ) { the_mutex->nest_count = 1; the_mutex->holder = executing; if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) || _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) { Priority_Control ceiling = the_mutex->Attributes.priority_ceiling; /* * The mutex initialization is only protected by the allocator lock in * general. Disable thread dispatching before the priority check to * prevent interference with priority inheritance. */ _Thread_Disable_dispatch(); if ( executing->current_priority < ceiling ) { _Thread_Enable_dispatch(); return CORE_MUTEX_STATUS_CEILING_VIOLATED; } #ifdef __RTEMS_STRICT_ORDER_MUTEX__ _Chain_Prepend_unprotected( &executing->lock_mutex, &the_mutex->queue.lock_queue ); the_mutex->queue.priority_before = executing->current_priority; #endif executing->resource_count++; _Thread_Change_priority( executing, ceiling, false ); _Thread_Enable_dispatch(); } } else { the_mutex->nest_count = 0; the_mutex->holder = NULL; } _Thread_queue_Initialize( &the_mutex->Wait_queue, _CORE_mutex_Is_fifo( the_mutex_attributes ) ? THREAD_QUEUE_DISCIPLINE_FIFO : THREAD_QUEUE_DISCIPLINE_PRIORITY, STATES_WAITING_FOR_MUTEX, CORE_MUTEX_TIMEOUT ); return CORE_MUTEX_STATUS_SUCCESSFUL; }
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 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; }
CORE_mutex_Status _CORE_mutex_Initialize( CORE_mutex_Control *the_mutex, CORE_mutex_Attributes *the_mutex_attributes, uint32_t initial_lock ) { /* Add this to the RTEMS environment later ????????? rtems_assert( initial_lock == CORE_MUTEX_LOCKED || initial_lock == CORE_MUTEX_UNLOCKED ); */ the_mutex->Attributes = *the_mutex_attributes; the_mutex->lock = initial_lock; the_mutex->blocked_count = 0; if ( initial_lock == CORE_MUTEX_LOCKED ) { the_mutex->nest_count = 1; the_mutex->holder = _Thread_Executing; the_mutex->holder_id = _Thread_Executing->Object.id; if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) || _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) { if ( _Thread_Executing->current_priority < the_mutex->Attributes.priority_ceiling ) return CORE_MUTEX_STATUS_CEILING_VIOLATED; #ifdef __RTEMS_STRICT_ORDER_MUTEX__ _Chain_Prepend_unprotected( &_Thread_Executing->lock_mutex, &the_mutex->queue.lock_queue ); the_mutex->queue.priority_before = _Thread_Executing->current_priority; #endif _Thread_Executing->resource_count++; } } else { the_mutex->nest_count = 0; the_mutex->holder = NULL; the_mutex->holder_id = 0; } _Thread_queue_Initialize( &the_mutex->Wait_queue, _CORE_mutex_Is_fifo( the_mutex_attributes ) ? THREAD_QUEUE_DISCIPLINE_FIFO : THREAD_QUEUE_DISCIPLINE_PRIORITY, STATES_WAITING_FOR_MUTEX, CORE_MUTEX_TIMEOUT ); return CORE_MUTEX_STATUS_SUCCESSFUL; }
void threadq_first_empty( const char *discipline_string, Thread_queue_Disciplines discipline ) { Thread_queue_Control tq; printf( "Init - initialize thread queue for %s\n", discipline_string ); _Thread_queue_Initialize( &tq, discipline, 0x01, 3 ); puts( "Init - _Thread_queue_Extract - thread not blocked on a thread queue" ); _Thread_queue_Extract( &tq, _Thread_Executing ); /* is there anything to check? */ }
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 ); }
void _POSIX_signals_Manager_Initialization(void) { uint32_t signo; uint32_t maximum_queued_signals; maximum_queued_signals = Configuration_POSIX_API.maximum_queued_signals; memcpy( _POSIX_signals_Vectors, _POSIX_signals_Default_vectors, sizeof( _POSIX_signals_Vectors ) ); /* * Initialize the set of pending signals for the entire process */ sigemptyset( &_POSIX_signals_Pending ); /* * Initialize the queue we use to block for signals */ _Thread_queue_Initialize( &_POSIX_signals_Wait_queue, THREAD_QUEUE_DISCIPLINE_FIFO, STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL, EAGAIN ); /* XXX status codes */ /* * Allocate the siginfo pools. */ for ( signo=1 ; signo<= SIGRTMAX ; signo++ ) _Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] ); if ( maximum_queued_signals ) { _Chain_Initialize( &_POSIX_signals_Inactive_siginfo, _Workspace_Allocate_or_fatal_error( maximum_queued_signals * sizeof( POSIX_signals_Siginfo_node ) ), maximum_queued_signals, sizeof( POSIX_signals_Siginfo_node ) ); } else { _Chain_Initialize_empty( &_POSIX_signals_Inactive_siginfo ); } }
void _CORE_barrier_Initialize( CORE_barrier_Control *the_barrier, CORE_barrier_Attributes *the_barrier_attributes ) { the_barrier->Attributes = *the_barrier_attributes; the_barrier->number_of_waiting_threads = 0; _Thread_queue_Initialize( &the_barrier->Wait_queue, THREAD_QUEUE_DISCIPLINE_FIFO, CORE_BARRIER_TIMEOUT ); }
void _CORE_semaphore_Initialize( CORE_semaphore_Control *the_semaphore, const CORE_semaphore_Attributes *the_semaphore_attributes, uint32_t initial_value ) { the_semaphore->Attributes = *the_semaphore_attributes; the_semaphore->count = initial_value; _Thread_queue_Initialize( &the_semaphore->Wait_queue, _CORE_semaphore_Is_priority( the_semaphore_attributes ) ? THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO, STATES_WAITING_FOR_SEMAPHORE, CORE_SEMAPHORE_TIMEOUT ); }
void _CORE_RWLock_Initialize( CORE_RWLock_Control *the_rwlock, CORE_RWLock_Attributes *the_rwlock_attributes ) { the_rwlock->Attributes = *the_rwlock_attributes; /* the_rwlock->number_of_waiting_threads = 0; */ the_rwlock->number_of_readers = 0; the_rwlock->current_state = CORE_RWLOCK_UNLOCKED; _Thread_queue_Initialize( &the_rwlock->Wait_queue, THREAD_QUEUE_DISCIPLINE_FIFO, STATES_WAITING_FOR_RWLOCK, CORE_RWLOCK_TIMEOUT ); }
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; _RTEMS_Lock_allocator(); /* to prevent deletion */ 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; } } _RTEMS_Unlock_allocator(); return return_status; }
bool _CORE_message_queue_Initialize( CORE_message_queue_Control *the_message_queue, CORE_message_queue_Attributes *the_message_queue_attributes, uint32_t maximum_pending_messages, size_t maximum_message_size ) { size_t message_buffering_required; size_t allocated_message_size; the_message_queue->maximum_pending_messages = maximum_pending_messages; the_message_queue->number_of_pending_messages = 0; the_message_queue->maximum_message_size = maximum_message_size; _CORE_message_queue_Set_notify( the_message_queue, NULL, NULL ); /* * Round size up to multiple of a pointer for chain init and * check for overflow on adding overhead to each message. */ allocated_message_size = maximum_message_size; if (allocated_message_size & (sizeof(uint32_t) - 1)) { allocated_message_size += sizeof(uint32_t); allocated_message_size &= ~(sizeof(uint32_t) - 1); } if (allocated_message_size < maximum_message_size) return false; /* * Calculate how much total memory is required for message buffering and * check for overflow on the multiplication. */ message_buffering_required = (size_t) maximum_pending_messages * (allocated_message_size + sizeof(CORE_message_queue_Buffer_control)); if (message_buffering_required < allocated_message_size) return false; /* * Attempt to allocate the message memory */ the_message_queue->message_buffers = (CORE_message_queue_Buffer *) _Workspace_Allocate( message_buffering_required ); if (the_message_queue->message_buffers == 0) return false; /* * Initialize the pool of inactive messages, pending messages, * and set of waiting threads. */ _Chain_Initialize ( &the_message_queue->Inactive_messages, the_message_queue->message_buffers, (size_t) maximum_pending_messages, allocated_message_size + sizeof( CORE_message_queue_Buffer_control ) ); _Chain_Initialize_empty( &the_message_queue->Pending_messages ); _Thread_queue_Initialize( &the_message_queue->Wait_queue, _CORE_message_queue_Is_priority( the_message_queue_attributes ) ? THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO, STATES_WAITING_FOR_MESSAGE, CORE_MESSAGE_QUEUE_STATUS_TIMEOUT ); return true; }
bool _CORE_message_queue_Initialize( CORE_message_queue_Control *the_message_queue, CORE_message_queue_Disciplines discipline, uint32_t maximum_pending_messages, size_t maximum_message_size ) { size_t message_buffering_required = 0; size_t aligned_message_size; size_t align_mask; the_message_queue->maximum_pending_messages = maximum_pending_messages; the_message_queue->number_of_pending_messages = 0; the_message_queue->maximum_message_size = maximum_message_size; _CORE_message_queue_Set_notify( the_message_queue, NULL ); /* * Align up the maximum message size to be an integral multiple of the * pointer size. */ align_mask = sizeof(uintptr_t) - 1; aligned_message_size = ( maximum_message_size + align_mask ) & ~align_mask; /* * Check for an integer overflow. It can occur while aligning up the maximum * message size. */ if (aligned_message_size < maximum_message_size) return false; /* * Calculate how much total memory is required for message buffering and * check for overflow on the multiplication. */ if ( !size_t_mult32_with_overflow( (size_t) maximum_pending_messages, aligned_message_size + sizeof(CORE_message_queue_Buffer_control), &message_buffering_required ) ) return false; /* * Attempt to allocate the message memory */ the_message_queue->message_buffers = (CORE_message_queue_Buffer *) _Workspace_Allocate( message_buffering_required ); if (the_message_queue->message_buffers == 0) return false; /* * Initialize the pool of inactive messages, pending messages, * and set of waiting threads. */ _Chain_Initialize ( &the_message_queue->Inactive_messages, the_message_queue->message_buffers, (size_t) maximum_pending_messages, aligned_message_size + sizeof( CORE_message_queue_Buffer_control ) ); _Chain_Initialize_empty( &the_message_queue->Pending_messages ); _Thread_queue_Initialize( &the_message_queue->Wait_queue ); if ( discipline == CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY ) { the_message_queue->operations = &_Thread_queue_Operations_priority; } else { the_message_queue->operations = &_Thread_queue_Operations_FIFO; } return true; }
void _POSIX_signals_Manager_Initialization(void) { uint32_t signo; uint32_t maximum_queued_signals; maximum_queued_signals = Configuration_POSIX_API.maximum_queued_signals; /* * Ensure we have the same number of vectors and default vector entries */ #if defined(RTEMS_DEBUG) assert( sizeof(_POSIX_signals_Vectors) == sizeof(_POSIX_signals_Default_vectors) ); #endif memcpy( _POSIX_signals_Vectors, _POSIX_signals_Default_vectors, sizeof( _POSIX_signals_Vectors ) ); /* * Initialize the set of pending signals for the entire process */ sigemptyset( &_POSIX_signals_Pending ); /* * Initialize the queue we use to block for signals */ _Thread_queue_Initialize( &_POSIX_signals_Wait_queue, THREAD_QUEUE_DISCIPLINE_FIFO, STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL, EAGAIN ); /* XXX status codes */ /* * Allocate the siginfo pools. */ for ( signo=1 ; signo<= SIGRTMAX ; signo++ ) _Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] ); if ( maximum_queued_signals ) { _Chain_Initialize( &_POSIX_signals_Inactive_siginfo, _Workspace_Allocate_or_fatal_error( maximum_queued_signals * sizeof( POSIX_signals_Siginfo_node ) ), maximum_queued_signals, sizeof( POSIX_signals_Siginfo_node ) ); } else { _Chain_Initialize_empty( &_POSIX_signals_Inactive_siginfo ); } /* * Initialize the Alarm Timer */ _Watchdog_Initialize( &_POSIX_signals_Alarm_timer, NULL, 0, NULL ); _Watchdog_Initialize( &_POSIX_signals_Ualarm_timer, NULL, 0, NULL ); }
bool _Thread_Initialize( Thread_Information *information, Thread_Control *the_thread, const Scheduler_Control *scheduler, void *stack_area, size_t stack_size, bool is_fp, Priority_Control priority, bool is_preemptible, Thread_CPU_budget_algorithms budget_algorithm, Thread_CPU_budget_algorithm_callout budget_callout, uint32_t isr_level, Objects_Name name ) { uintptr_t tls_size = _TLS_Get_size(); size_t actual_stack_size = 0; void *stack = NULL; #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) void *fp_area = NULL; #endif bool extension_status; size_t i; bool scheduler_node_initialized = false; Per_CPU_Control *cpu = _Per_CPU_Get_by_index( 0 ); #if defined( RTEMS_SMP ) if ( rtems_configuration_is_smp_enabled() && !is_preemptible ) { return false; } #endif memset( &the_thread->current_state, 0, information->Objects.size - offsetof( Thread_Control, current_state ) ); for ( i = 0 ; i < _Thread_Control_add_on_count ; ++i ) { const Thread_Control_add_on *add_on = &_Thread_Control_add_ons[ i ]; *(void **) ( (char *) the_thread + add_on->destination_offset ) = (char *) the_thread + add_on->source_offset; } /* * Allocate and Initialize the stack for this thread. */ #if !defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API) actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size ); if ( !actual_stack_size || actual_stack_size < stack_size ) return false; /* stack allocation failed */ stack = the_thread->Start.stack; #else if ( !stack_area ) { actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size ); if ( !actual_stack_size || actual_stack_size < stack_size ) return false; /* stack allocation failed */ stack = the_thread->Start.stack; the_thread->Start.core_allocated_stack = true; } else { stack = stack_area; actual_stack_size = stack_size; the_thread->Start.core_allocated_stack = false; } #endif _Stack_Initialize( &the_thread->Start.Initial_stack, stack, actual_stack_size ); /* Thread-local storage (TLS) area allocation */ if ( tls_size > 0 ) { uintptr_t tls_align = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment ); uintptr_t tls_alloc = _TLS_Get_allocation_size( tls_size, tls_align ); the_thread->Start.tls_area = _Workspace_Allocate_aligned( tls_alloc, tls_align ); if ( the_thread->Start.tls_area == NULL ) { goto failed; } } /* * Allocate the floating point area for this thread */ #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) if ( is_fp ) { fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE ); if ( !fp_area ) goto failed; fp_area = _Context_Fp_start( fp_area, 0 ); } the_thread->fp_context = fp_area; the_thread->Start.fp_context = fp_area; #endif /* * Get thread queue heads */ the_thread->Wait.spare_heads = _Freechain_Get( &information->Free_thread_queue_heads, _Workspace_Allocate, _Objects_Extend_size( &information->Objects ), THREAD_QUEUE_HEADS_SIZE( _Scheduler_Count ) ); if ( the_thread->Wait.spare_heads == NULL ) { goto failed; } _Thread_queue_Heads_initialize( the_thread->Wait.spare_heads ); /* * General initialization */ the_thread->is_fp = is_fp; the_thread->Start.isr_level = isr_level; the_thread->Start.is_preemptible = is_preemptible; the_thread->Start.budget_algorithm = budget_algorithm; the_thread->Start.budget_callout = budget_callout; _Thread_Timer_initialize( &the_thread->Timer, cpu ); switch ( budget_algorithm ) { case THREAD_CPU_BUDGET_ALGORITHM_NONE: case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE: break; #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE) case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE: the_thread->cpu_time_budget = rtems_configuration_get_ticks_per_timeslice(); break; #endif #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT) case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT: break; #endif } #if defined(RTEMS_SMP) RTEMS_STATIC_ASSERT( THREAD_SCHEDULER_BLOCKED == 0, Scheduler_state ); the_thread->Scheduler.own_control = scheduler; the_thread->Scheduler.control = scheduler; the_thread->Scheduler.own_node = the_thread->Scheduler.node; _Resource_Node_initialize( &the_thread->Resource_node ); the_thread->Lock.current = &the_thread->Lock.Default; _SMP_ticket_lock_Initialize( &the_thread->Lock.Default ); _SMP_lock_Stats_initialize( &the_thread->Lock.Stats, "Thread Lock" ); _SMP_lock_Stats_initialize( &the_thread->Potpourri_stats, "Thread Potpourri" ); #endif _Thread_Debug_set_real_processor( the_thread, cpu ); /* Initialize the CPU for the non-SMP schedulers */ _Thread_Set_CPU( the_thread, cpu ); _Thread_queue_Initialize( &the_thread->Join_queue ); the_thread->current_state = STATES_DORMANT; the_thread->Wait.operations = &_Thread_queue_Operations_default; the_thread->current_priority = priority; the_thread->real_priority = priority; the_thread->Start.initial_priority = priority; RTEMS_STATIC_ASSERT( THREAD_WAIT_FLAGS_INITIAL == 0, Wait_flags ); _Scheduler_Node_initialize( scheduler, the_thread ); scheduler_node_initialized = true; _Scheduler_Update_priority( the_thread, priority ); /* POSIX Keys */ _RBTree_Initialize_empty( &the_thread->Keys.Key_value_pairs ); _ISR_lock_Initialize( &the_thread->Keys.Lock, "POSIX Key Value Pairs" ); _Thread_Action_control_initialize( &the_thread->Post_switch_actions ); RTEMS_STATIC_ASSERT( THREAD_LIFE_NORMAL == 0, Life_state ); /* * Open the object */ _Objects_Open( &information->Objects, &the_thread->Object, name ); /* * We assume the Allocator Mutex is locked and dispatching is * enabled when we get here. We want to be able to run the * user extensions with dispatching enabled. The Allocator * Mutex provides sufficient protection to let the user extensions * run safely. */ extension_status = _User_extensions_Thread_create( the_thread ); if ( extension_status ) return true; failed: if ( scheduler_node_initialized ) { _Scheduler_Node_destroy( scheduler, the_thread ); } _Workspace_Free( the_thread->Start.tls_area ); _Freechain_Put( &information->Free_thread_queue_heads, the_thread->Wait.spare_heads ); #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) _Workspace_Free( fp_area ); #endif _Thread_Stack_Free( the_thread ); return false; }
bool _CORE_message_queue_Initialize( CORE_message_queue_Control *the_message_queue, CORE_message_queue_Attributes *the_message_queue_attributes, uint32_t maximum_pending_messages, size_t maximum_message_size ) { size_t message_buffering_required = 0; size_t allocated_message_size; the_message_queue->maximum_pending_messages = maximum_pending_messages; the_message_queue->number_of_pending_messages = 0; the_message_queue->maximum_message_size = maximum_message_size; _CORE_message_queue_Set_notify( the_message_queue, NULL, NULL ); allocated_message_size = maximum_message_size; /* * Check if allocated_message_size is aligned to uintptr-size boundary. * If not, it will increase allocated_message_size to multiplicity of pointer * size. */ if (allocated_message_size & (sizeof(uintptr_t) - 1)) { allocated_message_size += sizeof(uintptr_t); allocated_message_size &= ~(sizeof(uintptr_t) - 1); } /* * Check for an overflow. It can occur while increasing allocated_message_size * to multiplicity of uintptr_t above. */ if (allocated_message_size < maximum_message_size) return false; /* * Calculate how much total memory is required for message buffering and * check for overflow on the multiplication. */ if ( !size_t_mult32_with_overflow( (size_t) maximum_pending_messages, allocated_message_size + sizeof(CORE_message_queue_Buffer_control), &message_buffering_required ) ) return false; /* * Attempt to allocate the message memory */ the_message_queue->message_buffers = (CORE_message_queue_Buffer *) _Workspace_Allocate( message_buffering_required ); if (the_message_queue->message_buffers == 0) return false; /* * Initialize the pool of inactive messages, pending messages, * and set of waiting threads. */ _Chain_Initialize ( &the_message_queue->Inactive_messages, the_message_queue->message_buffers, (size_t) maximum_pending_messages, allocated_message_size + sizeof( CORE_message_queue_Buffer_control ) ); _Chain_Initialize_empty( &the_message_queue->Pending_messages ); _Thread_queue_Initialize( &the_message_queue->Wait_queue, _CORE_message_queue_Is_priority( the_message_queue_attributes ) ? THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO, STATES_WAITING_FOR_MESSAGE, CORE_MESSAGE_QUEUE_STATUS_TIMEOUT ); return true; }
CORE_mutex_Status _CORE_mutex_Initialize( CORE_mutex_Control *the_mutex, Thread_Control *executing, const CORE_mutex_Attributes *the_mutex_attributes, bool initially_locked ) { /* Add this to the RTEMS environment later ????????? rtems_assert( initial_lock == CORE_MUTEX_LOCKED || initial_lock == CORE_MUTEX_UNLOCKED ); */ the_mutex->Attributes = *the_mutex_attributes; if ( initially_locked ) { bool is_priority_ceiling = _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ); the_mutex->nest_count = 1; the_mutex->holder = executing; if ( is_priority_ceiling || _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ) { Priority_Control ceiling = the_mutex->Attributes.priority_ceiling; Per_CPU_Control *cpu_self; /* The mutex initialization is only protected by the allocator lock */ cpu_self = _Thread_Dispatch_disable(); /* * The test to check for a ceiling violation is a bit arbitrary. In case * this thread is the owner of a priority inheritance mutex, then it may * get a higher priority later or anytime on SMP configurations. */ if ( is_priority_ceiling && executing->current_priority < ceiling ) { /* * There is no need to undo the previous work since this error aborts * the object creation. */ _Thread_Dispatch_enable( cpu_self ); return CORE_MUTEX_STATUS_CEILING_VIOLATED; } #ifdef __RTEMS_STRICT_ORDER_MUTEX__ _Chain_Prepend_unprotected( &executing->lock_mutex, &the_mutex->queue.lock_queue ); the_mutex->queue.priority_before = executing->current_priority; #endif executing->resource_count++; if ( is_priority_ceiling ) { _Thread_Raise_priority( executing, ceiling ); } _Thread_Dispatch_enable( cpu_self ); } } else { the_mutex->nest_count = 0; the_mutex->holder = NULL; } _Thread_queue_Initialize( &the_mutex->Wait_queue ); if ( _CORE_mutex_Is_priority( the_mutex_attributes ) ) { the_mutex->operations = &_Thread_queue_Operations_priority; } else { the_mutex->operations = &_Thread_queue_Operations_FIFO; } return CORE_MUTEX_STATUS_SUCCESSFUL; }