source: rtems/cpukit/score/include/rtems/score/coremutex.h @ 96d0b64

4.104.114.84.95
Last change on this file since 96d0b64 was 96d0b64, checked in by Joel Sherrill <joel.sherrill@…>, on 03/05/07 at 21:01:40

2007-03-05 Joel Sherrill <joel@…>

PR 1222/cpukit

  • score/Makefile.am, score/include/rtems/score/coremutex.h, score/include/rtems/score/threadq.h, score/inline/rtems/score/coremutex.inl, score/src/coremsgsubmit.c, score/src/coremutexsurrender.c, score/src/threadchangepriority.c, score/src/threadclearstate.c, score/src/threadhandler.c, score/src/threadinitialize.c, score/src/threadqdequeuefifo.c, score/src/threadqdequeuepriority.c, score/src/threadqenqueue.c, score/src/threadqenqueuefifo.c, score/src/threadqenqueuepriority.c, score/src/threadqextractfifo.c, score/src/threadqextractpriority.c, score/src/threadsetstate.c: Enhance so that when the prioirity of a thread that is blocked on a priority based thread queue is changed, that its placement in the queue is reevaluated based upon the new priority. This enhancement includes modifications to the SuperCore? as well as new test cases.
  • score/src/threadqrequeue.c: New file.
  • Property mode set to 100644
File size: 11.8 KB
Line 
1/**
2 *  @file  rtems/score/coremutex.h
3 *
4 *  This include file contains all the constants and structures associated
5 *  with the Mutex Handler.  A mutex is an enhanced version of the standard
6 *  Dijkstra binary semaphore used to provide synchronization and mutual
7 *  exclusion capabilities.
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.com/license/LICENSE.
17 *
18 *  $Id$
19 */
20
21#ifndef _RTEMS_SCORE_COREMUTEX_H
22#define _RTEMS_SCORE_COREMUTEX_H
23
24/**
25 *  @defgroup ScoreMutex Mutex Handler
26 *
27 *  This handler encapsulates functionality which provides the foundation
28 *  Mutex services used in all of the APIs supported by RTEMS.
29 */
30/**@{*/
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35
36#include <rtems/score/thread.h>
37#include <rtems/score/threadq.h>
38#include <rtems/score/priority.h>
39#include <rtems/score/watchdog.h>
40#include <rtems/score/interr.h>
41#include <rtems/score/sysstate.h>
42
43/**
44 *  @brief MP Support Callback Prototype
45 *
46 *  The following type defines the callout which the API provides
47 *  to support global/multiprocessor operations on mutexes.
48 */
49typedef void ( *CORE_mutex_API_mp_support_callout )(
50                 Thread_Control *,
51                 Objects_Id
52             );
53
54/**
55 *  @brief Blocking Disciplines Enumerated Type
56 *
57 *  This enumerated type defines the blocking disciplines for a mutex.
58 */
59typedef enum {
60  /** This specifies that threads will wait for the mutex in FIFO order. */
61  CORE_MUTEX_DISCIPLINES_FIFO,
62  /** This specifies that threads will wait for the mutex in priority order.  */
63  CORE_MUTEX_DISCIPLINES_PRIORITY,
64  /** This specifies that threads will wait for the mutex in priority order.
65   *  Additionally, the Priority Inheritance Protocol will be in effect.
66   */
67  CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT,
68  /** This specifies that threads will wait for the mutex in priority order.
69   *  Additionally, the Priority Ceiling Protocol will be in effect.
70   */
71  CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING
72}   CORE_mutex_Disciplines;
73
74/**
75 *  @brief Mutex method return statuses
76 *
77 *  This enumerated type defines the possible Mutex handler return statuses.
78 */
79typedef enum {
80  /** This status indicates that the operation completed successfully. */
81  CORE_MUTEX_STATUS_SUCCESSFUL,
82  /** This status indicates that the calling task did not want to block
83   *  and the operation was unable to complete immediately because the
84   *  resource was unavailable.
85   */
86  CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT,
87  /** This status indicates that an attempt was made to relock a mutex
88   *  for which nesting is not configured.
89   */
90  CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED,
91  /** This status indicates that an attempt was made to release a mutex
92   *  by a thread other than the thread which locked it.
93   */
94  CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE,
95  /** This status indicates that the thread was blocked waiting for an
96   *  operation to complete and the mutex was deleted.
97   */
98  CORE_MUTEX_WAS_DELETED,
99  /** This status indicates that the calling task was willing to block
100   *  but the operation was unable to complete within the time allotted
101   *  because the resource never became available.
102   */
103  CORE_MUTEX_TIMEOUT,
104  /** This status indicates that a thread of logically greater importance
105   *  than the ceiling priority attempted to lock this mutex.
106   */
107  CORE_MUTEX_STATUS_CEILING_VIOLATED
108}   CORE_mutex_Status;
109
110/**
111 *  @brief Mutex Lock Nesting Behavior Enumeration
112 *
113 *  This enumerated type defines the possible behaviors for
114 *  lock nesting.
115 */
116typedef enum {
117  /**
118   *    This sequence has no blocking or errors:
119   *
120   *         + lock(m)
121   *         + lock(m)
122   *         + unlock(m)
123   *         + unlock(m)
124   */
125  CORE_MUTEX_NESTING_ACQUIRES,
126  /**
127   *    This sequence returns an error at the indicated point:
128   *
129   *        + lock(m)
130   *        + lock(m)   - already locked error
131   *        + unlock(m)
132   */
133  CORE_MUTEX_NESTING_IS_ERROR,
134  /**
135   *    This sequence performs as indicated:
136   *        + lock(m)
137   *        + lock(m)   - deadlocks or timeouts
138   *        + unlock(m) - releases
139   */
140  CORE_MUTEX_NESTING_BLOCKS
141}  CORE_mutex_Nesting_behaviors;
142
143/**
144 *  This is the value of a mutex when it is unlocked.
145 */
146#define CORE_MUTEX_UNLOCKED 1
147
148/**
149 *  This is the value of a mutex when it is locked.
150 */
151#define CORE_MUTEX_LOCKED   0
152
153/**
154 *  @brief Core Mutex Attributes
155 *
156 *  The following defines the control block used to manage the
157 *  attributes of each mutex.
158 */
159typedef struct {
160  /** This field determines what the behavior of this mutex instance will
161   *  be when attempting to acquire the mutex when it is already locked.
162   */
163  CORE_mutex_Nesting_behaviors lock_nesting_behavior;
164  /** When this field is TRUE, then only the thread that locked the mutex
165   *  is allowed to unlock it.
166   */
167  boolean                      only_owner_release;
168  /** This field indicates whether threads waiting on the mutex block in
169   *  FIFO or priority order.
170   */
171  CORE_mutex_Disciplines       discipline;
172  /** This field contains the ceiling priority to be used if that protocol
173   *  is selected.
174   */
175  Priority_Control             priority_ceiling;
176}   CORE_mutex_Attributes;
177
178/**
179 *  @brief Core Mutex Control Structure
180 *
181 *  The following defines the control block used to manage each mutex.
182 */
183typedef struct {
184  /** This field is the Waiting Queue used to manage the set of tasks
185   *  which are blocked waiting to lock the mutex.
186   */
187  Thread_queue_Control    Wait_queue;
188  /** This element is the set of attributes which define this instance's
189   *  behavior.
190   */
191  CORE_mutex_Attributes   Attributes;
192  /** This element contains the current state of the mutex.
193   */
194  uint32_t                lock;
195  /** This element contains the number of times the mutex has been acquired
196   *  nested.  This must be zero (0) before the mutex is actually unlocked.
197   */
198  uint32_t                nest_count;
199  /** This is the number of waiting threads. */
200  uint32_t                blocked_count;
201  /** This element points to the thread which is currently holding this mutex.
202   *  The holder is the last thread to successfully lock the mutex and which
203   *  has not unlocked it.  If the thread is not locked, there is no holder.
204   */
205  Thread_Control         *holder;
206  /** This element contains the object Id of the holding thread.  */
207  Objects_Id              holder_id;
208}   CORE_mutex_Control;
209
210/**
211 *  @brief Initialize a Core Mutex
212 *
213 *  This routine initializes the mutex based on the parameters passed.
214 *
215 *  @param[in] the_mutex is the mutex to initalize
216 *  @param[in] the_mutex_attributes is the attributes associated with this
217 *         mutex instance
218 *  @param[in] initial_lock is the initial value of the mutex
219 */
220void _CORE_mutex_Initialize(
221  CORE_mutex_Control           *the_mutex,
222  CORE_mutex_Attributes        *the_mutex_attributes,
223  uint32_t                      initial_lock
224);
225
226#ifndef __RTEMS_APPLICATION__
227/**
228 *  @brief Seize Mutex with Quick Success Path
229 *
230 *  This routine attempts to receive a unit from the_mutex.
231 *  If a unit is available or if the wait flag is FALSE, then the routine
232 *  returns.  Otherwise, the calling task is blocked until a unit becomes
233 *  available.
234 *
235 *  @param[in] the_mutex is the mutex to attempt to lock
236 *  @param[in] level_p is the interrupt level holder
237 *
238 *  @return This routine returns 0 if "trylock" can resolve whether or not
239 *  the mutex is immediately obtained or there was an error attempting to
240 *  get it.  It returns 1 to indicate that the caller cannot obtain
241 *  the mutex and will have to block to do so.
242 *
243 *  @note  For performance reasons, this routine is implemented as
244 *         a macro that uses two support routines.
245 */
246RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock(
247  CORE_mutex_Control  *the_mutex,
248  ISR_Level           *level_p
249);
250
251/**
252 *  @brief Seize Mutex with Blocking
253 *
254 *  This routine performs the blocking portion of a mutex obtain.
255 *  It is an actual subroutine and is not implemented as something
256 *  that may be inlined.
257 *
258 *  @param[in] the_mutex is the mutex to attempt to lock
259 *  @param[in] timeout is the maximum number of ticks to block
260 */
261void _CORE_mutex_Seize_interrupt_blocking(
262  CORE_mutex_Control  *the_mutex,
263  Watchdog_Interval    timeout
264);
265
266/**
267 *  @brief Sieze Interrupt Wrapper
268 *
269 *  This routine attempts to obtain the mutex.  If the mutex is available,
270 *  then it will return immediately.  Otherwise, it will invoke the
271 *  support routine @a _Core_mutex_Seize_interrupt_blocking.
272 *
273 *  @param[in] _the_mutex is the mutex to attempt to lock
274 *  @param[in] _id is the Id of the owning API level Semaphore object
275 *  @param[in] _wait is TRUE if the thread is willing to wait
276 *  @param[in] _timeout is the maximum number of ticks to block
277 *  @param[in] _level is a temporary variable used to contain the ISR
278 *         disable level cookie
279 *
280 *  @note If the mutex is called from an interrupt service routine,
281 *        with context switching disabled, or before multitasking,
282 *        then a fatal error is generated.
283 *
284 *
285 *  The logic on this routine is as follows:
286 *
287 *  * If incorrect system state
288 *      return an error
289 *  * If mutex is available without any contention or blocking
290 *      obtain it with interrupts disabled and returned
291 *  * If the caller is willing to wait
292 *      then they are blocked.
293 */
294#define _CORE_mutex_Seize( \
295  _the_mutex, _id, _wait, _timeout, _level ) \
296  do { \
297    if ( _Thread_Dispatch_disable_level \
298        && (_wait) \
299        && (_System_state_Get() >= SYSTEM_STATE_BEGIN_MULTITASKING ) \
300       ) { \
301        _Internal_error_Occurred( \
302           INTERNAL_ERROR_CORE, \
303           FALSE, \
304           18 /* called from wrong environment */); \
305    } \
306    if ( _CORE_mutex_Seize_interrupt_trylock( _the_mutex, &_level ) ) {  \
307      if ( !_wait ) { \
308        _ISR_Enable( _level ); \
309        _Thread_Executing->Wait.return_code = \
310          CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT; \
311      } else { \
312        _Thread_queue_Enter_critical_section( &(_the_mutex)->Wait_queue ); \
313        _Thread_Executing->Wait.queue = &(_the_mutex)->Wait_queue; \
314        _Thread_Executing->Wait.id    = _id; \
315        _Thread_Disable_dispatch(); \
316        _ISR_Enable( _level ); \
317       _CORE_mutex_Seize_interrupt_blocking( _the_mutex, _timeout ); \
318      } \
319    } \
320  } while (0)
321
322/**
323 *  @brief Surrender the Mutex
324 *
325 *  This routine frees a unit to the mutex.  If a task was blocked waiting for
326 *  a unit from this mutex, then that task will be readied and the unit
327 *  given to that task.  Otherwise, the unit will be returned to the mutex.
328 *
329 *  @param[in] the_mutex is the mutex to surrender
330 *  @param[in] id is the id of the RTEMS Object associated with this mutex
331 *  @param[in] api_mutex_mp_support is the routine that will be called when
332 *         unblocking a remote mutex
333 *
334 *  @return an indication of whether the routine succeeded or failed
335 */
336CORE_mutex_Status _CORE_mutex_Surrender(
337  CORE_mutex_Control                *the_mutex,
338  Objects_Id                         id,
339  CORE_mutex_API_mp_support_callout  api_mutex_mp_support
340);
341
342/**
343 *  @brief Flush all waiting threads
344 *
345 *  This routine assists in the deletion of a mutex by flushing the associated
346 *  wait queue.
347 *
348 *  @param[in] the_mutex is the mutex to flush
349 *  @param[in] remote_extract_callout is the routine to invoke when a remote
350 *         thread is extracted
351 *  @param[in] status is the status value which each unblocked thread will
352 *         return to its caller.
353 */
354void _CORE_mutex_Flush(
355  CORE_mutex_Control         *the_mutex,
356  Thread_queue_Flush_callout  remote_extract_callout,
357  uint32_t                    status
358);
359
360#include <rtems/score/coremutex.inl>
361#endif
362
363#ifdef __cplusplus
364}
365#endif
366
367/**@}*/
368
369#endif
370/*  end of include file */
Note: See TracBrowser for help on using the repository browser.