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

4.115
Last change on this file since df244cfc was df244cfc, checked in by Sebastian Huber <sebastian.huber@…>, on 06/12/13 at 07:16:30

smp: Protect decrement operation

  • 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/threaddispatch.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  disable_level = _Thread_Dispatch_disable_level;
92  --disable_level;
93  _Thread_Dispatch_disable_level = disable_level;
94
95  --level_lock->nest_level;
96  if ( level_lock->nest_level == 0 ) {
97    level_lock->owner_cpu = NO_OWNER_CPU;
98    _SMP_lock_Release( &level_lock->lock );
99  }
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.