score: Avoid Giant lock for CBS scheduler

Update #2555.
This commit is contained in:
Sebastian Huber
2016-05-06 08:17:05 +02:00
parent 64051ec80b
commit f65f803a26
4 changed files with 106 additions and 90 deletions
+37 -33
View File
@@ -26,42 +26,46 @@ int _Scheduler_CBS_Attach_thread (
rtems_id task_id
)
{
Objects_Locations location;
Thread_Control *the_thread;
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 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 {
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_interrupt_disable( 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;
}
+31 -25
View File
@@ -27,34 +27,40 @@ int _Scheduler_CBS_Detach_thread (
rtems_id task_id
)
{
Objects_Locations location;
Thread_Control *the_thread;
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 is not valid. */
if ( !_Scheduler_CBS_Server_list[server_id].initialized )
return SCHEDULER_CBS_ERROR_NOSERVER;
/* Thread and server are not attached. */
if ( _Scheduler_CBS_Server_list[server_id].task_id != task_id )
return SCHEDULER_CBS_ERROR_INVALID_PARAMETER;
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 );
_Scheduler_CBS_Server_list[server_id].task_id = -1;
node->cbs_server = NULL;
the_thread->budget_algorithm = the_thread->Start.budget_algorithm;
the_thread->budget_callout = the_thread->Start.budget_callout;
the_thread->is_preemptible = the_thread->Start.is_preemptible;
_Objects_Put( &the_thread->Object );
} else {
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 != task_id ) {
return SCHEDULER_CBS_ERROR_INVALID_PARAMETER;
}
the_thread = _Thread_Get_interrupt_disable( task_id, &lock_context );
if ( the_thread == NULL ) {
return SCHEDULER_CBS_ERROR_INVALID_PARAMETER;
}
node = _Scheduler_CBS_Thread_get_node( the_thread );
node->cbs_server = NULL;
server->task_id = -1;
the_thread->budget_algorithm = the_thread->Start.budget_algorithm;
the_thread->budget_callout = the_thread->Start.budget_callout;
the_thread->is_preemptible = the_thread->Start.is_preemptible;
_ISR_lock_ISR_enable( &lock_context );
return SCHEDULER_CBS_OK;
}
+20 -17
View File
@@ -28,30 +28,33 @@ int _Scheduler_CBS_Get_execution_time (
time_t *abs_time
)
{
Objects_Locations location;
Thread_Control *the_thread;
Scheduler_CBS_Server *server;
ISR_lock_Context lock_context;
Thread_Control *the_thread;
if ( server_id >= _Scheduler_CBS_Maximum_servers )
if ( server_id >= _Scheduler_CBS_Maximum_servers ) {
return SCHEDULER_CBS_ERROR_INVALID_PARAMETER;
if ( !_Scheduler_CBS_Server_list[server_id].initialized )
}
server = &_Scheduler_CBS_Server_list[ server_id ];
if ( !server->initialized ) {
return SCHEDULER_CBS_ERROR_NOSERVER;
if ( _Scheduler_CBS_Server_list[server_id].task_id == -1 ) {
}
if ( server->task_id == -1 ) {
*exec_time = 0;
return SCHEDULER_CBS_OK;
}
the_thread = _Thread_Get(
_Scheduler_CBS_Server_list[server_id].task_id,
&location
);
/* The routine _Thread_Get may disable dispatch and not enable again. */
if ( the_thread ) {
*exec_time = _Scheduler_CBS_Server_list[server_id].parameters.budget -
the_thread->cpu_time_budget;
_Objects_Put( &the_thread->Object );
}
else {
*exec_time = _Scheduler_CBS_Server_list[server_id].parameters.budget;
the_thread = _Thread_Get_interrupt_disable( server->task_id, &lock_context );
if ( the_thread != NULL ) {
*exec_time = server->parameters.budget - the_thread->cpu_time_budget;
_ISR_lock_ISR_enable( &lock_context );
} else {
*exec_time = server->parameters.budget;
}
return SCHEDULER_CBS_OK;
}
@@ -26,28 +26,31 @@ int _Scheduler_CBS_Get_remaining_budget (
time_t *remaining_budget
)
{
Objects_Locations location;
Thread_Control *the_thread;
Scheduler_CBS_Server *server;
ISR_lock_Context lock_context;
Thread_Control *the_thread;
if ( server_id >= _Scheduler_CBS_Maximum_servers )
if ( server_id >= _Scheduler_CBS_Maximum_servers ) {
return SCHEDULER_CBS_ERROR_INVALID_PARAMETER;
if ( !_Scheduler_CBS_Server_list[server_id].initialized )
}
server = &_Scheduler_CBS_Server_list[ server_id ];
if ( !server->initialized ) {
return SCHEDULER_CBS_ERROR_NOSERVER;
if ( _Scheduler_CBS_Server_list[server_id].task_id == -1 ) {
*remaining_budget = _Scheduler_CBS_Server_list[server_id].parameters.budget;
}
if ( server->task_id == -1 ) {
*remaining_budget = server->parameters.budget;
return SCHEDULER_CBS_OK;
}
the_thread = _Thread_Get(
_Scheduler_CBS_Server_list[server_id].task_id,
&location
);
/* The routine _Thread_Get may disable dispatch and not enable again. */
if ( the_thread ) {
the_thread = _Thread_Get_interrupt_disable( server->task_id, &lock_context );
if ( the_thread != NULL ) {
*remaining_budget = the_thread->cpu_time_budget;
_Objects_Put( &the_thread->Object );
}
else {
_ISR_lock_ISR_enable( &lock_context );
} else {
*remaining_budget = 0;
}