epos_status_code epos_task_set_priority( epos_id id, epos_task_priority new_priority, epos_task_priority *old_priority ) { register Thread_Control *the_thread; Objects_Locations location; if ( new_priority != RTEMS_CURRENT_PRIORITY && !_RTEMS_tasks_Priority_is_valid( new_priority ) ) return RTEMS_INVALID_PRIORITY; if ( !old_priority ) return RTEMS_INVALID_ADDRESS; the_thread = _Thread_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: /* XXX need helper to "convert" from core priority */ *old_priority = the_thread->current_priority; if ( new_priority != RTEMS_CURRENT_PRIORITY ) { the_thread->real_priority = new_priority; if ( the_thread->resource_count == 0 || the_thread->current_priority > new_priority ) _Thread_Change_priority( the_thread, new_priority, false ); } _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: _Thread_Executing->Wait.return_argument = old_priority; return _RTEMS_tasks_MP_Send_request_packet( RTEMS_TASKS_MP_SET_PRIORITY_REQUEST, id, new_priority, 0, /* Not used */ 0 /* Not used */ ); #endif case OBJECTS_ERROR: break; } return RTEMS_INVALID_ID; }
rtems_status_code rtems_task_create( rtems_name name, rtems_task_priority initial_priority, size_t stack_size, rtems_mode initial_modes, rtems_attribute attribute_set, rtems_id *id ) { Thread_Control *the_thread; bool is_fp; #if defined(RTEMS_MULTIPROCESSING) Objects_MP_Control *the_global_object = NULL; bool is_global; #endif bool status; rtems_attribute the_attribute_set; Priority_Control core_priority; RTEMS_API_Control *api; ASR_Information *asr; if ( !id ) return RTEMS_INVALID_ADDRESS; if ( !rtems_is_name_valid( name ) ) return RTEMS_INVALID_NAME; /* * Core Thread Initialize insures we get the minimum amount of * stack space. */ /* * Fix the attribute set to match the attributes which * this processor (1) requires and (2) is able to support. * First add in the required flags for attribute_set * Typically this might include FP if the platform * or application required all tasks to be fp aware. * Then turn off the requested bits which are not supported. */ the_attribute_set = _Attributes_Set( attribute_set, ATTRIBUTES_REQUIRED ); the_attribute_set = _Attributes_Clear( the_attribute_set, ATTRIBUTES_NOT_SUPPORTED ); if ( _Attributes_Is_floating_point( the_attribute_set ) ) is_fp = true; else is_fp = false; /* * Validate the RTEMS API priority and convert it to the core priority range. */ if ( !_Attributes_Is_system_task( the_attribute_set ) ) { if ( !_RTEMS_tasks_Priority_is_valid( initial_priority ) ) return RTEMS_INVALID_PRIORITY; } core_priority = _RTEMS_tasks_Priority_to_Core( initial_priority ); #if defined(RTEMS_MULTIPROCESSING) if ( _Attributes_Is_global( the_attribute_set ) ) { is_global = true; if ( !_System_state_Is_multiprocessing ) return RTEMS_MP_NOT_CONFIGURED; } else is_global = false; #endif /* * Make sure system is MP if this task is global */ /* * Allocate the thread control block and -- if the task is global -- * allocate a global object control block. * * NOTE: This routine does not use the combined allocate and open * global object routine because this results in a lack of * control over when memory is allocated and can be freed in * the event of an error. */ the_thread = _RTEMS_tasks_Allocate(); if ( !the_thread ) { _Objects_Allocator_unlock(); return RTEMS_TOO_MANY; } #if defined(RTEMS_MULTIPROCESSING) if ( is_global ) { the_global_object = _Objects_MP_Allocate_global_object(); if ( _Objects_MP_Is_null_global_object( the_global_object ) ) { _RTEMS_tasks_Free( the_thread ); _Objects_Allocator_unlock(); return RTEMS_TOO_MANY; } } #endif /* * Initialize the core thread for this task. */ status = _Thread_Initialize( &_RTEMS_tasks_Information, the_thread, _Scheduler_Get_by_CPU_index( _SMP_Get_current_processor() ), NULL, stack_size, is_fp, core_priority, _Modes_Is_preempt(initial_modes) ? true : false, _Modes_Is_timeslice(initial_modes) ? THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE : THREAD_CPU_BUDGET_ALGORITHM_NONE, NULL, /* no budget algorithm callout */ _Modes_Get_interrupt_level(initial_modes), (Objects_Name) name ); if ( !status ) { #if defined(RTEMS_MULTIPROCESSING) if ( is_global ) _Objects_MP_Free_global_object( the_global_object ); #endif _RTEMS_tasks_Free( the_thread ); _Objects_Allocator_unlock(); return RTEMS_UNSATISFIED; } api = the_thread->API_Extensions[ THREAD_API_RTEMS ]; asr = &api->Signal; asr->is_enabled = _Modes_Is_asr_disabled(initial_modes) ? false : true; *id = the_thread->Object.id; #if defined(RTEMS_MULTIPROCESSING) the_thread->is_global = is_global; if ( is_global ) { _Objects_MP_Open( &_RTEMS_tasks_Information.Objects, the_global_object, name, the_thread->Object.id ); _RTEMS_tasks_MP_Send_process_packet( RTEMS_TASKS_MP_ANNOUNCE_CREATE, the_thread->Object.id, name ); } #endif _Objects_Allocator_unlock(); return RTEMS_SUCCESSFUL; }
/** * @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; }