source: rtems/cpukit/score/src/threaddispatchdisablelevel.c @ 7cba8ae6

4.115
Last change on this file since 7cba8ae6 was 7cba8ae6, checked in by Sebastian Huber <sebastian.huber@…>, on 08/23/13 at 10:53:04

smp: Fix warnings

  • Property mode set to 100644
File size: 3.6 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/score/threaddispatch.h>
19#include <rtems/score/assert.h>
20
21#define NO_OWNER_CPU 0xffffffffU
22
23typedef struct {
24  SMP_lock_Control lock;
25  uint32_t owner_cpu;
26  uint32_t nest_level;
27} Giant_Control;
28
29static Giant_Control _Giant = {
30  .lock = SMP_LOCK_INITIALIZER,
31  .owner_cpu = NO_OWNER_CPU,
32  .nest_level = 0
33};
34
35static void _Giant_Do_acquire( uint32_t self_cpu_index )
36{
37  Giant_Control *giant = &_Giant;
38
39  if ( giant->owner_cpu != self_cpu_index ) {
40    _SMP_lock_Acquire( &giant->lock );
41    giant->owner_cpu = self_cpu_index;
42    giant->nest_level = 1;
43  } else {
44    ++giant->nest_level;
45  }
46}
47
48static void _Giant_Do_release( void )
49{
50  Giant_Control *giant = &_Giant;
51
52  --giant->nest_level;
53  if ( giant->nest_level == 0 ) {
54    giant->owner_cpu = NO_OWNER_CPU;
55    _SMP_lock_Release( &giant->lock );
56  }
57}
58
59uint32_t _Thread_Dispatch_increment_disable_level( void )
60{
61  ISR_Level isr_level;
62  uint32_t self_cpu_index;
63  uint32_t disable_level;
64  Per_CPU_Control *self_cpu;
65
66  _ISR_Disable( isr_level );
67
68  /*
69   * We must obtain the processor ID after interrupts are disabled to prevent
70   * thread migration.
71   */
72  self_cpu_index = _SMP_Get_current_processor();
73
74  _Giant_Do_acquire( self_cpu_index );
75
76  self_cpu = _Per_CPU_Get_by_index( self_cpu_index );
77  disable_level = self_cpu->thread_dispatch_disable_level;
78  ++disable_level;
79  self_cpu->thread_dispatch_disable_level = disable_level;
80
81  _ISR_Enable( isr_level );
82
83  return disable_level;
84}
85
86uint32_t _Thread_Dispatch_decrement_disable_level( void )
87{
88  ISR_Level isr_level;
89  uint32_t disable_level;
90  Per_CPU_Control *self_cpu;
91
92  _ISR_Disable( isr_level );
93
94  self_cpu = _Per_CPU_Get();
95  disable_level = self_cpu->thread_dispatch_disable_level;
96  --disable_level;
97  self_cpu->thread_dispatch_disable_level = disable_level;
98
99  _Giant_Do_release();
100
101  _ISR_Enable( 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  ISR_Level isr_level;
119  uint32_t disable_level;
120
121  _ISR_Disable( isr_level );
122  disable_level = _Thread_Dispatch_disable_level;
123  _ISR_Enable( isr_level );
124
125  /*
126   * If we need the dispatch level to go higher
127   * call increment method the desired number of times.
128   */
129
130  while ( value > disable_level ) {
131    disable_level = _Thread_Dispatch_increment_disable_level();
132  }
133
134  /*
135   * If we need the dispatch level to go lower
136   * call increment method the desired number of times.
137   */
138
139  while ( value < disable_level ) {
140    disable_level = _Thread_Dispatch_decrement_disable_level();
141  }
142
143  return value;
144}
145
146void _Giant_Acquire( void )
147{
148  ISR_Level isr_level;
149
150  _ISR_Disable( isr_level );
151  _Assert( _Thread_Dispatch_disable_level != 0 );
152  _Giant_Do_acquire( _SMP_Get_current_processor() );
153  _ISR_Enable( isr_level );
154}
155
156void _Giant_Release( void )
157{
158  ISR_Level isr_level;
159
160  _ISR_Disable( isr_level );
161  _Assert( _Thread_Dispatch_disable_level != 0 );
162  _Giant_Do_release();
163  _ISR_Enable( isr_level );
164}
Note: See TracBrowser for help on using the repository browser.