source: rtems/cpukit/score/src/condition.c @ 21275b58

5
Last change on this file since 21275b58 was a1f7d7d, checked in by Sebastian Huber <sebastian.huber@…>, on 07/24/18 at 07:00:18

score: RTEMS_PREDICT_TRUE(), RTEMS_PREDICT_FALSE()

Add RTEMS_PREDICT_TRUE() and RTEMS_PREDICT_FALSE() for static branch
prediction hints.

Close #3475.

  • Property mode set to 100644
File size: 7.4 KB
Line 
1/*
2 * Copyright (c) 2015, 2016 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#if HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include <sys/lock.h>
20#include <errno.h>
21#include <limits.h>
22
23#include <rtems/score/atomic.h>
24#include <rtems/score/chainimpl.h>
25#include <rtems/score/threadimpl.h>
26#include <rtems/score/threadqimpl.h>
27#include <rtems/score/todimpl.h>
28#include <rtems/score/watchdogimpl.h>
29
30#define CONDITION_TQ_OPERATIONS &_Thread_queue_Operations_FIFO
31
32typedef struct {
33  Thread_queue_Syslock_queue Queue;
34} Condition_Control;
35
36RTEMS_STATIC_ASSERT(
37  offsetof( Condition_Control, Queue )
38    == offsetof( struct _Condition_Control, _Queue ),
39  CONDITION_CONTROL_QUEUE
40);
41
42RTEMS_STATIC_ASSERT(
43  sizeof( Condition_Control ) == sizeof( struct _Condition_Control ),
44  CONDITION_CONTROL_SIZE
45);
46
47static Condition_Control *_Condition_Get(
48  struct _Condition_Control *_condition
49)
50{
51  return (Condition_Control *) _condition;
52}
53
54static Thread_Control *_Condition_Queue_acquire_critical(
55  Condition_Control    *condition,
56  Thread_queue_Context *queue_context
57)
58{
59  Thread_Control *executing;
60
61  executing = _Thread_Executing;
62  _Thread_queue_Queue_acquire_critical(
63    &condition->Queue.Queue,
64    &executing->Potpourri_stats,
65    &queue_context->Lock_context.Lock_context
66  );
67
68  return executing;
69}
70
71static void _Condition_Queue_release(
72  Condition_Control    *condition,
73  Thread_queue_Context *queue_context
74)
75{
76  _Thread_queue_Queue_release(
77    &condition->Queue.Queue,
78    &queue_context->Lock_context.Lock_context
79  );
80}
81
82typedef struct {
83  Thread_queue_Context   Base;
84  struct _Mutex_Control *mutex;
85} Condition_Enqueue_context;
86
87static void _Condition_Mutex_release( Thread_queue_Context *queue_context )
88{
89  Condition_Enqueue_context *context;
90
91  context = (Condition_Enqueue_context *) queue_context;
92  _Mutex_Release( context->mutex );
93}
94
95static void _Condition_Enqueue_no_timeout(
96  Thread_queue_Queue   *queue,
97  Thread_Control       *the_thread,
98  Per_CPU_Control      *cpu_self,
99  Thread_queue_Context *queue_context
100)
101{
102  _Condition_Mutex_release( queue_context );
103}
104
105static void _Condition_Enqueue_with_timeout(
106  Thread_queue_Queue   *queue,
107  Thread_Control       *the_thread,
108  Per_CPU_Control      *cpu_self,
109  Thread_queue_Context *queue_context
110)
111{
112  _Thread_queue_Add_timeout_realtime_timespec(
113    queue,
114    the_thread,
115    cpu_self,
116    queue_context
117  );
118  _Condition_Mutex_release( queue_context );
119}
120
121static Thread_Control *_Condition_Do_wait(
122  struct _Condition_Control *_condition,
123  struct _Mutex_Control     *_mutex,
124  Condition_Enqueue_context *context
125)
126{
127  Condition_Control *condition;
128  Thread_Control    *executing;
129
130  context->mutex = _mutex;
131  condition = _Condition_Get( _condition );
132  _ISR_lock_ISR_disable( &context->Base.Lock_context.Lock_context );
133  executing = _Condition_Queue_acquire_critical( condition, &context->Base );
134  _Thread_queue_Context_set_thread_state(
135    &context->Base,
136    STATES_WAITING_FOR_CONDITION_VARIABLE
137  );
138  _Thread_queue_Enqueue(
139    &condition->Queue.Queue,
140    CONDITION_TQ_OPERATIONS,
141    executing,
142    &context->Base
143  );
144
145  return executing;
146}
147
148void _Condition_Wait(
149  struct _Condition_Control *_condition,
150  struct _Mutex_Control     *_mutex
151)
152{
153  Condition_Enqueue_context context;
154
155  _Thread_queue_Context_initialize( &context.Base );
156  _Thread_queue_Context_set_enqueue_callout(
157    &context.Base,
158    _Condition_Enqueue_no_timeout
159  );
160  _Condition_Do_wait( _condition, _mutex, &context );
161  _Mutex_Acquire( _mutex );
162}
163
164int _Condition_Wait_timed(
165  struct _Condition_Control *_condition,
166  struct _Mutex_Control     *_mutex,
167  const struct timespec     *abstime
168)
169{
170  Condition_Enqueue_context  context;
171  Thread_Control            *executing;
172  int                        eno;
173
174  _Thread_queue_Context_initialize( &context.Base );
175  _Thread_queue_Context_set_enqueue_callout(
176    &context.Base,
177    _Condition_Enqueue_with_timeout
178  );
179  _Thread_queue_Context_set_timeout_argument( &context.Base, abstime );
180  executing = _Condition_Do_wait( _condition, _mutex, &context );
181  eno = STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
182  _Mutex_Acquire( _mutex );
183
184  return eno;
185}
186
187static unsigned int _Condition_Unnest_mutex(
188  struct _Mutex_recursive_Control *_mutex
189)
190{
191  unsigned int nest_level;
192
193  nest_level = _mutex->_nest_level;
194  _mutex->_nest_level = 0;
195
196  return nest_level;
197}
198
199void _Condition_Wait_recursive(
200  struct _Condition_Control       *_condition,
201  struct _Mutex_recursive_Control *_mutex
202)
203{
204  Condition_Enqueue_context context;
205  unsigned int              nest_level;
206
207  _Thread_queue_Context_initialize( &context.Base );
208  _Thread_queue_Context_set_enqueue_callout(
209    &context.Base,
210    _Condition_Enqueue_no_timeout
211  );
212  nest_level = _Condition_Unnest_mutex( _mutex );
213  _Condition_Do_wait( _condition, &_mutex->_Mutex, &context );
214  _Mutex_recursive_Acquire( _mutex );
215  _mutex->_nest_level = nest_level;
216}
217
218int _Condition_Wait_recursive_timed(
219  struct _Condition_Control       *_condition,
220  struct _Mutex_recursive_Control *_mutex,
221  const struct timespec           *abstime
222)
223{
224  Condition_Enqueue_context  context;
225  Thread_Control            *executing;
226  int                        eno;
227  unsigned int               nest_level;
228
229  _Thread_queue_Context_initialize( &context.Base );
230  _Thread_queue_Context_set_enqueue_callout(
231    &context.Base,
232    _Condition_Enqueue_with_timeout
233  );
234  _Thread_queue_Context_set_timeout_argument( &context.Base, abstime );
235  nest_level = _Condition_Unnest_mutex( _mutex );
236  executing = _Condition_Do_wait( _condition, &_mutex->_Mutex, &context );
237  eno = STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
238  _Mutex_recursive_Acquire( _mutex );
239  _mutex->_nest_level = nest_level;
240
241  return eno;
242}
243
244typedef struct {
245  Thread_queue_Context Base;
246  int                  count;
247} Condition_Flush_context;
248
249static Thread_Control *_Condition_Flush_filter(
250  Thread_Control       *the_thread,
251  Thread_queue_Queue   *queue,
252  Thread_queue_Context *queue_context
253)
254{
255  Condition_Flush_context *context;
256
257  context = (Condition_Flush_context *) queue_context;
258
259  if ( context->count <= 0 ) {
260    return NULL;
261  }
262
263  --context->count;
264
265  return the_thread;
266}
267
268static void _Condition_Wake( struct _Condition_Control *_condition, int count )
269{
270  Condition_Control       *condition;
271  Condition_Flush_context  context;
272
273  condition = _Condition_Get( _condition );
274  _Thread_queue_Context_initialize( &context.Base );
275  _ISR_lock_ISR_disable( &context.Base.Lock_context.Lock_context );
276  _Condition_Queue_acquire_critical( condition, &context.Base );
277
278  /*
279   * In common uses cases of condition variables there are normally no threads
280   * on the queue, so check this condition early.
281   */
282  if (
283    RTEMS_PREDICT_TRUE( _Thread_queue_Is_empty( &condition->Queue.Queue ) )
284  ) {
285    _Condition_Queue_release( condition, &context.Base );
286    return;
287  }
288
289  context.count = count;
290  _Thread_queue_Flush_critical(
291    &condition->Queue.Queue,
292    CONDITION_TQ_OPERATIONS,
293    _Condition_Flush_filter,
294    &context.Base
295  );
296}
297
298void _Condition_Signal( struct _Condition_Control *_condition )
299{
300  _Condition_Wake( _condition, 1 );
301}
302
303void _Condition_Broadcast( struct _Condition_Control *_condition )
304{
305  _Condition_Wake( _condition, INT_MAX );
306}
Note: See TracBrowser for help on using the repository browser.