source: rtems/cpukit/score/src/corespinlockwait.c @ c398c66

4.115
Last change on this file since c398c66 was 4fc370e, checked in by Sebastian Huber <sebastian.huber@…>, on 06/05/13 at 10:08:23

score: Move thread dispatch content to new file

Move thread dispatch declarations and inline functions to new header
<rtems/score/threaddispatch.h> to make it independent of the
Thread_Control structure. This avoids a cyclic dependency in case
thread dispatch functions are used for the object implementation.

  • Property mode set to 100644
File size: 3.4 KB
Line 
1/*
2 *  @file
3 *
4 *  @brief Wait for Spinlock
5 *  @ingroup ScoreSpinlock
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2009.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.com/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/system.h>
22#include <rtems/score/corespinlock.h>
23#include <rtems/score/states.h>
24#include <rtems/score/thread.h>
25#include <rtems/score/threaddispatch.h>
26#include <rtems/score/watchdog.h>
27
28/*
29 *  _CORE_spinlock_Wait
30 *
31 *  This function waits for the spinlock to become available.  Optionally,
32 *  a limit may be placed on the duration of the spin.
33 *
34 *  Input parameters:
35 *    the_spinlock - the spinlock control block to initialize
36 *    wait         - true if willing to wait
37 *    timeout      - the maximum number of ticks to spin (0 is forever)
38 *
39 *  Output parameters:  NONE
40 */
41
42CORE_spinlock_Status _CORE_spinlock_Wait(
43  CORE_spinlock_Control  *the_spinlock,
44  bool                    wait,
45  Watchdog_Interval       timeout
46)
47{
48  ISR_Level level;
49  #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
50    Watchdog_Interval       limit = _Watchdog_Ticks_since_boot + timeout;
51  #endif
52
53  _ISR_Disable( level );
54    if ( (the_spinlock->lock == CORE_SPINLOCK_LOCKED) &&
55         (the_spinlock->holder == _Thread_Executing->Object.id) ) {
56      _ISR_Enable( level );
57      return CORE_SPINLOCK_HOLDER_RELOCKING;
58    }
59    the_spinlock->users += 1;
60    for ( ;; ) {
61      if ( the_spinlock->lock == CORE_SPINLOCK_UNLOCKED ) {
62        the_spinlock->lock = CORE_SPINLOCK_LOCKED;
63        the_spinlock->holder = _Thread_Executing->Object.id;
64        _ISR_Enable( level );
65        return CORE_SPINLOCK_SUCCESSFUL;
66      }
67
68      /*
69       *  Spinlock is unavailable.  If not willing to wait, return.
70       */
71      if ( !wait ) {
72        the_spinlock->users -= 1;
73        _ISR_Enable( level );
74        return CORE_SPINLOCK_UNAVAILABLE;
75      }
76
77      #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
78        /*
79         *  They are willing to wait but there could be a timeout.
80         */
81        if ( timeout && (limit <= _Watchdog_Ticks_since_boot) ) {
82          the_spinlock->users -= 1;
83          _ISR_Enable( level );
84          return CORE_SPINLOCK_TIMEOUT;
85        }
86      #endif
87
88      /*
89       *  The thread is willing to spin so let's set things up so
90       *  another thread has a chance of running.  This spinlock has
91       *  to be released by either another thread or an ISR.  Since
92       *  POSIX does not say anything about ISRs, that implies that
93       *  another thread must be able to run while spinning.  We are
94       *  not blocking so that implies we are at least preemptible
95       *  and possibly time-sliced.
96       *
97       *  So first, we will enable interrpts to allow for them to happen.
98       *  Then we will "flash" the thread dispatching critical section
99       *  so other threads have a chance to run.
100       *
101       *  A spinlock cannot be deleted while it is being used so we are
102       *  safe from deletion.
103       */
104
105       _ISR_Enable( level );
106       /* An ISR could occur here */
107
108       _Thread_Enable_dispatch();
109       /* Another thread could get dispatched here */
110
111       /* Reenter the critical sections so we can attempt the lock again. */
112       _Thread_Disable_dispatch();
113
114       _ISR_Disable( level );
115    }
116
117}
Note: See TracBrowser for help on using the repository browser.