No longer inlines spin_lock
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 15 Nov 2012 03:40:08 +0000 (19:40 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 21 Nov 2012 23:41:18 +0000 (15:41 -0800)
Arch-specific locking is done in __spin_{lock,unlock,init}.  Debugging
and whatnot is all done in k/s/atomic.c.

Also adds irq_okay fields and different types of spinlock inits, based
on whether or not it is okay to use the lock in IRQ context or not.  We
don't enforce anything yet (wait for the next patch or three).

kern/arch/i686/atomic.h
kern/arch/i686/smp_boot.c
kern/arch/riscv/atomic.h
kern/arch/sparc/atomic.h
kern/include/atomic.h
kern/include/kthread.h
kern/src/atomic.c

index d181d91..5dfbfad 100644 (file)
@@ -144,7 +144,7 @@ static inline bool spin_locked(spinlock_t *lock)
        return lock->rlock & 0xff;
 }
 
-static inline void __spin_lock(volatile uint32_t *rlock)
+static inline void __spin_lock_raw(volatile uint32_t *rlock)
 {
        asm volatile(
                        "1:                       "
@@ -160,41 +160,19 @@ static inline void __spin_lock(volatile uint32_t *rlock)
                : : "m"(*rlock) : "eax", "cc");
 }
 
-static inline void spin_lock(spinlock_t *lock)
+static inline void __spin_lock(spinlock_t *lock)
 {
-       __spin_lock(&lock->rlock);
-#ifdef __CONFIG_SPINLOCK_DEBUG__
-       lock->call_site = (void RACY*CT(1))TC(read_eip());
-       lock->calling_core = core_id();
-       increase_lock_depth(lock->calling_core);
-#endif
-       cmb();  /* need cmb(), the CPU mb() was handled by the xchgb */
+       __spin_lock_raw(&lock->rlock);
 }
 
-static inline void spin_unlock(spinlock_t *lock)
+static inline void __spin_unlock(spinlock_t *lock)
 {
-#ifdef __CONFIG_SPINLOCK_DEBUG__
-       decrease_lock_depth(lock->calling_core);
-#endif
-       /* Need to prevent the compiler (and some arches) from reordering older
-        * stores. */
-       wmb();
-       rwmb(); /* x86 makes both of these a cmb() */
        lock->rlock = 0;
 }
 
-static inline void spinlock_init(spinlock_t *lock)
-#ifdef __CONFIG_SPINLOCK_DEBUG__
-WRITES(lock->rlock,lock->call_site,lock->calling_core)
-#else
-WRITES(lock->rlock)
-#endif
+static inline void __spinlock_init(spinlock_t *lock)
 {
        lock->rlock = 0;
-#ifdef __CONFIG_SPINLOCK_DEBUG__
-       lock->call_site = 0;
-       lock->calling_core = 0;
-#endif
 }
 
 #endif /* ROS_KERN_ARCH_ATOMIC_H */
index 4c13660..d5bf3ef 100644 (file)
@@ -160,7 +160,7 @@ void smp_boot(void)
        // booting.  Specifically, it's when they turn on paging and have that temp
        // mapping pulled out from under them.  Now, if a core loses, it will spin
        // on the trampoline (which we must be careful to not deallocate)
-       __spin_lock(get_smp_bootlock());
+       __spin_lock_raw(get_smp_bootlock());
        printk("Number of Cores Detected: %d\n", num_cpus);
 #ifdef __CONFIG_DISABLE_SMT__
        assert(!(num_cpus % 2));
index 0741afa..f4b5d9d 100644 (file)
@@ -117,21 +117,15 @@ static inline void spin_lock(spinlock_t *lock)
        while(spin_trylock(lock))
                while(lock->rlock);
        mb();
-#ifdef __CONFIG_SPINLOCK_DEBUG__
-       increase_lock_depth(core_id());
-#endif
 }
 
 static inline void spin_unlock(spinlock_t *lock)
 {
-#ifdef __CONFIG_SPINLOCK_DEBUG__
-       decrease_lock_depth(core_id());
-#endif
        mb();
        lock->rlock = 0;
 }
 
-static inline void spinlock_init(spinlock_t *lock)
+static inline void __spinlock_init(spinlock_t *lock)
 {
        lock->rlock = 0;
 }
index c2522df..2961b9d 100644 (file)
@@ -185,7 +185,7 @@ static inline void spin_unlock(spinlock_t*SAFE lock)
        lock->rlock = 0;
 }
 
-static inline void spinlock_init(spinlock_t* lock)
+static inline void __spinlock_init(spinlock_t* lock)
 {
        lock->rlock = 0;
 }
index 2f7ce24..76932c7 100644 (file)
@@ -42,28 +42,38 @@ extern inline bool atomic_sub_and_test(atomic_t *number, long val);
 struct spinlock {
        volatile uint32_t RACY rlock;
 #ifdef __CONFIG_SPINLOCK_DEBUG__
-       void *call_site;        
+       uintptr_t call_site;
        uint32_t calling_core;
+       bool irq_okay;
 #endif
 };
 typedef struct spinlock spinlock_t;
 #define SPINLOCK_INITIALIZER {0}
 
-extern inline void spinlock_init(spinlock_t *lock);
+#ifdef __CONFIG_SPINLOCK_DEBUG__
+#define SPINLOCK_INITIALIZER_IRQSAVE {0, .irq_okay = TRUE}
+#else
+#define SPINLOCK_INITIALIZER_IRQSAVE SPINLOCK_INITIALIZER
+#endif
+
+/* Arch dependent helpers/funcs: */
+extern inline void __spinlock_init(spinlock_t *lock);
 extern inline bool spin_locked(spinlock_t *lock);
-extern inline void spin_lock(spinlock_t *lock);
-extern inline void spin_unlock(spinlock_t *lock);
+extern inline void __spin_lock(spinlock_t *lock);
+extern inline void __spin_unlock(spinlock_t *lock);
 extern inline void spinlock_debug(spinlock_t *lock);
 
+/* Arch indep, in k/s/atomic.c */
+void spin_lock(spinlock_t *lock);
+void spin_unlock(spinlock_t *lock);
+
+/* Inlines, defined below */
+static inline void spinlock_init(spinlock_t *lock);
+static inline void spinlock_init_irqsave(spinlock_t *lock);
 static inline void spin_lock_irqsave(spinlock_t *lock);
 static inline void spin_unlock_irqsave(spinlock_t *lock);
 static inline bool spin_lock_irq_enabled(spinlock_t *lock);
 
-/* Used for spinlock debugging.  When we move spinlocks into .c, we can move
- * these too */
-void increase_lock_depth(uint32_t coreid);
-void decrease_lock_depth(uint32_t coreid);
-
 /* Hash locks (array of spinlocks).  Most all users will want the default one,
  * so point your pointer to one of them, though you could always kmalloc a
  * bigger one.  In the future, they might be growable, etc, which init code may
@@ -79,6 +89,7 @@ struct small_hashlock {
 };
 
 void hashlock_init(struct hashlock *hl, unsigned int nr_entries);
+void hashlock_init_irqsave(struct hashlock *hl, unsigned int nr_entries);
 void hash_lock(struct hashlock *hl, long key);
 void hash_unlock(struct hashlock *hl, long key);
 void hash_lock_irqsave(struct hashlock *hl, long key);
@@ -192,6 +203,26 @@ void waiton_barrier(barrier_t* barrier);
 /* Spinlock bit flags */
 #define SPINLOCK_IRQ_EN                        0x80000000
 
+static inline void spinlock_init(spinlock_t *lock)
+{
+       __spinlock_init(lock);
+#ifdef __CONFIG_SPINLOCK_DEBUG__
+       lock->call_site = 0;
+       lock->calling_core = 0;
+       lock->irq_okay = FALSE;
+#endif
+}
+
+static inline void spinlock_init_irqsave(spinlock_t *lock)
+{
+       __spinlock_init(lock);
+#ifdef __CONFIG_SPINLOCK_DEBUG__
+       lock->call_site = 0;
+       lock->calling_core = 0;
+       lock->irq_okay = TRUE;
+#endif
+}
+
 // If ints are enabled, disable them and note it in the top bit of the lock
 // There is an assumption about releasing locks in order here...
 static inline void spin_lock_irqsave(spinlock_t *SAFE lock)
index 43d899f..776c639 100644 (file)
@@ -35,12 +35,14 @@ struct semaphore {
        struct kthread_tailq            waiters;
        int                                             nr_signals;
        spinlock_t                                      lock;
+       bool                                            irq_okay;
 };
 
 struct cond_var {
        struct semaphore                        sem;
        spinlock_t                                      lock;
        unsigned long                           nr_waiters;
+       bool                                            irq_okay;
 };
 
 void kthread_init(void);
index dac394c..557899e 100644 (file)
@@ -3,6 +3,7 @@
 #endif
 
 #include <arch/arch.h>
+#include <arch/kdebug.h>
 
 #include <bitmask.h>
 #include <atomic.h>
 #include <hashtable.h>
 #include <smp.h>
 
-void increase_lock_depth(uint32_t coreid)
+static void increase_lock_depth(uint32_t coreid)
 {
        per_cpu_info[coreid].lock_depth++;
 }
 
-void decrease_lock_depth(uint32_t coreid)
+static void decrease_lock_depth(uint32_t coreid)
 {
        per_cpu_info[coreid].lock_depth--;
 }
 
+/* TODO: make this inline if we aren't doing DEBUG? */
+void spin_lock(spinlock_t *lock)
+{
+#ifdef __CONFIG_SPINLOCK_DEBUG__
+       uint32_t coreid = core_id();
+       __spin_lock(lock);
+       lock->call_site = get_caller_pc();
+       lock->calling_core = coreid;
+       /* TODO consider merging this with __ctx_depth (unused field) */
+       increase_lock_depth(lock->calling_core);
+#else
+       __spin_lock(lock);
+#endif
+       cmb();  /* need cmb(), the CPU mb() was handled by the arch-specific xchg */
+}
+
+void spin_unlock(spinlock_t *lock)
+{
+#ifdef __CONFIG_SPINLOCK_DEBUG__
+       decrease_lock_depth(lock->calling_core);
+#endif
+       /* Need to prevent the compiler (and some arches) from reordering older
+        * stores. */
+       wmb();
+       rwmb(); /* x86 makes both of these a cmb() */
+       __spin_unlock(lock);
+}
+
 /* Inits a hashlock. */
 void hashlock_init(struct hashlock *hl, unsigned int nr_entries)
 {
@@ -33,6 +62,16 @@ void hashlock_init(struct hashlock *hl, unsigned int nr_entries)
        }
 }
 
+void hashlock_init_irqsave(struct hashlock *hl, unsigned int nr_entries)
+{
+       hl->nr_entries = nr_entries;
+       /* this is the right way to do it, though memset is faster.  If we ever
+        * find that this is taking a lot of time, we can change it. */
+       for (int i = 0; i < hl->nr_entries; i++) {
+               spinlock_init_irqsave(&hl->locks[i]);
+       }
+}
+
 /* Helper, gets the specific spinlock for a hl/key combo. */
 static spinlock_t *get_spinlock(struct hashlock *hl, long key)
 {