static void test_case_change_priority( Thread_Control *executing, Scheduler_SMP_Node *node, Scheduler_SMP_Node_state start_state, Priority_Control prio, bool prepend_it, Scheduler_SMP_Node_state new_state ) { switch (start_state) { case SCHEDULER_SMP_NODE_SCHEDULED: _Thread_Change_priority(executing, 1, true); break; case SCHEDULER_SMP_NODE_READY: _Thread_Change_priority(executing, 4, true); break; default: rtems_test_assert(0); break; } rtems_test_assert(node->state == start_state); _Thread_Change_priority(executing, prio, prepend_it); rtems_test_assert(node->state == new_state); }
void _Scheduler_CBS_Release_job( Thread_Control *the_thread, uint32_t deadline ) { Priority_Control new_priority; Scheduler_CBS_Per_thread *sched_info = (Scheduler_CBS_Per_thread *) the_thread->scheduler_info; Scheduler_CBS_Server *serv_info = (Scheduler_CBS_Server *) sched_info->cbs_server; if (deadline) { /* Initializing or shifting deadline. */ if (serv_info) new_priority = (_Watchdog_Ticks_since_boot + serv_info->parameters.deadline) & ~SCHEDULER_EDF_PRIO_MSB; else new_priority = (_Watchdog_Ticks_since_boot + deadline) & ~SCHEDULER_EDF_PRIO_MSB; } else { /* Switch back to background priority. */ new_priority = the_thread->Start.initial_priority; } /* Budget replenishment for the next job. */ if (serv_info) the_thread->cpu_time_budget = serv_info->parameters.budget; the_thread->real_priority = new_priority; _Thread_Change_priority(the_thread, new_priority, true); }
static void test_unblock_op(void) { rtems_status_code sc; rtems_id task_id; Thread_Control *executing; Scheduler_SMP_Node *executing_node; Thread_Control *other; size_t i; task_id = start_task(3); _Thread_Disable_dispatch(); executing = _Thread_Executing; executing_node = _Scheduler_SMP_Thread_get_node(executing); other = get_thread_by_id(task_id); for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) { test_case_unblock_op( executing, executing_node, other, states[i] ); } _Thread_Change_priority(executing, 1, true); rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED); _Thread_Enable_dispatch(); sc = rtems_task_delete(task_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); }
void _Scheduler_CBS_Budget_callout( Thread_Control *the_thread ) { Priority_Control new_priority; Scheduler_CBS_Per_thread *sched_info; Scheduler_CBS_Server_id server_id; /* Put violating task to background until the end of period. */ new_priority = the_thread->Start.initial_priority; if ( the_thread->real_priority != new_priority ) the_thread->real_priority = new_priority; if ( the_thread->current_priority != new_priority ) _Thread_Change_priority(the_thread, new_priority, true); /* Invoke callback function if any. */ sched_info = (Scheduler_CBS_Per_thread *) the_thread->scheduler_info; if ( sched_info->cbs_server->cbs_budget_overrun ) { _Scheduler_CBS_Get_server_id( sched_info->cbs_server->task_id, &server_id ); sched_info->cbs_server->cbs_budget_overrun( server_id ); } }
static inline CORE_mutex_Status _CORE_mutex_Pop_priority( CORE_mutex_Control *mutex, Thread_Control *holder ) { /* * Check whether the holder release the mutex in LIFO order if not return * error code. */ if ( _Chain_First( holder->lock_mutex ) != &mutex->queue.lock_queue ) { mutex->nest_count++; return CORE_MUTEX_RELEASE_NOT_ORDER; } /* * This pops the first node from the list. */ _Chain_Get_first_unprotected( &holder->lock_mutex ); if ( mutex->queue.priority_before != holder->current_priority ) _Thread_Change_priority( holder, mutex->queue.priority_before, true ); return CORE_MUTEX_STATUS_SUCCESSFUL; }
/* * _POSIX_Threads_Sporadic_budget_TSR */ void _POSIX_Threads_Sporadic_budget_TSR( Objects_Id id RTEMS_UNUSED, void *argument ) { uint32_t ticks; Thread_Control *the_thread; POSIX_API_Control *api; the_thread = argument; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; /* ticks is guaranteed to be at least one */ ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_init_budget ); the_thread->cpu_time_budget = ticks; _Thread_Change_priority( the_thread, _POSIX_Priority_To_core( api->schedparam.sched_priority ), NULL, _POSIX_Threads_Sporadic_budget_TSR_filter, true ); /* ticks is guaranteed to be at least one */ ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period ); _Watchdog_Insert_ticks( &api->Sporadic_timer, ticks ); }
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; }
void _CORE_mutex_Seize_interrupt_blocking( CORE_mutex_Control *the_mutex, Watchdog_Interval timeout ) { Thread_Control *executing; executing = _Thread_Executing; if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ) { if ( _Scheduler_Is_priority_higher_than( executing->current_priority, the_mutex->holder->current_priority)) { _Thread_Change_priority( the_mutex->holder, executing->current_priority, false ); } } the_mutex->blocked_count++; _Thread_queue_Enqueue( &the_mutex->Wait_queue, timeout ); _Thread_Enable_dispatch(); }
rtems_status_code rtems_task_set_priority( rtems_id id, rtems_task_priority new_priority, rtems_task_priority *old_priority_p ) { Thread_Control *the_thread; ISR_lock_Context lock_context; const Scheduler_Control *scheduler; Priority_Control old_priority; rtems_status_code status; if ( old_priority_p == NULL ) { return RTEMS_INVALID_ADDRESS; } the_thread = _Thread_Get( id, &lock_context ); if ( the_thread == NULL ) { #if defined(RTEMS_MULTIPROCESSING) return _RTEMS_tasks_MP_Set_priority( id, new_priority, old_priority_p ); #else return RTEMS_INVALID_ID; #endif } if ( new_priority != RTEMS_CURRENT_PRIORITY ) { RTEMS_tasks_Set_priority_context context; Per_CPU_Control *cpu_self; cpu_self = _Thread_Dispatch_disable_critical( &lock_context ); _ISR_lock_ISR_enable( &lock_context ); context.new_priority = new_priority; _Thread_Change_priority( the_thread, 0, &context, _RTEMS_tasks_Set_priority_filter, false ); _Thread_Dispatch_enable( cpu_self ); scheduler = context.scheduler; old_priority = context.old_priority; status = context.status; } else { _Thread_State_acquire_critical( the_thread, &lock_context ); scheduler = _Scheduler_Get_own( the_thread ); old_priority = _Thread_Get_priority( the_thread ); _Thread_State_release( the_thread, &lock_context ); status = RTEMS_SUCCESSFUL; } *old_priority_p = _RTEMS_Priority_From_core( scheduler, old_priority ); return status; }
static void test_case_change_priority_op( Thread_Control *executing, Scheduler_SMP_Node *executing_node, Thread_Control *other, Scheduler_SMP_Node_state start_state, Priority_Control prio, bool prepend_it, Scheduler_SMP_Node_state new_state ) { Thread_Control *needs_help; switch (start_state) { case SCHEDULER_SMP_NODE_SCHEDULED: _Thread_Change_priority(executing, 1, true); break; case SCHEDULER_SMP_NODE_READY: _Thread_Change_priority(executing, 4, true); break; default: rtems_test_assert(0); break; } rtems_test_assert(executing_node->state == start_state); needs_help = change_priority_op(executing, prio, prepend_it); rtems_test_assert(executing_node->state == new_state); if (start_state != new_state) { switch (start_state) { case SCHEDULER_SMP_NODE_SCHEDULED: rtems_test_assert(needs_help == executing); break; case SCHEDULER_SMP_NODE_READY: rtems_test_assert(needs_help == other); break; default: rtems_test_assert(0); break; } } else { rtems_test_assert(needs_help == NULL); } }
void _Thread_Restore_priority( Thread_Control *the_thread ) { _Thread_Change_priority( the_thread, 0, NULL, _Thread_Restore_priority_filter, true ); }
static void test_case_unblock_op( Thread_Control *executing, Scheduler_SMP_Node *executing_node, Thread_Control *other, Scheduler_SMP_Node_state new_state ) { Thread_Control *needs_help; switch (new_state) { case SCHEDULER_SMP_NODE_SCHEDULED: _Thread_Change_priority(executing, 2, false); rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_SCHEDULED); break; case SCHEDULER_SMP_NODE_READY: _Thread_Change_priority(executing, 4, false); rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_READY); break; default: rtems_test_assert(0); break; } block_op(executing); rtems_test_assert(executing_node->state == SCHEDULER_SMP_NODE_BLOCKED); needs_help = unblock_op(executing); rtems_test_assert(executing_node->state == new_state); switch (new_state) { case SCHEDULER_SMP_NODE_SCHEDULED: rtems_test_assert(needs_help == other); break; case SCHEDULER_SMP_NODE_READY: rtems_test_assert(needs_help == executing); break; default: rtems_test_assert(0); break; } }
void _Thread_Raise_priority( Thread_Control *the_thread, Priority_Control new_priority ) { _Thread_Change_priority( the_thread, new_priority, NULL, _Thread_Raise_priority_filter, false ); }
void _Thread_Inherit_priority( Thread_Control *inheritor, Thread_Control *ancestor ) { _Thread_Change_priority( inheritor, PRIORITY_PSEUDO_ISR, ancestor, _Thread_Inherit_priority_filter, false ); }
static void _Thread_Raise_real_priority( Thread_Control *the_thread, Priority_Control priority ) { _Thread_Change_priority( the_thread, priority, NULL, _Thread_Raise_real_priority_filter, false ); }
static void test(void) { rtems_status_code sc; rtems_id task_id; Thread_Control *executing; Scheduler_SMP_Node *node; size_t i; size_t j; size_t k; sc = rtems_task_create( rtems_build_name('T', 'A', 'S', 'K'), 3, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &task_id ); rtems_test_assert(sc == RTEMS_SUCCESSFUL); sc = rtems_task_start(task_id, task, 0); rtems_test_assert(sc == RTEMS_SUCCESSFUL); _Thread_Disable_dispatch(); executing = _Thread_Executing; node = _Scheduler_SMP_Node_get( executing ); for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) { for (j = 0; j < RTEMS_ARRAY_SIZE(priorities); ++j) { for (k = 0; k < RTEMS_ARRAY_SIZE(prepend_it); ++k) { test_case( executing, node, states[i], priorities[j], prepend_it[k], states[j] ); } } } _Thread_Change_priority(executing, 1, true); rtems_test_assert(node->state == SCHEDULER_SMP_NODE_SCHEDULED); _Thread_Enable_dispatch(); sc = rtems_task_delete(task_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); }
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; }
/* * _POSIX_Threads_Sporadic_budget_TSR */ void _POSIX_Threads_Sporadic_budget_TSR( Objects_Id id __attribute__((unused)), void *argument ) { uint32_t ticks; uint32_t new_priority; Thread_Control *the_thread; POSIX_API_Control *api; the_thread = argument; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; /* ticks is guaranteed to be at least one */ ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_init_budget ); the_thread->cpu_time_budget = ticks; new_priority = _POSIX_Priority_To_core( api->schedparam.sched_priority ); the_thread->real_priority = new_priority; /* * If holding a resource, then do not change it. */ #if 0 printk( "TSR %d %d %d\n", the_thread->resource_count, the_thread->current_priority, new_priority ); #endif if ( the_thread->resource_count == 0 ) { /* * If this would make them less important, then do not change it. */ if ( the_thread->current_priority > new_priority ) { _Thread_Change_priority( the_thread, new_priority, true ); #if 0 printk( "raise priority\n" ); #endif } } /* ticks is guaranteed to be at least one */ ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period ); _Watchdog_Insert_ticks( &api->Sporadic_timer, ticks ); }
void _Scheduler_EDF_Release_job( Thread_Control *the_thread, uint32_t deadline ) { Priority_Control new_priority; if (deadline) { /* Initializing or shifting deadline. */ new_priority = (_Watchdog_Ticks_since_boot + deadline) & ~SCHEDULER_EDF_PRIO_MSB; } else { /* Switch back to background priority. */ new_priority = the_thread->Start.initial_priority; } the_thread->real_priority = new_priority; _Thread_Change_priority(the_thread, new_priority, true); }
ER chg_pri( ID tskid, PRI tskpri ) { register Thread_Control *the_thread; Objects_Locations location; Priority_Control new_priority; the_thread = _ITRON_Task_Get( tskid, &location ); switch ( location ) { #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: #endif case OBJECTS_ERROR: return _ITRON_Task_Clarify_get_id_error( tskid ); case OBJECTS_LOCAL: if (_States_Is_dormant( the_thread->current_state )) _ITRON_return_errorno( E_OBJ ); if (( tskpri <= 0 ) || ( tskpri >= PRIORITY_MAXIMUM-1 )) _ITRON_return_errorno( E_PAR ); new_priority = _ITRON_Task_Priority_to_Core( tskpri ); the_thread->real_priority = new_priority; /* * The priority should not be changed until later if priority * inheratance has occured. */ if ( the_thread->resource_count == 0 || the_thread->current_priority > new_priority ) _Thread_Change_priority( the_thread, new_priority, false ); break; } _ITRON_return_errorno( E_OK ); }
static void test_change_priority(void) { rtems_status_code sc; rtems_id task_id; Thread_Control *executing; Scheduler_SMP_Node *node; size_t i; size_t j; size_t k; task_id = start_task(3); _Thread_Disable_dispatch(); executing = _Thread_Executing; node = _Scheduler_SMP_Thread_get_node( executing ); for (i = 0; i < RTEMS_ARRAY_SIZE(states); ++i) { for (j = 0; j < RTEMS_ARRAY_SIZE(priorities); ++j) { for (k = 0; k < RTEMS_ARRAY_SIZE(prepend_it); ++k) { test_case_change_priority( executing, node, states[i], priorities[j], prepend_it[k], states[j] ); } } } _Thread_Change_priority(executing, 1, true); rtems_test_assert(node->state == SCHEDULER_SMP_NODE_SCHEDULED); _Thread_Enable_dispatch(); sc = rtems_task_delete(task_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); }
/* * _POSIX_Threads_Sporadic_budget_callout */ void _POSIX_Threads_Sporadic_budget_callout( Thread_Control *the_thread ) { POSIX_API_Control *api; uint32_t new_priority; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; /* * This will prevent the thread from consuming its entire "budget" * while at low priority. */ the_thread->cpu_time_budget = 0xFFFFFFFF; /* XXX should be based on MAX_U32 */ new_priority = _POSIX_Priority_To_core(api->schedparam.sched_ss_low_priority); the_thread->real_priority = new_priority; /* * If holding a resource, then do not change it. */ #if 0 printk( "callout %d %d %d\n", the_thread->resource_count, the_thread->current_priority, new_priority ); #endif if ( the_thread->resource_count == 0 ) { /* * Make sure we are actually lowering it. If they have lowered it * to logically lower than sched_ss_low_priority, then we do not want to * change it. */ if ( the_thread->current_priority < new_priority ) { _Thread_Change_priority( the_thread, new_priority, true ); #if 0 printk( "lower priority\n" ); #endif } } }
/* * _POSIX_Threads_Sporadic_budget_callout */ void _POSIX_Threads_Sporadic_budget_callout( Thread_Control *the_thread ) { POSIX_API_Control *api; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; /* * This will prevent the thread from consuming its entire "budget" * while at low priority. */ the_thread->cpu_time_budget = UINT32_MAX; _Thread_Change_priority( the_thread, _POSIX_Priority_To_core( api->schedparam.sched_ss_low_priority ), NULL, _POSIX_Threads_Sporadic_budget_callout_filter, true ); }
static void _Thread_Request_life_change( Thread_Control *the_thread, Thread_Control *executing, Priority_Control priority, Thread_Life_state additional_life_state ) { Thread_Life_state previous_life_state; Per_CPU_Control *cpu; ISR_Level level; const Scheduler_Control *scheduler; cpu = _Thread_Action_ISR_disable_and_acquire( the_thread, &level ); previous_life_state = the_thread->Life.state; the_thread->Life.state = previous_life_state | additional_life_state; _Thread_Action_release_and_ISR_enable( cpu, level ); scheduler = _Scheduler_Get( the_thread ); if ( the_thread == executing ) { Priority_Control unused; _Thread_Set_priority( the_thread, priority, &unused, true ); _Thread_Start_life_change_for_executing( executing ); } else if ( previous_life_state == THREAD_LIFE_NORMAL ) { _Thread_Start_life_change( the_thread, scheduler, priority ); } else { _Thread_Clear_state( the_thread, STATES_SUSPENDED ); if ( _Thread_Is_life_terminating( additional_life_state ) ) { _Thread_Change_priority( the_thread, priority, NULL, _Thread_Raise_real_priority_filter, false ); } } }
static void _Thread_Start_life_change( Thread_Control *the_thread, const Scheduler_Control *scheduler, Priority_Control priority ) { the_thread->is_preemptible = the_thread->Start.is_preemptible; the_thread->budget_algorithm = the_thread->Start.budget_algorithm; the_thread->budget_callout = the_thread->Start.budget_callout; _Thread_Set_state( the_thread, STATES_RESTARTING ); _Thread_queue_Extract_with_proxy( the_thread ); _Watchdog_Remove_ticks( &the_thread->Timer ); _Thread_Change_priority( the_thread, priority, NULL, _Thread_Raise_real_priority_filter, false ); _Thread_Add_life_change_action( the_thread ); _Thread_Ready( the_thread ); }
CORE_mutex_Status _CORE_mutex_Surrender( CORE_mutex_Control *the_mutex, #if defined(RTEMS_MULTIPROCESSING) Objects_Id id, CORE_mutex_API_mp_support_callout api_mutex_mp_support #else Objects_Id id __attribute__((unused)), CORE_mutex_API_mp_support_callout api_mutex_mp_support __attribute__((unused)) #endif ) { Thread_Control *the_thread; Thread_Control *holder; holder = the_mutex->holder; /* * The following code allows a thread (or ISR) other than the thread * which acquired the mutex to release that mutex. This is only * allowed when the mutex in quetion is FIFO or simple Priority * discipline. But Priority Ceiling or Priority Inheritance mutexes * must be released by the thread which acquired them. */ if ( the_mutex->Attributes.only_owner_release ) { if ( !_Thread_Is_executing( holder ) ) return CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE; } /* XXX already unlocked -- not right status */ if ( !the_mutex->nest_count ) return CORE_MUTEX_STATUS_SUCCESSFUL; the_mutex->nest_count--; if ( the_mutex->nest_count != 0 ) { /* * All error checking is on the locking side, so if the lock was * allowed to acquired multiple times, then we should just deal with * that. The RTEMS_DEBUG is just a validation. */ #if defined(RTEMS_DEBUG) switch ( the_mutex->Attributes.lock_nesting_behavior ) { case CORE_MUTEX_NESTING_ACQUIRES: return CORE_MUTEX_STATUS_SUCCESSFUL; #if defined(RTEMS_POSIX_API) case CORE_MUTEX_NESTING_IS_ERROR: /* should never occur */ return CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED; #endif case CORE_MUTEX_NESTING_BLOCKS: /* Currently no API exercises this behavior. */ break; } #else /* must be CORE_MUTEX_NESTING_ACQUIRES or we wouldn't be here */ return CORE_MUTEX_STATUS_SUCCESSFUL; #endif } /* * Formally release the mutex before possibly transferring it to a * blocked thread. */ if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) || _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) { CORE_mutex_Status pop_status = _CORE_mutex_Pop_priority( the_mutex, holder ); if ( pop_status != CORE_MUTEX_STATUS_SUCCESSFUL ) return pop_status; holder->resource_count--; /* * Whether or not someone is waiting for the mutex, an * inherited priority must be lowered if this is the last * mutex (i.e. resource) this task has. */ if ( holder->resource_count == 0 && holder->real_priority != holder->current_priority ) { _Thread_Change_priority( holder, holder->real_priority, true ); } } the_mutex->holder = NULL; the_mutex->holder_id = 0; /* * Now we check if another thread was waiting for this mutex. If so, * transfer the mutex to that thread. */ if ( ( the_thread = _Thread_queue_Dequeue( &the_mutex->Wait_queue ) ) ) { #if defined(RTEMS_MULTIPROCESSING) if ( !_Objects_Is_local_id( the_thread->Object.id ) ) { the_mutex->holder = NULL; the_mutex->holder_id = the_thread->Object.id; the_mutex->nest_count = 1; ( *api_mutex_mp_support)( the_thread, id ); } else #endif { the_mutex->holder = the_thread; the_mutex->holder_id = the_thread->Object.id; the_mutex->nest_count = 1; switch ( the_mutex->Attributes.discipline ) { case CORE_MUTEX_DISCIPLINES_FIFO: case CORE_MUTEX_DISCIPLINES_PRIORITY: break; case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT: _CORE_mutex_Push_priority( the_mutex, the_thread ); the_thread->resource_count++; break; case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING: _CORE_mutex_Push_priority( the_mutex, the_thread ); the_thread->resource_count++; if (the_mutex->Attributes.priority_ceiling < the_thread->current_priority){ _Thread_Change_priority( the_thread, the_mutex->Attributes.priority_ceiling, false ); } break; } } } else the_mutex->lock = CORE_MUTEX_UNLOCKED; return CORE_MUTEX_STATUS_SUCCESSFUL; }
void _Scheduler_CBS_Unblock( Scheduler_Control *scheduler, Thread_Control *the_thread ) { Scheduler_CBS_Per_thread *sched_info; Scheduler_CBS_Server *serv_info; Priority_Control new_priority; _Scheduler_EDF_Enqueue( scheduler, the_thread ); /* TODO: flash critical section? */ sched_info = (Scheduler_CBS_Per_thread *) the_thread->scheduler_info; serv_info = (Scheduler_CBS_Server *) sched_info->cbs_server; /* * Late unblock rule for deadline-driven tasks. The remaining time to * deadline must be sufficient to serve the remaining computation time * without increased utilization of this task. It might cause a deadline * miss of another task. */ if (serv_info) { time_t deadline = serv_info->parameters.deadline; time_t budget = serv_info->parameters.budget; time_t deadline_left = the_thread->cpu_time_budget; time_t budget_left = the_thread->real_priority - _Watchdog_Ticks_since_boot; if ( deadline*budget_left > budget*deadline_left ) { /* Put late unblocked task to background until the end of period. */ new_priority = the_thread->Start.initial_priority; if ( the_thread->real_priority != new_priority ) the_thread->real_priority = new_priority; if ( the_thread->current_priority != new_priority ) _Thread_Change_priority(the_thread, new_priority, true); } } /* * If the thread that was unblocked is more important than the heir, * then we have a new heir. This may or may not result in a * context switch. * * Normal case: * If the current thread is preemptible, then we need to do * a context switch. * Pseudo-ISR case: * Even if the thread isn't preemptible, if the new heir is * a pseudo-ISR system task, we need to do a context switch. */ if ( _Scheduler_Is_priority_higher_than( scheduler, the_thread->current_priority, _Thread_Heir->current_priority ) ) { _Thread_Heir = the_thread; if ( _Thread_Executing->is_preemptible || the_thread->current_priority == 0 ) _Thread_Dispatch_necessary = true; } }
int pthread_setschedparam( pthread_t thread, int policy, struct sched_param *param ) { register Thread_Control *the_thread; POSIX_API_Control *api; Thread_CPU_budget_algorithms budget_algorithm; Thread_CPU_budget_algorithm_callout budget_callout; Objects_Locations location; int rc; /* * Check all the parameters */ if ( !param ) return EINVAL; rc = _POSIX_Thread_Translate_sched_param( policy, param, &budget_algorithm, &budget_callout ); if ( rc ) return rc; /* * Actually change the scheduling policy and parameters */ the_thread = _Thread_Get( thread, &location ); switch ( location ) { case OBJECTS_LOCAL: api = the_thread->API_Extensions[ THREAD_API_POSIX ]; if ( api->schedpolicy == SCHED_SPORADIC ) (void) _Watchdog_Remove( &api->Sporadic_timer ); api->schedpolicy = policy; api->schedparam = *param; the_thread->budget_algorithm = budget_algorithm; the_thread->budget_callout = budget_callout; switch ( api->schedpolicy ) { case SCHED_OTHER: case SCHED_FIFO: case SCHED_RR: the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice; the_thread->real_priority = _POSIX_Priority_To_core( api->schedparam.sched_priority ); _Thread_Change_priority( the_thread, the_thread->real_priority, true ); break; case SCHED_SPORADIC: api->ss_high_priority = api->schedparam.sched_priority; _Watchdog_Remove( &api->Sporadic_timer ); _POSIX_Threads_Sporadic_budget_TSR( 0, the_thread ); break; } _Thread_Enable_dispatch(); return 0; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: #endif case OBJECTS_ERROR: break; } return ESRCH; }
static void test_case_yield_op( Thread_Control *executing, Scheduler_SMP_Node *executing_node, Thread_Control *other, Scheduler_SMP_Node_state start_state, Scheduler_SMP_Node_state new_state ) { Thread_Control *needs_help; _Thread_Change_priority(executing, 4, false); _Thread_Change_priority(other, 4, false); switch (start_state) { case SCHEDULER_SMP_NODE_SCHEDULED: switch (new_state) { case SCHEDULER_SMP_NODE_SCHEDULED: _Thread_Change_priority(executing, 2, false); _Thread_Change_priority(other, 3, false); break; case SCHEDULER_SMP_NODE_READY: _Thread_Change_priority(executing, 2, false); _Thread_Change_priority(other, 2, false); break; default: rtems_test_assert(0); break; } break; case SCHEDULER_SMP_NODE_READY: switch (new_state) { case SCHEDULER_SMP_NODE_SCHEDULED: rtems_test_assert(0); break; case SCHEDULER_SMP_NODE_READY: _Thread_Change_priority(executing, 3, false); _Thread_Change_priority(other, 2, false); break; default: rtems_test_assert(0); break; } break; default: rtems_test_assert(0); break; } rtems_test_assert(executing_node->state == start_state); needs_help = yield_op(executing); rtems_test_assert(executing_node->state == new_state); if (start_state != new_state) { switch (start_state) { case SCHEDULER_SMP_NODE_SCHEDULED: rtems_test_assert(needs_help == executing); break; case SCHEDULER_SMP_NODE_READY: rtems_test_assert(needs_help == other); break; default: rtems_test_assert(0); break; } } else { rtems_test_assert(needs_help == NULL); } }