source: rtems/cpukit/score/src/threaddispatchdisablelevel.c @ e358088

4.115
Last change on this file since e358088 was e358088, checked in by Sebastian Huber <sebastian.huber@…>, on 05/28/13 at 08:54:46

smp: New SMP lock API

Move the SMP lock implementation to the CPU port. An optimal SMP lock
implementation is highly architecture dependent. For example the memory
models may be fundamentally different.

The new SMP lock API has a flaw. It does not provide the ability to use
a local context for acquire and release pairs. Such a context is
necessary to implement for example the Mellor-Crummey and Scott (MCS)
locks. The SMP lock is currently used in _Thread_Disable_dispatch() and
_Thread_Enable_dispatch() and makes them to a giant lock acquire and
release. Since these functions do not pass state information via a
local context there is currently no use case for such a feature.

  • Property mode set to 100644
File size: 3.3 KB
Line 
1/**
2 * @file
3 *
4 * @brief Thread Dispatch Disable Functions
5 *
6 * @ingroup ScoreThread
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-2011.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.com/license/LICENSE.
16 */
17
18#include <rtems/system.h>
19#include <rtems/score/apiext.h>
20#include <rtems/score/context.h>
21#include <rtems/score/interr.h>
22#include <rtems/score/isr.h>
23#include <rtems/score/object.h>
24#include <rtems/score/priority.h>
25#include <rtems/score/states.h>
26#include <rtems/score/sysstate.h>
27#include <rtems/score/thread.h>
28
29#define NO_OWNER_CPU (-1)
30
31void _Thread_Dispatch_initialization( void )
32{
33  Thread_Dispatch_disable_level_lock_control *level_lock =
34    &_Thread_Dispatch_disable_level_lock;
35
36  _Thread_Dispatch_disable_level = 0;
37  _SMP_lock_Initialize( &level_lock->lock );
38  level_lock->owner_cpu = NO_OWNER_CPU;
39  _Thread_Dispatch_set_disable_level( 1 );
40}
41
42bool _Thread_Dispatch_in_critical_section(void)
43{
44  if (  _Thread_Dispatch_disable_level == 0 )
45   return false;
46
47  return true;
48}
49
50uint32_t _Thread_Dispatch_get_disable_level(void)
51{
52  return _Thread_Dispatch_disable_level;
53}
54
55uint32_t _Thread_Dispatch_increment_disable_level( void )
56{
57  Thread_Dispatch_disable_level_lock_control *level_lock =
58    &_Thread_Dispatch_disable_level_lock;
59  int self_cpu = bsp_smp_processor_id();
60  ISR_Level isr_level;
61  uint32_t disable_level;
62
63  _ISR_Disable_on_this_core( isr_level );
64
65  if ( level_lock->owner_cpu != self_cpu ) {
66    _SMP_lock_Acquire( &level_lock->lock );
67    level_lock->owner_cpu = self_cpu;
68    level_lock->nest_level = 1;
69  } else {
70    ++level_lock->nest_level;
71  }
72
73  disable_level = _Thread_Dispatch_disable_level;
74  ++disable_level;
75  _Thread_Dispatch_disable_level = disable_level;
76
77  _ISR_Enable_on_this_core( isr_level );
78
79  return disable_level;
80}
81
82uint32_t _Thread_Dispatch_decrement_disable_level( void )
83{
84  Thread_Dispatch_disable_level_lock_control *level_lock =
85    &_Thread_Dispatch_disable_level_lock;
86  ISR_Level isr_level;
87  uint32_t disable_level;
88
89  _ISR_Disable_on_this_core( isr_level );
90
91  --level_lock->nest_level;
92  if ( level_lock->nest_level == 0 ) {
93    level_lock->owner_cpu = NO_OWNER_CPU;
94    _SMP_lock_Release( &level_lock->lock );
95  }
96
97  disable_level = _Thread_Dispatch_disable_level;
98  --disable_level;
99  _Thread_Dispatch_disable_level = disable_level;
100
101  _ISR_Enable_on_this_core( isr_level );
102
103  return disable_level;
104}
105
106
107/*
108 * Note this method is taking a heavy handed approach to
109 * setting the dispatch level. This may be optimized at a
110 * later timee, but it must be in such a way that the nesting
111 * level is decremented by the same number as the dispatch level.
112 * This approach is safest until we are sure the nested spinlock
113 * is successfully working with smp isr source code. 
114 */
115
116uint32_t _Thread_Dispatch_set_disable_level(uint32_t value)
117{
118  /*
119   * If we need the dispatch level to go higher
120   * call increment method the desired number of times.
121   */
122
123  while ( value > _Thread_Dispatch_disable_level ) {
124    _Thread_Dispatch_increment_disable_level();
125  }
126
127  /*
128   * If we need the dispatch level to go lower
129   * call increment method the desired number of times.
130   */
131
132  while ( value < _Thread_Dispatch_disable_level ) {
133    _Thread_Dispatch_decrement_disable_level();
134  }
135
136  return value;
137}
Note: See TracBrowser for help on using the repository browser.