Split atomic library
authorBarret Rhoden <brho@cs.berkeley.edu>
Sat, 6 Jun 2009 01:08:28 +0000 (18:08 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sat, 6 Jun 2009 01:08:28 +0000 (18:08 -0700)
Now an arch/atomic that has lower layer atomic primitives, and the
regular include/atomic (and a userspace version) with higher level
primitives (which should be renamed or changed later).  Esp since they
are still arch specific.

Also removed printks from some userspace apps, and changed back the
printk macro.

16 files changed:
include/arch/atomic.h
include/arch/smp.h
include/atomic.h [new file with mode: 0644]
include/pmap.h
kern/src/atomic.c
kern/src/env.c
kern/src/init.c
kern/src/manager.c
kern/src/pmap.c
kern/src/printf.c
kern/src/smp.c
kern/src/testing.c
kern/src/workqueue.c
user/apps/roslib/measurements.c
user/roslib/inc/atomic.h
user/roslib/inc/stdio.h

index bc250b1..aeaff81 100644 (file)
-#ifndef ROS_KERN_ATOMIC_H
-#define ROS_KERN_ATOMIC_H
+#ifndef ROS_INCLUDE_ATOMIC_H
+#define ROS_INCLUDE_ATOMIC_H
 
 #include <arch/types.h>
-#include <arch/mmu.h>
-#include <arch/x86.h>
 
 #define mb() {rmb(); wmb();}
 #define rmb() ({ asm volatile("lfence"); })
 #define wmb() 
 
-/* //linux style atomic ops
-typedef struct {uint32_t real_num;} atomic_t;
-#define atomic_read(atom) ((atom)->real_num)
-#define atomic_set(atom, val) (((atom)->real_num) = (val))
-#define atomic_init(i) {(i)}
-//and the atomic incs, etc take an atomic_t ptr, deref inside
-*/
-
-static inline void spin_lock(volatile uint32_t* lock);
-static inline void spin_unlock(volatile uint32_t* lock);
-static inline void spin_lock_irqsave(volatile uint32_t* lock);
-static inline void spin_unlock_irqsave(volatile uint32_t* lock);
 static inline void atomic_inc(volatile uint32_t* number);
 static inline void atomic_dec(volatile uint32_t* number);
 static inline void atomic_andb(volatile uint8_t* number, uint8_t mask);
 
-/*********************** Checklist stuff **********************/
-typedef struct checklist_mask {
-       // only need an uint8_t, but we need the bits[] to be word aligned
-       uint32_t size;
-       volatile uint8_t (COUNT(BYTES_FOR_BITMASK(size)) bits)[];
-} checklist_mask_t;
-
-// mask contains an unspecified array, so it needs to be at the bottom
-typedef struct checklist {
-       volatile uint32_t lock;
-       checklist_mask_t mask;
-} checklist_t;
-
-#define ZEROS_ARRAY(size) {[0 ... ((size)-1)] 0}
-
-#define DEFAULT_CHECKLIST_MASK(sz) {(sz), ZEROS_ARRAY(BYTES_FOR_BITMASK(sz))}
-#define DEFAULT_CHECKLIST(sz) {0, DEFAULT_CHECKLIST_MASK(sz)}
-#define INIT_CHECKLIST(nm, sz) \
-       checklist_t nm = DEFAULT_CHECKLIST(sz);
-#define INIT_CHECKLIST_MASK(nm, sz)    \
-       checklist_mask_t nm = DEFAULT_CHECKLIST_MASK(sz);
-
-int commit_checklist_wait(checklist_t* list, checklist_mask_t* mask);
-int commit_checklist_nowait(checklist_t* list, checklist_mask_t* mask);
-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);
-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)
-// TODO - do we want to be able to call waiton without having called commit?
-//     - in the case of protected checklists
-// TODO - want a destroy checklist (when we have kmalloc, or whatever)
-// TODO - some sort of dynamic allocation of them in the future
-// TODO - think about deadlock issues with one core spinning on a lock for
-// something that it is the hold out for...
-//     - probably should have interrupts enabled, and never grab these locks
-//     from interrupt context (and not use irq_save)
-/**************************************************************/
-
-/* Barrier: currently made for everyone barriering.  Change to use checklist */
-typedef struct barrier {
-       volatile uint32_t lock;
-       uint32_t init_count;
-       uint32_t current_count;
-    volatile uint8_t ready;
-} barrier_t;
-
-void init_barrier(barrier_t* barrier, uint32_t count);
-void reset_barrier(barrier_t* barrier);
-void waiton_barrier(barrier_t* barrier);
-
-/* Inlined functions declared above */
-static inline void spin_lock(volatile uint32_t* lock)
-{
-       asm volatile(
-                       "1:                       "
-                       "       cmpb $0, %0;          "
-                       "       je 2f;                "
-                       "       pause;                "
-                       "       jmp 1b;               "
-                       "2:                       " 
-                       "       movb $1, %%al;        "
-                       "       xchgb %%al, %0;       "
-                       "       cmpb $0, %%al;        "
-                       "       jne 1b;               "
-               : : "m"(*lock) : "eax", "cc");
-}
-
-static inline void spin_unlock(volatile uint32_t* lock)
-{
-       *lock = 0;
-}
-
-// 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(volatile uint32_t* lock)
-{
-       uint32_t eflags;
-       eflags = read_eflags();
-       disable_irq();
-       spin_lock(lock);
-       if (eflags & FL_IF)
-               *lock |= 0x80000000;
-}
-
-// if the top bit of the lock is set, then re-enable interrupts
-static inline void spin_unlock_irqsave(volatile uint32_t* lock)
-{
-       if (*lock & 0x80000000) {
-               *lock = 0;
-               enable_irq();
-       } else
-               *lock = 0;
-}
-
 // need to do this with pointers and deref.  %0 needs to be the memory address
 static inline void atomic_inc(volatile uint32_t* number)
 {
@@ -137,4 +26,4 @@ static inline void atomic_andb(volatile uint8_t* number, uint8_t mask)
 {
        asm volatile("lock andb %1,%0" : "=m"(*number) : "r"(mask) : "cc");
 }
-#endif /* !ROS_KERN_ATOMIC_H */
+#endif /* !ROS_INCLUDE_ATOMIC_H */
index be0f0bb..b1c8201 100644 (file)
@@ -4,8 +4,10 @@
 /* SMP related functions */
 
 #include <arch/types.h>
-#include <arch/atomic.h>
+
 #include <ros/queue.h>
+
+#include <atomic.h>
 #include <trap.h>
 #include <workqueue.h>
 
diff --git a/include/atomic.h b/include/atomic.h
new file mode 100644 (file)
index 0000000..c845f48
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef ROS_KERN_ATOMIC_H
+#define ROS_KERN_ATOMIC_H
+
+#include <arch/types.h>
+#include <arch/mmu.h>
+#include <arch/x86.h>
+#include <arch/atomic.h>
+
+/* //linux style atomic ops
+typedef struct {uint32_t real_num;} atomic_t;
+#define atomic_read(atom) ((atom)->real_num)
+#define atomic_set(atom, val) (((atom)->real_num) = (val))
+#define atomic_init(i) {(i)}
+//and the atomic incs, etc take an atomic_t ptr, deref inside
+*/
+
+static inline void spin_lock(volatile uint32_t* lock);
+static inline void spin_unlock(volatile uint32_t* lock);
+static inline void spin_lock_irqsave(volatile uint32_t* lock);
+static inline void spin_unlock_irqsave(volatile uint32_t* lock);
+
+/*********************** Checklist stuff **********************/
+typedef struct checklist_mask {
+       // only need an uint8_t, but we need the bits[] to be word aligned
+       uint32_t size;
+       volatile uint8_t (COUNT(BYTES_FOR_BITMASK(size)) bits)[];
+} checklist_mask_t;
+
+// mask contains an unspecified array, so it needs to be at the bottom
+typedef struct checklist {
+       volatile uint32_t lock;
+       checklist_mask_t mask;
+} checklist_t;
+
+#define ZEROS_ARRAY(size) {[0 ... ((size)-1)] 0}
+
+#define DEFAULT_CHECKLIST_MASK(sz) {(sz), ZEROS_ARRAY(BYTES_FOR_BITMASK(sz))}
+#define DEFAULT_CHECKLIST(sz) {0, DEFAULT_CHECKLIST_MASK(sz)}
+#define INIT_CHECKLIST(nm, sz) \
+       checklist_t nm = DEFAULT_CHECKLIST(sz);
+#define INIT_CHECKLIST_MASK(nm, sz)    \
+       checklist_mask_t nm = DEFAULT_CHECKLIST_MASK(sz);
+
+int commit_checklist_wait(checklist_t* list, checklist_mask_t* mask);
+int commit_checklist_nowait(checklist_t* list, checklist_mask_t* mask);
+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);
+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)
+// TODO - do we want to be able to call waiton without having called commit?
+//     - in the case of protected checklists
+// TODO - want a destroy checklist (when we have kmalloc, or whatever)
+// TODO - some sort of dynamic allocation of them in the future
+// TODO - think about deadlock issues with one core spinning on a lock for
+// something that it is the hold out for...
+//     - probably should have interrupts enabled, and never grab these locks
+//     from interrupt context (and not use irq_save)
+/**************************************************************/
+
+/* Barrier: currently made for everyone barriering.  Change to use checklist */
+typedef struct barrier {
+       volatile uint32_t lock;
+       uint32_t init_count;
+       uint32_t current_count;
+    volatile uint8_t ready;
+} barrier_t;
+
+void init_barrier(barrier_t* barrier, uint32_t count);
+void reset_barrier(barrier_t* barrier);
+void waiton_barrier(barrier_t* barrier);
+
+/* Inlined functions declared above */
+static inline void spin_lock(volatile uint32_t* lock)
+{
+       asm volatile(
+                       "1:                       "
+                       "       cmpb $0, %0;          "
+                       "       je 2f;                "
+                       "       pause;                "
+                       "       jmp 1b;               "
+                       "2:                       " 
+                       "       movb $1, %%al;        "
+                       "       xchgb %%al, %0;       "
+                       "       cmpb $0, %%al;        "
+                       "       jne 1b;               "
+               : : "m"(*lock) : "eax", "cc");
+}
+
+static inline void spin_unlock(volatile uint32_t* lock)
+{
+       *lock = 0;
+}
+
+// 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(volatile uint32_t* lock)
+{
+       uint32_t eflags;
+       eflags = read_eflags();
+       disable_irq();
+       spin_lock(lock);
+       if (eflags & FL_IF)
+               *lock |= 0x80000000;
+}
+
+// if the top bit of the lock is set, then re-enable interrupts
+static inline void spin_unlock_irqsave(volatile uint32_t* lock)
+{
+       if (*lock & 0x80000000) {
+               *lock = 0;
+               enable_irq();
+       } else
+               *lock = 0;
+}
+
+#endif /* !ROS_KERN_ATOMIC_H */
index 92b4bf3..f899f04 100644 (file)
@@ -7,8 +7,10 @@
 #endif
 
 #include <arch/multiboot.h>
-#include <arch/atomic.h>
+
 #include <ros/memlayout.h>
+
+#include <atomic.h>
 #include <env.h>
 #include <assert.h>
 
index 5d522f0..1135416 100644 (file)
@@ -1,5 +1,6 @@
 #include <arch/apic.h>
-#include <arch/atomic.h>
+
+#include <atomic.h>
 #include <ros/error.h>
 #include <string.h>
 #include <assert.h>
index 5b206eb..77c6d44 100644 (file)
@@ -8,8 +8,8 @@
 #include <arch/elf.h>
 #include <arch/apic.h>
 #include <arch/smp.h>
-#include <arch/atomic.h>
 
+#include <atomic.h>
 #include <string.h>
 #include <assert.h>
 #include <env.h>
index 746070d..3a6c6a8 100644 (file)
@@ -14,8 +14,8 @@
 #include <arch/multiboot.h>
 #include <arch/stab.h>
 #include <arch/smp.h>
-#include <arch/atomic.h>
 
+#include <atomic.h>
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
index f065d5d..9e87df7 100644 (file)
@@ -30,7 +30,7 @@ void manager(void)
        switch (progress++) {
                case 0:
                        printk("Beginning Tests\n");
-                       test_run_measurements(progress);  // should never return
+                       test_run_measurements(progress-1);  // should never return
                        break;
                case 1:
                case 2:
@@ -46,7 +46,7 @@ void manager(void)
                case 12:
                case 13:
                case 14:
-                       test_run_measurements(progress);
+                       test_run_measurements(progress-1);
                        break;
                default:
                        panic("Don't Panic");
index 7f81604..3a0aefa 100644 (file)
@@ -6,9 +6,10 @@
 #include <arch/x86.h>
 #include <arch/mmu.h>
 #include <arch/apic.h>
-#include <arch/atomic.h>
+
 #include <ros/error.h>
 
+#include <atomic.h>
 #include <string.h>
 #include <assert.h>
 #include <pmap.h>
index 110add4..b52320e 100644 (file)
@@ -6,7 +6,8 @@
 #endif
 
 #include <arch/types.h>
-#include <arch/atomic.h>
+
+#include <atomic.h>
 #include <stdio.h>
 #include <stdarg.h>
 
index 32744ae..0ec8771 100644 (file)
@@ -6,7 +6,8 @@
 #include <arch/smp.h>
 #include <arch/console.h>
 #include <arch/apic.h>
-#include <arch/atomic.h>
+
+#include <atomic.h>
 #include <ros/error.h>
 #include <stdio.h>
 #include <string.h>
index 56fe16b..b99ce2e 100644 (file)
@@ -3,11 +3,13 @@
 #endif
 
 #include <arch/mmu.h>
-#include <ros/memlayout.h>
 #include <arch/x86.h>
 #include <arch/smp.h>
 #include <arch/apic.h>
-#include <arch/atomic.h>
+
+#include <ros/memlayout.h>
+
+#include <atomic.h>
 #include <stdio.h>
 #include <assert.h>
 #include <string.h>
index c934b2f..f5bdd40 100644 (file)
@@ -6,7 +6,8 @@
 #include <arch/x86.h>
 #include <arch/apic.h>
 #include <arch/smp.h>
-#include <arch/atomic.h>
+
+#include <atomic.h>
 
 #include <workqueue.h>
 
index 074991a..8e86443 100644 (file)
@@ -1,13 +1,13 @@
 #include <arch/types.h>
 #include <arch/x86.h>
 #include <arch/timer.h>
-#include <arch/atomic.h>
 
 #include <ros/syscall.h>
 
 #include <lib.h>
 #include <measure.h>
 #include <syswrapper.h>
+#include <atomic.h>
 
 #ifdef __DEPUTY__
 #pragma nodeputy
@@ -129,7 +129,7 @@ void buster_thruput_sync(uint32_t flags, char* text)
                buster_sync_wrapper(100, i, flags);
                waiton_barrier(bar);
                thruput_ticks = stop_timing(thruput_ticks);     
-               printk("XME:BUSTER:%d:S:%s:%d:W:%llu\n", corecount, text, i, thruput_ticks);
+               cprintf("XME:BUSTER:%d:S:%s:%d:W:%llu\n", corecount, text, i, thruput_ticks);
        }
 }
 
@@ -143,7 +143,7 @@ void buster_thruput_async(uint32_t flags, char* text)
                buster_async_wrapper(100, i, flags);
                waiton_barrier(bar);
                thruput_ticks = stop_timing(thruput_ticks);     
-               printk("XME:BUSTER:%d:A:%s:%d:W:%llu\n", corecount, text, i, thruput_ticks);
+               cprintf("XME:BUSTER:%d:A:%s:%d:W:%llu\n", corecount, text, i, thruput_ticks);
        }
 }
 
@@ -153,7 +153,7 @@ void buster_latency_sync(uint32_t flags, char* text)
        for (int i = 1; i < MAX_CACHELINE_WRITES; i=i*2) { // 1 - 128
                measure_func_runtime(buster_sync_wrapper, 100,  i , flags);
                tick = measure_func_runtime(buster_sync_wrapper, 1,  i , flags);
-               printk("XME:BUSTER:%d:S:%s:LATENCY:%d:W:%llu\n", corecount, text,i, tick);
+               cprintf("XME:BUSTER:%d:S:%s:LATENCY:%d:W:%llu\n", corecount, text,i, tick);
        }
 }
 
@@ -163,7 +163,7 @@ void buster_latency_async(uint32_t flags, char* text)
        for (int i = 1; i < MAX_CACHELINE_WRITES; i=i*2) { // 1 - 128
                measure_func_runtime(buster_async_wrapper, 100,  i , flags);
                tick = measure_func_runtime(buster_async_wrapper, 1,  i , flags);
-               printk("XME:BUSTER:%d:A:%s:LATENCY:%d:W:%llu\n", corecount, text,i, tick);
+               cprintf("XME:BUSTER:%d:A:%s:LATENCY:%d:W:%llu\n", corecount, text,i, tick);
        }
 }
 
@@ -175,7 +175,6 @@ int main(int argc, char** argv)
        
        #define MAX_ITERS 10
 
-       disable_irq();
        switch(*job_to_run) {
                case 0:
                        /* NULL SYSCALLS */
@@ -184,37 +183,37 @@ int main(int argc, char** argv)
                        // Sync Null Syscalls
                        sys_cache_invalidate();
                        ticks = measure_func_runtime(null_wrapper, 1);
-                       printk("XME:Null:S:1:1:C:%llu\n", ticks);
+                       cprintf("XME:Null:S:1:1:C:%llu\n", ticks);
                        for (int i = 1; i <= MAX_ITERS; i++) {
                                ticks = measure_func_runtime(null_wrapper, i);
-                               printk("XME:Null:S:1:%d:W:%llu\n", i, ticks);
+                               cprintf("XME:Null:S:1:%d:W:%llu\n", i, ticks);
                        }
 
                        // Async Null Syscalls
                        sys_cache_invalidate();
                        ticks = measure_func_runtime(null_async_wrapper, 1);
-                       printk("XME:Null:A:1:1:C:%llu\n", ticks);
+                       cprintf("XME:Null:A:1:1:C:%llu\n", ticks);
                        for (int i = 1; i <= MAX_ITERS; i++) {
                                ticks = measure_func_runtime(null_async_wrapper, i);
-                               printk("XME:Null:A:1:%d:W:%llu\n", i, ticks);
+                               cprintf("XME:Null:A:1:%d:W:%llu\n", i, ticks);
                        }
 
                        // raw sysenter
                        sys_cache_invalidate();
                        ticks = measure_func_runtime(sysenter_wrapper, 1);
-                       printk("XME:SYSE:S:1:1:C:%llu\n", ticks);
+                       cprintf("XME:SYSE:S:1:1:C:%llu\n", ticks);
                        for (int i = 1; i <= MAX_ITERS; i++) {
                                ticks = measure_func_runtime(sysenter_wrapper, i);
-                               printk("XME:SYSE:S:1:%d:W:%llu\n", i, ticks);
+                               cprintf("XME:SYSE:S:1:%d:W:%llu\n", i, ticks);
                        }
 
                        // raw trap
                        sys_cache_invalidate();
                        ticks = measure_func_runtime(systrap_wrapper, 1);
-                       printk("XME:TRAP:S:1:1:C:%llu\n", ticks);
+                       cprintf("XME:TRAP:S:1:1:C:%llu\n", ticks);
                        for (int i = 1; i <= MAX_ITERS; i++) {
                                ticks = measure_func_runtime(systrap_wrapper, i);
-                               printk("XME:TRAP:S:1:%d:W:%llu\n", i, ticks);
+                               cprintf("XME:TRAP:S:1:%d:W:%llu\n", i, ticks);
                        }
 
                        break;
index 48627c0..e7596ce 100644 (file)
@@ -1,10 +1,8 @@
 #ifndef ROS_INC_ATOMIC_H
 #define ROS_INC_ATOMIC_H
 
-// TODO - check these, wrt x86
-#define mb() {rmb(); wmb();}
-#define rmb() ({ asm volatile("lfence"); })
-#define wmb()
+#include <arch/atomic.h>
+
 
 /* Ghetto-atomics, stolen from kern/atomic.* */
 static inline void spin_lock(volatile uint32_t* lock)
@@ -39,5 +37,4 @@ void init_barrier(barrier_t* barrier, uint32_t count);
 void reset_barrier(barrier_t* barrier);
 void waiton_barrier(barrier_t* barrier);
 
-
 #endif /* !ROS_INC_ATOMIC_H */
index cb96d5d..75bab8b 100644 (file)
@@ -8,13 +8,11 @@
 #endif /* !NULL */
 
 #ifdef DEBUG
-#define printd(fmt, ...) cprintf(fmt, #__VA_ARGS__)
+#define printd(args...) cprintf(args)
 #else
 #define printd(fmt, ...) {}
 #endif
 
-#define printk(fmt, ...) cprintf(fmt, #__VA_ARGS__)
-
 // lib/stdio.c
 void cputchar(int c);
 int     getchar(void);