RTEMS 6.1-rc6
Loading...
Searching...
No Matches
smplockmcs.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-2-Clause */
2
12/*
13 * Copyright (c) 2016 embedded brains GmbH & Co. KG
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _RTEMS_SCORE_SMPLOCKMCS_H
38#define _RTEMS_SCORE_SMPLOCKMCS_H
39
40#include <rtems/score/cpuopts.h>
41
42#if defined(RTEMS_SMP)
43
44#include <rtems/score/atomic.h>
46
47#ifdef __cplusplus
48extern "C" {
49#endif /* __cplusplus */
50
60typedef struct SMP_MCS_lock_Context {
64 union {
68 Atomic_Uintptr atomic;
69
75 struct SMP_MCS_lock_Context *normal;
76 } next;
77
86 Atomic_Uint locked;
87
88#if defined(RTEMS_PROFILING)
89 SMP_lock_Stats_context Stats_context;
90
91 unsigned int queue_length;
92#endif
93} SMP_MCS_lock_Context;
94
98typedef struct {
105 union {
110 Atomic_Uintptr atomic;
111
117 struct SMP_MCS_lock_Context *normal;
118 } queue;
119} SMP_MCS_lock_Control;
120
124#define SMP_MCS_LOCK_INITIALIZER { { ATOMIC_INITIALIZER_UINTPTR( 0 ) } }
125
133static inline void _SMP_MCS_lock_Initialize( SMP_MCS_lock_Control *lock )
134{
135 _Atomic_Init_uintptr( &lock->queue.atomic, 0 );
136}
137
145static inline void _SMP_MCS_lock_Destroy( SMP_MCS_lock_Control *lock )
146{
147 (void) lock;
148}
149
157static inline void _SMP_MCS_lock_Do_acquire(
158 SMP_MCS_lock_Control *lock,
159 SMP_MCS_lock_Context *context
160#if defined(RTEMS_PROFILING)
161 ,
162 SMP_lock_Stats *stats
163#endif
164)
165{
166 SMP_MCS_lock_Context *previous;
167#if defined(RTEMS_PROFILING)
168 SMP_lock_Stats_acquire_context acquire_context;
169
170 _SMP_lock_Stats_acquire_begin( &acquire_context );
171 context->queue_length = 0;
172#endif
173
174 _Atomic_Store_uintptr( &context->next.atomic, 0, ATOMIC_ORDER_RELAXED );
175 _Atomic_Store_uint( &context->locked, 1, ATOMIC_ORDER_RELAXED );
176
177 previous = (SMP_MCS_lock_Context *) _Atomic_Exchange_uintptr(
178 &lock->queue.atomic,
179 (uintptr_t) context,
180 ATOMIC_ORDER_ACQ_REL
181 );
182
183 if ( previous != NULL ) {
184 unsigned int locked;
185
186 _Atomic_Store_uintptr(
187 &previous->next.atomic,
188 (uintptr_t) context,
189 ATOMIC_ORDER_RELAXED
190 );
191
192 do {
193 locked = _Atomic_Load_uint( &context->locked, ATOMIC_ORDER_ACQUIRE );
194 } while ( locked != 0 );
195 }
196
197#if defined(RTEMS_PROFILING)
198 _SMP_lock_Stats_acquire_end(
199 &acquire_context,
200 stats,
201 &context->Stats_context,
202 context->queue_length
203 );
204#endif
205}
206
218#if defined(RTEMS_PROFILING)
219 #define _SMP_MCS_lock_Acquire( lock, context, stats ) \
220 _SMP_MCS_lock_Do_acquire( lock, context, stats )
221#else
222 #define _SMP_MCS_lock_Acquire( lock, context, stats ) \
223 _SMP_MCS_lock_Do_acquire( lock, context )
224#endif
225
232static inline void _SMP_MCS_lock_Release(
233 SMP_MCS_lock_Control *lock,
234 SMP_MCS_lock_Context *context
235)
236{
237 SMP_MCS_lock_Context *next;
238
239 next = (SMP_MCS_lock_Context *) _Atomic_Load_uintptr(
240 &context->next.atomic,
241 ATOMIC_ORDER_RELAXED
242 );
243
244 if ( next == NULL ) {
245 uintptr_t expected;
246 bool success;
247
248 expected = (uintptr_t) context;
249 success = _Atomic_Compare_exchange_uintptr(
250 &lock->queue.atomic,
251 &expected,
252 0,
253 ATOMIC_ORDER_RELEASE,
254 ATOMIC_ORDER_RELAXED
255 );
256
257 if ( success ) {
258#if defined(RTEMS_PROFILING)
259 _SMP_lock_Stats_release_update( &context->Stats_context );
260#endif
261 /* Nobody waits. So, we are done */
262 return;
263 }
264
265 do {
266 next = (SMP_MCS_lock_Context *) _Atomic_Load_uintptr(
267 &context->next.atomic,
268 ATOMIC_ORDER_RELAXED
269 );
270 } while ( next == NULL );
271 }
272
273#if defined(RTEMS_PROFILING)
274 next->queue_length = context->queue_length + 1;
275 _SMP_lock_Stats_release_update( &context->Stats_context );
276#endif
277
278 _Atomic_Store_uint( &next->locked, 0, ATOMIC_ORDER_RELEASE );
279}
280
283#ifdef __cplusplus
284}
285#endif /* __cplusplus */
286
287#endif /* RTEMS_SMP */
288
289#endif /* _RTEMS_SCORE_SMPLOCKMCS_H */
This header file provides the interfaces of the Atomic Operations.
rtems_termios_device_context * context
Definition: console-config.c:62
This header file provides the interfaces of the SMP Locks related to lock statistics.