summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src/threadunpin.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/src/threadunpin.c')
-rw-r--r--cpukit/score/src/threadunpin.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/cpukit/score/src/threadunpin.c b/cpukit/score/src/threadunpin.c
new file mode 100644
index 0000000000..bf05790694
--- /dev/null
+++ b/cpukit/score/src/threadunpin.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2018 embedded brains GmbH
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/score/schedulerimpl.h>
+
+void _Thread_Do_unpin( Thread_Control *executing, Per_CPU_Control *cpu_self )
+{
+ ISR_lock_Context state_lock_context;
+ ISR_lock_Context scheduler_lock_context;
+ Scheduler_Node *pinned_node;
+ const Scheduler_Control *pinned_scheduler;
+ Scheduler_Node *home_node;
+ const Scheduler_Control *home_scheduler;
+ const Scheduler_Control *scheduler;
+
+ _Thread_State_acquire( executing, &state_lock_context );
+
+ executing->Scheduler.pin_level = 0;
+
+ pinned_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE(
+ _Chain_First( &executing->Scheduler.Scheduler_nodes )
+ );
+ pinned_scheduler = _Scheduler_Node_get_scheduler( pinned_node );
+ home_node = _Thread_Scheduler_get_home_node( executing );
+ home_scheduler = _Thread_Scheduler_get_home( executing );
+ scheduler = pinned_scheduler;
+
+ executing->Scheduler.pinned_scheduler = NULL;
+
+ _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context );
+
+ if ( _Thread_Is_ready( executing ) ) {
+ ( *scheduler->Operations.block )( scheduler, executing, pinned_node );
+ }
+
+ ( *scheduler->Operations.unpin )(
+ scheduler,
+ executing,
+ pinned_node,
+ cpu_self
+ );
+
+ if ( home_node != pinned_node ) {
+ _Scheduler_Release_critical( scheduler, &scheduler_lock_context );
+
+ _Chain_Extract_unprotected( &home_node->Thread.Scheduler_node.Chain );
+ _Chain_Prepend_unprotected(
+ &executing->Scheduler.Scheduler_nodes,
+ &home_node->Thread.Scheduler_node.Chain
+ );
+ scheduler = home_scheduler;
+
+ _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context );
+ }
+
+ if ( _Thread_Is_ready( executing ) ) {
+ ( *scheduler->Operations.unblock )( scheduler, executing, home_node );
+ }
+
+ _Scheduler_Release_critical( scheduler, &scheduler_lock_context );
+
+ _Thread_State_release( executing, &state_lock_context );
+}