source: rtems/cpukit/score/include/rtems/score/coremutex.h @ 5a58b1e

4.115
Last change on this file since 5a58b1e was 5a58b1e, checked in by Daniel Georgiev <daniel.georgiev95@…>, on 12/01/12 at 14:53:45

score misc: Score misc: Clean up Doxygen #11 (GCI 2012)

This patch is a task from GCI 2012 which improves the Doxygen
comments in the RTEMS source.

http://www.google-melange.com/gci/task/view/google/gci2012/8013204

  • Property mode set to 100644
File size: 15.3 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-2011.
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
19#ifndef _RTEMS_SCORE_COREMUTEX_H
20#define _RTEMS_SCORE_COREMUTEX_H
21/**
22 *  @defgroup ScoreMutex Mutex Handler
23 *
24 *  @ingroup Score
25 *
26 *  This handler encapsulates functionality which provides the foundation
27 *  Mutex services used in all of the APIs supported by RTEMS.
28 */
29/**@{*/
30
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35#include <rtems/score/thread.h>
36#include <rtems/score/threadq.h>
37#include <rtems/score/priority.h>
38#include <rtems/score/watchdog.h>
39#include <rtems/score/interr.h>
40#include <rtems/score/sysstate.h>
41
42/**
43 *  @brief MP Support Callback Prototype
44 *
45 *  The following type defines the callout which the API provides
46 *  to support global/multiprocessor operations on mutexes.
47 */
48typedef void ( *CORE_mutex_API_mp_support_callout )(
49                 Thread_Control *,
50                 Objects_Id
51             );
52
53/**
54 *  @brief Blocking Disciplines Enumerated Type
55 *
56 *  This enumerated type defines the blocking disciplines for a mutex.
57 */
58typedef enum {
59  /** This specifies that threads will wait for the mutex in FIFO order. */
60  CORE_MUTEX_DISCIPLINES_FIFO,
61  /** This specifies that threads will wait for the mutex in priority order.  */
62  CORE_MUTEX_DISCIPLINES_PRIORITY,
63  /** This specifies that threads will wait for the mutex in priority order.
64   *  Additionally, the Priority Inheritance Protocol will be in effect.
65   */
66  CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT,
67  /** This specifies that threads will wait for the mutex in priority order.
68   *  Additionally, the Priority Ceiling Protocol will be in effect.
69   */
70  CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING
71}   CORE_mutex_Disciplines;
72
73/**
74 *  @brief Mutex method return statuses
75 *
76 *  This enumerated type defines the possible Mutex handler return statuses.
77 */
78typedef enum {
79  /** This status indicates that the operation completed successfully. */
80  CORE_MUTEX_STATUS_SUCCESSFUL,
81  /** This status indicates that the calling task did not want to block
82   *  and the operation was unable to complete immediately because the
83   *  resource was unavailable.
84   */
85  CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT,
86#if defined(RTEMS_POSIX_API)
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#endif
92  /** This status indicates that an attempt was made to release a mutex
93   *  by a thread other than the thread which locked it.
94   */
95  CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE,
96  /** This status indicates that the thread was blocked waiting for an
97   *  operation to complete and the mutex was deleted.
98   */
99  CORE_MUTEX_WAS_DELETED,
100  /** This status indicates that the calling task was willing to block
101   *  but the operation was unable to complete within the time allotted
102   *  because the resource never became available.
103   */
104  CORE_MUTEX_TIMEOUT,
105
106#if defined(__RTEMS_STRICT_ORDER_MUTEX__)
107  /** This status indicates that a thread not release the mutex which has
108   *  the priority inheritance property in a right order.
109   */
110  CORE_MUTEX_RELEASE_NOT_ORDER,
111#endif
112
113  /** This status indicates that a thread of logically greater importance
114   *  than the ceiling priority attempted to lock this mutex.
115   */
116  CORE_MUTEX_STATUS_CEILING_VIOLATED
117
118}   CORE_mutex_Status;
119
120/**
121 *  @brief Core Mutex Last Status
122 *
123 *  This is the last status value.
124 */
125#define CORE_MUTEX_STATUS_LAST CORE_MUTEX_STATUS_CEILING_VIOLATED
126
127/**
128 *  @brief Mutex Lock Nesting Behavior Enumeration
129 *
130 *  This enumerated type defines the possible behaviors for
131 *  lock nesting.
132 */
133typedef enum {
134  /**
135   *    This sequence has no blocking or errors:
136   *
137   *         + lock(m)
138   *         + lock(m)
139   *         + unlock(m)
140   *         + unlock(m)
141   */
142  CORE_MUTEX_NESTING_ACQUIRES,
143#if defined(RTEMS_POSIX_API)
144  /**
145   *    This sequence returns an error at the indicated point:
146   *
147   *        + lock(m)
148   *        + lock(m)   - already locked error
149   *        + unlock(m)
150   */
151  CORE_MUTEX_NESTING_IS_ERROR,
152#endif
153  /**
154   *    This sequence performs as indicated:
155   *        + lock(m)
156   *        + lock(m)   - deadlocks or timeouts
157   *        + unlock(m) - releases
158   */
159  CORE_MUTEX_NESTING_BLOCKS
160}  CORE_mutex_Nesting_behaviors;
161
162/**
163 *  This is the value of a mutex when it is unlocked.
164 */
165#define CORE_MUTEX_UNLOCKED 1
166
167/**
168 *  This is the value of a mutex when it is locked.
169 */
170#define CORE_MUTEX_LOCKED   0
171
172/**
173 *  @brief Core Mutex Attributes
174 *
175 *  The following defines the control block used to manage the
176 *  attributes of each mutex.
177 */
178typedef struct {
179  /** This field determines what the behavior of this mutex instance will
180   *  be when attempting to acquire the mutex when it is already locked.
181   */
182  CORE_mutex_Nesting_behaviors lock_nesting_behavior;
183  /** When this field is true, then only the thread that locked the mutex
184   *  is allowed to unlock it.
185   */
186  bool                         only_owner_release;
187  /** This field indicates whether threads waiting on the mutex block in
188   *  FIFO or priority order.
189   */
190  CORE_mutex_Disciplines       discipline;
191  /** This field contains the ceiling priority to be used if that protocol
192   *  is selected.
193   */
194  Priority_Control             priority_ceiling;
195}   CORE_mutex_Attributes;
196
197#ifdef __RTEMS_STRICT_ORDER_MUTEX__
198/*@brief Core Mutex Lock_Chain Struct
199 *
200 * The following defines the control block used to manage lock chain of
201 * priority inheritance mutex.
202 */
203  typedef struct{
204    /** This field is a chian of locked mutex by a thread,new mutex will
205     *  be added to the head of queue, and the mutex which will be released
206     *  must be the head of queue.
207     */
208    Chain_Node                lock_queue;
209    /** This field is the priority of thread before locking this mutex
210     *
211     */
212    Priority_Control          priority_before;
213  }  CORE_mutex_order_list;
214#endif
215
216/**
217 *  @brief Core Mutex Control Structure
218 *
219 *  The following defines the control block used to manage each mutex.
220 */
221typedef struct {
222  /** This field is the Waiting Queue used to manage the set of tasks
223   *  which are blocked waiting to lock the mutex.
224   */
225  Thread_queue_Control    Wait_queue;
226  /** This element is the set of attributes which define this instance's
227   *  behavior.
228   */
229  CORE_mutex_Attributes   Attributes;
230  /** This element contains the current state of the mutex.
231   */
232  uint32_t                lock;
233  /** This element contains the number of times the mutex has been acquired
234   *  nested.  This must be zero (0) before the mutex is actually unlocked.
235   */
236  uint32_t                nest_count;
237  /** This is the number of waiting threads. */
238  uint32_t                blocked_count;
239  /** This element points to the thread which is currently holding this mutex.
240   *  The holder is the last thread to successfully lock the mutex and which
241   *  has not unlocked it.  If the thread is not locked, there is no holder.
242   */
243  Thread_Control         *holder;
244  /** This element contains the object Id of the holding thread.  */
245  Objects_Id              holder_id;
246#ifdef __RTEMS_STRICT_ORDER_MUTEX__
247  /** This field is used to manipulate the priority inheritance mutex queue*/
248  CORE_mutex_order_list   queue;
249#endif
250
251}   CORE_mutex_Control;
252
253/**
254 *  @brief Initialize a Core Mutex
255 *
256 *  This routine initializes the mutex based on the parameters passed.
257 *
258 *  @param[in] the_mutex is the mutex to initalize
259 *  @param[in] the_mutex_attributes is the attributes associated with this
260 *         mutex instance
261 *  @param[in] initial_lock is the initial value of the mutex
262 *
263 *  @return This method returns CORE_MUTEX_STATUS_SUCCESSFUL if successful.
264 */
265CORE_mutex_Status _CORE_mutex_Initialize(
266  CORE_mutex_Control           *the_mutex,
267  CORE_mutex_Attributes        *the_mutex_attributes,
268  uint32_t                      initial_lock
269);
270
271#ifndef __RTEMS_APPLICATION__
272/**
273 *  @brief Seize Mutex with Quick Success Path
274 *
275 *  This routine attempts to receive a unit from the_mutex.
276 *  If a unit is available or if the wait flag is false, then the routine
277 *  returns.  Otherwise, the calling task is blocked until a unit becomes
278 *  available.
279 *
280 *  @param[in] the_mutex is the mutex to attempt to lock
281 *  @param[in] level_p is the interrupt level holder
282 *
283 *  @return This routine returns 0 if "trylock" can resolve whether or not
284 *  the mutex is immediately obtained or there was an error attempting to
285 *  get it.  It returns 1 to indicate that the caller cannot obtain
286 *  the mutex and will have to block to do so.
287 *
288 *  @note  For performance reasons, this routine is implemented as
289 *         a macro that uses two support routines.
290 */
291
292RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock_body(
293  CORE_mutex_Control  *the_mutex,
294  ISR_Level           *level_p
295);
296
297#if defined(__RTEMS_DO_NOT_INLINE_CORE_MUTEX_SEIZE__)
298  /**
299   *  @brief Trylock CORE Mutex Seize Interrupt
300   *  When doing test coverage analysis or trying to minimize the code
301   *  space for RTEMS, it is often helpful to not inline this method
302   *  multiple times.  It is fairly large and has a high branch complexity
303   *  which makes it harder to get full binary test coverage.
304   *
305   *  @param[in] the_mutex will attempt to lock
306   *  @param[in] level_p is the interrupt level holder
307   */
308  int _CORE_mutex_Seize_interrupt_trylock(
309    CORE_mutex_Control  *the_mutex,
310    ISR_Level           *level_p
311  );
312#else
313  /**
314   *  The default is to favor speed and inlining this definitely saves
315   *  a few instructions.  This is very important for mutex performance.
316   *
317   *  @param[in] _mutex will attempt to lock
318   *  @param[in] _level_p is the interrupt level holder
319   */
320  #define _CORE_mutex_Seize_interrupt_trylock( _mutex, _level_p ) \
321     _CORE_mutex_Seize_interrupt_trylock_body( _mutex, _level_p )
322#endif
323
324/**
325 *  @brief Seize Mutex with Blocking
326 *
327 *  This routine performs the blocking portion of a mutex obtain.
328 *  It is an actual subroutine and is not implemented as something
329 *  that may be inlined.
330 *
331 *  @param[in] the_mutex is the mutex to attempt to lock
332 *  @param[in] timeout is the maximum number of ticks to block
333 */
334void _CORE_mutex_Seize_interrupt_blocking(
335  CORE_mutex_Control  *the_mutex,
336  Watchdog_Interval    timeout
337);
338/**
339 *  @brief Sieze Interrupt Wrapper
340 *
341 *  This macro is to verify that a mutex blocking seize is
342 *  performed from a safe system state.  For example, one
343 *  cannot block inside an isr.
344 *
345 *  @return this method returns true if dispatch is in an unsafe state.
346 */
347#ifdef RTEMS_SMP
348  #define _CORE_mutex_Check_dispatch_for_seize(_wait) 0
349#else
350  #define _CORE_mutex_Check_dispatch_for_seize(_wait) \
351      (_Thread_Dispatch_in_critical_section() \
352        && (_wait) \
353        && (_System_state_Get() >= SYSTEM_STATE_BEGIN_MULTITASKING))
354#endif
355
356/**
357 *  @brief Sieze Interrupt Wrapper
358 *
359 *  This routine attempts to obtain the mutex.  If the mutex is available,
360 *  then it will return immediately.  Otherwise, it will invoke the
361 *  support routine @a _Core_mutex_Seize_interrupt_blocking.
362 *
363 *  @param[in] _the_mutex is the mutex to attempt to lock
364 *  @param[in] _id is the Id of the owning API level Semaphore object
365 *  @param[in] _wait is true if the thread is willing to wait
366 *  @param[in] _timeout is the maximum number of ticks to block
367 *  @param[in] _level is a temporary variable used to contain the ISR
368 *         disable level cookie
369 *
370 *  @note If the mutex is called from an interrupt service routine,
371 *        with context switching disabled, or before multitasking,
372 *        then a fatal error is generated.
373 *
374 *  The logic on this routine is as follows:
375 *
376 *  * If incorrect system state
377 *      return an error
378 *  * If mutex is available without any contention or blocking
379 *      obtain it with interrupts disabled and returned
380 *  * If the caller is willing to wait
381 *      then they are blocked.
382 */
383#define _CORE_mutex_Seize_body( \
384  _the_mutex, _id, _wait, _timeout, _level ) \
385  do { \
386    if ( _CORE_mutex_Check_dispatch_for_seize(_wait) ) { \
387        _Internal_error_Occurred( \
388           INTERNAL_ERROR_CORE, \
389           false, \
390           INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE \
391           ); \
392    } \
393    if ( _CORE_mutex_Seize_interrupt_trylock( _the_mutex, &(_level) ) ) {  \
394      if ( !(_wait) ) { \
395        _ISR_Enable( _level ); \
396        _Thread_Executing->Wait.return_code = \
397          CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT; \
398      } else { \
399        _Thread_queue_Enter_critical_section( &(_the_mutex)->Wait_queue ); \
400        _Thread_Executing->Wait.queue = &(_the_mutex)->Wait_queue; \
401        _Thread_Executing->Wait.id    = _id; \
402        _Thread_Disable_dispatch(); \
403        _ISR_Enable( _level ); \
404       _CORE_mutex_Seize_interrupt_blocking( _the_mutex, _timeout ); \
405      } \
406    } \
407  } while (0)
408
409/**
410 *  This method is used to obtain a core mutex.
411 *
412 *  @param[in] _the_mutex is the mutex to attempt to lock
413 *  @param[in] _id is the Id of the owning API level Semaphore object
414 *  @param[in] _wait is true if the thread is willing to wait
415 *  @param[in] _timeout is the maximum number of ticks to block
416 *  @param[in] _level is a temporary variable used to contain the ISR
417 *         disable level cookie
418 */
419#if defined(__RTEMS_DO_NOT_INLINE_CORE_MUTEX_SEIZE__)
420  void _CORE_mutex_Seize(
421    CORE_mutex_Control  *_the_mutex,
422    Objects_Id           _id,
423    bool                 _wait,
424    Watchdog_Interval    _timeout,
425    ISR_Level            _level
426  );
427#else
428  #define _CORE_mutex_Seize( _the_mutex, _id, _wait, _timeout, _level ) \
429     _CORE_mutex_Seize_body( _the_mutex, _id, _wait, _timeout, _level )
430#endif
431
432/**
433 *  @brief Surrender the Mutex
434 *
435 *  This routine frees a unit to the mutex.  If a task was blocked waiting for
436 *  a unit from this mutex, then that task will be readied and the unit
437 *  given to that task.  Otherwise, the unit will be returned to the mutex.
438 *
439 *  @param[in] the_mutex is the mutex to surrender
440 *  @param[in] id is the id of the RTEMS Object associated with this mutex
441 *  @param[in] api_mutex_mp_support is the routine that will be called when
442 *         unblocking a remote mutex
443 *
444 *  @return an indication of whether the routine succeeded or failed
445 */
446CORE_mutex_Status _CORE_mutex_Surrender(
447  CORE_mutex_Control                *the_mutex,
448  Objects_Id                         id,
449  CORE_mutex_API_mp_support_callout  api_mutex_mp_support
450);
451
452/**
453 *  @brief Flush all waiting threads
454 *
455 *  This routine assists in the deletion of a mutex by flushing the associated
456 *  wait queue.
457 *
458 *  @param[in] the_mutex is the mutex to flush
459 *  @param[in] remote_extract_callout is the routine to invoke when a remote
460 *         thread is extracted
461 *  @param[in] status is the status value which each unblocked thread will
462 *         return to its caller.
463 */
464void _CORE_mutex_Flush(
465  CORE_mutex_Control         *the_mutex,
466  Thread_queue_Flush_callout  remote_extract_callout,
467  uint32_t                    status
468);
469
470#include <rtems/score/coremutex.inl>
471#endif
472
473#ifdef __cplusplus
474}
475#endif
476
477/**@}*/
478
479#endif
480/*  end of include file */
Note: See TracBrowser for help on using the repository browser.