source: rtems/cpukit/score/include/rtems/score/coresemimpl.h @ 8f96581

Last change on this file since 8f96581 was 8f96581, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 1, 2016 at 9:38:47 AM

score: Rework MP thread queue callout support

The thread queue implementation was heavily reworked to support SMP.
This broke the multiprocessing support of the thread queues. This is
fixed by this patch.

A thread proxy is unblocked due to three reasons

1) timeout,
2) request satisfaction, and
3) extraction.

In case 1) no MPCI message must be sent. This is ensured via the
_Thread_queue_MP_callout_do_nothing() callout set during
_Thread_MP_Allocate_proxy().

In case 2) and 3) an MPCI message must be sent. In case we interrupt
the blocking operation during _Thread_queue_Enqueue_critical(), then
this message must be sent by the blocking thread. For this the new
fields Thread_Proxy_control::thread_queue_callout and
Thread_Proxy_control::thread_queue_id are used.

Delete the individual API MP callout types and use
Thread_queue_MP_callout throughout. This type is only defined in
multiprocessing configurations. Prefix the multiprocessing parameters
with mp_ to ease code review. Multiprocessing specific parameters are
optional due to use of a similar macro pattern. There is no overhead
for non-multiprocessing configurations.

  • Property mode set to 100644
File size: 7.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_Destroy(
90  CORE_semaphore_Control *the_semaphore
91)
92{
93  _Thread_queue_Destroy( &the_semaphore->Wait_queue );
94}
95
96RTEMS_INLINE_ROUTINE CORE_semaphore_Status _CORE_semaphore_Do_surrender(
97  CORE_semaphore_Control  *the_semaphore,
98#if defined(RTEMS_MULTIPROCESSING)
99  Thread_queue_MP_callout  mp_callout,
100  Objects_Id               mp_id,
101#endif
102  ISR_lock_Context        *lock_context
103)
104{
105  Thread_Control *the_thread;
106  CORE_semaphore_Status status;
107
108  status = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
109
110  _Thread_queue_Acquire_critical( &the_semaphore->Wait_queue, lock_context );
111
112  the_thread = _Thread_queue_First_locked(
113    &the_semaphore->Wait_queue,
114    the_semaphore->operations
115  );
116  if ( the_thread != NULL ) {
117    _Thread_queue_Extract_critical(
118      &the_semaphore->Wait_queue.Queue,
119      the_semaphore->operations,
120      the_thread,
121      mp_callout,
122      mp_id,
123      lock_context
124    );
125  } else {
126    if ( the_semaphore->count < UINT32_MAX )
127      the_semaphore->count += 1;
128    else
129      status = CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED;
130
131    _Thread_queue_Release( &the_semaphore->Wait_queue, lock_context );
132  }
133
134  return status;
135}
136
137/**
138 *  @brief Surrender a unit to a semaphore.
139 *
140 *  This routine frees a unit to the semaphore.  If a task was blocked waiting
141 *  for a unit from this semaphore, then that task will be readied and the unit
142 *  given to that task.  Otherwise, the unit will be returned to the semaphore.
143 *
144 *  @param[in] the_semaphore is the semaphore to surrender
145 *  @param[in] mp_callout is the routine to invoke if the
146 *         thread unblocked is remote
147 *  @param[in] mp_id is the Id of the API level Semaphore object associated
148 *         with this instance of a SuperCore Semaphore
149 *  @param[in] lock_context is a temporary variable used to contain the ISR
150 *        disable level cookie
151 *
152 *  @retval an indication of whether the routine succeeded or failed
153 */
154#if defined(RTEMS_MULTIPROCESSING)
155  #define _CORE_semaphore_Surrender( \
156    the_semaphore, \
157    mp_callout, \
158    mp_id, \
159    lock_context \
160  ) \
161    _CORE_semaphore_Do_surrender( \
162      the_semaphore, \
163      mp_callout, \
164      mp_id, \
165      lock_context \
166    )
167#else
168  #define _CORE_semaphore_Surrender( \
169    the_semaphore, \
170    mp_callout, \
171    mp_id, \
172    lock_context \
173  ) \
174    _CORE_semaphore_Do_surrender( \
175      the_semaphore, \
176      lock_context \
177    )
178#endif
179
180/* Must be a macro due to the multiprocessing dependent parameters */
181#define _CORE_semaphore_Flush( \
182  the_semaphore, \
183  status, \
184  mp_callout, \
185  mp_id \
186) \
187  _Thread_queue_Flush( \
188    &( the_semaphore )->Wait_queue, \
189    ( the_semaphore )->operations, \
190    status, \
191    mp_callout, \
192    mp_id \
193  )
194
195/**
196 * This routine returns the current count associated with the semaphore.
197 *
198 * @param[in] the_semaphore is the semaphore to obtain the count of
199 *
200 * @return the current count of this semaphore
201 */
202RTEMS_INLINE_ROUTINE uint32_t  _CORE_semaphore_Get_count(
203  CORE_semaphore_Control  *the_semaphore
204)
205{
206  return the_semaphore->count;
207}
208
209/**
210 * This routine attempts to receive a unit from the_semaphore.
211 * If a unit is available or if the wait flag is false, then the routine
212 * returns.  Otherwise, the calling task is blocked until a unit becomes
213 * available.
214 *
215 * @param[in] the_semaphore is the semaphore to obtain
216 * @param[in,out] executing The currently executing thread.
217 * @param[in] id is the Id of the owning API level Semaphore object
218 * @param[in] wait is true if the thread is willing to wait
219 * @param[in] timeout is the maximum number of ticks to block
220 * @param[in] lock_context is a temporary variable used to contain the ISR
221 *        disable level cookie
222 *
223 * @note There is currently no MACRO version of this routine.
224 */
225RTEMS_INLINE_ROUTINE void _CORE_semaphore_Seize(
226  CORE_semaphore_Control  *the_semaphore,
227  Thread_Control          *executing,
228  Objects_Id               id,
229  bool                     wait,
230  Watchdog_Interval        timeout,
231  ISR_lock_Context        *lock_context
232)
233{
234  /* disabled when you get here */
235
236  executing->Wait.return_code = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
237  _Thread_queue_Acquire_critical( &the_semaphore->Wait_queue, lock_context );
238  if ( the_semaphore->count != 0 ) {
239    the_semaphore->count -= 1;
240    _Thread_queue_Release( &the_semaphore->Wait_queue, lock_context );
241    return;
242  }
243
244  if ( !wait ) {
245    _Thread_queue_Release( &the_semaphore->Wait_queue, lock_context );
246    executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
247    return;
248  }
249
250  _Thread_queue_Enqueue_critical(
251    &the_semaphore->Wait_queue.Queue,
252    the_semaphore->operations,
253    executing,
254    STATES_WAITING_FOR_SEMAPHORE,
255    timeout,
256    CORE_SEMAPHORE_TIMEOUT,
257    lock_context
258  );
259}
260
261/** @} */
262
263#ifdef __cplusplus
264}
265#endif
266
267#endif
268/* end of include file */
Note: See TracBrowser for help on using the repository browser.