Fixes waiton_checklist()
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 7 Jan 2015 22:43:33 +0000 (17:43 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 7 Jan 2015 22:43:33 +0000 (17:43 -0500)
Geez, this bug was around since nearly the dawn of time (2009-04-17).

If someone actually did an smp_call with a wait wrapper, they might get lucky
and have core 0 blow through the check before anyone set a bit.

I'd love to get rid of the smp_call_function business, and replace it with
broadcast kernel messages (at least do so internally) or something.  It is a
somewhat cheap version of a broadcast message, albeit with a limited number of
slots.

kern/arch/riscv/bitmask.h
kern/arch/x86/bitmask.h
kern/include/atomic.h
kern/src/atomic.c

index abb8a94..a4d3bc6 100644 (file)
@@ -86,7 +86,7 @@ static void SET_BITMASK_BIT_ATOMIC(uint8_t* name, size_t bit)
        } \
        clear; })
 
-static inline bool BITMASK_IS_FULL(uint8_t* map, size_t size)
+static inline bool BITMASK_IS_FULL(volatile uint8_t *map, size_t size)
 {
        int _size = size;
        for (int i = 0; i < BYTES_FOR_BITMASK(size); i++) {
index abb8a94..a4d3bc6 100644 (file)
@@ -86,7 +86,7 @@ static void SET_BITMASK_BIT_ATOMIC(uint8_t* name, size_t bit)
        } \
        clear; })
 
-static inline bool BITMASK_IS_FULL(uint8_t* map, size_t size)
+static inline bool BITMASK_IS_FULL(volatile uint8_t *map, size_t size)
 {
        int _size = size;
        for (int i = 0; i < BYTES_FOR_BITMASK(size); i++) {
index dbe2c68..5a8d351 100644 (file)
@@ -204,6 +204,7 @@ int waiton_checklist(checklist_t* list);
 int release_checklist(checklist_t* list);
 int checklist_is_locked(checklist_t* list);
 int checklist_is_clear(checklist_t* list);
+int checklist_is_full(checklist_t* list);
 void reset_checklist(checklist_t* list);
 void down_checklist(checklist_t* list);
 // TODO - do we want to adjust the size?  (YES, don't want to check it all)
index 10d7e25..2552f3b 100644 (file)
@@ -274,7 +274,7 @@ int waiton_checklist(checklist_t* list)
 {
        extern atomic_t outstanding_calls;
        // can consider breakout out early, like above, and erroring out
-       while (!checklist_is_clear(list))
+       while (!checklist_is_full(list))
                cpu_relax();
        spin_unlock_irqsave(&list->lock);
        // global counter of wrappers either waited on or being contended for.
@@ -301,6 +301,12 @@ int checklist_is_clear(checklist_t* list)
        return BITMASK_IS_CLEAR(list->mask.bits, list->mask.size);
 }
 
+// no synch guarantees - just looks at the list
+int checklist_is_full(checklist_t* list)
+{
+       return BITMASK_IS_FULL(list->mask.bits, list->mask.size);
+}
+
 // no synch guarantees - just resets the list to empty
 void reset_checklist(checklist_t* list)
 {