source: rtems/cpukit/score/src/smplock.c @ 9b4422a2

4.115
Last change on this file since 9b4422a2 was 9b4422a2, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 15:09:24

Remove All CVS Id Strings Possible Using a Script

Script does what is expected and tries to do it as
smartly as possible.

+ remove occurrences of two blank comment lines

next to each other after Id string line removed.

+ remove entire comment blocks which only exited to

contain CVS Ids

+ If the processing left a blank line at the top of

a file, it was removed.

  • Property mode set to 100644
File size: 6.6 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-2011.
3 *  On-Line Applications Research Corporation (OAR).
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.rtems.com/license/LICENSE.
8 */
9
10#if HAVE_CONFIG_H
11#include "config.h"
12#endif
13
14#include <rtems/system.h>
15#include <rtems/score/smplock.h>
16#include <rtems/score/smp.h>
17#include <rtems/score/isr.h>
18
19/*
20 * Some debug stuff that is being left in, but disabled.  This will keep
21 * a log of lock/unlock sequences that can be printed out when the
22 * lockcount appears to have gotten off track.
23 */
24/* #define SMPLOCK_DEBUG */
25#if defined (SMPLOCK_DEBUG)
26  #include <rtems/score/thread.h>
27  #include <rtems/bspIo.h>
28  #include <rtems/score/percpu.h>
29  #if (0)
30    #define  ENABLE_ONESHOT_DEBUG_LOGGING
31  #else
32    #define ENABLE_LOOPED_DEBUG_LOGGING
33  #endif
34  #define ENABLE_DEBUG_LOGGING
35#endif
36
37/*
38 * Prototypes and structures used in the debug lock/unlock error log.
39 */
40#if defined(ENABLE_DEBUG_LOGGING)
41  typedef struct {
42    char      action;
43    char      lock;
44    char      cpu;
45    char      count;
46    uint32_t  nest_level;
47    void      *ret1;
48    void      *ret2;
49    void      *ret3;
50    void      *ret4;
51  } debug_spinlog_t;
52
53  extern void start(void);
54  extern void _fini(void);
55
56  #define DEBUG_SPINLOG_MAX 1024
57  debug_spinlog_t DEBUG_SPINLOG[DEBUG_SPINLOG_MAX];
58  int DEBUG_SPINLOG_INDEX = 0;
59
60  static void debug_logit(
61    char                             act,
62    SMP_lock_spinlock_nested_Control *lock
63  );
64  static void debug_dump_log(void);
65#else
66  #define debug_logit( _act, _lock )
67  #define debug_dump_log()
68#endif
69
70/*
71 * SMP spinlock simple methods
72 */
73void _SMP_lock_spinlock_simple_Initialize(
74  SMP_lock_spinlock_simple_Control *lock
75)
76{
77  *lock = 0;
78}
79
80ISR_Level _SMP_lock_spinlock_simple_Obtain(
81  SMP_lock_spinlock_simple_Control *lock
82)
83{
84   ISR_Level  level = 0;
85   uint32_t   value = 1;
86   uint32_t   previous;
87
88   /* Note: Disable provides an implicit memory barrier. */
89  _ISR_Disable_on_this_core( level );
90   do {
91     RTEMS_COMPILER_MEMORY_BARRIER();
92     SMP_CPU_SWAP( lock, value, previous );
93     RTEMS_COMPILER_MEMORY_BARRIER();
94   } while (previous == 1);
95
96  return level;
97}
98
99void _SMP_lock_spinlock_simple_Release(
100  SMP_lock_spinlock_simple_Control *lock,
101  ISR_Level                        level
102)
103{
104   *lock = 0;
105   _ISR_Enable_on_this_core( level );
106}
107
108/*
109 * SMP spinlock nested methods.
110 */
111void _SMP_lock_spinlock_nested_Initialize(
112  SMP_lock_spinlock_nested_Control *lock
113)
114{
115  lock->lock = 0;
116  lock->count = 0;
117  lock->cpu_id = -1;
118}
119
120void _SMP_lock_spinlock_nested_Release(
121  SMP_lock_spinlock_nested_Control *lock,
122  ISR_Level                        level
123)
124{
125  #if defined (RTEMS_DEBUG) || defined(SMPLOCK_DEBUG)
126    if ( lock->count == 0 ) {
127      printk(
128        "\ncpu %d lock %d Releasing spinlock when count is already "
129        "zero (%p from %p,%p)?!?!\n",
130        bsp_smp_processor_id(), 
131        lock->cpu_id,
132        lock,
133        __builtin_return_address(0),
134        __builtin_return_address(1)
135      );
136      debug_dump_log();
137      return;
138    }
139  #endif
140
141  /* assume we actually have it */
142  if (lock->count == 1) {
143    lock->cpu_id = -1;
144    debug_logit( 'U', lock );
145    lock->count  = 0;
146    RTEMS_COMPILER_MEMORY_BARRIER();
147    lock->lock = 0;
148  } else {
149    debug_logit( 'u', lock );
150    lock->count--;
151  }
152
153  _ISR_Enable_on_this_core( level );
154}
155
156ISR_Level _SMP_lock_spinlock_nested_Obtain(
157  SMP_lock_spinlock_nested_Control *lock
158)
159{
160  ISR_Level  level = 0;
161  uint32_t   value = 1;
162  uint32_t   previous;
163  int        cpu_id;
164
165  /* Note: Disable provides an implicit memory barrier. */
166  _ISR_Disable_on_this_core( level );
167
168  cpu_id = bsp_smp_processor_id();
169
170  /*
171   *  Attempt to obtain the lock.  If we do not get it immediately, then
172   *  do a single "monitor" iteration.  This should allow the loop to back
173   *  off the bus a bit and allow the other core to finish sooner.
174   */
175  while (1) {
176    RTEMS_COMPILER_MEMORY_BARRIER();
177    SMP_CPU_SWAP( &lock->lock, value, previous );
178    RTEMS_COMPILER_MEMORY_BARRIER();
179    if ( previous == 0 ) {
180      /* was not locked */
181      break;
182    }
183
184    /* Deal with nested calls from one cpu */
185    if (cpu_id == lock->cpu_id) {
186      lock->count++;
187      debug_logit( 'l', lock );
188      return level;
189    }
190  }
191
192  lock->cpu_id = cpu_id;
193  lock->count = 1;
194  debug_logit( 'L', lock );
195
196  return level;
197}
198
199/*
200 * Debug log for debugging nested lock/unlock problems.
201 */
202#if defined(ENABLE_DEBUG_LOGGING)
203  static void debug_logit(
204    char                             act,
205    SMP_lock_spinlock_nested_Control *lock
206  )
207  {
208    debug_debug_spinlog_t *sp;
209    if ( DEBUG_SPINLOG_INDEX == DEBUG_SPINLOG_MAX )
210      #if defined (ENABLE_LOOPED_DEBUG_LOGGING)
211        DEBUG_SPINLOG_INDEX = 0;
212      #else
213        return;
214      #endif
215
216    sp = &DEBUG_SPINLOG[ DEBUG_SPINLOG_INDEX++ ];
217    sp->action = act;
218
219    #if 0
220      if ( lock == &_ISR_SMP_Lock )
221        sp->lock = 'I';
222      else
223    #endif
224    if ( lock == &_Thread_Dispatch_disable_level_lock )
225      sp->lock   = 'D';
226    sp->cpu    = bsp_smp_processor_id() + '0';
227    sp->count  = lock->count;
228    #if 0
229      if ( sp->lock == 'I' ) {
230        if ( _Thread_Dispatch_smp_spin_lock.id == 0 )
231          printk( "not nested %p from %p %p %p %p\n", sp,
232          __builtin_return_address(0), __builtin_return_address(1),
233          __builtin_return_address(2), __builtin_return_address(3)
234        );
235      }
236    #endif
237    sp->nest_level =  _ISR_Nest_level;
238    sp->ret1 = 0;
239    sp->ret2 = 0;
240    sp->ret3 = 0;
241    sp->ret4 = 0;
242    sp->ret1 = __builtin_return_address(0);
243    if ( sp->ret1 >= start && sp->ret1 <= _fini ) {
244      sp->ret2   = __builtin_return_address(1);
245      if ( sp->ret2 >= start && sp->ret2 <= _fini ) {
246        sp->ret3   = __builtin_return_address(2);
247        if ( sp->ret3 >= start && sp->ret3 <= _fini ) {
248          sp->ret4   = __builtin_return_address(3);
249        }
250      }
251    }
252  }
253 
254  static void debug_dump_log(void)
255  {
256    debug_debug_spinlog_t *sp;
257    int       index;
258    bool      done =false;
259   
260    #if defined (ENABLE_ONESHOT_DEBUG_LOGGING)
261      index = 0;
262    #else
263      if (DEBUG_SPINLOG_INDEX >= DEBUG_SPINLOG_MAX)
264        index = 0;
265      else
266        index = DEBUG_SPINLOG_INDEX;
267    #endif
268
269
270    do {
271      sp = &DEBUG_SPINLOG[ index ];
272      printk("%d) act %c lock %c cpu %c count=%d nest %d (%p, %p, %p, %p)\n",
273        index, sp->action, sp->lock, sp->cpu, sp->count, sp->nest_level,
274        sp->ret1, sp->ret2, sp->ret3, sp->ret4
275      );
276
277      index++;
278      if (index == DEBUG_SPINLOG_INDEX)
279        break;
280      if (index >= DEBUG_SPINLOG_MAX)
281        index = 0;
282    } while (1);
283  }
284#endif
Note: See TracBrowser for help on using the repository browser.