source: rtems/cpukit/include/rtems/score/isrlock.h @ 18d45d9

Last change on this file since 18d45d9 was 18d45d9, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 11, 2019 at 10:10:53 AM

score: Add _ISR_lock_Set_name()

Add _ISR_lock_Set_name() to optimize the initialization of
zero-initialized locks.

  • Property mode set to 100644
File size: 11.0 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSScoreISRLocks
5 *
6 * @brief ISR Locks
7 */
8
9/*
10 * Copyright (c) 2013, 2019 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#ifndef _RTEMS_SCORE_ISR_LOCK_H
24#define _RTEMS_SCORE_ISR_LOCK_H
25
26#include <rtems/score/isrlevel.h>
27#include <rtems/score/smplock.h>
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33/**
34 * @defgroup RTEMSScoreISRLocks ISR Locks
35 *
36 * @ingroup RTEMSScoreISR
37 *
38 * @brief Low-level lock to protect critical sections accessed by threads and
39 * interrupt service routines.
40 *
41 * On single processor configurations the ISR locks degrade to simple ISR
42 * disable/enable sequences.  No additional storage or objects are required.
43 *
44 * This synchronization primitive is supported on SMP configurations.  Here SMP
45 * locks are used.
46 *
47 * @{
48 */
49
50/**
51 * @brief ISR lock control.
52 *
53 * @warning Empty structures are implementation-defined in C.  GCC gives them a
54 * size of zero.  In C++ empty structures have a non-zero size.
55 */
56typedef struct {
57#if defined( RTEMS_SMP )
58  SMP_lock_Control Lock;
59#endif
60} ISR_lock_Control;
61
62/**
63 * @brief Local ISR lock context for acquire and release pairs.
64 */
65typedef struct {
66#if defined( RTEMS_SMP )
67  SMP_lock_Context Lock_context;
68#else
69  ISR_Level isr_level;
70#endif
71#if defined( RTEMS_PROFILING )
72  /**
73   * @brief The last interrupt disable instant in CPU counter ticks.
74   */
75  CPU_Counter_ticks ISR_disable_instant;
76#endif
77} ISR_lock_Context;
78
79/**
80 * @brief Defines an ISR lock member.
81 *
82 * Do not add a ';' after this macro.
83 *
84 * @param _designator The designator for the interrupt lock.
85 */
86#if defined( RTEMS_SMP )
87  #define ISR_LOCK_MEMBER( _designator ) ISR_lock_Control _designator;
88#else
89  #define ISR_LOCK_MEMBER( _designator )
90#endif
91
92/**
93 * @brief Declares an ISR lock variable.
94 *
95 * Do not add a ';' after this macro.
96 *
97 * @param _qualifier The qualifier for the interrupt lock, e.g. extern.
98 * @param _designator The designator for the interrupt lock.
99 */
100#if defined( RTEMS_SMP )
101  #define ISR_LOCK_DECLARE( _qualifier, _designator ) \
102    _qualifier ISR_lock_Control _designator;
103#else
104  #define ISR_LOCK_DECLARE( _qualifier, _designator )
105#endif
106
107/**
108 * @brief Defines an ISR lock variable.
109 *
110 * Do not add a ';' after this macro.
111 *
112 * @param _qualifier The qualifier for the interrupt lock, e.g. static.
113 * @param _designator The designator for the interrupt lock.
114 * @param _name The name for the interrupt lock.  It must be a string.  The
115 * name is only used if profiling is enabled.
116 */
117#if defined( RTEMS_SMP )
118  #define ISR_LOCK_DEFINE( _qualifier, _designator, _name ) \
119    _qualifier ISR_lock_Control _designator = { SMP_LOCK_INITIALIZER( _name ) };
120#else
121  #define ISR_LOCK_DEFINE( _qualifier, _designator, _name )
122#endif
123
124/**
125 * @brief Defines an ISR lock variable reference.
126 *
127 * Do not add a ';' after this macro.
128 *
129 * @param _designator The designator for the interrupt lock reference.
130 * @param _target The target for the interrupt lock reference.
131 */
132#if defined( RTEMS_SMP )
133  #define ISR_LOCK_REFERENCE( _designator, _target ) \
134    ISR_lock_Control *_designator = _target;
135#else
136  #define ISR_LOCK_REFERENCE( _designator, _target )
137#endif
138
139/**
140 * @brief Initializer for static initialization of ISR locks.
141 *
142 * @param _name The name for the interrupt lock.  It must be a string.  The
143 * name is only used if profiling is enabled.
144 */
145#if defined( RTEMS_SMP )
146  #define ISR_LOCK_INITIALIZER( _name ) \
147    { SMP_LOCK_INITIALIZER( _name ) }
148#else
149  #define ISR_LOCK_INITIALIZER( _name ) \
150    { }
151#endif
152
153/**
154 * @brief Sets the ISR level in the ISR lock context.
155 *
156 * @param[in] context The ISR lock context.
157 * @param[in] level The ISR level.
158 */
159RTEMS_INLINE_ROUTINE void _ISR_lock_Context_set_level(
160  ISR_lock_Context *context,
161  ISR_Level         level
162)
163{
164#if defined( RTEMS_SMP )
165  context->Lock_context.isr_level = level;
166#else
167  context->isr_level = level;
168#endif
169}
170
171/**
172 * @brief Initializes an ISR lock.
173 *
174 * Concurrent initialization leads to unpredictable results.
175 *
176 * @param[in] _lock The ISR lock control.
177 * @param[in] _name The name for the ISR lock.  This name must be a
178 * string persistent throughout the life time of this lock.  The name is only
179 * used if profiling is enabled.
180 */
181#if defined( RTEMS_SMP )
182  #define _ISR_lock_Initialize( _lock, _name ) \
183    _SMP_lock_Initialize( &( _lock )->Lock, _name )
184#else
185  #define _ISR_lock_Initialize( _lock, _name )
186#endif
187
188/**
189 * @brief Destroys an ISR lock.
190 *
191 * Concurrent destruction leads to unpredictable results.
192 *
193 * @param[in] _lock The ISR lock control.
194 */
195#if defined( RTEMS_SMP )
196  #define _ISR_lock_Destroy( _lock ) \
197    _SMP_lock_Destroy( &( _lock )->Lock )
198#else
199  #define _ISR_lock_Destroy( _lock )
200#endif
201
202/**
203 * @brief Sets the name of an ISR lock.
204 *
205 * @param[out] _lock The ISR lock control.
206 * @param _name The name for the ISR lock.  This name must be a string
207 *   persistent throughout the life time of this lock.  The name is only used
208 *   if profiling is enabled.
209 */
210#if defined( RTEMS_SMP )
211  #define _ISR_lock_Set_name( _lock, _name ) \
212    _SMP_lock_Set_name( &( _lock )->Lock, _name )
213#else
214  #define _ISR_lock_Set_name( _lock, _name )
215#endif
216
217/**
218 * @brief Acquires an ISR lock.
219 *
220 * Interrupts will be disabled.  On SMP configurations this function acquires
221 * an SMP lock.
222 *
223 * This function can be used in thread and interrupt context.
224 *
225 * @param[in] _lock The ISR lock control.
226 * @param[in] _context The local ISR lock context for an acquire and release
227 * pair.
228 *
229 * @see _ISR_lock_Release_and_ISR_enable().
230 */
231#if defined( RTEMS_SMP )
232  #define _ISR_lock_ISR_disable_and_acquire( _lock, _context ) \
233    _SMP_lock_ISR_disable_and_acquire( \
234      &( _lock )->Lock, \
235      &( _context )->Lock_context \
236    )
237#else
238  #define _ISR_lock_ISR_disable_and_acquire( _lock, _context ) \
239    _ISR_Local_disable( ( _context )->isr_level )
240#endif
241
242/**
243 * @brief Releases an ISR lock.
244 *
245 * The interrupt status will be restored.  On SMP configurations this function
246 * releases an SMP lock.
247 *
248 * This function can be used in thread and interrupt context.
249 *
250 * @param[in] _lock The ISR lock control.
251 * @param[in] _context The local ISR lock context for an acquire and release
252 * pair.
253 *
254 * @see _ISR_lock_ISR_disable_and_acquire().
255 */
256#if defined( RTEMS_SMP )
257  #define _ISR_lock_Release_and_ISR_enable( _lock, _context ) \
258    _SMP_lock_Release_and_ISR_enable( \
259      &( _lock )->Lock, \
260      &( _context )->Lock_context \
261    )
262#else
263  #define _ISR_lock_Release_and_ISR_enable( _lock, _context ) \
264    _ISR_Local_enable( ( _context )->isr_level )
265#endif
266
267/**
268 * @brief Acquires an ISR lock inside an ISR disabled section.
269 *
270 * The interrupt status will remain unchanged.  On SMP configurations this
271 * function acquires an SMP lock.
272 *
273 * In case the executing context can be interrupted by higher priority
274 * interrupts and these interrupts enter the critical section protected by this
275 * lock, then the result is unpredictable.
276 *
277 * @param[in] _lock The ISR lock control.
278 * @param[in] _context The local ISR lock context for an acquire and release
279 * pair.
280 *
281 * @see _ISR_lock_Release().
282 */
283#if defined( RTEMS_SMP )
284  #define _ISR_lock_Acquire( _lock, _context ) \
285    do { \
286      _Assert( _ISR_Get_level() != 0 ); \
287      _SMP_lock_Acquire( \
288        &( _lock )->Lock, \
289        &( _context )->Lock_context \
290      ); \
291    } while ( 0 )
292#else
293  #define _ISR_lock_Acquire( _lock, _context ) \
294    do { (void) _context; } while ( 0 )
295#endif
296
297/**
298 * @brief Releases an ISR lock inside an ISR disabled section.
299 *
300 * The interrupt status will remain unchanged.  On SMP configurations this
301 * function releases an SMP lock.
302 *
303 * @param[in] _lock The ISR lock control.
304 * @param[in] _context The local ISR lock context for an acquire and release
305 * pair.
306 *
307 * @see _ISR_lock_Acquire().
308 */
309#if defined( RTEMS_SMP )
310  #define _ISR_lock_Release( _lock, _context ) \
311    _SMP_lock_Release( \
312      &( _lock )->Lock, \
313      &( _context )->Lock_context \
314    )
315#else
316  #define _ISR_lock_Release( _lock, _context ) \
317    do { (void) _context; } while ( 0 )
318#endif
319
320/**
321 * @brief Acquires an ISR lock inside an ISR disabled section (inline).
322 *
323 * @see _ISR_lock_Acquire().
324 */
325#if defined( RTEMS_SMP )
326  #define _ISR_lock_Acquire_inline( _lock, _context ) \
327    do { \
328      _Assert( _ISR_Get_level() != 0 ); \
329      _SMP_lock_Acquire_inline( \
330        &( _lock )->Lock, \
331        &( _context )->Lock_context \
332      ); \
333    } while ( 0 )
334#else
335  #define _ISR_lock_Acquire_inline( _lock, _context ) \
336    do { (void) _context; } while ( 0 )
337#endif
338
339/**
340 * @brief Releases an ISR lock inside an ISR disabled section (inline).
341 *
342 * @see _ISR_lock_Release().
343 */
344#if defined( RTEMS_SMP )
345  #define _ISR_lock_Release_inline( _lock, _context ) \
346    _SMP_lock_Release_inline( \
347      &( _lock )->Lock, \
348      &( _context )->Lock_context \
349    )
350#else
351  #define _ISR_lock_Release_inline( _lock, _context ) \
352    do { (void) _context; } while ( 0 )
353#endif
354
355#if defined( RTEMS_DEBUG )
356  /**
357   * @brief Returns true, if the ISR lock is owned by the current processor,
358   * otherwise false.
359   *
360   * On uni-processor configurations, this function returns true, if interrupts
361   * are disabled, otherwise false.
362   *
363   * @param[in] _lock The ISR lock control.
364   */
365  #if defined( RTEMS_SMP )
366    #define _ISR_lock_Is_owner( _lock ) \
367      _SMP_lock_Is_owner( &( _lock )->Lock )
368  #else
369    #define _ISR_lock_Is_owner( _lock ) \
370      ( _ISR_Get_level() != 0 )
371  #endif
372#endif
373
374#if defined( RTEMS_PROFILING )
375  #define _ISR_lock_ISR_disable_profile( _context ) \
376    ( _context )->ISR_disable_instant = _CPU_Counter_read();
377#else
378  #define _ISR_lock_ISR_disable_profile( _context )
379#endif
380
381/**
382 * @brief Disables interrupts and saves the previous interrupt state in the ISR
383 * lock context.
384 *
385 * This function can be used in thread and interrupt context.
386 *
387 * @param[in] _context The local ISR lock context to store the interrupt state.
388 *
389 * @see _ISR_lock_ISR_enable().
390 */
391#if defined( RTEMS_SMP )
392  #define _ISR_lock_ISR_disable( _context ) \
393    do { \
394      _ISR_Local_disable( ( _context )->Lock_context.isr_level ); \
395      _ISR_lock_ISR_disable_profile( _context ) \
396    } while ( 0 )
397#else
398  #define _ISR_lock_ISR_disable( _context ) \
399    do { \
400      _ISR_Local_disable( ( _context )->isr_level ); \
401      _ISR_lock_ISR_disable_profile( _context ) \
402    } while ( 0 )
403#endif
404
405/**
406 * @brief Restores the saved interrupt state of the ISR lock context.
407 *
408 * This function can be used in thread and interrupt context.
409 *
410 * @param[in] _context The local ISR lock context containing the saved
411 * interrupt state.
412 *
413 * @see _ISR_lock_ISR_disable().
414 */
415#if defined( RTEMS_SMP )
416  #define _ISR_lock_ISR_enable( _context ) \
417    _ISR_Local_enable( ( _context )->Lock_context.isr_level )
418#else
419  #define _ISR_lock_ISR_enable( _context ) \
420    _ISR_Local_enable( ( _context )->isr_level )
421#endif
422
423/** @} */
424
425#ifdef __cplusplus
426}
427#endif
428
429#endif /* _RTEMS_SCORE_ISR_LOCK_H */
Note: See TracBrowser for help on using the repository browser.