Userspace atomics library
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 4 Jun 2009 21:50:48 +0000 (14:50 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 5 Jun 2009 23:46:20 +0000 (16:46 -0700)
include/ros/memlayout.h
user/roslib/inc/atomic.h [new file with mode: 0644]
user/roslib/src/Makefrag
user/roslib/src/atomic.c [new file with mode: 0644]

index d3d7c98..24be641 100644 (file)
@@ -42,7 +42,7 @@
  *                     |     Per-Process R/O Info     | R-/R-  PGSIZE     |
  * UTOP, UINFO  ---->  +------------------------------+ 0xbec00000      --+
  *                     |      Global Shared Page      | RW/RW  PGSIZE     |
- *      UGDATA  ---->  +------------------------------+ 0xbebff000        | 
+ *      UGDATA  ---->  +------------------------------+ 0xbebff000        |
  *                     |  Unmapped (future expansion) | --/--             |
  *                     +------------------------------+ 0xbe801000      PTSIZE
  *                     |     Per-Process R/W Data     | RW/RW  PGSIZE     |
@@ -98,7 +98,7 @@
 #define VPT                    (KERNBASE - PTSIZE)
 #define KSTACKTOP      VPT
 #define KSTKSIZE       (8*PGSIZE)              // size of a kernel stack
-#define ULIM           (KSTACKTOP - PTSIZE) 
+#define ULIM           (KSTACKTOP - PTSIZE)
 
 /*
  * User read-only mappings! Anything below here til UTOP are readonly to user.
 // (should not conflict with other temporary page mappings)
 #define PFTEMP         (UTEMP + PTSIZE - PGSIZE)
 // The location of the user-level STABS data structure
-#define USTABDATA      (PTSIZE / 2)    
+#define USTABDATA      (PTSIZE / 2)
 
 
 #ifndef __ASSEMBLER__
diff --git a/user/roslib/inc/atomic.h b/user/roslib/inc/atomic.h
new file mode 100644 (file)
index 0000000..48627c0
--- /dev/null
@@ -0,0 +1,43 @@
+#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()
+
+/* Ghetto-atomics, stolen from kern/atomic.* */
+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;
+}
+
+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);
+
+
+#endif /* !ROS_INC_ATOMIC_H */
index 00d6e24..3d7e35f 100644 (file)
@@ -15,6 +15,7 @@ USER_ROSLIB_SRC_SRCFILES := $(USER_ROSLIB_SRC_DIR)/console.c \
                             $(USER_ROSLIB_SRC_DIR)/string.c \
                             $(USER_ROSLIB_SRC_DIR)/syscall.c \
                             $(USER_ROSLIB_SRC_DIR)/asynccall.c \
+                            $(USER_ROSLIB_SRC_DIR)/atomic.c \
                             $(USER_ROSLIB_SRC_DIR)/timer.c 
 
 USER_ROSLIB_SRC_OBJFILES := $(patsubst $(USER_ROSLIB_SRC_DIR)/%.c, \
diff --git a/user/roslib/src/atomic.c b/user/roslib/src/atomic.c
new file mode 100644 (file)
index 0000000..d808418
--- /dev/null
@@ -0,0 +1,33 @@
+#include <arch/x86.h>
+
+#include <atomic.h>
+
+void init_barrier(barrier_t* barrier, uint32_t count)
+{
+       barrier->lock = 0;
+       barrier->init_count = count;
+       barrier->current_count = count;
+       barrier->ready = 0;
+}
+
+void reset_barrier(barrier_t* barrier)
+{
+       barrier->current_count = barrier->init_count;
+}
+
+void waiton_barrier(barrier_t* barrier)
+{
+       uint8_t local_ready = barrier->ready;
+
+       spin_lock(&barrier->lock);
+       barrier->current_count--;
+       if (barrier->current_count) {
+               spin_unlock(&barrier->lock);
+               while (barrier->ready == local_ready)
+                       cpu_relax();
+       } else {
+               spin_unlock(&barrier->lock);
+               reset_barrier(barrier);
+               barrier->ready++;
+       }
+}