RTEMS  5.0.0
smplockmcs.h
Go to the documentation of this file.
1 
9 /*
10  * Copyright (c) 2016 embedded brains GmbH
11  *
12  * The license and distribution terms for this file may be
13  * found in the file LICENSE in this distribution or at
14  * http://www.rtems.org/license/LICENSE.
15  */
16 
17 #ifndef _RTEMS_SCORE_SMPLOCKMCS_H
18 #define _RTEMS_SCORE_SMPLOCKMCS_H
19 
20 #include <rtems/score/cpuopts.h>
21 
22 #if defined(RTEMS_SMP)
23 
24 #include <rtems/score/atomic.h>
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif /* __cplusplus */
30 
40 typedef struct SMP_MCS_lock_Context {
44  union {
48  Atomic_Uintptr atomic;
49 
55  struct SMP_MCS_lock_Context *normal;
56  } next;
57 
66  Atomic_Uint locked;
67 
68 #if defined(RTEMS_PROFILING)
69  SMP_lock_Stats_context Stats_context;
70 
71  unsigned int queue_length;
72 #endif
73 } SMP_MCS_lock_Context;
74 
78 typedef struct {
85  union {
90  Atomic_Uintptr atomic;
91 
97  struct SMP_MCS_lock_Context *normal;
98  } queue;
99 } SMP_MCS_lock_Control;
100 
104 #define SMP_MCS_LOCK_INITIALIZER { { ATOMIC_INITIALIZER_UINTPTR( 0 ) } }
105 
113 static inline void _SMP_MCS_lock_Initialize( SMP_MCS_lock_Control *lock )
114 {
115  _Atomic_Init_uintptr( &lock->queue.atomic, 0 );
116 }
117 
125 static inline void _SMP_MCS_lock_Destroy( SMP_MCS_lock_Control *lock )
126 {
127  (void) lock;
128 }
129 
130 static inline void _SMP_MCS_lock_Do_acquire(
131  SMP_MCS_lock_Control *lock,
132  SMP_MCS_lock_Context *context
133 #if defined(RTEMS_PROFILING)
134  ,
135  SMP_lock_Stats *stats
136 #endif
137 )
138 {
139  SMP_MCS_lock_Context *previous;
140 #if defined(RTEMS_PROFILING)
141  SMP_lock_Stats_acquire_context acquire_context;
142 
143  _SMP_lock_Stats_acquire_begin( &acquire_context );
144  context->queue_length = 0;
145 #endif
146 
147  _Atomic_Store_uintptr( &context->next.atomic, 0, ATOMIC_ORDER_RELAXED );
148  _Atomic_Store_uint( &context->locked, 1, ATOMIC_ORDER_RELAXED );
149 
150  previous = (SMP_MCS_lock_Context *) _Atomic_Exchange_uintptr(
151  &lock->queue.atomic,
152  (uintptr_t) context,
153  ATOMIC_ORDER_ACQ_REL
154  );
155 
156  if ( previous != NULL ) {
157  unsigned int locked;
158 
159  _Atomic_Store_uintptr(
160  &previous->next.atomic,
161  (uintptr_t) context,
162  ATOMIC_ORDER_RELAXED
163  );
164 
165  do {
166  locked = _Atomic_Load_uint( &context->locked, ATOMIC_ORDER_ACQUIRE );
167  } while ( locked != 0 );
168  }
169 
170 #if defined(RTEMS_PROFILING)
171  _SMP_lock_Stats_acquire_end(
172  &acquire_context,
173  stats,
174  &context->Stats_context,
175  context->queue_length
176  );
177 #endif
178 }
179 
191 #if defined(RTEMS_PROFILING)
192  #define _SMP_MCS_lock_Acquire( lock, context, stats ) \
193  _SMP_MCS_lock_Do_acquire( lock, context, stats )
194 #else
195  #define _SMP_MCS_lock_Acquire( lock, context, stats ) \
196  _SMP_MCS_lock_Do_acquire( lock, context )
197 #endif
198 
205 static inline void _SMP_MCS_lock_Release(
206  SMP_MCS_lock_Control *lock,
207  SMP_MCS_lock_Context *context
208 )
209 {
210  SMP_MCS_lock_Context *next;
211 
212  next = (SMP_MCS_lock_Context *) _Atomic_Load_uintptr(
213  &context->next.atomic,
214  ATOMIC_ORDER_RELAXED
215  );
216 
217  if ( next == NULL ) {
218  uintptr_t expected;
219  bool success;
220 
221  expected = (uintptr_t) context;
222  success = _Atomic_Compare_exchange_uintptr(
223  &lock->queue.atomic,
224  &expected,
225  0,
226  ATOMIC_ORDER_RELEASE,
227  ATOMIC_ORDER_RELAXED
228  );
229 
230  if ( success ) {
231 #if defined(RTEMS_PROFILING)
232  _SMP_lock_Stats_release_update( &context->Stats_context );
233 #endif
234  /* Nobody waits. So, we are done */
235  return;
236  }
237 
238  do {
239  next = (SMP_MCS_lock_Context *) _Atomic_Load_uintptr(
240  &context->next.atomic,
241  ATOMIC_ORDER_RELAXED
242  );
243  } while ( next == NULL );
244  }
245 
246 #if defined(RTEMS_PROFILING)
247  next->queue_length = context->queue_length + 1;
248  _SMP_lock_Stats_release_update( &context->Stats_context );
249 #endif
250 
251  _Atomic_Store_uint( &next->locked, 0, ATOMIC_ORDER_RELEASE );
252 }
253 
256 #ifdef __cplusplus
257 }
258 #endif /* __cplusplus */
259 
260 #endif /* RTEMS_SMP */
261 
262 #endif /* _RTEMS_SCORE_SMPLOCKMCS_H */
Atomic Operations API.
unsigned context
Definition: tlb.h:108
SMP Lock API.
#define NULL
Requests a GPIO pin group configuration.
Definition: bestcomm_api.h:77