source: rtems/cpukit/include/rtems/score/smplock.h @ 4c20da4b

5
Last change on this file since 4c20da4b was 4c20da4b, checked in by Sebastian Huber <sebastian.huber@…>, on 04/04/19 at 07:18:11

doxygen: Rename Score* groups in RTEMSScore*

Update #3706

  • Property mode set to 100644
File size: 7.6 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSScoreSMPLock
5 *
6 * @brief SMP Lock API
7 */
8
9/*
10 * COPYRIGHT (c) 1989-2011.
11 * On-Line Applications Research Corporation (OAR).
12 *
13 * Copyright (c) 2013, 2016 embedded brains GmbH
14 *
15 * The license and distribution terms for this file may be
16 * found in the file LICENSE in this distribution or at
17 * http://www.rtems.org/license/LICENSE.
18 */
19
20#ifndef _RTEMS_SCORE_SMPLOCK_H
21#define _RTEMS_SCORE_SMPLOCK_H
22
23#include <rtems/score/cpuopts.h>
24
25/**
26 * @defgroup RTEMSScoreSMPLock SMP Locks
27 *
28 * @ingroup RTEMSScore
29 *
30 * @brief The SMP lock provides mutual exclusion for SMP systems at the lowest
31 * level.
32 *
33 * The SMP lock is implemented as a ticket lock.  This provides fairness in
34 * case of concurrent lock attempts.
35 *
36 * This SMP lock API uses a local context for acquire and release pairs.  Such
37 * a context may be used to implement for example the Mellor-Crummey and Scott
38 * (MCS) locks in the future.
39 *
40 * @{
41 */
42
43#if defined(RTEMS_SMP)
44
45#include <rtems/score/smplockstats.h>
46#include <rtems/score/smplockticket.h>
47#include <rtems/score/isrlevel.h>
48
49#if defined(RTEMS_DEBUG)
50#include <rtems/score/assert.h>
51#include <rtems/score/smp.h>
52#endif
53
54#ifdef __cplusplus
55extern "C" {
56#endif /* __cplusplus */
57
58#if defined(RTEMS_DEBUG) || defined(RTEMS_PROFILING)
59#define RTEMS_SMP_LOCK_DO_NOT_INLINE
60#endif
61
62/**
63 * @brief SMP lock control.
64 */
65typedef struct {
66  SMP_ticket_lock_Control Ticket_lock;
67#if defined(RTEMS_DEBUG)
68  /**
69   * @brief The index of the owning processor of this lock.
70   *
71   * The processor index is used instead of the executing thread, so that this
72   * works in interrupt and system initialization context.  It is assumed that
73   * thread dispatching is disabled in SMP lock critical sections.
74   *
75   * In case the lock is free, then the value of this field is
76   * SMP_LOCK_NO_OWNER.
77   *
78   * @see _SMP_lock_Is_owner().
79   */
80  uint32_t owner;
81#endif
82#if defined(RTEMS_PROFILING)
83  SMP_lock_Stats Stats;
84#endif
85} SMP_lock_Control;
86
87/**
88 * @brief Local SMP lock context for acquire and release pairs.
89 */
90typedef struct {
91  ISR_Level isr_level;
92#if defined(RTEMS_DEBUG)
93  SMP_lock_Control *lock_used_for_acquire;
94#endif
95#if defined(RTEMS_PROFILING)
96  SMP_lock_Stats_context Stats_context;
97#endif
98} SMP_lock_Context;
99
100#if defined(RTEMS_DEBUG)
101#define SMP_LOCK_NO_OWNER 0
102#endif
103
104/**
105 * @brief SMP lock control initializer for static initialization.
106 */
107#if defined(RTEMS_DEBUG) && defined(RTEMS_PROFILING)
108  #define SMP_LOCK_INITIALIZER( name ) \
109    { \
110      SMP_TICKET_LOCK_INITIALIZER, \
111      SMP_LOCK_NO_OWNER, \
112      SMP_LOCK_STATS_INITIALIZER( name ) \
113    }
114#elif defined(RTEMS_DEBUG)
115  #define SMP_LOCK_INITIALIZER( name ) \
116    { SMP_TICKET_LOCK_INITIALIZER, SMP_LOCK_NO_OWNER }
117#elif defined(RTEMS_PROFILING)
118  #define SMP_LOCK_INITIALIZER( name ) \
119    { SMP_TICKET_LOCK_INITIALIZER, SMP_LOCK_STATS_INITIALIZER( name ) }
120#else
121  #define SMP_LOCK_INITIALIZER( name ) { SMP_TICKET_LOCK_INITIALIZER }
122#endif
123
124static inline void _SMP_lock_Initialize_inline(
125  SMP_lock_Control *lock,
126  const char       *name
127)
128{
129  _SMP_ticket_lock_Initialize( &lock->Ticket_lock );
130#if defined(RTEMS_DEBUG)
131  lock->owner = SMP_LOCK_NO_OWNER;
132#endif
133#if defined(RTEMS_PROFILING)
134  _SMP_lock_Stats_initialize( &lock->Stats, name );
135#else
136  (void) name;
137#endif
138}
139
140/**
141 * @brief Initializes an SMP lock.
142 *
143 * Concurrent initialization leads to unpredictable results.
144 *
145 * @param[in] lock The SMP lock control.
146 * @param[in] name The name for the SMP lock statistics.  This name must be
147 * persistent throughout the life time of this statistics block.
148 */
149#if defined(RTEMS_SMP_LOCK_DO_NOT_INLINE)
150void _SMP_lock_Initialize(
151  SMP_lock_Control *lock,
152  const char *      name
153);
154#else
155#define _SMP_lock_Initialize( lock, name ) \
156  _SMP_lock_Initialize_inline( lock, name )
157#endif
158
159static inline void _SMP_lock_Destroy_inline( SMP_lock_Control *lock )
160{
161  _SMP_ticket_lock_Destroy( &lock->Ticket_lock );
162  _SMP_lock_Stats_destroy( &lock->Stats );
163}
164
165/**
166 * @brief Destroys an SMP lock.
167 *
168 * Concurrent destruction leads to unpredictable results.
169 *
170 * @param[in] lock The SMP lock control.
171 */
172#if defined(RTEMS_SMP_LOCK_DO_NOT_INLINE)
173void _SMP_lock_Destroy( SMP_lock_Control *lock );
174#else
175#define _SMP_lock_Destroy( lock ) \
176  _SMP_lock_Destroy_inline( lock )
177#endif
178
179#if defined(RTEMS_DEBUG)
180static inline uint32_t _SMP_lock_Who_am_I( void )
181{
182  /*
183   * The CPU index starts with zero.  Increment it by one, to allow global SMP
184   * locks to reside in the BSS section.
185   */
186  return _SMP_Get_current_processor() + 1;
187}
188#endif
189
190static inline void _SMP_lock_Acquire_inline(
191  SMP_lock_Control *lock,
192  SMP_lock_Context *context
193)
194{
195#if defined(RTEMS_DEBUG)
196  context->lock_used_for_acquire = lock;
197#else
198  (void) context;
199#endif
200  _SMP_ticket_lock_Acquire(
201    &lock->Ticket_lock,
202    &lock->Stats,
203    &context->Stats_context
204  );
205#if defined(RTEMS_DEBUG)
206  lock->owner = _SMP_lock_Who_am_I();
207#endif
208}
209
210/**
211 * @brief Acquires an SMP lock.
212 *
213 * This function will not disable interrupts.  The caller must ensure that the
214 * current thread of execution is not interrupted indefinite once it obtained
215 * the SMP lock.
216 *
217 * @param[in] lock The SMP lock control.
218 * @param[in] context The local SMP lock context for an acquire and release
219 * pair.
220 */
221void _SMP_lock_Acquire(
222  SMP_lock_Control *lock,
223  SMP_lock_Context *context
224);
225
226static inline void _SMP_lock_Release_inline(
227  SMP_lock_Control *lock,
228  SMP_lock_Context *context
229)
230{
231#if defined(RTEMS_DEBUG)
232  _Assert( context->lock_used_for_acquire == lock );
233  context->lock_used_for_acquire = NULL;
234  _Assert( lock->owner == _SMP_lock_Who_am_I() );
235  lock->owner = SMP_LOCK_NO_OWNER;
236#else
237  (void) context;
238#endif
239  _SMP_ticket_lock_Release(
240    &lock->Ticket_lock,
241    &context->Stats_context
242  );
243}
244
245/**
246 * @brief Releases an SMP lock.
247 *
248 * @param[in] lock The SMP lock control.
249 * @param[in] context The local SMP lock context for an acquire and release
250 * pair.
251 */
252#if defined(RTEMS_SMP_LOCK_DO_NOT_INLINE)
253void _SMP_lock_Release(
254  SMP_lock_Control *lock,
255  SMP_lock_Context *context
256);
257#else
258#define _SMP_lock_Release( lock, context ) \
259  _SMP_lock_Release_inline( lock, context )
260#endif
261
262static inline void _SMP_lock_ISR_disable_and_acquire_inline(
263  SMP_lock_Control *lock,
264  SMP_lock_Context *context
265)
266{
267  _ISR_Local_disable( context->isr_level );
268  _SMP_lock_Acquire_inline( lock, context );
269}
270
271/**
272 * @brief Disables interrupts and acquires the SMP lock.
273 *
274 * @param[in] lock The SMP lock control.
275 * @param[in] context The local SMP lock context for an acquire and release
276 * pair.
277 */
278void _SMP_lock_ISR_disable_and_acquire(
279  SMP_lock_Control *lock,
280  SMP_lock_Context *context
281);
282
283static inline void _SMP_lock_Release_and_ISR_enable_inline(
284  SMP_lock_Control *lock,
285  SMP_lock_Context *context
286)
287{
288  _SMP_lock_Release_inline( lock, context );
289  _ISR_Local_enable( context->isr_level );
290}
291
292/**
293 * @brief Releases the SMP lock and enables interrupts.
294 *
295 * @param[in] lock The SMP lock control.
296 * @param[in] context The local SMP lock context for an acquire and release
297 * pair.
298 */
299#if defined(RTEMS_SMP_LOCK_DO_NOT_INLINE)
300void _SMP_lock_Release_and_ISR_enable(
301  SMP_lock_Control *lock,
302  SMP_lock_Context *context
303);
304#else
305#define _SMP_lock_Release_and_ISR_enable( lock, context ) \
306  _SMP_lock_Release_and_ISR_enable_inline( lock, context )
307#endif
308
309#if defined(RTEMS_DEBUG)
310/**
311 * @brief Returns true, if the SMP lock is owned by the current processor,
312 * otherwise false.
313 *
314 * @param[in] lock The SMP lock control.
315 */
316bool _SMP_lock_Is_owner( const SMP_lock_Control *lock );
317#endif
318
319/** @} */
320
321#ifdef __cplusplus
322}
323#endif /* __cplusplus */
324
325#endif /* RTEMS_SMP */
326
327#endif /* _RTEMS_SCORE_SMPLOCK_H */
Note: See TracBrowser for help on using the repository browser.