void _Thread_queue_Initialize( Thread_queue_Control *the_thread_queue, Thread_queue_Disciplines the_discipline, States_Control state, uint32_t timeout_status ) { if ( _Scheduler_FIXME_thread_priority_queues_are_broken ) { the_discipline = THREAD_QUEUE_DISCIPLINE_FIFO; } the_thread_queue->state = state; the_thread_queue->discipline = the_discipline; the_thread_queue->timeout_status = timeout_status; the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; if ( the_discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY ) { uint32_t index; for( index=0 ; index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ; index++) _Chain_Initialize_empty( &the_thread_queue->Queues.Priority[index] ); } else { /* must be THREAD_QUEUE_DISCIPLINE_FIFO */ _Chain_Initialize_empty( &the_thread_queue->Queues.Fifo ); } }
void _Scheduler_simple_smp_Initialize( void ) { Scheduler_simple_smp_Control *self = _Workspace_Allocate_or_fatal_error( sizeof( *self ) ); _Chain_Initialize_empty( &self->ready ); _Chain_Initialize_empty( &self->scheduled ); _Scheduler.information = self; }
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 _Thread_Set_transient( Thread_Control *the_thread ) { ISR_Level level; uint32_t old_state; Chain_Control *ready; ready = the_thread->ready; _ISR_Disable( level ); old_state = the_thread->current_state; the_thread->current_state = _States_Set( STATES_TRANSIENT, old_state ); if ( _States_Is_ready( old_state ) ) { if ( _Chain_Has_only_one_node( ready ) ) { _Chain_Initialize_empty( ready ); _Priority_Remove_from_bit_map( &the_thread->Priority_map ); } else _Chain_Extract_unprotected( &the_thread->Object.Node ); } _ISR_Enable( level ); }
void _Scheduler_simple_SMP_Initialize( const Scheduler_Control *scheduler ) { Scheduler_simple_SMP_Context *self = _Scheduler_simple_SMP_Get_context( scheduler ); _Scheduler_SMP_Initialize( &self->Base ); _Chain_Initialize_empty( &self->Ready ); }
void _Scheduler_simple_Initialize ( void ) { Scheduler_simple_Control *scheduler = _Workspace_Allocate_or_fatal_error( sizeof( *scheduler ) ); _Chain_Initialize_empty( &scheduler->Ready ); _Scheduler.information = scheduler; }
static void _Thread_queue_Priority_do_initialize( Thread_queue_Heads *heads ) { #if defined(RTEMS_SMP) _Chain_Initialize_empty( &heads->Heads.Fifo ); #else _RBTree_Initialize_empty( &heads->Heads.Priority.Queue ); #endif }
void _Scheduler_priority_SMP_Initialize( void ) { Scheduler_SMP_Control *self = _Workspace_Allocate_or_fatal_error( sizeof( *self ) + PRIORITY_MAXIMUM * sizeof( Chain_Control ) ); _Chain_Initialize_empty( &self->scheduled ); _Scheduler_priority_Ready_queue_initialize( &self->ready[ 0 ] ); _Scheduler.information = self; }
void _Thread_MP_Handler_initialization ( uint32_t maximum_proxies ) { _Chain_Initialize_empty( &_Thread_MP_Active_proxies ); if ( maximum_proxies == 0 ) { _Chain_Initialize_empty( &_Thread_MP_Inactive_proxies ); return; } _Chain_Initialize( &_Thread_MP_Inactive_proxies, _Workspace_Allocate_or_fatal_error( maximum_proxies * sizeof( Thread_Proxy_control ) ), maximum_proxies, sizeof( Thread_Proxy_control ) ); }
rtems_task Init( rtems_task_argument argument ) { rtems_time_of_day time; rtems_status_code status; Chain_Control empty; puts( "\n*** RTEMS WATCHDOG ***" ); puts( "INIT - report on empty watchdog chain" ); _Chain_Initialize_empty( &empty ); _Watchdog_Report_chain( "Empty Chain", &empty ); build_time( &time, 12, 31, 1988, 9, 0, 0, 0 ); status = rtems_clock_set( &time ); directive_failed( status, "rtems_clock_set" ); Task_name[ 1 ] = rtems_build_name( 'T', 'A', '1', ' ' ); Timer_name[ 1 ] = rtems_build_name( 'T', 'M', '1', ' ' ); status = rtems_task_create( Task_name[ 1 ], 1, RTEMS_MINIMUM_STACK_SIZE * 2, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &Task_id[ 1 ] ); directive_failed( status, "rtems_task_create of TA1" ); status = rtems_task_start( Task_id[ 1 ], Task_1, 0 ); directive_failed( status, "rtems_task_start of TA1" ); puts( "INIT - rtems_timer_create - creating timer 1" ); status = rtems_timer_create( Timer_name[ 1 ], &Timer_id[ 1 ] ); directive_failed( status, "rtems_timer_create" ); printf( "INIT - timer 1 has id (0x%" PRIxrtems_id ")\n", Timer_id[ 1 ] ); status = rtems_task_delete( RTEMS_SELF ); directive_failed( status, "rtems_task_delete of RTEMS_SELF" ); rtems_test_exit( 0 ); }
void _Thread_Suspend( Thread_Control *the_thread ) { ISR_Level level; Chain_Control *ready; ready = the_thread->ready; _ISR_Disable( level ); #if defined(RTEMS_ITRON_API) the_thread->suspend_count++; #endif if ( !_States_Is_ready( the_thread->current_state ) ) { the_thread->current_state = _States_Set( STATES_SUSPENDED, the_thread->current_state ); _ISR_Enable( level ); return; } the_thread->current_state = STATES_SUSPENDED; if ( _Chain_Has_only_one_node( ready ) ) { _Chain_Initialize_empty( ready ); _Priority_Remove_from_bit_map( &the_thread->Priority_map ); } else _Chain_Extract_unprotected( &the_thread->Object.Node ); _ISR_Flash( level ); if ( _Thread_Is_heir( the_thread ) ) _Thread_Calculate_heir(); if ( _Thread_Is_executing( the_thread ) ) _Context_Switch_necessary = true; _ISR_Enable( level ); }
void ReadFileIntoChain2( FILE *InFile ) { int line_count; int max_length; char *line; char Buffer[ BUFFER_SIZE ]; Line_Control *new_line; if ( !InFile ) { fprintf( stderr, "Unable to open (%s)\n", "stdin" ); exit( 1 ); } assert( InFile ); max_length = 0; line_count = 0; _Chain_Initialize_empty( &Lines ); for ( ;; ) { line = fgets( Buffer, BUFFER_SIZE, InFile ); if ( !line ) break; Buffer[ strlen( Buffer ) - 1 ] = '\0'; new_line = AllocateLine(); strcpy( new_line->Contents, Buffer ); new_line->number = ++line_count; _Chain_Append( &Lines, &new_line->Node ); } fclose( InFile ); }
void _Chain_Insert_chain( Chain_Node *insert_after, Chain_Control *to_insert ) { Chain_Node *first; Chain_Node *last; Chain_Node *insert_after_next; first = to_insert->first; last = to_insert->last; insert_after_next = insert_after->next; insert_after->next = first; first->previous = insert_after; insert_after_next->previous = last; last->next = insert_after_next; _Chain_Initialize_empty( to_insert ); }
void _SMP_Handler_initialize( void ) { uint32_t cpu_max = rtems_configuration_get_maximum_processors(); uint32_t cpu_count; uint32_t cpu_index; for ( cpu_index = 0 ; cpu_index < cpu_max; ++cpu_index ) { Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); _ISR_lock_Initialize( &cpu->Watchdog.Lock, "Watchdog" ); _SMP_ticket_lock_Initialize( &cpu->Lock ); _SMP_lock_Stats_initialize( &cpu->Lock_stats, "Per-CPU" ); _Chain_Initialize_empty( &cpu->Threads_in_need_for_help ); } /* * Discover and initialize the secondary cores in an SMP system. */ cpu_count = _CPU_SMP_Initialize(); cpu_count = cpu_count < cpu_max ? cpu_count : cpu_max; _SMP_Processor_count = cpu_count; for ( cpu_index = cpu_count ; cpu_index < cpu_max; ++cpu_index ) { const Scheduler_Assignment *assignment; assignment = _Scheduler_Get_initial_assignment( cpu_index ); if ( _Scheduler_Is_mandatory_processor( assignment ) ) { _SMP_Fatal( SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT ); } } _SMP_Start_processors( cpu_count ); _CPU_SMP_Finalize_initialization( cpu_count ); }
void _Thread_Set_state( Thread_Control *the_thread, States_Control state ) { ISR_Level level; Chain_Control *ready; ready = the_thread->ready; _ISR_Disable( level ); if ( !_States_Is_ready( the_thread->current_state ) ) { the_thread->current_state = _States_Set( state, the_thread->current_state ); _ISR_Enable( level ); return; } the_thread->current_state = state; if ( _Chain_Has_only_one_node( ready ) ) { _Chain_Initialize_empty( ready ); _Priority_Remove_from_bit_map( &the_thread->Priority_map ); } else _Chain_Extract_unprotected( &the_thread->Object.Node ); _ISR_Flash( level ); if ( _Thread_Is_heir( the_thread ) ) _Thread_Calculate_heir(); if ( _Thread_Is_executing( the_thread ) ) _Context_Switch_necessary = TRUE; _ISR_Enable( level ); }
void _Objects_MP_Handler_initialization(void) { uint32_t maximum_global_objects; maximum_global_objects = _Configuration_MP_table->maximum_global_objects; _Objects_MP_Maximum_global_objects = maximum_global_objects; if ( maximum_global_objects == 0 ) { _Chain_Initialize_empty( &_Objects_MP_Inactive_global_objects ); return; } _Chain_Initialize( &_Objects_MP_Inactive_global_objects, _Workspace_Allocate_or_fatal_error( maximum_global_objects * sizeof( Objects_MP_Control ) ), maximum_global_objects, sizeof( Objects_MP_Control ) ); }
void _Objects_Initialize_information( Objects_Information *information, Objects_APIs the_api, uint32_t the_class, uint32_t maximum, uint16_t size, bool is_string, uint32_t maximum_name_length #if defined(RTEMS_MULTIPROCESSING) , bool supports_global, Objects_Thread_queue_Extract_callout extract #endif ) { static Objects_Control *null_local_table = NULL; uint32_t minimum_index; uint32_t name_length; uint32_t maximum_per_allocation; #if defined(RTEMS_MULTIPROCESSING) uint32_t index; #endif information->the_api = the_api; information->the_class = the_class; information->size = size; information->local_table = 0; information->inactive_per_block = 0; information->object_blocks = 0; information->inactive = 0; #if defined(RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES) information->is_string = is_string; #endif /* * Set the maximum value to 0. It will be updated when objects are * added to the inactive set from _Objects_Extend_information() */ information->maximum = 0; /* * Register this Object Class in the Object Information Table. */ _Objects_Information_table[ the_api ][ the_class ] = information; /* * Are we operating in limited or unlimited (e.g. auto-extend) mode. */ information->auto_extend = (maximum & OBJECTS_UNLIMITED_OBJECTS) ? true : false; maximum_per_allocation = maximum & ~OBJECTS_UNLIMITED_OBJECTS; /* * Unlimited and maximum of zero is illogical. */ if ( information->auto_extend && maximum_per_allocation == 0) { _Internal_error_Occurred( INTERNAL_ERROR_CORE, true, INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0 ); } /* * The allocation unit is the maximum value */ information->allocation_size = maximum_per_allocation; /* * Provide a null local table entry for the case of any empty table. */ information->local_table = &null_local_table; /* * Calculate minimum and maximum Id's */ minimum_index = (maximum_per_allocation == 0) ? 0 : 1; information->minimum_id = _Objects_Build_id( the_api, the_class, _Objects_Local_node, minimum_index ); /* * Calculate the maximum name length */ name_length = maximum_name_length; if ( name_length & (OBJECTS_NAME_ALIGNMENT-1) ) name_length = (name_length + OBJECTS_NAME_ALIGNMENT) & ~(OBJECTS_NAME_ALIGNMENT-1); information->name_length = name_length; _Chain_Initialize_empty( &information->Inactive ); /* * Initialize objects .. if there are any */ if ( maximum_per_allocation ) { /* * Always have the maximum size available so the current performance * figures are create are met. If the user moves past the maximum * number then a performance hit is taken. */ _Objects_Extend_information( information ); } /* * Take care of multiprocessing */ #if defined(RTEMS_MULTIPROCESSING) information->extract = extract; if ( (supports_global == true) && _System_state_Is_multiprocessing ) { information->global_table = (Chain_Control *) _Workspace_Allocate_or_fatal_error( (_Objects_Maximum_nodes + 1) * sizeof(Chain_Control) ); for ( index=1; index <= _Objects_Maximum_nodes ; index++ ) _Chain_Initialize_empty( &information->global_table[ index ] ); } else information->global_table = NULL; #endif }
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; }
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; }
/** * @brief Timer server body. * * This is the server for task based timers. This task executes whenever a * task-based timer should fire. It services both "after" and "when" timers. * It is not created automatically but must be created explicitly by the * application before task-based timers may be initiated. The parameter * @a arg points to the corresponding timer server control block. */ static rtems_task _Timer_server_Body( rtems_task_argument arg ) { Timer_server_Control *ts = (Timer_server_Control *) arg; Chain_Control insert_chain; Chain_Control fire_chain; _Chain_Initialize_empty( &insert_chain ); _Chain_Initialize_empty( &fire_chain ); while ( true ) { _Timer_server_Get_watchdogs_that_fire_now( ts, &insert_chain, &fire_chain ); if ( !_Chain_Is_empty( &fire_chain ) ) { /* * Fire the watchdogs. */ while ( true ) { Watchdog_Control *watchdog; ISR_Level level; /* * It is essential that interrupts are disable here since an interrupt * service routine may remove a watchdog from the chain. */ _ISR_Disable( level ); watchdog = (Watchdog_Control *) _Chain_Get_unprotected( &fire_chain ); if ( watchdog != NULL ) { watchdog->state = WATCHDOG_INACTIVE; _ISR_Enable( level ); } else { _ISR_Enable( level ); break; } /* * The timer server may block here and wait for resources or time. * The system watchdogs are inactive and will remain inactive since * the active flag of the timer server is true. */ (*watchdog->routine)( watchdog->id, watchdog->user_data ); } } else { ts->active = false; /* * Block until there is something to do. */ _Thread_Disable_dispatch(); _Thread_Set_state( ts->thread, STATES_DELAYING ); _Timer_server_Reset_interval_system_watchdog( ts ); _Timer_server_Reset_tod_system_watchdog( ts ); _Thread_Enable_dispatch(); ts->active = true; /* * Maybe an interrupt did reset the system timers, so we have to stop * them here. Since we are active now, there will be no more resets * until we are inactive again. */ _Timer_server_Stop_interval_system_watchdog( ts ); _Timer_server_Stop_tod_system_watchdog( ts ); } } }
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; }
bool _Thread_Initialize( Objects_Information *information, Thread_Control *the_thread, 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 ) { size_t actual_stack_size = 0; void *stack = NULL; #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) void *fp_area; #endif void *sched = NULL; void *extensions_area; bool extension_status; int i; #if defined( RTEMS_SMP ) if ( rtems_configuration_is_smp_enabled() && !is_preemptible ) { return false; } #endif /* * Initialize the Ada self pointer */ #if __RTEMS_ADA__ the_thread->rtems_ada_self = NULL; #endif /* * Zero out all the allocated memory fields */ for ( i=0 ; i <= THREAD_API_LAST ; i++ ) the_thread->API_Extensions[i] = NULL; extensions_area = NULL; the_thread->libc_reent = NULL; #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) fp_area = NULL; #endif /* * 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 ); /* * 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 /* * Initialize the thread timer */ _Watchdog_Initialize( &the_thread->Timer, NULL, 0, NULL ); #ifdef __RTEMS_STRICT_ORDER_MUTEX__ /* Initialize the head of chain of held mutexes */ _Chain_Initialize_empty(&the_thread->lock_mutex); #endif /* * Allocate the extensions area for this thread */ if ( _Thread_Maximum_extensions ) { extensions_area = _Workspace_Allocate( (_Thread_Maximum_extensions + 1) * sizeof( void * ) ); if ( !extensions_area ) goto failed; } the_thread->extensions = (void **) extensions_area; /* * Clear the extensions area so extension users can determine * if they are linked to the thread. An extension user may * create the extension long after tasks have been created * so they cannot rely on the thread create user extension * call. */ if ( the_thread->extensions ) { for ( i = 0; i <= _Thread_Maximum_extensions ; i++ ) the_thread->extensions[i] = NULL; } /* * General initialization */ the_thread->Start.is_preemptible = is_preemptible; the_thread->Start.budget_algorithm = budget_algorithm; the_thread->Start.budget_callout = budget_callout; 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 = _Thread_Ticks_per_timeslice; break; #endif #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT) case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT: break; #endif } the_thread->Start.isr_level = isr_level; #if defined(RTEMS_SMP) the_thread->is_scheduled = false; the_thread->is_executing = false; /* Initialize the cpu field for the non-SMP schedulers */ the_thread->cpu = _Per_CPU_Get_by_index( 0 ); #endif the_thread->current_state = STATES_DORMANT; the_thread->Wait.queue = NULL; the_thread->resource_count = 0; the_thread->real_priority = priority; the_thread->Start.initial_priority = priority; sched =_Scheduler_Allocate( the_thread ); if ( !sched ) goto failed; _Thread_Set_priority( the_thread, priority ); /* * Initialize the CPU usage statistics */ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ _Timestamp_Set_to_zero( &the_thread->cpu_time_used ); #else the_thread->cpu_time_used = 0; #endif /* * Open the object */ _Objects_Open( information, &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: _Workspace_Free( the_thread->libc_reent ); for ( i=0 ; i <= THREAD_API_LAST ; i++ ) _Workspace_Free( the_thread->API_Extensions[i] ); _Workspace_Free( extensions_area ); #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) _Workspace_Free( fp_area ); #endif _Workspace_Free( sched ); _Thread_Stack_Free( the_thread ); return false; }
/** * @brief rtems_timer_initiate_server * * This directive creates and starts the server for task-based timers. * It must be invoked before any task-based timers can be initiated. * * @param[in] priority is the timer server priority * @param[in] stack_size is the stack size in bytes * @param[in] attribute_set is the timer server attributes * * @return This method returns RTEMS_SUCCESSFUL if successful and an * error code otherwise. */ rtems_status_code rtems_timer_initiate_server( uint32_t priority, uint32_t stack_size, rtems_attribute attribute_set ) { rtems_id id; rtems_status_code status; rtems_task_priority _priority; static bool initialized = false; bool tmpInitialized; Timer_server_Control *ts = &_Timer_server_Default; /* * Make sure the requested priority is valid. The if is * structured so we check it is invalid before looking for * a specific invalid value as the default. */ _priority = priority; if ( !_RTEMS_tasks_Priority_is_valid( priority ) ) { if ( priority != RTEMS_TIMER_SERVER_DEFAULT_PRIORITY ) return RTEMS_INVALID_PRIORITY; _priority = 0; } /* * Just to make sure this is only called once. */ _Thread_Disable_dispatch(); tmpInitialized = initialized; initialized = true; _Thread_Enable_dispatch(); if ( tmpInitialized ) return RTEMS_INCORRECT_STATE; /* * Create the Timer Server with the name the name of "TIME". The attribute * RTEMS_SYSTEM_TASK allows us to set a priority to 0 which will makes it * higher than any other task in the system. It can be viewed as a low * priority interrupt. It is also always NO_PREEMPT so it looks like * an interrupt to other tasks. * * We allow the user to override the default priority because the Timer * Server can invoke TSRs which must adhere to language run-time or * other library rules. For example, if using a TSR written in Ada the * Server should run at the same priority as the priority Ada task. * Otherwise, the priority ceiling for the mutex used to protect the * GNAT run-time is violated. */ status = rtems_task_create( _Objects_Build_name('T','I','M','E'), /* "TIME" */ _priority, /* create with priority 1 since 0 is illegal */ stack_size, /* let user specify stack size */ RTEMS_NO_PREEMPT, /* no preempt is like an interrupt */ /* user may want floating point but we need */ /* system task specified for 0 priority */ attribute_set | RTEMS_SYSTEM_TASK, &id /* get the id back */ ); if (status) { initialized = false; return status; } /* * Do all the data structure initialization before starting the * Timer Server so we do not have to have a critical section. */ /* * We work with the TCB pointer, not the ID, so we need to convert * to a TCB pointer from here out. */ ts->thread = (Thread_Control *)_Objects_Get_local_object( &_RTEMS_tasks_Information, _Objects_Get_index(id) ); /* * Initialize the timer lists that the server will manage. */ _Chain_Initialize_empty( &ts->Interval_watchdogs.Chain ); _Chain_Initialize_empty( &ts->TOD_watchdogs.Chain ); /* * Initialize the timers that will be used to control when the * Timer Server wakes up and services the task-based timers. */ _Watchdog_Initialize( &ts->Interval_watchdogs.System_watchdog, _Thread_Delay_ended, id, NULL ); _Watchdog_Initialize( &ts->TOD_watchdogs.System_watchdog, _Thread_Delay_ended, id, NULL ); /* * Initialize the pointer to the timer schedule method so applications that * do not use the Timer Server do not have to pull it in. */ ts->schedule_operation = _Timer_server_Schedule_operation_method; ts->Interval_watchdogs.last_snapshot = _Watchdog_Ticks_since_boot; ts->TOD_watchdogs.last_snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch(); ts->insert_chain = NULL; ts->active = false; /* * The default timer server is now available. */ _Timer_server = ts; /* * Start the timer server */ status = rtems_task_start( id, _Timer_server_Body, (rtems_task_argument) ts ); #if defined(RTEMS_DEBUG) /* * One would expect a call to rtems_task_delete() here to clean up * but there is actually no way (in normal circumstances) that the * start can fail. The id and starting address are known to be * be good. If this service fails, something is weirdly wrong on the * target such as a stray write in an ISR or incorrect memory layout. */ if (status) { initialized = false; } #endif return status; }
Thread_blocking_operation_States _Thread_queue_Enqueue_priority ( Thread_queue_Control *the_thread_queue, Thread_Control *the_thread, ISR_Level *level_p ) { Priority_Control search_priority; Thread_Control *search_thread; ISR_Level level; Chain_Control *header; uint32_t header_index; Chain_Node *the_node; Chain_Node *next_node; Chain_Node *previous_node; Chain_Node *search_node; Priority_Control priority; States_Control block_state; _Chain_Initialize_empty( &the_thread->Wait.Block2n ); priority = the_thread->current_priority; header_index = _Thread_queue_Header_number( priority ); header = &the_thread_queue->Queues.Priority[ header_index ]; block_state = the_thread_queue->state; if ( _Thread_queue_Is_reverse_search( priority ) ) goto restart_reverse_search; restart_forward_search: search_priority = PRIORITY_MINIMUM - 1; _ISR_Disable( level ); search_thread = (Thread_Control *) header->first; while ( !_Chain_Is_tail( header, (Chain_Node *)search_thread ) ) { search_priority = search_thread->current_priority; if ( priority <= search_priority ) break; #if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE ) search_thread = (Thread_Control *) search_thread->Object.Node.next; if ( _Chain_Is_tail( header, (Chain_Node *)search_thread ) ) break; search_priority = search_thread->current_priority; if ( priority <= search_priority ) break; #endif _ISR_Flash( level ); if ( !_States_Are_set( search_thread->current_state, block_state) ) { _ISR_Enable( level ); goto restart_forward_search; } search_thread = (Thread_Control *)search_thread->Object.Node.next; } if ( the_thread_queue->sync_state != THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) goto synchronize; the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; if ( priority == search_priority ) goto equal_priority; search_node = (Chain_Node *) search_thread; previous_node = search_node->previous; the_node = (Chain_Node *) the_thread; the_node->next = search_node; the_node->previous = previous_node; previous_node->next = the_node; search_node->previous = the_node; the_thread->Wait.queue = the_thread_queue; _ISR_Enable( level ); return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; restart_reverse_search: search_priority = PRIORITY_MAXIMUM + 1; _ISR_Disable( level ); search_thread = (Thread_Control *) header->last; while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) { search_priority = search_thread->current_priority; if ( priority >= search_priority ) break; #if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE ) search_thread = (Thread_Control *) search_thread->Object.Node.previous; if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) ) break; search_priority = search_thread->current_priority; if ( priority >= search_priority ) break; #endif _ISR_Flash( level ); if ( !_States_Are_set( search_thread->current_state, block_state) ) { _ISR_Enable( level ); goto restart_reverse_search; } search_thread = (Thread_Control *) search_thread->Object.Node.previous; } if ( the_thread_queue->sync_state != THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) goto synchronize; the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; if ( priority == search_priority ) goto equal_priority; search_node = (Chain_Node *) search_thread; next_node = search_node->next; the_node = (Chain_Node *) the_thread; the_node->next = next_node; the_node->previous = search_node; search_node->next = the_node; next_node->previous = the_node; the_thread->Wait.queue = the_thread_queue; _ISR_Enable( level ); return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; equal_priority: /* add at end of priority group */ search_node = _Chain_Tail( &search_thread->Wait.Block2n ); previous_node = search_node->previous; the_node = (Chain_Node *) the_thread; the_node->next = search_node; the_node->previous = previous_node; previous_node->next = the_node; search_node->previous = the_node; the_thread->Wait.queue = the_thread_queue; _ISR_Enable( level ); return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; synchronize: /* * An interrupt completed the thread's blocking request. * For example, the blocking thread could have been given * the mutex by an ISR or timed out. * * WARNING! Returning with interrupts disabled! */ *level_p = level; return the_thread_queue->sync_state; }
bool _Thread_Initialize( Objects_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 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; } /* * Initialize the Ada self pointer */ #if __RTEMS_ADA__ the_thread->rtems_ada_self = NULL; #endif the_thread->Start.tls_area = NULL; /* * 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 /* * Initialize the thread timer */ _Watchdog_Initialize( &the_thread->Timer, NULL, 0, NULL ); #ifdef __RTEMS_STRICT_ORDER_MUTEX__ /* Initialize the head of chain of held mutexes */ _Chain_Initialize_empty(&the_thread->lock_mutex); #endif /* * Clear the extensions area so extension users can determine * if they are linked to the thread. An extension user may * create the extension long after tasks have been created * so they cannot rely on the thread create user extension * call. The object index starts with one, so the first extension context is * unused. */ for ( i = 1 ; i <= rtems_configuration_get_maximum_extensions() ; ++i ) the_thread->extensions[ i ] = NULL; /* * General initialization */ 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; 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) the_thread->Scheduler.state = THREAD_SCHEDULER_BLOCKED; 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 ); _CPU_Context_Set_is_executing( &the_thread->Registers, false ); #endif _Thread_Debug_set_real_processor( the_thread, cpu ); /* Initialize the CPU for the non-SMP schedulers */ _Thread_Set_CPU( the_thread, cpu ); the_thread->current_state = STATES_DORMANT; the_thread->Wait.queue = NULL; the_thread->resource_count = 0; the_thread->real_priority = priority; the_thread->Start.initial_priority = priority; _Scheduler_Node_initialize( scheduler, the_thread ); scheduler_node_initialized = true; _Thread_Set_priority( the_thread, priority ); /* * Initialize the CPU usage statistics */ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ _Timestamp_Set_to_zero( &the_thread->cpu_time_used ); #else the_thread->cpu_time_used = 0; #endif /* * initialize thread's key vaule node chain */ _Chain_Initialize_empty( &the_thread->Key_Chain ); _Thread_Action_control_initialize( &the_thread->Post_switch_actions ); _Thread_Action_initialize( &the_thread->Life.Action, _Thread_Life_action_handler ); the_thread->Life.state = THREAD_LIFE_NORMAL; the_thread->Life.terminator = NULL; /* * Open the object */ _Objects_Open( information, &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 ); #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) _Workspace_Free( fp_area ); #endif _Thread_Stack_Free( the_thread ); return false; }
/* fat_init_volume_info -- * Get inforamtion about volume on which filesystem is mounted on * * PARAMETERS: * mt_entry - mount table entry * * RETURNS: * RC_OK on success, or -1 if error occured * and errno set appropriately */ int fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry) { int rc = RC_OK; fat_fs_info_t *fs_info = mt_entry->fs_info; register fat_vol_t *vol = &fs_info->vol; uint32_t data_secs = 0; char boot_rec[FAT_MAX_BPB_SIZE]; char fs_info_sector[FAT_USEFUL_INFO_SIZE]; ssize_t ret = 0; int fd; struct stat stat_buf; int i = 0; rc = stat(mt_entry->dev, &stat_buf); if (rc == -1) return rc; /* rtmes feature: no block devices, all are character devices */ if (!S_ISCHR(stat_buf.st_mode)) set_errno_and_return_minus_one(ENOTBLK); /* check that device is registred as block device and lock it */ vol->dd = rtems_disk_lookup(stat_buf.st_dev); if (vol->dd == NULL) set_errno_and_return_minus_one(ENOTBLK); vol->dev = stat_buf.st_dev; fd = open(mt_entry->dev, O_RDONLY); if (fd == -1) { rtems_disk_release(vol->dd); return -1; } ret = read(fd, (void *)boot_rec, FAT_MAX_BPB_SIZE); if ( ret != FAT_MAX_BPB_SIZE ) { close(fd); rtems_disk_release(vol->dd); set_errno_and_return_minus_one( EIO ); } close(fd); vol->bps = FAT_GET_BR_BYTES_PER_SECTOR(boot_rec); if ( (vol->bps != 512) && (vol->bps != 1024) && (vol->bps != 2048) && (vol->bps != 4096)) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one( EINVAL ); } for (vol->sec_mul = 0, i = (vol->bps >> FAT_SECTOR512_BITS); (i & 1) == 0; i >>= 1, vol->sec_mul++); for (vol->sec_log2 = 0, i = vol->bps; (i & 1) == 0; i >>= 1, vol->sec_log2++); vol->spc = FAT_GET_BR_SECTORS_PER_CLUSTER(boot_rec); /* * "sectors per cluster" of zero is invalid * (and would hang the following loop) */ if (vol->spc == 0) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one(EINVAL); } for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0; i >>= 1, vol->spc_log2++); /* * "bytes per cluster" value greater than 32K is invalid */ if ((vol->bpc = vol->bps << vol->spc_log2) > MS_BYTES_PER_CLUSTER_LIMIT) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one(EINVAL); } for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0; i >>= 1, vol->bpc_log2++); vol->fats = FAT_GET_BR_FAT_NUM(boot_rec); vol->fat_loc = FAT_GET_BR_RESERVED_SECTORS_NUM(boot_rec); vol->rdir_entrs = FAT_GET_BR_FILES_PER_ROOT_DIR(boot_rec); /* calculate the count of sectors occupied by the root directory */ vol->rdir_secs = ((vol->rdir_entrs * FAT_DIRENTRY_SIZE) + (vol->bps - 1)) / vol->bps; vol->rdir_size = vol->rdir_secs << vol->sec_log2; if ( (FAT_GET_BR_SECTORS_PER_FAT(boot_rec)) != 0) vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT(boot_rec); else vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT32(boot_rec); vol->data_fsec = vol->fat_loc + vol->fats * vol->fat_length + vol->rdir_secs; /* for FAT12/16 root dir starts at(sector) */ vol->rdir_loc = vol->fat_loc + vol->fats * vol->fat_length; if ( (FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec)) != 0) vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec); else vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM32(boot_rec); data_secs = vol->tot_secs - vol->data_fsec; vol->data_cls = data_secs / vol->spc; /* determine FAT type at least */ if ( vol->data_cls < FAT_FAT12_MAX_CLN) { vol->type = FAT_FAT12; vol->mask = FAT_FAT12_MASK; vol->eoc_val = FAT_FAT12_EOC; } else { if ( vol->data_cls < FAT_FAT16_MAX_CLN) { vol->type = FAT_FAT16; vol->mask = FAT_FAT16_MASK; vol->eoc_val = FAT_FAT16_EOC; } else { vol->type = FAT_FAT32; vol->mask = FAT_FAT32_MASK; vol->eoc_val = FAT_FAT32_EOC; } } if (vol->type == FAT_FAT32) { vol->rdir_cl = FAT_GET_BR_FAT32_ROOT_CLUSTER(boot_rec); vol->mirror = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_MIRROR; if (vol->mirror) vol->afat = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_FAT_NUM; else vol->afat = 0; vol->info_sec = FAT_GET_BR_FAT32_FS_INFO_SECTOR(boot_rec); if( vol->info_sec == 0 ) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one( EINVAL ); } else { ret = _fat_block_read(mt_entry, vol->info_sec , 0, FAT_FSI_LEADSIG_SIZE, fs_info_sector); if ( ret < 0 ) { rtems_disk_release(vol->dd); return -1; } if (FAT_GET_FSINFO_LEAD_SIGNATURE(fs_info_sector) != FAT_FSINFO_LEAD_SIGNATURE_VALUE) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one( EINVAL ); } else { ret = _fat_block_read(mt_entry, vol->info_sec , FAT_FSI_INFO, FAT_USEFUL_INFO_SIZE, fs_info_sector); if ( ret < 0 ) { rtems_disk_release(vol->dd); return -1; } vol->free_cls = FAT_GET_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector); vol->next_cl = FAT_GET_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector); rc = fat_fat32_update_fsinfo_sector(mt_entry, 0xFFFFFFFF, 0xFFFFFFFF); if ( rc != RC_OK ) { rtems_disk_release(vol->dd); return rc; } } } } else { vol->rdir_cl = 0; vol->mirror = 0; vol->afat = 0; vol->free_cls = 0xFFFFFFFF; vol->next_cl = 0xFFFFFFFF; } vol->afat_loc = vol->fat_loc + vol->fat_length * vol->afat; /* set up collection of fat-files fd */ fs_info->vhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control)); if ( fs_info->vhash == NULL ) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one( ENOMEM ); } for (i = 0; i < FAT_HASH_SIZE; i++) _Chain_Initialize_empty(fs_info->vhash + i); fs_info->rhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control)); if ( fs_info->rhash == NULL ) { rtems_disk_release(vol->dd); free(fs_info->vhash); set_errno_and_return_minus_one( ENOMEM ); } for (i = 0; i < FAT_HASH_SIZE; i++) _Chain_Initialize_empty(fs_info->rhash + i); fs_info->uino_pool_size = FAT_UINO_POOL_INIT_SIZE; fs_info->uino_base = (vol->tot_secs << vol->sec_mul) << 4; fs_info->index = 0; fs_info->uino = (char *)calloc(fs_info->uino_pool_size, sizeof(char)); if ( fs_info->uino == NULL ) { rtems_disk_release(vol->dd); free(fs_info->vhash); free(fs_info->rhash); set_errno_and_return_minus_one( ENOMEM ); } fs_info->sec_buf = (uint8_t *)calloc(vol->bps, sizeof(uint8_t)); if (fs_info->sec_buf == NULL) { rtems_disk_release(vol->dd); free(fs_info->vhash); free(fs_info->rhash); free(fs_info->uino); set_errno_and_return_minus_one( ENOMEM ); } return RC_OK; }
static int _Condition_Wake( struct _Condition_Control *_condition, int count ) { Condition_Control *condition; ISR_lock_Context lock_context; Thread_queue_Heads *heads; Chain_Control unblock; Chain_Node *node; Chain_Node *tail; int woken; condition = _Condition_Get( _condition ); _ISR_lock_ISR_disable( &lock_context ); _Condition_Queue_acquire_critical( condition, &lock_context ); /* * In common uses cases of condition variables there are normally no threads * on the queue, so check this condition early. */ heads = condition->Queue.Queue.heads; if ( __predict_true( heads == NULL ) ) { _Condition_Queue_release( condition, &lock_context ); return 0; } woken = 0; _Chain_Initialize_empty( &unblock ); while ( count > 0 && heads != NULL ) { const Thread_queue_Operations *operations; Thread_Control *first; bool do_unblock; operations = CONDITION_TQ_OPERATIONS; first = ( *operations->first )( heads ); do_unblock = _Thread_queue_Extract_locked( &condition->Queue.Queue, operations, first ); if (do_unblock) { _Chain_Append_unprotected( &unblock, &first->Wait.Node.Chain ); } ++woken; --count; heads = condition->Queue.Queue.heads; } node = _Chain_First( &unblock ); tail = _Chain_Tail( &unblock ); if ( node != tail ) { Per_CPU_Control *cpu_self; cpu_self = _Thread_Dispatch_disable_critical( &lock_context ); _Condition_Queue_release( condition, &lock_context ); do { Thread_Control *thread; Chain_Node *next; next = _Chain_Next( node ); thread = THREAD_CHAIN_NODE_TO_THREAD( node ); _Watchdog_Remove_ticks( &thread->Timer ); _Thread_Unblock( thread ); node = next; } while ( node != tail ); _Thread_Dispatch_enable( cpu_self ); } else { _Condition_Queue_release( condition, &lock_context ); } return woken; }
void _API_extensions_Initialization( void ) { _Chain_Initialize_empty( &_API_extensions_List ); }
static void _Thread_queue_FIFO_do_initialize( Thread_queue_Heads *heads ) { _Chain_Initialize_empty( &heads->Heads.Fifo ); }
static #endif bool _Thread_queue_Path_acquire_critical( Thread_queue_Queue *queue, Thread_Control *the_thread, Thread_queue_Context *queue_context ) { Thread_Control *owner; #if defined(RTEMS_SMP) Thread_queue_Link *link; Thread_queue_Queue *target; /* * For an overview please look at the non-SMP part below. We basically do * the same on SMP configurations. The fact that we may have more than one * executing thread and each thread queue has its own SMP lock makes the task * a bit more difficult. We have to avoid deadlocks at SMP lock level, since * this would result in an unrecoverable deadlock of the overall system. */ _Chain_Initialize_empty( &queue_context->Path.Links ); owner = queue->owner; if ( owner == NULL ) { return true; } if ( owner == the_thread ) { return false; } _Chain_Initialize_node( &queue_context->Path.Start.Lock_context.Wait.Gate.Node ); link = &queue_context->Path.Start; _RBTree_Initialize_node( &link->Registry_node ); _Chain_Initialize_node( &link->Path_node ); do { _Chain_Append_unprotected( &queue_context->Path.Links, &link->Path_node ); link->owner = owner; _Thread_Wait_acquire_default_critical( owner, &link->Lock_context.Lock_context ); target = owner->Wait.queue; link->Lock_context.Wait.queue = target; if ( target != NULL ) { if ( _Thread_queue_Link_add( link, queue, target ) ) { _Thread_queue_Gate_add( &owner->Wait.Lock.Pending_requests, &link->Lock_context.Wait.Gate ); _Thread_Wait_release_default_critical( owner, &link->Lock_context.Lock_context ); _Thread_Wait_acquire_queue_critical( target, &link->Lock_context ); if ( link->Lock_context.Wait.queue == NULL ) { _Thread_queue_Link_remove( link ); _Thread_Wait_release_queue_critical( target, &link->Lock_context ); _Thread_Wait_acquire_default_critical( owner, &link->Lock_context.Lock_context ); _Thread_Wait_remove_request_locked( owner, &link->Lock_context ); _Assert( owner->Wait.queue == NULL ); return true; } } else { link->Lock_context.Wait.queue = NULL; _Thread_queue_Path_append_deadlock_thread( owner, queue_context ); return false; } } else { return true; } link = &owner->Wait.Link; queue = target; owner = queue->owner; } while ( owner != NULL ); #else do { owner = queue->owner; if ( owner == NULL ) { return true; } if ( owner == the_thread ) { return false; } queue = owner->Wait.queue; } while ( queue != NULL ); #endif return true; }