void _Thread_Create_idle( void ) { #if defined(RTEMS_SMP) int cpu; for ( cpu=0 ; cpu < _SMP_Processor_count ; cpu++ ) { _Thread_Create_idle_helper( _Objects_Build_name( 'I', 'D', 'L', 'E' ), cpu ); } #else _Thread_Create_idle_helper(_Objects_Build_name( 'I', 'D', 'L', 'E' ), 0); #endif }
rtems_name rtems_build_name( char C1, char C2, char C3, char C4 ) { return _Objects_Build_name( C1, C2, C3, C4 ); }
static void _Thread_Create_idle_for_cpu( Per_CPU_Control *cpu ) { Objects_Name name; Thread_Control *idle; const Scheduler_Control *scheduler; name.name_u32 = _Objects_Build_name( 'I', 'D', 'L', 'E' ); /* * The entire workspace is zeroed during its initialization. Thus, all * fields not explicitly assigned were explicitly zeroed by * _Workspace_Initialization. */ idle = _Thread_Internal_allocate(); _Thread_Initialize( &_Thread_Internal_information, idle, _Scheduler_Get_by_CPU( cpu ), NULL, /* allocate the stack */ _Stack_Ensure_minimum( rtems_configuration_get_idle_task_stack_size() ), CPU_IDLE_TASK_IS_FP, PRIORITY_MAXIMUM, true, /* preemptable */ THREAD_CPU_BUDGET_ALGORITHM_NONE, NULL, /* no budget algorithm callout */ 0, /* all interrupts enabled */ name ); /* * WARNING!!! This is necessary to "kick" start the system and * MUST be done before _Thread_Start is invoked. */ cpu->heir = cpu->executing = idle; idle->Start.Entry.adaptor = _Thread_Entry_adaptor_idle; idle->Start.Entry.Kinds.Idle.entry = rtems_configuration_get_idle_task(); _Thread_Load_environment( idle ); scheduler = _Scheduler_Get_by_CPU( cpu ); #if defined(RTEMS_SMP) if (scheduler == NULL) { return; } #endif idle->current_state = STATES_READY; _Scheduler_Start_idle( scheduler, idle, cpu ); _User_extensions_Thread_start( idle ); }
bool _Objects_Set_name( Objects_Information *information, Objects_Control *the_object, const char *name ) { size_t length; const char *s; s = name; length = strnlen( name, information->name_length ); #if defined(RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES) if ( information->is_string ) { char *d; d = _Workspace_Allocate( length + 1 ); if ( !d ) return false; if ( the_object->name.name_p ) { _Workspace_Free( (void *)the_object->name.name_p ); the_object->name.name_p = NULL; } strncpy( d, name, length ); d[length] = '\0'; the_object->name.name_p = d; } else #endif { the_object->name.name_u32 = _Objects_Build_name( ((0 <= length) ? s[ 0 ] : ' '), ((1 < length) ? s[ 1 ] : ' '), ((2 < length) ? s[ 2 ] : ' '), ((3 < length) ? s[ 3 ] : ' ') ); } return true; }
void _MPCI_Create_server( void ) { Objects_Name name; if ( !_System_state_Is_multiprocessing ) return; /* * Initialize the MPCI Receive Server */ _MPCI_Receive_server_tcb = _Thread_Internal_allocate(); name.name_u32 = _Objects_Build_name( 'M', 'P', 'C', 'I' ); _Thread_Initialize( &_Thread_Internal_information, _MPCI_Receive_server_tcb, NULL, /* allocate the stack */ _Stack_Minimum() + CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK + _Configuration_MP_table->extra_mpci_receive_server_stack, CPU_ALL_TASKS_ARE_FP, PRIORITY_MINIMUM, false, /* no preempt */ THREAD_CPU_BUDGET_ALGORITHM_NONE, NULL, /* no budget algorithm callout */ 0, /* all interrupts enabled */ name ); _Thread_Start( _MPCI_Receive_server_tcb, THREAD_START_NUMERIC, (void *) _MPCI_Receive_server, NULL, 0, NULL ); }
/** * @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; }