[PATCH 3/3] score: Avoid Giant lock for CBS scheduler

Sebastian Huber sebastian.huber at embedded-brains.de
Wed May 4 09:35:11 UTC 2016


Update #2555.
---
 cpukit/score/src/schedulercbsattachthread.c       | 54 ++++++++++++-----------
 cpukit/score/src/schedulercbsdetachthread.c       | 46 ++++++++++---------
 cpukit/score/src/schedulercbsgetexecutiontime.c   | 37 +++++++++-------
 cpukit/score/src/schedulercbsgetremainingbudget.c | 33 +++++++-------
 4 files changed, 93 insertions(+), 77 deletions(-)

diff --git a/cpukit/score/src/schedulercbsattachthread.c b/cpukit/score/src/schedulercbsattachthread.c
index 2d1e0ee..49162f6 100644
--- a/cpukit/score/src/schedulercbsattachthread.c
+++ b/cpukit/score/src/schedulercbsattachthread.c
@@ -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 )
+  if ( server_id >= _Scheduler_CBS_Maximum_servers ) {
     return SCHEDULER_CBS_ERROR_INVALID_PARAMETER;
+  }
+
+  server = &_Scheduler_CBS_Server_list[ server_id ];
 
-  /* Server is not valid. */
-  if ( !_Scheduler_CBS_Server_list[server_id].initialized )
+  if ( !server->initialized ) {
     return SCHEDULER_CBS_ERROR_NOSERVER;
+  }
 
-  /* Server is already attached to a thread. */
-  if ( _Scheduler_CBS_Server_list[server_id].task_id != -1 )
+  if ( server->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;
-    }
+  the_thread = _Thread_Get_interrupt_disable( task_id, &lock_context );
 
-    _Scheduler_CBS_Server_list[server_id].task_id = task_id;
-    node->cbs_server = &_Scheduler_CBS_Server_list[server_id];
+  if ( the_thread == NULL ) {
+    return SCHEDULER_CBS_ERROR_INVALID_PARAMETER;
+  }
 
-    the_thread->budget_callout   = _Scheduler_CBS_Budget_callout;
-    the_thread->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT;
-    the_thread->is_preemptible   = true;
+  node = _Scheduler_CBS_Thread_get_node( the_thread );
 
-    _Objects_Put( &the_thread->Object );
-  } else {
-    return SCHEDULER_CBS_ERROR_INVALID_PARAMETER;
+  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;
 }
diff --git a/cpukit/score/src/schedulercbsdetachthread.c b/cpukit/score/src/schedulercbsdetachthread.c
index 97ce1ad..872d4b8 100644
--- a/cpukit/score/src/schedulercbsdetachthread.c
+++ b/cpukit/score/src/schedulercbsdetachthread.c
@@ -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 )
+  if ( server_id >= _Scheduler_CBS_Maximum_servers ) {
     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 );
+  server = &_Scheduler_CBS_Server_list[ server_id ];
 
-    _Scheduler_CBS_Server_list[server_id].task_id = -1;
-    node->cbs_server = NULL;
+  if ( !server->initialized ) {
+    return SCHEDULER_CBS_ERROR_NOSERVER;
+  }
 
-    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;
+  if ( server->task_id != task_id ) {
+    return SCHEDULER_CBS_ERROR_INVALID_PARAMETER;
+  }
+
+  the_thread = _Thread_Get_interrupt_disable( task_id, &lock_context );
 
-    _Objects_Put( &the_thread->Object );
-  } else {
+  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;
 }
diff --git a/cpukit/score/src/schedulercbsgetexecutiontime.c b/cpukit/score/src/schedulercbsgetexecutiontime.c
index ee139e6..a16d297 100644
--- a/cpukit/score/src/schedulercbsgetexecutiontime.c
+++ b/cpukit/score/src/schedulercbsgetexecutiontime.c
@@ -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;
 }
diff --git a/cpukit/score/src/schedulercbsgetremainingbudget.c b/cpukit/score/src/schedulercbsgetremainingbudget.c
index a031ba4..947a811 100644
--- a/cpukit/score/src/schedulercbsgetremainingbudget.c
+++ b/cpukit/score/src/schedulercbsgetremainingbudget.c
@@ -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;
   }
 
-- 
1.8.4.5




More information about the devel mailing list