source: rtems/cpukit/score/src/semaphore.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: 5.3 KB
Line 
1/*
2 * Copyright (c) 2015, 2017 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 <rtems/score/semaphoreimpl.h>
20#include <rtems/score/statesimpl.h>
21#include <rtems/score/threadimpl.h>
22
23#include <errno.h>
24
25RTEMS_STATIC_ASSERT(
26  offsetof( Sem_Control, Queue )
27    == offsetof( struct _Semaphore_Control, _Queue ),
28  SEMAPHORE_CONTROL_QUEUE
29);
30
31RTEMS_STATIC_ASSERT(
32  offsetof( Sem_Control, count )
33    == offsetof( struct _Semaphore_Control, _count ),
34  SEMAPHORE_CONTROL_COUNT
35);
36
37RTEMS_STATIC_ASSERT(
38  sizeof( Sem_Control ) == sizeof( struct _Semaphore_Control ),
39  SEMAPHORE_CONTROL_SIZE
40);
41
42void _Semaphore_Wait( struct _Semaphore_Control *_sem )
43{
44  Sem_Control          *sem;
45  ISR_Level             level;
46  Thread_queue_Context  queue_context;
47  Thread_Control       *executing;
48  unsigned int          count;
49
50  sem = _Sem_Get( _sem );
51  _Thread_queue_Context_initialize( &queue_context );
52  _Thread_queue_Context_ISR_disable( &queue_context, level );
53  executing = _Sem_Queue_acquire_critical( sem, &queue_context );
54
55  count = sem->count;
56  if ( RTEMS_PREDICT_TRUE( count > 0 ) ) {
57    sem->count = count - 1;
58    _Sem_Queue_release( sem, level, &queue_context );
59  } else {
60    _Thread_queue_Context_set_thread_state(
61      &queue_context,
62      STATES_WAITING_FOR_SEMAPHORE
63    );
64    _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
65    _Thread_queue_Context_set_ISR_level( &queue_context, level );
66    _Thread_queue_Enqueue(
67      &sem->Queue.Queue,
68      SEMAPHORE_TQ_OPERATIONS,
69      executing,
70      &queue_context
71    );
72  }
73}
74
75int _Semaphore_Wait_timed_ticks( struct _Semaphore_Control *_sem, uint32_t ticks )
76{
77  Sem_Control          *sem;
78  ISR_Level             level;
79  Thread_queue_Context  queue_context;
80  Thread_Control       *executing;
81  unsigned int          count;
82
83  sem = _Sem_Get( _sem );
84  _Thread_queue_Context_initialize( &queue_context );
85  _Thread_queue_Context_ISR_disable( &queue_context, level );
86  executing = _Sem_Queue_acquire_critical( sem, &queue_context );
87
88  count = sem->count;
89  if ( RTEMS_PREDICT_TRUE( count > 0 ) ) {
90    sem->count = count - 1;
91    _Sem_Queue_release( sem, level, &queue_context );
92    return 0;
93  } else {
94    _Thread_queue_Context_set_thread_state(
95      &queue_context,
96      STATES_WAITING_FOR_SEMAPHORE
97    );
98    _Thread_queue_Context_set_enqueue_timeout_ticks( &queue_context, ticks );
99    _Thread_queue_Context_set_ISR_level( &queue_context, level );
100    _Thread_queue_Enqueue(
101      &sem->Queue.Queue,
102      SEMAPHORE_TQ_OPERATIONS,
103      executing,
104      &queue_context
105    );
106    return STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
107  }
108}
109
110int _Semaphore_Try_wait( struct _Semaphore_Control *_sem )
111{
112  Sem_Control          *sem;
113  ISR_Level             level;
114  Thread_queue_Context  queue_context;
115  unsigned int          count;
116  int                   eno;
117
118  sem = _Sem_Get( _sem );
119  _Thread_queue_Context_initialize( &queue_context );
120  _Thread_queue_Context_ISR_disable( &queue_context, level );
121  _Sem_Queue_acquire_critical( sem, &queue_context );
122
123  count = sem->count;
124  if ( RTEMS_PREDICT_TRUE( count > 0 ) ) {
125    sem->count = count - 1;
126    eno = 0;
127  } else {
128    eno = EAGAIN;
129  }
130
131  _Sem_Queue_release( sem, level, &queue_context );
132  return eno;
133}
134
135void _Semaphore_Post( struct _Semaphore_Control *_sem )
136{
137  Sem_Control          *sem;
138  ISR_Level             level;
139  Thread_queue_Context  queue_context;
140  Thread_queue_Heads   *heads;
141
142  sem = _Sem_Get( _sem );
143  _Thread_queue_Context_initialize( &queue_context );
144  _Thread_queue_Context_ISR_disable( &queue_context, level );
145  _Sem_Queue_acquire_critical( sem, &queue_context );
146
147  heads = sem->Queue.Queue.heads;
148  if ( RTEMS_PREDICT_TRUE( heads == NULL ) ) {
149    ++sem->count;
150    _Sem_Queue_release( sem, level, &queue_context );
151  } else {
152    const Thread_queue_Operations *operations;
153    Thread_Control *first;
154
155    _Thread_queue_Context_set_ISR_level( &queue_context, level );
156    operations = SEMAPHORE_TQ_OPERATIONS;
157    first = ( *operations->first )( heads );
158
159    _Thread_queue_Extract_critical(
160      &sem->Queue.Queue,
161      operations,
162      first,
163      &queue_context
164    );
165  }
166}
167
168void _Semaphore_Post_binary( struct _Semaphore_Control *_sem )
169{
170  Sem_Control          *sem;
171  ISR_Level             level;
172  Thread_queue_Context  queue_context;
173  Thread_queue_Heads   *heads;
174
175  sem = _Sem_Get( _sem );
176  _Thread_queue_Context_initialize( &queue_context );
177  _Thread_queue_Context_ISR_disable( &queue_context, level );
178  _Sem_Queue_acquire_critical( sem, &queue_context );
179
180  heads = sem->Queue.Queue.heads;
181  if ( RTEMS_PREDICT_TRUE( heads == NULL ) ) {
182    sem->count = 1;
183    _Sem_Queue_release( sem, level, &queue_context );
184  } else {
185    const Thread_queue_Operations *operations;
186    Thread_Control *first;
187
188    _Thread_queue_Context_set_ISR_level( &queue_context, level );
189    operations = SEMAPHORE_TQ_OPERATIONS;
190    first = ( *operations->first )( heads );
191
192    _Thread_queue_Extract_critical(
193      &sem->Queue.Queue,
194      operations,
195      first,
196      &queue_context
197    );
198  }
199}
Note: See TracBrowser for help on using the repository browser.