RTEMS 5.2
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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
28extern "C" {
29#endif /* __cplusplus */
30
40typedef 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
78typedef 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
113static inline void _SMP_MCS_lock_Initialize( SMP_MCS_lock_Control *lock )
114{
115 _Atomic_Init_uintptr( &lock->queue.atomic, 0 );
116}
117
125static inline void _SMP_MCS_lock_Destroy( SMP_MCS_lock_Control *lock )
126{
127 (void) lock;
128}
129
137static inline void _SMP_MCS_lock_Do_acquire(
138 SMP_MCS_lock_Control *lock,
139 SMP_MCS_lock_Context *context
140#if defined(RTEMS_PROFILING)
141 ,
142 SMP_lock_Stats *stats
143#endif
144)
145{
146 SMP_MCS_lock_Context *previous;
147#if defined(RTEMS_PROFILING)
148 SMP_lock_Stats_acquire_context acquire_context;
149
150 _SMP_lock_Stats_acquire_begin( &acquire_context );
151 context->queue_length = 0;
152#endif
153
154 _Atomic_Store_uintptr( &context->next.atomic, 0, ATOMIC_ORDER_RELAXED );
155 _Atomic_Store_uint( &context->locked, 1, ATOMIC_ORDER_RELAXED );
156
157 previous = (SMP_MCS_lock_Context *) _Atomic_Exchange_uintptr(
158 &lock->queue.atomic,
159 (uintptr_t) context,
160 ATOMIC_ORDER_ACQ_REL
161 );
162
163 if ( previous != NULL ) {
164 unsigned int locked;
165
166 _Atomic_Store_uintptr(
167 &previous->next.atomic,
168 (uintptr_t) context,
169 ATOMIC_ORDER_RELAXED
170 );
171
172 do {
173 locked = _Atomic_Load_uint( &context->locked, ATOMIC_ORDER_ACQUIRE );
174 } while ( locked != 0 );
175 }
176
177#if defined(RTEMS_PROFILING)
178 _SMP_lock_Stats_acquire_end(
179 &acquire_context,
180 stats,
181 &context->Stats_context,
182 context->queue_length
183 );
184#endif
185}
186
198#if defined(RTEMS_PROFILING)
199 #define _SMP_MCS_lock_Acquire( lock, context, stats ) \
200 _SMP_MCS_lock_Do_acquire( lock, context, stats )
201#else
202 #define _SMP_MCS_lock_Acquire( lock, context, stats ) \
203 _SMP_MCS_lock_Do_acquire( lock, context )
204#endif
205
212static inline void _SMP_MCS_lock_Release(
213 SMP_MCS_lock_Control *lock,
214 SMP_MCS_lock_Context *context
215)
216{
217 SMP_MCS_lock_Context *next;
218
219 next = (SMP_MCS_lock_Context *) _Atomic_Load_uintptr(
220 &context->next.atomic,
221 ATOMIC_ORDER_RELAXED
222 );
223
224 if ( next == NULL ) {
225 uintptr_t expected;
226 bool success;
227
228 expected = (uintptr_t) context;
229 success = _Atomic_Compare_exchange_uintptr(
230 &lock->queue.atomic,
231 &expected,
232 0,
233 ATOMIC_ORDER_RELEASE,
234 ATOMIC_ORDER_RELAXED
235 );
236
237 if ( success ) {
238#if defined(RTEMS_PROFILING)
239 _SMP_lock_Stats_release_update( &context->Stats_context );
240#endif
241 /* Nobody waits. So, we are done */
242 return;
243 }
244
245 do {
246 next = (SMP_MCS_lock_Context *) _Atomic_Load_uintptr(
247 &context->next.atomic,
248 ATOMIC_ORDER_RELAXED
249 );
250 } while ( next == NULL );
251 }
252
253#if defined(RTEMS_PROFILING)
254 next->queue_length = context->queue_length + 1;
255 _SMP_lock_Stats_release_update( &context->Stats_context );
256#endif
257
258 _Atomic_Store_uint( &next->locked, 0, ATOMIC_ORDER_RELEASE );
259}
260
263#ifdef __cplusplus
264}
265#endif /* __cplusplus */
266
267#endif /* RTEMS_SMP */
268
269#endif /* _RTEMS_SCORE_SMPLOCKMCS_H */
#define NULL
Requests a GPIO pin group configuration.
Definition: bestcomm_api.h:77
Atomic Operations API.
SMP Lock API.
unsigned context
Definition: tlb.h:1