RTEMS  5.0.0
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 
81 static inline void _SMP_ticket_lock_Do_acquire(
82  SMP_ticket_lock_Control *lock
83 #if defined(RTEMS_PROFILING)
84  ,
85  SMP_lock_Stats *stats,
86  SMP_lock_Stats_context *stats_context
87 #endif
88 )
89 {
90  unsigned int my_ticket;
91  unsigned int now_serving;
92 #if defined(RTEMS_PROFILING)
93  unsigned int initial_queue_length;
94  SMP_lock_Stats_acquire_context acquire_context;
95 
96  _SMP_lock_Stats_acquire_begin( &acquire_context );
97 #endif
98 
99  my_ticket =
100  _Atomic_Fetch_add_uint( &lock->next_ticket, 1U, ATOMIC_ORDER_RELAXED );
101 
102 #if defined(RTEMS_PROFILING)
103  now_serving =
104  _Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_ACQUIRE );
105  initial_queue_length = my_ticket - now_serving;
106 
107  if ( initial_queue_length > 0 ) {
108 #endif
109 
110  do {
111  now_serving =
112  _Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_ACQUIRE );
113  } while ( now_serving != my_ticket );
114 
115 #if defined(RTEMS_PROFILING)
116  }
117 
118  _SMP_lock_Stats_acquire_end(
119  &acquire_context,
120  stats,
121  stats_context,
122  initial_queue_length
123  );
124 #endif
125 }
126 
138 #if defined(RTEMS_PROFILING)
139  #define _SMP_ticket_lock_Acquire( lock, stats, stats_context ) \
140  _SMP_ticket_lock_Do_acquire( lock, stats, stats_context )
141 #else
142  #define _SMP_ticket_lock_Acquire( lock, stats, stats_context ) \
143  _SMP_ticket_lock_Do_acquire( lock )
144 #endif
145 
146 static inline void _SMP_ticket_lock_Do_release(
147  SMP_ticket_lock_Control *lock
148 #if defined(RTEMS_PROFILING)
149  ,
150  const SMP_lock_Stats_context *stats_context
151 #endif
152 )
153 {
154  unsigned int current_ticket =
155  _Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_RELAXED );
156  unsigned int next_ticket = current_ticket + 1U;
157 
158 #if defined(RTEMS_PROFILING)
159  _SMP_lock_Stats_release_update( stats_context );
160 #endif
161 
162  _Atomic_Store_uint( &lock->now_serving, next_ticket, ATOMIC_ORDER_RELEASE );
163 }
164 
171 #if defined(RTEMS_PROFILING)
172  #define _SMP_ticket_lock_Release( lock, stats_context ) \
173  _SMP_ticket_lock_Do_release( lock, stats_context )
174 #else
175  #define _SMP_ticket_lock_Release( lock, stats_context ) \
176  _SMP_ticket_lock_Do_release( lock )
177 #endif
178 
181 #ifdef __cplusplus
182 }
183 #endif /* __cplusplus */
184 
185 #endif /* RTEMS_SMP */
186 
187 #endif /* _RTEMS_SCORE_SMPLOCKTICKET_H */
Atomic Operations API.
SMP Lock API.