source: rtems/cpukit/score/include/rtems/score/coresemimpl.h @ e2735012

5
Last change on this file since e2735012 was e2735012, checked in by Sebastian Huber <sebastian.huber@…>, on 06/24/15 at 09:05:39

score: Introduce Thread_queue_Queue

Separate the thread queue heads and lock from the operations. This
enables the support for light weight objects which only support one
queuing discipline.

  • Property mode set to 100644
File size: 8.5 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 *  The following type defines the callout which the API provides
72 *  to support global/multiprocessor operations on semaphores.
73 */
74typedef void ( *CORE_semaphore_API_mp_support_callout )(
75                 Thread_Control *,
76                 Objects_Id
77             );
78
79/**
80 *  @brief Initialize the semaphore based on the parameters passed.
81 *
82 *  This package is the implementation of the CORE Semaphore Handler.
83 *  This core object utilizes standard Dijkstra counting semaphores to provide
84 *  synchronization and mutual exclusion capabilities.
85 *
86 *  This routine initializes the semaphore based on the parameters passed.
87 *
88 *  @param[in] the_semaphore is the semaphore to initialize
89 *  @param[in] the_semaphore_attributes define the behavior of this instance
90 *  @param[in] initial_value is the initial count of the semaphore
91 */
92void _CORE_semaphore_Initialize(
93  CORE_semaphore_Control          *the_semaphore,
94  const CORE_semaphore_Attributes *the_semaphore_attributes,
95  uint32_t                         initial_value
96);
97
98RTEMS_INLINE_ROUTINE void _CORE_semaphore_Destroy(
99  CORE_semaphore_Control *the_semaphore
100)
101{
102  _Thread_queue_Destroy( &the_semaphore->Wait_queue );
103}
104
105/**
106 *  @brief Surrender a unit to a semaphore.
107 *
108 *  This routine frees a unit to the semaphore.  If a task was blocked waiting
109 *  for a unit from this semaphore, then that task will be readied and the unit
110 *  given to that task.  Otherwise, the unit will be returned to the semaphore.
111 *
112 *  @param[in] the_semaphore is the semaphore to surrender
113 *  @param[in] id is the Id of the API level Semaphore object associated
114 *         with this instance of a SuperCore Semaphore
115 *  @param[in] api_semaphore_mp_support is the routine to invoke if the
116 *         thread unblocked is remote
117 *  @param[in] lock_context is a temporary variable used to contain the ISR
118 *        disable level cookie
119 *
120 *  @retval an indication of whether the routine succeeded or failed
121 */
122RTEMS_INLINE_ROUTINE CORE_semaphore_Status _CORE_semaphore_Surrender(
123  CORE_semaphore_Control                *the_semaphore,
124  Objects_Id                             id,
125  CORE_semaphore_API_mp_support_callout  api_semaphore_mp_support,
126  ISR_lock_Context                      *lock_context
127)
128{
129  Thread_Control *the_thread;
130  CORE_semaphore_Status status;
131
132  status = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
133
134  _Thread_queue_Acquire_critical( &the_semaphore->Wait_queue, lock_context );
135
136  the_thread = _Thread_queue_First_locked( &the_semaphore->Wait_queue );
137  if ( the_thread != NULL ) {
138#if defined(RTEMS_MULTIPROCESSING)
139    _Thread_Dispatch_disable();
140#endif
141
142    _Thread_queue_Extract_critical(
143      &the_semaphore->Wait_queue.Queue,
144      the_semaphore->Wait_queue.operations,
145      the_thread,
146      lock_context
147    );
148
149#if defined(RTEMS_MULTIPROCESSING)
150    if ( !_Objects_Is_local_id( the_thread->Object.id ) )
151      (*api_semaphore_mp_support) ( the_thread, id );
152
153    _Thread_Dispatch_enable( _Per_CPU_Get() );
154#endif
155  } else {
156    if ( the_semaphore->count < the_semaphore->Attributes.maximum_count )
157      the_semaphore->count += 1;
158    else
159      status = CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED;
160
161    _Thread_queue_Release( &the_semaphore->Wait_queue, lock_context );
162  }
163
164  return status;
165}
166
167/**
168 *  @brief Core semaphore flush.
169 *
170 *  This package is the implementation of the CORE Semaphore Handler.
171 *  This core object utilizes standard Dijkstra counting semaphores to provide
172 *  synchronization and mutual exclusion capabilities.
173 *
174 *  This routine assists in the deletion of a semaphore by flushing the
175 *  associated wait queue.
176 *
177 *  @param[in] the_semaphore is the semaphore to flush
178 *  @param[in] remote_extract_callout is the routine to invoke if the
179 *         thread unblocked is remote
180 *  @param[in] status is the status to be returned to the unblocked thread
181 */
182RTEMS_INLINE_ROUTINE void _CORE_semaphore_Flush(
183  CORE_semaphore_Control         *the_semaphore,
184  Thread_queue_Flush_callout      remote_extract_callout,
185  uint32_t                        status
186)
187{
188  _Thread_queue_Flush(
189    &the_semaphore->Wait_queue,
190    remote_extract_callout,
191    status
192  );
193}
194
195/**
196 * This function returns true if the priority attribute is
197 * enabled in the @a attribute_set and false otherwise.
198 *
199 * @param[in] the_attribute is the attribute set to test
200 *
201 * @return true if the priority attribute is enabled
202 */
203RTEMS_INLINE_ROUTINE bool _CORE_semaphore_Is_priority(
204  const CORE_semaphore_Attributes *the_attribute
205)
206{
207   return ( the_attribute->discipline == CORE_SEMAPHORE_DISCIPLINES_PRIORITY );
208}
209
210/**
211 * This routine returns the current count associated with the semaphore.
212 *
213 * @param[in] the_semaphore is the semaphore to obtain the count of
214 *
215 * @return the current count of this semaphore
216 */
217RTEMS_INLINE_ROUTINE uint32_t  _CORE_semaphore_Get_count(
218  CORE_semaphore_Control  *the_semaphore
219)
220{
221  return the_semaphore->count;
222}
223
224/**
225 * This routine attempts to receive a unit from the_semaphore.
226 * If a unit is available or if the wait flag is false, then the routine
227 * returns.  Otherwise, the calling task is blocked until a unit becomes
228 * available.
229 *
230 * @param[in] the_semaphore is the semaphore to obtain
231 * @param[in,out] executing The currently executing thread.
232 * @param[in] id is the Id of the owning API level Semaphore object
233 * @param[in] wait is true if the thread is willing to wait
234 * @param[in] timeout is the maximum number of ticks to block
235 * @param[in] lock_context is a temporary variable used to contain the ISR
236 *        disable level cookie
237 *
238 * @note There is currently no MACRO version of this routine.
239 */
240RTEMS_INLINE_ROUTINE void _CORE_semaphore_Seize(
241  CORE_semaphore_Control  *the_semaphore,
242  Thread_Control          *executing,
243  Objects_Id               id,
244  bool                     wait,
245  Watchdog_Interval        timeout,
246  ISR_lock_Context        *lock_context
247)
248{
249  /* disabled when you get here */
250
251  executing->Wait.return_code = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
252  _Thread_queue_Acquire_critical( &the_semaphore->Wait_queue, lock_context );
253  if ( the_semaphore->count != 0 ) {
254    the_semaphore->count -= 1;
255    _Thread_queue_Release( &the_semaphore->Wait_queue, lock_context );
256    return;
257  }
258
259  if ( !wait ) {
260    _Thread_queue_Release( &the_semaphore->Wait_queue, lock_context );
261    executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
262    return;
263  }
264
265  executing->Wait.id = id;
266  _Thread_queue_Enqueue_critical(
267    &the_semaphore->Wait_queue.Queue,
268    the_semaphore->Wait_queue.operations,
269    executing,
270    STATES_WAITING_FOR_SEMAPHORE,
271    timeout,
272    CORE_SEMAPHORE_TIMEOUT,
273    lock_context
274  );
275}
276
277/** @} */
278
279#ifdef __cplusplus
280}
281#endif
282
283#endif
284/* end of include file */
Note: See TracBrowser for help on using the repository browser.