Cleans up run_once and friends (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 19 Dec 2012 19:56:42 +0000 (11:56 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 19 Dec 2012 19:56:42 +0000 (11:56 -0800)
run_once() -> run_once_safe().  The safe one can handle races.  The
others (run_once and init_once) are for known-single-threaded areas.

Reinstall your kernel headers.

kern/include/ros/common.h
user/parlib/slab.c
user/pthread/futex.c

index af2c3e7..ac12bcd 100644 (file)
@@ -119,7 +119,10 @@ static inline bool mult_will_overflow_u64(uint64_t a, uint64_t b)
 // a uint64_t programatically
 #define UINT64(upper, lower) ( (((uint64_t)(upper)) << 32) | (lower) )
 
-#define run_once(func) \
+/* Makes sure func is run exactly once.  Can handle concurrent callers, and
+ * other callers spin til the func is complete. */
+/* TODO: look in to optimizing this, with the initialized check first */
+#define run_once_safe(func) \
 {\
        static atomic_t initializing = FALSE; \
        static bool initialized = FALSE; \
@@ -133,4 +136,26 @@ static inline bool mult_will_overflow_u64(uint64_t a, uint64_t b)
        } \
 }
 
+/* Unprotected, single-threaded version, makes sure func is run exactly once */
+#define run_once(func)                                                         \
+{                                                                              \
+       static bool ran_once = FALSE;                                              \
+       if (!ran_once) {                                                           \
+               func;                                                                  \
+               ran_once = TRUE;                                                       \
+       }                                                                          \
+}
+
+/* Aborts with 'retcmd' if this function has already been called.  Compared to
+ * run_once, this is put at the top of a function that can be called from
+ * multiple sources but should only execute once. */
+#define init_once(retcmd)                                                      \
+{                                                                              \
+       static bool initialized = FALSE;                                           \
+       if (initialized) {                                                         \
+               retcmd;                                                                \
+       }                                                                          \
+       initialized = TRUE;                                                        \
+}
+
 #endif /* ROS_COMMON_H */
index 1c4fc99..7c20e79 100644 (file)
@@ -89,7 +89,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t obj_size,
                                      void (*ctor)(void *, size_t),
                                      void (*dtor)(void *, size_t))
 {
-       run_once(kmem_cache_init());
+       run_once_safe(kmem_cache_init());
        struct kmem_cache *kc = kmem_cache_alloc(&kmem_cache_cache, 0);
        __kmem_cache_create(kc, name, obj_size, align, flags, ctor, dtor);
        return kc;
index 58b4131..381a9ef 100644 (file)
@@ -83,7 +83,7 @@ int futex(int *uaddr, int op, int val, const struct timespec *timeout,
   assert(uaddr2 == NULL);
   assert(val3 == 0);
 
-  run_once(futex_init());
+  run_once_safe(futex_init());
   switch(op) {
     case FUTEX_WAIT:
       return futex_wait(uaddr, val);