source: rtems/cpukit/score/include/rtems/score/isrlock.h @ 347ef928

5
Last change on this file since 347ef928 was 347ef928, checked in by Sebastian Huber <sebastian.huber@…>, on 11/03/16 at 16:19:43

score: Provide inline variants for ISR lock ops

  • Property mode set to 100644
File size: 10.9 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreISRLocks
5 *
6 * @brief ISR Locks
7 */
8
9/*
10 * Copyright (c) 2013-2015 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 ScoreISRLocks ISR Locks
35 *
36 * @ingroup ScoreISR
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 Initializes an ISR lock.
155 *
156 * Concurrent initialization leads to unpredictable results.
157 *
158 * @param[in] _lock The ISR lock control.
159 * @param[in] _name The name for the ISR lock.  This name must be a
160 * string persistent throughout the life time of this lock.  The name is only
161 * used if profiling is enabled.
162 */
163#if defined( RTEMS_SMP )
164  #define _ISR_lock_Initialize( _lock, _name ) \
165    _SMP_lock_Initialize( &( _lock )->Lock, _name )
166#else
167  #define _ISR_lock_Initialize( _lock, _name )
168#endif
169
170/**
171 * @brief Destroys an ISR lock.
172 *
173 * Concurrent destruction leads to unpredictable results.
174 *
175 * @param[in] _lock The ISR lock control.
176 */
177#if defined( RTEMS_SMP )
178  #define _ISR_lock_Destroy( _lock ) \
179    _SMP_lock_Destroy( &( _lock )->Lock )
180#else
181  #define _ISR_lock_Destroy( _lock )
182#endif
183
184/**
185 * @brief Acquires an ISR lock.
186 *
187 * Interrupts will be disabled.  On SMP configurations this function acquires
188 * an SMP lock.
189 *
190 * This function can be used in thread and interrupt context.
191 *
192 * @param[in] _lock The ISR lock control.
193 * @param[in] _context The local ISR lock context for an acquire and release
194 * pair.
195 *
196 * @see _ISR_lock_Release_and_ISR_enable().
197 */
198#if defined( RTEMS_SMP )
199  #define _ISR_lock_ISR_disable_and_acquire( _lock, _context ) \
200    _SMP_lock_ISR_disable_and_acquire( \
201      &( _lock )->Lock, \
202      &( _context )->Lock_context \
203    )
204#else
205  #define _ISR_lock_ISR_disable_and_acquire( _lock, _context ) \
206    _ISR_Local_disable( ( _context )->isr_level )
207#endif
208
209/**
210 * @brief Releases an ISR lock.
211 *
212 * The interrupt status will be restored.  On SMP configurations this function
213 * releases an SMP lock.
214 *
215 * This function can be used in thread and interrupt context.
216 *
217 * @param[in] _lock The ISR lock control.
218 * @param[in] _context The local ISR lock context for an acquire and release
219 * pair.
220 *
221 * @see _ISR_lock_ISR_disable_and_acquire().
222 */
223#if defined( RTEMS_SMP )
224  #define _ISR_lock_Release_and_ISR_enable( _lock, _context ) \
225    _SMP_lock_Release_and_ISR_enable( \
226      &( _lock )->Lock, \
227      &( _context )->Lock_context \
228    )
229#else
230  #define _ISR_lock_Release_and_ISR_enable( _lock, _context ) \
231    _ISR_Local_enable( ( _context )->isr_level )
232#endif
233
234/**
235 * @brief Acquires an ISR lock inside an ISR disabled section.
236 *
237 * The interrupt status will remain unchanged.  On SMP configurations this
238 * function acquires an SMP lock.
239 *
240 * In case the executing context can be interrupted by higher priority
241 * interrupts and these interrupts enter the critical section protected by this
242 * lock, then the result is unpredictable.
243 *
244 * @param[in] _lock The ISR lock control.
245 * @param[in] _context The local ISR lock context for an acquire and release
246 * pair.
247 *
248 * @see _ISR_lock_Release().
249 */
250#if defined( RTEMS_SMP )
251  #define _ISR_lock_Acquire( _lock, _context ) \
252    _SMP_lock_Acquire( \
253      &( _lock )->Lock, \
254      &( _context )->Lock_context \
255    )
256#else
257  #define _ISR_lock_Acquire( _lock, _context ) \
258    (void) _context;
259#endif
260
261/**
262 * @brief Releases an ISR lock inside an ISR disabled section.
263 *
264 * The interrupt status will remain unchanged.  On SMP configurations this
265 * function releases an SMP lock.
266 *
267 * @param[in] _lock The ISR lock control.
268 * @param[in] _context The local ISR lock context for an acquire and release
269 * pair.
270 *
271 * @see _ISR_lock_Acquire().
272 */
273#if defined( RTEMS_SMP )
274  #define _ISR_lock_Release( _lock, _context ) \
275    _SMP_lock_Release( \
276      &( _lock )->Lock, \
277      &( _context )->Lock_context \
278    )
279#else
280  #define _ISR_lock_Release( _lock, _context ) \
281    (void) _context;
282#endif
283
284/**
285 * @brief Acquires an ISR lock inside an ISR disabled section (inline).
286 *
287 * @see _ISR_lock_Acquire().
288 */
289#if defined( RTEMS_SMP )
290  #define _ISR_lock_Acquire_inline( _lock, _context ) \
291    _SMP_lock_Acquire_inline( \
292      &( _lock )->Lock, \
293      &( _context )->Lock_context \
294    )
295#else
296  #define _ISR_lock_Acquire_inline( _lock, _context ) \
297    (void) _context;
298#endif
299
300/**
301 * @brief Releases an ISR lock inside an ISR disabled section (inline).
302 *
303 * @see _ISR_lock_Release().
304 */
305#if defined( RTEMS_SMP )
306  #define _ISR_lock_Release_inline( _lock, _context ) \
307    _SMP_lock_Release_inline( \
308      &( _lock )->Lock, \
309      &( _context )->Lock_context \
310    )
311#else
312  #define _ISR_lock_Release_inline( _lock, _context ) \
313    (void) _context;
314#endif
315
316#if defined( RTEMS_DEBUG )
317  /**
318   * @brief Returns true, if the ISR lock is owned by the current processor,
319   * otherwise false.
320   *
321   * On uni-processor configurations, this function returns true, if interrupts
322   * are disabled, otherwise false.
323   *
324   * @param[in] _lock The ISR lock control.
325   */
326  #if defined( RTEMS_SMP )
327    #define _ISR_lock_Is_owner( _lock ) \
328      _SMP_lock_Is_owner( &( _lock )->Lock )
329  #else
330    #define _ISR_lock_Is_owner( _lock ) \
331      ( _ISR_Get_level() != 0 )
332  #endif
333#endif
334
335/**
336 * @brief Flashes an ISR lock.
337 *
338 * On uni-processor configurations this a simple _ISR_Local_flash().  On SMP
339 * configurations this function releases an SMP lock, restores the interrupt
340 * status, then disables interrupts and acquires the SMP lock again.
341 *
342 * This function can be used in thread and interrupt context.
343 *
344 * @param[in] _lock The ISR lock control.
345 * @param[in] _context The local ISR lock context for an acquire and release
346 * pair.
347 *
348 * @see _ISR_lock_ISR_disable_and_acquire() and
349 * _ISR_lock_Release_and_ISR_enable().
350 */
351#if defined( RTEMS_SMP )
352  #define _ISR_lock_Flash( _lock, _context ) \
353    _SMP_lock_Release_and_ISR_enable( \
354      &( _lock )->Lock, \
355      &( _context )->Lock_context \
356    ); \
357    _SMP_lock_ISR_disable_and_acquire( \
358      &( _lock )->Lock, \
359      &( _context )->Lock_context \
360    )
361#else
362  #define _ISR_lock_Flash( _lock, _context ) \
363    _ISR_Local_flash( ( _context )->isr_level )
364#endif
365
366#if defined( RTEMS_PROFILING )
367  #define _ISR_lock_ISR_disable_profile( _context ) \
368    ( _context )->ISR_disable_instant = _CPU_Counter_read();
369#else
370  #define _ISR_lock_ISR_disable_profile( _context )
371#endif
372
373/**
374 * @brief Disables interrupts and saves the previous interrupt state in the ISR
375 * lock context.
376 *
377 * This function can be used in thread and interrupt context.
378 *
379 * @param[in] _context The local ISR lock context to store the interrupt state.
380 *
381 * @see _ISR_lock_ISR_enable().
382 */
383#if defined( RTEMS_SMP )
384  #define _ISR_lock_ISR_disable( _context ) \
385    do { \
386      _ISR_Local_disable( ( _context )->Lock_context.isr_level ); \
387      _ISR_lock_ISR_disable_profile( _context ) \
388    } while ( 0 )
389#else
390  #define _ISR_lock_ISR_disable( _context ) \
391    do { \
392      _ISR_Local_disable( ( _context )->isr_level ); \
393      _ISR_lock_ISR_disable_profile( _context ) \
394    } while ( 0 )
395#endif
396
397/**
398 * @brief Restores the saved interrupt state of the ISR lock context.
399 *
400 * This function can be used in thread and interrupt context.
401 *
402 * @param[in] _context The local ISR lock context containing the saved
403 * interrupt state.
404 *
405 * @see _ISR_lock_ISR_disable().
406 */
407#if defined( RTEMS_SMP )
408  #define _ISR_lock_ISR_enable( _context ) \
409    _ISR_Local_enable( ( _context )->Lock_context.isr_level )
410#else
411  #define _ISR_lock_ISR_enable( _context ) \
412    _ISR_Local_enable( ( _context )->isr_level )
413#endif
414
415/** @} */
416
417#ifdef __cplusplus
418}
419#endif
420
421#endif /* _RTEMS_SCORE_ISR_LOCK_H */
Note: See TracBrowser for help on using the repository browser.