source: rtems/cpukit/score/src/semaphore.c @ 255fe43

Last change on this file since 255fe43 was 255fe43, checked in by Joel Sherrill <joel@…>, on 03/01/22 at 20:40:44

cpukit/: Scripted embedded brains header file clean up

Updates #4625.

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSScore
7 *
8 * @brief This source file contains the implementation of
9 *   _Semaphore_Wait(), _Semaphore_Wait_timed_ticks(), _Semaphore_Try_wait(),
10 *   _Semaphore_Post(), and _Semaphore_Post_binary().
11 */
12
13/*
14 * Copyright (c) 2015, 2017 embedded brains GmbH.  All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 *    notice, this list of conditions and the following disclaimer in the
23 *    documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif
41
42#include <rtems/score/semaphoreimpl.h>
43#include <rtems/score/statesimpl.h>
44#include <rtems/score/threadimpl.h>
45
46#include <errno.h>
47
48RTEMS_STATIC_ASSERT(
49  offsetof( Sem_Control, Queue )
50    == offsetof( struct _Semaphore_Control, _Queue ),
51  SEMAPHORE_CONTROL_QUEUE
52);
53
54RTEMS_STATIC_ASSERT(
55  offsetof( Sem_Control, count )
56    == offsetof( struct _Semaphore_Control, _count ),
57  SEMAPHORE_CONTROL_COUNT
58);
59
60RTEMS_STATIC_ASSERT(
61  sizeof( Sem_Control ) == sizeof( struct _Semaphore_Control ),
62  SEMAPHORE_CONTROL_SIZE
63);
64
65void _Semaphore_Wait( struct _Semaphore_Control *_sem )
66{
67  Sem_Control          *sem;
68  ISR_Level             level;
69  Thread_queue_Context  queue_context;
70  Thread_Control       *executing;
71  unsigned int          count;
72
73  sem = _Sem_Get( _sem );
74  _Thread_queue_Context_initialize( &queue_context );
75  _Thread_queue_Context_ISR_disable( &queue_context, level );
76  executing = _Sem_Queue_acquire_critical( sem, &queue_context );
77
78  count = sem->count;
79  if ( RTEMS_PREDICT_TRUE( count > 0 ) ) {
80    sem->count = count - 1;
81    _Sem_Queue_release( sem, level, &queue_context );
82  } else {
83    _Thread_queue_Context_set_thread_state(
84      &queue_context,
85      STATES_WAITING_FOR_SEMAPHORE
86    );
87    _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
88    _Thread_queue_Context_set_ISR_level( &queue_context, level );
89    _Thread_queue_Enqueue(
90      &sem->Queue.Queue,
91      SEMAPHORE_TQ_OPERATIONS,
92      executing,
93      &queue_context
94    );
95  }
96}
97
98int _Semaphore_Wait_timed_ticks( struct _Semaphore_Control *_sem, uint32_t ticks )
99{
100  Sem_Control          *sem;
101  ISR_Level             level;
102  Thread_queue_Context  queue_context;
103  Thread_Control       *executing;
104  unsigned int          count;
105
106  sem = _Sem_Get( _sem );
107  _Thread_queue_Context_initialize( &queue_context );
108  _Thread_queue_Context_ISR_disable( &queue_context, level );
109  executing = _Sem_Queue_acquire_critical( sem, &queue_context );
110
111  count = sem->count;
112  if ( RTEMS_PREDICT_TRUE( count > 0 ) ) {
113    sem->count = count - 1;
114    _Sem_Queue_release( sem, level, &queue_context );
115    return 0;
116  } else {
117    _Thread_queue_Context_set_thread_state(
118      &queue_context,
119      STATES_WAITING_FOR_SEMAPHORE
120    );
121    _Thread_queue_Context_set_enqueue_timeout_ticks( &queue_context, ticks );
122    _Thread_queue_Context_set_ISR_level( &queue_context, level );
123    _Thread_queue_Enqueue(
124      &sem->Queue.Queue,
125      SEMAPHORE_TQ_OPERATIONS,
126      executing,
127      &queue_context
128    );
129    return STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
130  }
131}
132
133int _Semaphore_Try_wait( struct _Semaphore_Control *_sem )
134{
135  Sem_Control          *sem;
136  ISR_Level             level;
137  Thread_queue_Context  queue_context;
138  unsigned int          count;
139  int                   eno;
140
141  sem = _Sem_Get( _sem );
142  _Thread_queue_Context_initialize( &queue_context );
143  _Thread_queue_Context_ISR_disable( &queue_context, level );
144  _Sem_Queue_acquire_critical( sem, &queue_context );
145
146  count = sem->count;
147  if ( RTEMS_PREDICT_TRUE( count > 0 ) ) {
148    sem->count = count - 1;
149    eno = 0;
150  } else {
151    eno = EAGAIN;
152  }
153
154  _Sem_Queue_release( sem, level, &queue_context );
155  return eno;
156}
157
158void _Semaphore_Post( struct _Semaphore_Control *_sem )
159{
160  Sem_Control          *sem;
161  ISR_Level             level;
162  Thread_queue_Context  queue_context;
163  Thread_queue_Heads   *heads;
164
165  sem = _Sem_Get( _sem );
166  _Thread_queue_Context_initialize( &queue_context );
167  _Thread_queue_Context_ISR_disable( &queue_context, level );
168  _Sem_Queue_acquire_critical( sem, &queue_context );
169
170  heads = sem->Queue.Queue.heads;
171  if ( RTEMS_PREDICT_TRUE( heads == NULL ) ) {
172    ++sem->count;
173    _Sem_Queue_release( sem, level, &queue_context );
174  } else {
175    _Thread_queue_Context_set_ISR_level( &queue_context, level );
176    _Thread_queue_Surrender_no_priority(
177      &sem->Queue.Queue,
178      heads,
179      &queue_context,
180      SEMAPHORE_TQ_OPERATIONS
181    );
182  }
183}
184
185void _Semaphore_Post_binary( struct _Semaphore_Control *_sem )
186{
187  Sem_Control          *sem;
188  ISR_Level             level;
189  Thread_queue_Context  queue_context;
190  Thread_queue_Heads   *heads;
191
192  sem = _Sem_Get( _sem );
193  _Thread_queue_Context_initialize( &queue_context );
194  _Thread_queue_Context_ISR_disable( &queue_context, level );
195  _Sem_Queue_acquire_critical( sem, &queue_context );
196
197  heads = sem->Queue.Queue.heads;
198  if ( RTEMS_PREDICT_TRUE( heads == NULL ) ) {
199    sem->count = 1;
200    _Sem_Queue_release( sem, level, &queue_context );
201  } else {
202    _Thread_queue_Context_set_ISR_level( &queue_context, level );
203    _Thread_queue_Surrender_no_priority(
204      &sem->Queue.Queue,
205      heads,
206      &queue_context,
207      SEMAPHORE_TQ_OPERATIONS
208    );
209  }
210}
Note: See TracBrowser for help on using the repository browser.