source: rtems/cpukit/score/src/threaddispatchdisablelevel.c @ 53ad908

4.115
Last change on this file since 53ad908 was 53ad908, checked in by Sebastian Huber <sebastian.huber@…>, on 03/07/14 at 13:36:22

score: Add SMP lock profiling support

  • 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#include <rtems/score/profiling.h>
21#include <rtems/score/sysstate.h>
22
23#define NO_OWNER_CPU 0xffffffffU
24
25typedef struct {
26  SMP_lock_Control lock;
27  uint32_t owner_cpu;
28  uint32_t nest_level;
29} Giant_Control;
30
31static Giant_Control _Giant = {
32  .lock = SMP_LOCK_INITIALIZER("Giant"),
33  .owner_cpu = NO_OWNER_CPU,
34  .nest_level = 0
35};
36
37static void _Giant_Do_acquire( Per_CPU_Control *self_cpu )
38{
39  Giant_Control *giant = &_Giant;
40  uint32_t self_cpu_index = _Per_CPU_Get_index( self_cpu );
41
42  if ( giant->owner_cpu != self_cpu_index ) {
43    _SMP_lock_Acquire( &giant->lock, &self_cpu->Giant_lock_context );
44    giant->owner_cpu = self_cpu_index;
45    giant->nest_level = 1;
46  } else {
47    ++giant->nest_level;
48  }
49}
50
51static void _Giant_Do_release( Per_CPU_Control *self_cpu )
52{
53  Giant_Control *giant = &_Giant;
54
55  --giant->nest_level;
56  if ( giant->nest_level == 0 ) {
57    giant->owner_cpu = NO_OWNER_CPU;
58    _SMP_lock_Release( &giant->lock, &self_cpu->Giant_lock_context );
59  }
60}
61
62void _Giant_Drop( Per_CPU_Control *self_cpu )
63{
64  Giant_Control *giant = &_Giant;
65  uint32_t self_cpu_index = _Per_CPU_Get_index( self_cpu );
66
67  _Assert( _ISR_Get_level() != 0 );
68
69  if ( giant->owner_cpu == self_cpu_index ) {
70    giant->nest_level = 0;
71    giant->owner_cpu = NO_OWNER_CPU;
72    _SMP_lock_Release( &giant->lock, &self_cpu->Giant_lock_context );
73  }
74}
75
76uint32_t _Thread_Dispatch_increment_disable_level( void )
77{
78  ISR_Level isr_level;
79  uint32_t disable_level;
80  Per_CPU_Control *self_cpu;
81
82  _ISR_Disable_without_giant( isr_level );
83
84  /*
85   * We must obtain the processor after interrupts are disabled to prevent
86   * thread migration.
87   */
88  self_cpu = _Per_CPU_Get();
89
90  _Giant_Do_acquire( self_cpu );
91
92  disable_level = self_cpu->thread_dispatch_disable_level;
93  _Profiling_Thread_dispatch_disable( self_cpu, disable_level );
94  ++disable_level;
95  self_cpu->thread_dispatch_disable_level = disable_level;
96
97  _ISR_Enable_without_giant( isr_level );
98
99  return disable_level;
100}
101
102uint32_t _Thread_Dispatch_decrement_disable_level( void )
103{
104  ISR_Level isr_level;
105  uint32_t disable_level;
106  Per_CPU_Control *self_cpu;
107
108  _ISR_Disable_without_giant( isr_level );
109
110  self_cpu = _Per_CPU_Get();
111  disable_level = self_cpu->thread_dispatch_disable_level;
112  --disable_level;
113  self_cpu->thread_dispatch_disable_level = disable_level;
114
115  _Giant_Do_release( self_cpu );
116  _Assert( disable_level != 0 || _Giant.owner_cpu == NO_OWNER_CPU );
117
118  _Profiling_Thread_dispatch_enable( self_cpu, disable_level );
119  _ISR_Enable_without_giant( isr_level );
120
121  return disable_level;
122}
123
124void _Giant_Acquire( void )
125{
126  ISR_Level isr_level;
127
128  _ISR_Disable_without_giant( isr_level );
129  _Assert( _Thread_Dispatch_disable_level != 0 );
130  _Giant_Do_acquire( _Per_CPU_Get() );
131  _ISR_Enable_without_giant( isr_level );
132}
133
134void _Giant_Release( void )
135{
136  ISR_Level isr_level;
137
138  _ISR_Disable_without_giant( isr_level );
139  _Assert( _Thread_Dispatch_disable_level != 0 );
140  _Giant_Do_release( _Per_CPU_Get() );
141  _ISR_Enable_without_giant( isr_level );
142}
143
144#if defined( RTEMS_DEBUG )
145void _Assert_Owner_of_giant( void )
146{
147  Giant_Control *giant = &_Giant;
148
149  _Assert(
150    giant->owner_cpu == _SMP_Get_current_processor()
151      || !_System_state_Is_up( _System_state_Get() )
152  );
153}
154#endif
Note: See TracBrowser for help on using the repository browser.