summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src/threaddispatchdisablelevel.c
diff options
context:
space:
mode:
authorJennifer Averett <Jennifer.Averett@OARcorp.com>2011-05-23 13:30:15 +0000
committerJennifer Averett <Jennifer.Averett@OARcorp.com>2011-05-23 13:30:15 +0000
commit3a8a9997866ded736b038322be6adccee63eb3bd (patch)
tree64909329b677082e99d3d8bcb71795a43e70192d /cpukit/score/src/threaddispatchdisablelevel.c
parentFix typo. (diff)
downloadrtems-3a8a9997866ded736b038322be6adccee63eb3bd.tar.bz2
2011-05-23 Jennifer Averett <Jennifer.Averett@OARcorp.com>
* score/Makefile.am, score/include/rtems/score/thread.h, score/inline/rtems/score/thread.inl: Add smp support to dispable dispatch level accesses. * score/src/threaddispatchdisablelevel.c: New file.
Diffstat (limited to 'cpukit/score/src/threaddispatchdisablelevel.c')
-rw-r--r--cpukit/score/src/threaddispatchdisablelevel.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/cpukit/score/src/threaddispatchdisablelevel.c b/cpukit/score/src/threaddispatchdisablelevel.c
new file mode 100644
index 0000000000..f0d1cf7a61
--- /dev/null
+++ b/cpukit/score/src/threaddispatchdisablelevel.c
@@ -0,0 +1,133 @@
+/*
+ * Thread Dispatch Disable Level Methods
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+
+void _Thread_Dispatch_initialization( void )
+{
+ _Thread_Dispatch_disable_level = 0;
+ _SMP_lock_spinlock_nested_Initialize(&_Thread_Dispatch_disable_level_lock);
+ _Thread_Dispatch_set_disable_level( 1 );
+}
+
+bool _Thread_Dispatch_in_critical_section(void)
+{
+ if ( _Thread_Dispatch_disable_level == 0 )
+ return false;
+
+ return true;
+}
+
+uint32_t _Thread_Dispatch_get_disable_level(void)
+{
+ return _Thread_Dispatch_disable_level;
+}
+
+uint32_t _Thread_Dispatch_increment_disable_level(void)
+{
+ ISR_Level isr_level;
+ uint32_t level;
+
+ /*
+ * Note: _SMP_lock_spinlock_nested_Obtain returns
+ * with ISR's disabled and the isr_level that
+ * should be restored after a short period.
+ *
+ * Here we obtain the lock and increment the
+ * Thread dispatch disable level while under the
+ * protection of the isr being off. After this
+ * point it is safe to re-enable ISRs and allow
+ * the dispatch disable lock to provide protection.
+ */
+
+ isr_level = _SMP_lock_spinlock_nested_Obtain(
+ &_Thread_Dispatch_disable_level_lock
+ );
+
+ _Thread_Dispatch_disable_level++;
+ level = _Thread_Dispatch_disable_level;
+
+ _ISR_Enable(isr_level);
+
+ return level;
+}
+
+uint32_t _Thread_Dispatch_decrement_disable_level(void)
+{
+ ISR_Level isr_level;
+ uint32_t level;
+
+ /* First we must disable ISRs in order to protect
+ * accesses to the dispatch disable level.
+ */
+
+ _ISR_Disable( isr_level );
+
+ _Thread_Dispatch_disable_level--;
+ level = _Thread_Dispatch_disable_level;
+
+
+ /*
+ * Note: _SMP_lock_spinlock_nested_Obtain returns with
+ * ISR's disabled and _SMP_lock_spinlock_nested_Release
+ * is responsable for re-enabling interrupts.
+ */
+ _SMP_lock_spinlock_nested_Release(
+ &_Thread_Dispatch_disable_level_lock,
+ isr_level
+ );
+
+ return level;
+}
+
+
+/*
+ * Note this method is taking a heavy handed approach to
+ * setting the dispatch level. This may be optimized at a
+ * later timee, but it must be in such a way that the nesting
+ * level is decremented by the same number as the dispatch level.
+ * This approach is safest until we are sure the nested spinlock
+ * is successfully working with smp isr source code.
+ */
+
+uint32_t _Thread_Dispatch_set_disable_level(uint32_t value)
+{
+ /*
+ * If we need the dispatch level to go higher
+ * call increment method the desired number of times.
+ */
+
+ while ( value > _Thread_Dispatch_disable_level ) {
+ _Thread_Dispatch_increment_disable_level();
+ }
+
+ /*
+ * If we need the dispatch level to go lower
+ * call increment method the desired number of times.
+ */
+
+ while ( value < _Thread_Dispatch_disable_level ) {
+ _Thread_Dispatch_decrement_disable_level();
+ }
+
+ return value;
+}