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

4.115
Last change on this file since d50acdbb was d50acdbb, checked in by Sebastian Huber <sebastian.huber@…>, on 03/10/14 at 07:25:32

score: Add local context to SMP lock API

Add a local context structure to the SMP lock API for acquire and
release pairs. This context can be used to store the ISR level and
profiling information. It may be later used to enable more
sophisticated lock algorithms, e.g. MCS locks.

There is only one lock that cannot be used with a local context. This
is the per-CPU lock since here we would have to transfer the local
context through a context switch which is very complicated.

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