RTEMS  5.1
smplockticket.h
Go to the documentation of this file.
1 
9 /*
10  * Copyright (c) 2013, 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_SMPLOCKTICKET_H
18 #define _RTEMS_SCORE_SMPLOCKTICKET_H
19 
20 #include <rtems/score/cpuopts.h>
21 
22 #if defined(RTEMS_SMP)
23 
24 #include <rtems/score/atomic.h>
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif /* __cplusplus */
30 
40 typedef struct {
41  Atomic_Uint next_ticket;
42  Atomic_Uint now_serving;
43 } SMP_ticket_lock_Control;
44 
48 #define SMP_TICKET_LOCK_INITIALIZER \
49  { \
50  ATOMIC_INITIALIZER_UINT( 0U ), \
51  ATOMIC_INITIALIZER_UINT( 0U ) \
52  }
53 
61 static inline void _SMP_ticket_lock_Initialize(
62  SMP_ticket_lock_Control *lock
63 )
64 {
65  _Atomic_Init_uint( &lock->next_ticket, 0U );
66  _Atomic_Init_uint( &lock->now_serving, 0U );
67 }
68 
76 static inline void _SMP_ticket_lock_Destroy( SMP_ticket_lock_Control *lock )
77 {
78  (void) lock;
79 }
80 
88 static inline void _SMP_ticket_lock_Do_acquire(
89  SMP_ticket_lock_Control *lock
90 #if defined(RTEMS_PROFILING)
91  ,
92  SMP_lock_Stats *stats,
93  SMP_lock_Stats_context *stats_context
94 #endif
95 )
96 {
97  unsigned int my_ticket;
98  unsigned int now_serving;
99 #if defined(RTEMS_PROFILING)
100  unsigned int initial_queue_length;
101  SMP_lock_Stats_acquire_context acquire_context;
102 
103  _SMP_lock_Stats_acquire_begin( &acquire_context );
104 #endif
105 
106  my_ticket =
107  _Atomic_Fetch_add_uint( &lock->next_ticket, 1U, ATOMIC_ORDER_RELAXED );
108 
109 #if defined(RTEMS_PROFILING)
110  now_serving =
111  _Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_ACQUIRE );
112  initial_queue_length = my_ticket - now_serving;
113 
114  if ( initial_queue_length > 0 ) {
115 #endif
116 
117  do {
118  now_serving =
119  _Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_ACQUIRE );
120  } while ( now_serving != my_ticket );
121 
122 #if defined(RTEMS_PROFILING)
123  }
124 
125  _SMP_lock_Stats_acquire_end(
126  &acquire_context,
127  stats,
128  stats_context,
129  initial_queue_length
130  );
131 #endif
132 }
133 
145 #if defined(RTEMS_PROFILING)
146  #define _SMP_ticket_lock_Acquire( lock, stats, stats_context ) \
147  _SMP_ticket_lock_Do_acquire( lock, stats, stats_context )
148 #else
149  #define _SMP_ticket_lock_Acquire( lock, stats, stats_context ) \
150  _SMP_ticket_lock_Do_acquire( lock )
151 #endif
152 
159 static inline void _SMP_ticket_lock_Do_release(
160  SMP_ticket_lock_Control *lock
161 #if defined(RTEMS_PROFILING)
162  ,
163  const SMP_lock_Stats_context *stats_context
164 #endif
165 )
166 {
167  unsigned int current_ticket =
168  _Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_RELAXED );
169  unsigned int next_ticket = current_ticket + 1U;
170 
171 #if defined(RTEMS_PROFILING)
172  _SMP_lock_Stats_release_update( stats_context );
173 #endif
174 
175  _Atomic_Store_uint( &lock->now_serving, next_ticket, ATOMIC_ORDER_RELEASE );
176 }
177 
184 #if defined(RTEMS_PROFILING)
185  #define _SMP_ticket_lock_Release( lock, stats_context ) \
186  _SMP_ticket_lock_Do_release( lock, stats_context )
187 #else
188  #define _SMP_ticket_lock_Release( lock, stats_context ) \
189  _SMP_ticket_lock_Do_release( lock )
190 #endif
191 
194 #ifdef __cplusplus
195 }
196 #endif /* __cplusplus */
197 
198 #endif /* RTEMS_SMP */
199 
200 #endif /* _RTEMS_SCORE_SMPLOCKTICKET_H */
Atomic Operations API.
SMP Lock API.