source: rtems/cpukit/score/src/semaphore.c @ 4a0e418

Last change on this file since 4a0e418 was 4a0e418, checked in by Joel Sherrill <joel@…>, on 02/16/22 at 21:09:20

score/src/[n-s]*.c: Change license to BSD-2

Updates #3053.

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