source: rtems/cpukit/include/rtems/score/smplockmcs.h @ 21275b58

Last change on this file since 21275b58 was 2afb22b, checked in by Chris Johns <chrisj@…>, on Dec 23, 2017 at 7:18:56 AM

Remove make preinstall

A speciality of the RTEMS build system was the make preinstall step. It
copied header files from arbitrary locations into the build tree. The
header files were included via the -Bsome/build/tree/path GCC command
line option.

This has at least seven problems:

  • The make preinstall step itself needs time and disk space.
  • Errors in header files show up in the build tree copy. This makes it hard for editors to open the right file to fix the error.
  • There is no clear relationship between source and build tree header files. This makes an audit of the build process difficult.
  • The visibility of all header files in the build tree makes it difficult to enforce API barriers. For example it is discouraged to use BSP-specifics in the cpukit.
  • An introduction of a new build system is difficult.
  • Include paths specified by the -B option are system headers. This may suppress warnings.
  • The parallel build had sporadic failures on some hosts.

This patch removes the make preinstall step. All installed header
files are moved to dedicated include directories in the source tree.
Let @RTEMS_CPU@ be the target architecture, e.g. arm, powerpc, sparc,
etc. Let @RTEMS_BSP_FAMILIY@ be a BSP family base directory, e.g.
erc32, imx, qoriq, etc.

The new cpukit include directories are:

  • cpukit/include
  • cpukit/score/cpu/@RTEMS_CPU@/include
  • cpukit/libnetworking

The new BSP include directories are:

  • bsps/include
  • bsps/@RTEMS_CPU@/include
  • bsps/@RTEMS_CPU@/@RTEMS_BSP_FAMILIY@/include

There are build tree include directories for generated files.

The include directory order favours the most general header file, e.g.
it is not possible to override general header files via the include path
order.

The "bootstrap -p" option was removed. The new "bootstrap -H" option
should be used to regenerate the "headers.am" files.

Update #3254.

  • Property mode set to 100644
File size: 5.7 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_SMPLOCKMCS_H
18#define _RTEMS_SCORE_SMPLOCKMCS_H
19
20#include <rtems/score/cpuopts.h>
21
22#if defined(RTEMS_SMP)
23
24#include <rtems/score/atomic.h>
25#include <rtems/score/smplockstats.h>
26
27#ifdef __cplusplus
28extern "C" {
29#endif /* __cplusplus */
30
31/**
32 * @addtogroup ScoreSMPLock
33 *
34 * @{
35 */
36
37/**
38 * @brief SMP Mellor-Crummey and Scott (MCS) lock context.
39 */
40typedef struct SMP_MCS_lock_Context {
41  /**
42   * @brief The next context on the queue if it exists.
43   */
44  union {
45    /**
46     * @brief The next context as an atomic unsigned integer pointer value.
47     */
48    Atomic_Uintptr atomic;
49
50    /**
51     * @brief The next context as a normal pointer.
52     *
53     * Only provided for debugging purposes.
54     */
55    struct SMP_MCS_lock_Context *normal;
56  } next;
57
58  /**
59   * @brief Indicates if the lock is owned or free in case a previous context
60   * exits on the queue.
61   *
62   * This field is initialized to a non-zero value.  The previous lock owner
63   * (which is the owner of the previous context) will set it to zero during
64   * its lock release.
65   */
66  Atomic_Uint locked;
67
68#if defined(RTEMS_PROFILING)
69  SMP_lock_Stats_context Stats_context;
70
71  unsigned int queue_length;
72#endif
73} SMP_MCS_lock_Context;
74
75/**
76 * @brief SMP Mellor-Crummey and Scott (MCS) lock control.
77 */
78typedef struct {
79  /**
80   * @brief The queue tail context.
81   *
82   * The lock is free, in case this field is zero, otherwise it is locked by
83   * the owner of the queue head.
84   */
85  union {
86    /**
87     * @brief The queue tail context as an atomic unsigned integer pointer
88     * value.
89     */
90    Atomic_Uintptr atomic;
91
92    /**
93     * @brief The queue tail context as a normal pointer.
94     *
95     * Only provided for debugging purposes.
96     */
97    struct SMP_MCS_lock_Context *normal;
98  } queue;
99} SMP_MCS_lock_Control;
100
101/**
102 * @brief SMP MCS lock control initializer for static initialization.
103 */
104#define SMP_MCS_LOCK_INITIALIZER { { ATOMIC_INITIALIZER_UINTPTR( 0 ) } }
105
106/**
107 * @brief Initializes an SMP MCS lock.
108 *
109 * Concurrent initialization leads to unpredictable results.
110 *
111 * @param lock The SMP MCS lock control.
112 */
113static inline void _SMP_MCS_lock_Initialize( SMP_MCS_lock_Control *lock )
114{
115  _Atomic_Init_uintptr( &lock->queue.atomic, 0 );
116}
117
118/**
119 * @brief Destroys an SMP MCS lock.
120 *
121 * Concurrent destruction leads to unpredictable results.
122 *
123 * @param lock The SMP MCS lock control.
124 */
125static inline void _SMP_MCS_lock_Destroy( SMP_MCS_lock_Control *lock )
126{
127  (void) lock;
128}
129
130static inline void _SMP_MCS_lock_Do_acquire(
131  SMP_MCS_lock_Control   *lock,
132  SMP_MCS_lock_Context   *context
133#if defined(RTEMS_PROFILING)
134  ,
135  SMP_lock_Stats         *stats
136#endif
137)
138{
139  SMP_MCS_lock_Context           *previous;
140#if defined(RTEMS_PROFILING)
141  SMP_lock_Stats_acquire_context  acquire_context;
142
143  _SMP_lock_Stats_acquire_begin( &acquire_context );
144  context->queue_length = 0;
145#endif
146
147  _Atomic_Store_uintptr( &context->next.atomic, 0, ATOMIC_ORDER_RELAXED );
148  _Atomic_Store_uint( &context->locked, 1, ATOMIC_ORDER_RELAXED );
149
150  previous = (SMP_MCS_lock_Context *) _Atomic_Exchange_uintptr(
151    &lock->queue.atomic,
152    (uintptr_t) context,
153    ATOMIC_ORDER_ACQ_REL
154  );
155
156  if ( previous != NULL ) {
157    unsigned int locked;
158
159    _Atomic_Store_uintptr(
160      &previous->next.atomic,
161      (uintptr_t) context,
162      ATOMIC_ORDER_RELAXED
163    );
164
165    do {
166      locked = _Atomic_Load_uint( &context->locked, ATOMIC_ORDER_ACQUIRE );
167    } while ( locked != 0 );
168  }
169
170#if defined(RTEMS_PROFILING)
171  _SMP_lock_Stats_acquire_end(
172    &acquire_context,
173    stats,
174    &context->Stats_context,
175    context->queue_length
176  );
177#endif
178}
179
180/**
181 * @brief Acquires an SMP MCS lock.
182 *
183 * This function will not disable interrupts.  The caller must ensure that the
184 * current thread of execution is not interrupted indefinite once it obtained
185 * the SMP MCS lock.
186 *
187 * @param lock The SMP MCS lock control.
188 * @param context The SMP MCS lock context.
189 * @param stats The SMP lock statistics.
190 */
191#if defined(RTEMS_PROFILING)
192  #define _SMP_MCS_lock_Acquire( lock, context, stats ) \
193    _SMP_MCS_lock_Do_acquire( lock, context, stats )
194#else
195  #define _SMP_MCS_lock_Acquire( lock, context, stats ) \
196    _SMP_MCS_lock_Do_acquire( lock, context )
197#endif
198
199/**
200 * @brief Releases an SMP MCS lock.
201 *
202 * @param lock The SMP MCS lock control.
203 * @param context The SMP MCS lock context.
204 */
205static inline void _SMP_MCS_lock_Release(
206  SMP_MCS_lock_Control *lock,
207  SMP_MCS_lock_Context *context
208)
209{
210  SMP_MCS_lock_Context *next;
211
212  next = (SMP_MCS_lock_Context *) _Atomic_Load_uintptr(
213    &context->next.atomic,
214    ATOMIC_ORDER_RELAXED
215  );
216
217  if ( next == NULL ) {
218    uintptr_t expected;
219    bool      success;
220
221    expected = (uintptr_t) context;
222    success = _Atomic_Compare_exchange_uintptr(
223      &lock->queue.atomic,
224      &expected,
225      0,
226      ATOMIC_ORDER_RELEASE,
227      ATOMIC_ORDER_RELAXED
228    );
229
230    if ( success ) {
231#if defined(RTEMS_PROFILING)
232      _SMP_lock_Stats_release_update( &context->Stats_context );
233#endif
234      /* Nobody waits. So, we are done */
235      return;
236    }
237
238    do {
239      next = (SMP_MCS_lock_Context *) _Atomic_Load_uintptr(
240        &context->next.atomic,
241        ATOMIC_ORDER_RELAXED
242      );
243    } while ( next == NULL );
244  }
245
246#if defined(RTEMS_PROFILING)
247  next->queue_length = context->queue_length + 1;
248  _SMP_lock_Stats_release_update( &context->Stats_context );
249#endif
250
251  _Atomic_Store_uint( &next->locked, 0, ATOMIC_ORDER_RELEASE );
252}
253
254/**@}*/
255
256#ifdef __cplusplus
257}
258#endif /* __cplusplus */
259
260#endif /* RTEMS_SMP */
261
262#endif /* _RTEMS_SCORE_SMPLOCKMCS_H */
Note: See TracBrowser for help on using the repository browser.