source: rtems/cpukit/score/include/rtems/score/smplockseq.h @ 05b7eec

5
Last change on this file since 05b7eec was 05b7eec, checked in by Sebastian Huber <sebastian.huber@…>, on Jun 8, 2016 at 1:18:14 PM

score: Add an SMP sequence lock implementation

  • Property mode set to 100644
File size: 4.1 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreSMPLock
5 *
6 * @brief SMP Lock API
7 */
8
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_SMPLOCKSEQ_H
18#define _RTEMS_SCORE_SMPLOCKSEQ_H
19
20#include <rtems/score/cpuopts.h>
21
22#if defined(RTEMS_SMP)
23
24#include <rtems/score/atomic.h>
25
26#ifdef __cplusplus
27extern "C" {
28#endif /* __cplusplus */
29
30/**
31 * @addtogroup ScoreSMPLock
32 *
33 * @{
34 */
35
36/**
37 * @brief SMP sequence lock control.
38 *
39 * The sequence lock offers a consistent data set for readers in the presence
40 * of at most one concurrent writer.  Due to the read-modify-write operation in
41 * _SMP_sequence_lock_Read_retry() the data corresponding to the last written
42 * sequence number is observed.  To allow multiple writers an additional SMP
43 * lock is necessary to serialize writes.
44 *
45 * See also Hans-J. Boehm, HP Laboratories,
46 * "Can Seqlocks Get Along With Programming Language Memory Models?",
47 * http://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf
48 */
49typedef struct {
50  /**
51   * @brief The sequence number.
52   *
53   * An odd value indicates that a write is in progress.
54   */
55  Atomic_Uint sequence;
56} SMP_sequence_lock_Control;
57
58/**
59 * @brief SMP sequence lock control initializer for static initialization.
60 */
61#define SMP_SEQUENCE_LOCK_INITIALIZER { ATOMIC_INITIALIZER_UINT( 0 ) }
62
63/**
64 * @brief Initializes an SMP sequence lock.
65 *
66 * Concurrent initialization leads to unpredictable results.
67 *
68 * @param lock The SMP sequence lock control.
69 */
70static inline void _SMP_sequence_lock_Initialize( SMP_sequence_lock_Control *lock )
71{
72  _Atomic_Init_uint( &lock->sequence, 0 );
73}
74
75/**
76 * @brief Destroys an SMP sequence lock.
77 *
78 * Concurrent destruction leads to unpredictable results.
79 *
80 * @param lock The SMP sequence lock control.
81 */
82static inline void _SMP_sequence_lock_Destroy( SMP_sequence_lock_Control *lock )
83{
84  (void) lock;
85}
86
87/**
88 * @brief Begins an SMP sequence lock write operation.
89 *
90 * This function will not disable interrupts.  The caller must ensure that the
91 * current thread of execution is not interrupted indefinite since this would
92 * starve readers.
93 *
94 * @param lock The SMP sequence lock control.
95 *
96 * @return The current sequence number.
97 */
98static inline unsigned int _SMP_sequence_lock_Write_begin(
99  SMP_sequence_lock_Control *lock
100)
101{
102  unsigned int seq;
103
104  seq = _Atomic_Load_uint( &lock->sequence, ATOMIC_ORDER_RELAXED );
105  _Atomic_Store_uint( &lock->sequence, seq + 1, ATOMIC_ORDER_RELAXED );
106
107  /* There is no atomic store with acquire/release semantics */
108  _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
109
110  return seq;
111}
112
113/**
114 * @brief Ends an SMP sequence lock write operation.
115 *
116 * @param lock The SMP sequence lock control.
117 * @param seq The sequence number returned by _SMP_sequence_lock_Write_begin().
118 */
119static inline void _SMP_sequence_lock_Write_end(
120  SMP_sequence_lock_Control *lock,
121  unsigned int               seq
122)
123{
124  _Atomic_Store_uint( &lock->sequence, seq + 2, ATOMIC_ORDER_RELEASE );
125}
126
127/**
128 * @brief Begins an SMP sequence lock read operation.
129 *
130 * This function will not disable interrupts.
131 *
132 * @param lock The SMP sequence lock control.
133 *
134 * @return The current sequence number.
135 */
136static inline unsigned int _SMP_sequence_lock_Read_begin(
137  const SMP_sequence_lock_Control *lock
138)
139{
140  return _Atomic_Load_uint( &lock->sequence, ATOMIC_ORDER_ACQUIRE );
141}
142
143/**
144 * @brief Ends an SMP sequence lock read operation and indicates if a retry is
145 * necessary.
146 *
147 * @param lock The SMP sequence lock control.
148 * @param seq The sequence number returned by _SMP_sequence_lock_Read_begin().
149 *
150 * @retval true The read operation must be retried with a call to
151 *   _SMP_sequence_lock_Read_begin().
152 * @retval false Otherwise.
153 */
154static inline bool _SMP_sequence_lock_Read_retry(
155  SMP_sequence_lock_Control *lock,
156  unsigned int               seq
157)
158{
159  unsigned int seq2;
160
161  seq2 = _Atomic_Fetch_add_uint( &lock->sequence, 0, ATOMIC_ORDER_RELEASE );
162  return seq != seq2 || seq % 2 != 0;
163}
164
165/**@}*/
166
167#ifdef __cplusplus
168}
169#endif /* __cplusplus */
170
171#endif /* RTEMS_SMP */
172
173#endif /* _RTEMS_SCORE_SMPLOCKSEQ_H */
Note: See TracBrowser for help on using the repository browser.