void _Scheduler_CBS_Budget_callout( Thread_Control *the_thread ) { Priority_Control new_priority; Scheduler_CBS_Node *node; 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. */ node = _Scheduler_CBS_Thread_get_node( the_thread ); if ( node->cbs_server->cbs_budget_overrun ) { _Scheduler_CBS_Get_server_id( node->cbs_server->task_id, &server_id ); node->cbs_server->cbs_budget_overrun( server_id ); } }
void _Scheduler_CBS_Release_job( const Scheduler_Control *scheduler, Thread_Control *the_thread, uint32_t deadline ) { Scheduler_CBS_Node *node = _Scheduler_CBS_Thread_get_node( the_thread ); Scheduler_CBS_Server *serv_info = node->cbs_server; Priority_Control new_priority; Priority_Control unused; 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; _Thread_Set_priority( the_thread, new_priority, &unused, true ); }
int _Scheduler_CBS_Attach_thread ( Scheduler_CBS_Server_id server_id, rtems_id task_id ) { Scheduler_CBS_Server *server; ISR_lock_Context lock_context; Thread_Control *the_thread; Scheduler_CBS_Node *node; if ( server_id >= _Scheduler_CBS_Maximum_servers ) { return SCHEDULER_CBS_ERROR_INVALID_PARAMETER; } server = &_Scheduler_CBS_Server_list[ server_id ]; if ( !server->initialized ) { return SCHEDULER_CBS_ERROR_NOSERVER; } if ( server->task_id != -1 ) { return SCHEDULER_CBS_ERROR_FULL; } the_thread = _Thread_Get( task_id, &lock_context ); if ( the_thread == NULL ) { return SCHEDULER_CBS_ERROR_INVALID_PARAMETER; } node = _Scheduler_CBS_Thread_get_node( the_thread ); if ( node->cbs_server != NULL ) { _ISR_lock_ISR_enable( &lock_context ); return SCHEDULER_CBS_ERROR_FULL; } node->cbs_server = server; server->task_id = task_id; the_thread->budget_callout = _Scheduler_CBS_Budget_callout; the_thread->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT; the_thread->is_preemptible = true; _ISR_lock_ISR_enable( &lock_context ); return SCHEDULER_CBS_OK; }
int _Scheduler_CBS_Attach_thread ( Scheduler_CBS_Server_id server_id, rtems_id task_id ) { Objects_Locations location; Thread_Control *the_thread; if ( server_id >= _Scheduler_CBS_Maximum_servers ) return SCHEDULER_CBS_ERROR_INVALID_PARAMETER; /* Server is not valid. */ if ( !_Scheduler_CBS_Server_list[server_id].initialized ) return SCHEDULER_CBS_ERROR_NOSERVER; /* Server is already attached to a thread. */ if ( _Scheduler_CBS_Server_list[server_id].task_id != -1 ) return SCHEDULER_CBS_ERROR_FULL; the_thread = _Thread_Get(task_id, &location); /* The routine _Thread_Get may disable dispatch and not enable again. */ if ( the_thread ) { Scheduler_CBS_Node *node = _Scheduler_CBS_Thread_get_node( the_thread ); /* Thread is already attached to a server. */ if ( node->cbs_server ) { _Objects_Put( &the_thread->Object ); return SCHEDULER_CBS_ERROR_FULL; } _Scheduler_CBS_Server_list[server_id].task_id = task_id; node->cbs_server = &_Scheduler_CBS_Server_list[server_id]; the_thread->budget_callout = _Scheduler_CBS_Budget_callout; the_thread->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT; the_thread->is_preemptible = true; _Objects_Put( &the_thread->Object ); } else { return SCHEDULER_CBS_ERROR_INVALID_PARAMETER; } return SCHEDULER_CBS_OK; }