Changeset 90c8b8d in mainline


Ignore:
Timestamp:
2009-08-21T14:08:20Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a71c158
Parents:
af8e565
Message:

extend the spinlock interface (static spinlocks, statically declared spinlocks with user-defined name)
ignore deadlock detection on all spinlocks whose name begins with "*" (this is more generic than a hardwired list of spinlocks to ignore)
printf_lock is not required to be public anymore

Location:
kernel/generic
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/print.h

    raf8e565 r90c8b8d  
    3737
    3838#include <arch/types.h>
    39 #include <synch/spinlock.h>
    4039#include <arch/arg.h>
    41 
    42 /* We need this address in spinlock to avoid deadlock in deadlock detection */
    43 SPINLOCK_EXTERN(printf_lock);
    4440
    4541#define EOF (-1)
  • kernel/generic/include/synch/spinlock.h

    raf8e565 r90c8b8d  
    4343
    4444#ifdef CONFIG_SMP
     45
    4546typedef struct {
     47        atomic_t val;
     48       
    4649#ifdef CONFIG_DEBUG_SPINLOCK
    4750        char *name;
    4851#endif
    49         atomic_t val;
    5052} spinlock_t;
    5153
     
    5456 * where the lock gets initialized in run time.
    5557 */
    56 #define SPINLOCK_DECLARE(slname)        spinlock_t slname
    57 #define SPINLOCK_EXTERN(slname)         extern spinlock_t slname
     58#define SPINLOCK_DECLARE(lock_name)  spinlock_t lock_name
     59#define SPINLOCK_EXTERN(lock_name)   extern spinlock_t lock_name
    5860
    5961/*
     
    6264 */
    6365#ifdef CONFIG_DEBUG_SPINLOCK
    64 #define SPINLOCK_INITIALIZE(slname)     \
    65         spinlock_t slname = {           \
    66                 .name = #slname,        \
    67                 .val = { 0 }            \
     66
     67#define SPINLOCK_INITIALIZE_NAME(lock_name, desc_name) \
     68        spinlock_t lock_name = { \
     69                .name = desc_name, \
     70                .val = { 0 } \
    6871        }
     72
     73#define SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, desc_name) \
     74        static spinlock_t lock_name = { \
     75                .name = desc_name, \
     76                .val = { 0 } \
     77        }
     78
     79#define spinlock_lock(lock)  spinlock_lock_debug(lock)
     80
    6981#else
    70 #define SPINLOCK_INITIALIZE(slname)     \
    71         spinlock_t slname = {           \
    72                 .val = { 0 }            \
     82
     83#define SPINLOCK_INITIALIZE_NAME(lock_name, desc_name) \
     84        spinlock_t lock_name = { \
     85                .val = { 0 } \
    7386        }
     87
     88#define SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, desc_name) \
     89        static spinlock_t lock_name = { \
     90                .val = { 0 } \
     91        }
     92
     93#define spinlock_lock(lock)  atomic_lock_arch(&(lock)->val)
     94
    7495#endif
    7596
    76 extern void spinlock_initialize(spinlock_t *sl, char *name);
    77 extern int spinlock_trylock(spinlock_t *sl);
    78 extern void spinlock_lock_debug(spinlock_t *sl);
     97#define SPINLOCK_INITIALIZE(lock_name) \
     98        SPINLOCK_INITIALIZE_NAME(lock_name, #lock_name)
    7999
    80 #ifdef CONFIG_DEBUG_SPINLOCK
    81 #  define spinlock_lock(x) spinlock_lock_debug(x)
    82 #else
    83 #  define spinlock_lock(x) atomic_lock_arch(&(x)->val)
    84 #endif
     100#define SPINLOCK_STATIC_INITIALIZE(lock_name) \
     101        SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, #lock_name)
     102
     103extern void spinlock_initialize(spinlock_t *lock, char *name);
     104extern int spinlock_trylock(spinlock_t *lock);
     105extern void spinlock_lock_debug(spinlock_t *lock);
    85106
    86107/** Unlock spinlock
     
    90111 * @param sl Pointer to spinlock_t structure.
    91112 */
    92 static inline void spinlock_unlock(spinlock_t *sl)
     113static inline void spinlock_unlock(spinlock_t *lock)
    93114{
    94         ASSERT(atomic_get(&sl->val) != 0);
    95 
     115        ASSERT(atomic_get(&lock->val) != 0);
     116       
    96117        /*
    97118         * Prevent critical section code from bleeding out this way down.
     
    99120        CS_LEAVE_BARRIER();
    100121       
    101         atomic_set(&sl->val, 0);
     122        atomic_set(&lock->val, 0);
    102123        preemption_enable();
    103124}
     
    105126#ifdef CONFIG_DEBUG_SPINLOCK
    106127
    107 extern int printf(const char *, ...);
     128#include <print.h>
    108129
    109 #define DEADLOCK_THRESHOLD              100000000
    110 #define DEADLOCK_PROBE_INIT(pname)      size_t pname = 0
    111 #define DEADLOCK_PROBE(pname, value)                                    \
    112         if ((pname)++ > (value)) {                                      \
    113                 (pname) = 0;                                            \
    114                 printf("Deadlock probe %s: exceeded threshold %u\n",    \
    115                     "cpu%u: function=%s, line=%u\n",                    \
    116                     #pname, (value), CPU->id, __func__, __LINE__);      \
     130#define DEADLOCK_THRESHOLD  100000000
     131
     132#define DEADLOCK_PROBE_INIT(pname)  size_t pname = 0
     133
     134#define DEADLOCK_PROBE(pname, value) \
     135        if ((pname)++ > (value)) { \
     136                (pname) = 0; \
     137                printf("Deadlock probe %s: exceeded threshold %u\n", \
     138                    "cpu%u: function=%s, line=%u\n", \
     139                    #pname, (value), CPU->id, __func__, __LINE__); \
    117140        }
    118 #else
    119 #define DEADLOCK_PROBE_INIT(pname)
    120 #define DEADLOCK_PROBE(pname, value)
    121 #endif
    122141
    123142#else
    124143
     144#define DEADLOCK_PROBE_INIT(pname)
     145#define DEADLOCK_PROBE(pname, value)
     146
     147#endif
     148
     149#else /* CONFIG_SMP */
     150
    125151/* On UP systems, spinlocks are effectively left out. */
     152
    126153#define SPINLOCK_DECLARE(name)
    127154#define SPINLOCK_EXTERN(name)
     155
    128156#define SPINLOCK_INITIALIZE(name)
     157#define SPINLOCK_STATIC_INITIALIZE(name)
    129158
    130 #define spinlock_initialize(x, name)
    131 #define spinlock_lock(x)                preemption_disable()
    132 #define spinlock_trylock(x)             (preemption_disable(), 1)
    133 #define spinlock_unlock(x)              preemption_enable()
     159#define SPINLOCK_INITIALIZE_NAME(name, desc_name)
     160#define SPINLOCK_STATIC_INITIALIZE_NAME(name, desc_name)
     161
     162#define spinlock_initialize(lock, name)
     163
     164#define spinlock_lock(lock)     preemption_disable()
     165#define spinlock_trylock(lock)  (preemption_disable(), 1)
     166#define spinlock_unlock(lock)   preemption_enable()
    134167
    135168#define DEADLOCK_PROBE_INIT(pname)
  • kernel/generic/src/printf/vprintf.c

    raf8e565 r90c8b8d  
    4242#include <string.h>
    4343
    44 SPINLOCK_INITIALIZE(printf_lock);  /**< vprintf spinlock */
     44SPINLOCK_STATIC_INITIALIZE_NAME(printf_lock, "*printf_lock");
    4545
    4646static int vprintf_str_write(const char *str, size_t size, void *data)
  • kernel/generic/src/synch/spinlock.c

    raf8e565 r90c8b8d  
    4545#include <symtab.h>
    4646
    47 #ifdef CONFIG_FB
    48 #include <genarch/fb/fb.h>
    49 #endif
    50 
    5147#ifdef CONFIG_SMP
    5248
    5349/** Initialize spinlock
    5450 *
    55  * Initialize spinlock.
     51 * @param sl Pointer to spinlock_t structure.
    5652 *
    57  * @param sl Pointer to spinlock_t structure.
    5853 */
    59 void spinlock_initialize(spinlock_t *sl, char *name)
     54void spinlock_initialize(spinlock_t *lock, char *name)
    6055{
    61         atomic_set(&sl->val, 0);
     56        atomic_set(&lock->val, 0);
    6257#ifdef CONFIG_DEBUG_SPINLOCK
    63         sl->name = name;
    64 #endif 
     58        lock->name = name;
     59#endif
    6560}
     61
     62#ifdef CONFIG_DEBUG_SPINLOCK
    6663
    6764/** Lock spinlock
     
    7168 * possible occurence of deadlock.
    7269 *
    73  * @param sl Pointer to spinlock_t structure.
     70 * @param lock Pointer to spinlock_t structure.
     71 *
    7472 */
    75 #ifdef CONFIG_DEBUG_SPINLOCK
    76 void spinlock_lock_debug(spinlock_t *sl)
     73void spinlock_lock_debug(spinlock_t *lock)
    7774{
    7875        size_t i = 0;
    7976        bool deadlock_reported = false;
    80 
     77       
    8178        preemption_disable();
    82         while (test_and_set(&sl->val)) {
    83 
     79        while (test_and_set(&lock->val)) {
    8480                /*
    85                  * We need to be careful about printf_lock and fb_lock.
    86                  * Both of them are used to report deadlocks via
    87                  * printf() and fb_putchar().
     81                 * We need to be careful about particular locks
     82                 * which are directly used to report deadlocks
     83                 * via printf() (and recursively other functions).
     84                 * This conserns especially printf_lock and the
     85                 * framebuffer lock.
    8886                 *
     87                 * Any lock whose name is prefixed by "*" will be
     88                 * ignored by this deadlock detection routine
     89                 * as this might cause an infinite recursion.
    8990                 * We trust our code that there is no possible deadlock
    90                  * caused by these two locks (except when an exception
    91                  * is triggered for instance by printf() or fb_putchar()).
    92                  * However, we encountered false positives caused by very
    93                  * slow VESA framebuffer interaction (especially when
     91                 * caused by these locks (except when an exception
     92                 * is triggered for instance by printf()).
     93                 *
     94                 * We encountered false positives caused by very
     95                 * slow framebuffer interaction (especially when
    9496                 * run in a simulator) that caused problems with both
    95                  * printf_lock and fb_lock.
     97                 * printf_lock and the framebuffer lock.
    9698                 *
    97                  * Possible deadlocks on both printf_lock and fb_lock
    98                  * are therefore not reported as they would cause an
    99                  * infinite recursion.
    10099                 */
    101                 if (sl == &printf_lock)
     100                if (lock->name[0] == '*')
    102101                        continue;
    103 #ifdef CONFIG_FB
    104                 if (sl == &fb_lock)
    105                         continue;
    106 #endif
     102               
    107103                if (i++ > DEADLOCK_THRESHOLD) {
    108104                        printf("cpu%u: looping on spinlock %" PRIp ":%s, "
    109                             "caller=%" PRIp "(%s)\n", CPU->id, sl, sl->name,
     105                            "caller=%" PRIp "(%s)\n", CPU->id, lock, lock->name,
    110106                            CALLER, symtab_fmt_name_lookup(CALLER));
    111107                       
     
    114110                }
    115111        }
    116 
     112       
    117113        if (deadlock_reported)
    118114                printf("cpu%u: not deadlocked\n", CPU->id);
    119 
     115       
    120116        /*
    121117         * Prevent critical section code from bleeding out this way up.
     
    123119        CS_ENTER_BARRIER();
    124120}
     121
    125122#endif
    126123
     
    131128 * signal failure.
    132129 *
    133  * @param sl Pointer to spinlock_t structure.
     130 * @param lock Pointer to spinlock_t structure.
    134131 *
    135132 * @return Zero on failure, non-zero otherwise.
     133 *
    136134 */
    137 int spinlock_trylock(spinlock_t *sl)
     135int spinlock_trylock(spinlock_t *lock)
    138136{
    139         int rc;
     137        preemption_disable();
     138        int rc = !test_and_set(&lock->val);
    140139       
    141         preemption_disable();
    142         rc = !test_and_set(&sl->val);
    143 
    144140        /*
    145141         * Prevent critical section code from bleeding out this way up.
    146142         */
    147143        CS_ENTER_BARRIER();
    148 
     144       
    149145        if (!rc)
    150146                preemption_enable();
Note: See TracChangeset for help on using the changeset viewer.