source: rtems/cpukit/score/include/rtems/score/coresemimpl.h @ 4025a60f

5
Last change on this file since 4025a60f was 4025a60f, checked in by Sebastian Huber <sebastian.huber@…>, on 04/19/16 at 15:02:54

score: Avoid Giant lock for CORE mtx/sem

Avoid Giant lock for CORE mutex and semaphore flush and delete
operations.

Update #2555.

  • Property mode set to 100644
File size: 8.4 KB
Line 
1/**
2 * @file
3 *
4 * @brief Inlined Routines Associated with the SuperCore Semaphore
5 *
6 * This include file contains all of the inlined routines associated
7 * with the SuperCore semaphore.
8 */
9
10/*
11 *  COPYRIGHT (c) 1989-2006.
12 *  On-Line Applications Research Corporation (OAR).
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19#ifndef _RTEMS_SCORE_CORESEMIMPL_H
20#define _RTEMS_SCORE_CORESEMIMPL_H
21
22#include <rtems/score/coresem.h>
23#include <rtems/score/objectimpl.h>
24#include <rtems/score/threaddispatch.h>
25#include <rtems/score/threadqimpl.h>
26#include <rtems/score/statesimpl.h>
27
28#ifdef __cplusplus
29extern "C" {
30#endif
31
32/**
33 * @addtogroup ScoreSemaphore
34 */
35/**@{**/
36
37/**
38 *  Core Semaphore handler return statuses.
39 */
40typedef enum {
41  /** This status indicates that the operation completed successfully. */
42  CORE_SEMAPHORE_STATUS_SUCCESSFUL,
43  /** This status indicates that the calling task did not want to block
44   *  and the operation was unable to complete immediately because the
45   *  resource was unavailable.
46   */
47  CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT,
48  /** This status indicates that the thread was blocked waiting for an
49   *  operation to complete and the semaphore was deleted.
50   */
51  CORE_SEMAPHORE_WAS_DELETED,
52  /** This status indicates that the calling task was willing to block
53   *  but the operation was unable to complete within the time allotted
54   *  because the resource never became available.
55   */
56  CORE_SEMAPHORE_TIMEOUT,
57  /** This status indicates that an attempt was made to unlock the semaphore
58   *  and this would have made its count greater than that allowed.
59   */
60  CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED
61}   CORE_semaphore_Status;
62
63/**
64 *  @brief Core semaphore last status value.
65 *
66 *  This is the last status value.
67 */
68#define CORE_SEMAPHORE_STATUS_LAST CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED
69
70/**
71 *  @brief Initialize the semaphore based on the parameters passed.
72 *
73 *  This package is the implementation of the CORE Semaphore Handler.
74 *  This core object utilizes standard Dijkstra counting semaphores to provide
75 *  synchronization and mutual exclusion capabilities.
76 *
77 *  This routine initializes the semaphore based on the parameters passed.
78 *
79 *  @param[in] the_semaphore is the semaphore to initialize
80 *  @param[in] discipline the blocking discipline
81 *  @param[in] initial_value is the initial count of the semaphore
82 */
83void _CORE_semaphore_Initialize(
84  CORE_semaphore_Control     *the_semaphore,
85  CORE_semaphore_Disciplines  discipline,
86  uint32_t                    initial_value
87);
88
89RTEMS_INLINE_ROUTINE void _CORE_semaphore_Acquire_critical(
90  CORE_semaphore_Control *the_semaphore,
91  ISR_lock_Context       *lock_context
92)
93{
94  _Thread_queue_Acquire_critical( &the_semaphore->Wait_queue, lock_context );
95}
96
97RTEMS_INLINE_ROUTINE void _CORE_semaphore_Release(
98  CORE_semaphore_Control *the_semaphore,
99  ISR_lock_Context       *lock_context
100)
101{
102  _Thread_queue_Release( &the_semaphore->Wait_queue, lock_context );
103}
104
105Thread_Control *_CORE_semaphore_Was_deleted(
106  Thread_Control     *the_thread,
107  Thread_queue_Queue *queue,
108  ISR_lock_Context   *lock_context
109);
110
111Thread_Control *_CORE_semaphore_Unsatisfied_nowait(
112  Thread_Control     *the_thread,
113  Thread_queue_Queue *queue,
114  ISR_lock_Context   *lock_context
115);
116
117#define _CORE_semaphore_Destroy( \
118  the_semaphore, \
119  mp_callout, \
120  mp_id, \
121  lock_context \
122) \
123  do { \
124    _Thread_queue_Flush_critical( \
125      &( the_semaphore )->Wait_queue.Queue, \
126      ( the_semaphore )->operations, \
127      _CORE_semaphore_Was_deleted, \
128      mp_callout, \
129      mp_id, \
130      lock_context \
131    ); \
132    _Thread_queue_Destroy( &( the_semaphore )->Wait_queue ); \
133  } while ( 0 )
134
135RTEMS_INLINE_ROUTINE CORE_semaphore_Status _CORE_semaphore_Do_surrender(
136  CORE_semaphore_Control  *the_semaphore,
137#if defined(RTEMS_MULTIPROCESSING)
138  Thread_queue_MP_callout  mp_callout,
139  Objects_Id               mp_id,
140#endif
141  ISR_lock_Context        *lock_context
142)
143{
144  Thread_Control *the_thread;
145  CORE_semaphore_Status status;
146
147  status = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
148
149  _CORE_semaphore_Acquire_critical( the_semaphore, lock_context );
150
151  the_thread = _Thread_queue_First_locked(
152    &the_semaphore->Wait_queue,
153    the_semaphore->operations
154  );
155  if ( the_thread != NULL ) {
156    _Thread_queue_Extract_critical(
157      &the_semaphore->Wait_queue.Queue,
158      the_semaphore->operations,
159      the_thread,
160      mp_callout,
161      mp_id,
162      lock_context
163    );
164  } else {
165    if ( the_semaphore->count < UINT32_MAX )
166      the_semaphore->count += 1;
167    else
168      status = CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED;
169
170    _CORE_semaphore_Release( the_semaphore, lock_context );
171  }
172
173  return status;
174}
175
176/**
177 *  @brief Surrender a unit to a semaphore.
178 *
179 *  This routine frees a unit to the semaphore.  If a task was blocked waiting
180 *  for a unit from this semaphore, then that task will be readied and the unit
181 *  given to that task.  Otherwise, the unit will be returned to the semaphore.
182 *
183 *  @param[in] the_semaphore is the semaphore to surrender
184 *  @param[in] mp_callout is the routine to invoke if the
185 *         thread unblocked is remote
186 *  @param[in] mp_id is the Id of the API level Semaphore object associated
187 *         with this instance of a SuperCore Semaphore
188 *  @param[in] lock_context is a temporary variable used to contain the ISR
189 *        disable level cookie
190 *
191 *  @retval an indication of whether the routine succeeded or failed
192 */
193#if defined(RTEMS_MULTIPROCESSING)
194  #define _CORE_semaphore_Surrender( \
195    the_semaphore, \
196    mp_callout, \
197    mp_id, \
198    lock_context \
199  ) \
200    _CORE_semaphore_Do_surrender( \
201      the_semaphore, \
202      mp_callout, \
203      mp_id, \
204      lock_context \
205    )
206#else
207  #define _CORE_semaphore_Surrender( \
208    the_semaphore, \
209    mp_callout, \
210    mp_id, \
211    lock_context \
212  ) \
213    _CORE_semaphore_Do_surrender( \
214      the_semaphore, \
215      lock_context \
216    )
217#endif
218
219/* Must be a macro due to the multiprocessing dependent parameters */
220#define _CORE_semaphore_Flush( \
221  the_semaphore, \
222  mp_callout, \
223  mp_id, \
224  lock_context \
225) \
226  do { \
227    _Thread_queue_Flush_critical( \
228      &( the_semaphore )->Wait_queue.Queue, \
229      ( the_semaphore )->operations, \
230      _CORE_semaphore_Unsatisfied_nowait, \
231      mp_callout, \
232      mp_id, \
233      lock_context \
234    ); \
235  } while ( 0 )
236
237/**
238 * This routine returns the current count associated with the semaphore.
239 *
240 * @param[in] the_semaphore is the semaphore to obtain the count of
241 *
242 * @return the current count of this semaphore
243 */
244RTEMS_INLINE_ROUTINE uint32_t  _CORE_semaphore_Get_count(
245  CORE_semaphore_Control  *the_semaphore
246)
247{
248  return the_semaphore->count;
249}
250
251/**
252 * This routine attempts to receive a unit from the_semaphore.
253 * If a unit is available or if the wait flag is false, then the routine
254 * returns.  Otherwise, the calling task is blocked until a unit becomes
255 * available.
256 *
257 * @param[in] the_semaphore is the semaphore to obtain
258 * @param[in,out] executing The currently executing thread.
259 * @param[in] id is the Id of the owning API level Semaphore object
260 * @param[in] wait is true if the thread is willing to wait
261 * @param[in] timeout is the maximum number of ticks to block
262 * @param[in] lock_context is a temporary variable used to contain the ISR
263 *        disable level cookie
264 *
265 * @note There is currently no MACRO version of this routine.
266 */
267RTEMS_INLINE_ROUTINE void _CORE_semaphore_Seize(
268  CORE_semaphore_Control  *the_semaphore,
269  Thread_Control          *executing,
270  Objects_Id               id,
271  bool                     wait,
272  Watchdog_Interval        timeout,
273  ISR_lock_Context        *lock_context
274)
275{
276  /* disabled when you get here */
277
278  executing->Wait.return_code = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
279  _CORE_semaphore_Acquire_critical( the_semaphore, lock_context );
280  if ( the_semaphore->count != 0 ) {
281    the_semaphore->count -= 1;
282    _CORE_semaphore_Release( the_semaphore, lock_context );
283    return;
284  }
285
286  if ( !wait ) {
287    _CORE_semaphore_Release( the_semaphore, lock_context );
288    executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
289    return;
290  }
291
292  _Thread_queue_Enqueue_critical(
293    &the_semaphore->Wait_queue.Queue,
294    the_semaphore->operations,
295    executing,
296    STATES_WAITING_FOR_SEMAPHORE,
297    timeout,
298    CORE_SEMAPHORE_TIMEOUT,
299    lock_context
300  );
301}
302
303/** @} */
304
305#ifdef __cplusplus
306}
307#endif
308
309#endif
310/* end of include file */
Note: See TracBrowser for help on using the repository browser.