ROUNDDOWN can handle uint64_t on 32 bit (XCC)
[akaros.git] / kern / include / ros / common.h
index 331a14f..46d2fa9 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef ROS_COMMON_H
 #define ROS_COMMON_H
 
+#ifndef __ASSEMBLER__
 #ifndef __IVY__
 #include <ros/noivy.h>
 #endif
@@ -8,11 +9,11 @@
 #include <stddef.h>
 #include <stdint.h>
 #include <sys/types.h>
+#include <stdbool.h>
 
 typedef uintptr_t physaddr_t;
-typedef ssize_t intreg_t;
-typedef size_t uintreg_t;
-typedef int bool;
+typedef long intreg_t;
+typedef unsigned long uintreg_t;
 
 #ifndef NULL
 #define NULL ((void*) 0)
@@ -32,6 +33,7 @@ typedef int bool;
        for (int _var = 0, var = (next); _var < (size); _var++, var = (var + 1) % (size))
 
 // Efficient min and max operations
+#ifdef ROS_KERNEL /* Glibc has their own */
 #define MIN(_a, _b)                                            \
 ({                                                             \
        typeof(_a) __a = (_a);                                  \
@@ -44,40 +46,68 @@ typedef int bool;
        typeof(_b) __b = (_b);                                  \
        __a >= __b ? __a : __b;                                 \
 })
+#endif
 
-// Rounding operations (efficient when n is a power of 2)
-// Round down to the nearest multiple of n
-#define ROUNDDOWN(a, n)                                                \
-({                                                             \
-       uint32_t __a = (uint32_t) (a);                          \
-       (typeof(a)) (__a - __a % (n));                          \
-})
-// Round up to the nearest multiple of n
-#define ROUNDUP(a, n)                                          \
-({                                                             \
-       uint32_t __n = (uint32_t) (n);                          \
-       (typeof(a)) (ROUNDDOWN((uint32_t) (a) + __n - 1, __n)); \
+/* Rounding operations (efficient when n is a power of 2)
+ * Round down to the nearest multiple of n.
+ * The compiler should compile out the branch.  This is needed for 32 bit, so
+ * that we can round down uint64_t, without chopping off the top 32 bits. */
+#define ROUNDDOWN(a, n)                                                        \
+({                                                                             \
+       typeof(a) __b;                                                             \
+       if (sizeof(a) == 8) {                                                      \
+               uint64_t __a = (uint64_t) (a);                                         \
+               __b = (typeof(a)) (__a - __a % (n));                                   \
+       } else {                                                                   \
+               uintptr_t __a = (uintptr_t) (a);                                       \
+               __b = (typeof(a)) (__a - __a % (n));                                   \
+       }                                                                          \
+       __b;                                                                       \
 })
 
-// Round down to the nearest multiple of n
-#define PTRROUNDDOWN(a, n)                                             \
-({                                                             \
-       char * __a = (char *) (a);                              \
-       (typeof(a)) (__a - (uint32_t)__a % (n));                                \
-})
-// Round pointer up to the nearest multiple of n
-#define PTRROUNDUP(a, n)                                               \
-({                                                             \
-       uint32_t __n = (uint32_t) (n);                          \
-       (typeof(a)) (PTRROUNDDOWN((char *) (a) + __n - 1, __n));        \
+/* Round up to the nearest multiple of n */
+#define ROUNDUP(a, n)                                                          \
+({                                                                             \
+       typeof(a) __b;                                                             \
+       if (sizeof(a) == 8) {                                                      \
+               uint64_t __n = (uint64_t) (n);                                         \
+               __b = (typeof(a)) (ROUNDDOWN((uint64_t) (a) + __n - 1, __n));          \
+       } else {                                                                   \
+               uintptr_t __n = (uintptr_t) (n);                                       \
+               __b = (typeof(a)) (ROUNDDOWN((uintptr_t) (a) + __n - 1, __n));         \
+       }                                                                          \
+       __b;                                                                       \
 })
 
+// Return the integer logarithm of the value provided rounded down
+static inline uintptr_t LOG2_DOWN(uintptr_t value)
+{
+       uintptr_t l = 0;
+       while( (value >> l) > 1 ) ++l;
+       return l;
+}
+
 // Return the integer logarithm of the value provided rounded up
-static inline uint32_t LOG2(uint32_t value)
+static inline uintptr_t LOG2_UP(uintptr_t value)
+{
+       uintptr_t _v = LOG2_DOWN(value);
+       if (value ^ (1 << _v))
+               return _v + 1;
+       else
+               return _v;
+}
+
+static inline uintptr_t ROUNDUPPWR2(uintptr_t value)
 {
-    uint32_t l = 0;
-    while( (value >> l) > 1 ) ++l;
-    return l;
+       return 1 << LOG2_UP(value);
+}
+
+/* We wraparound if UINT_MAX < a * b, which is also UINT_MAX / a < b. */
+static inline bool mult_will_overflow_u64(uint64_t a, uint64_t b)
+{
+       if (!a)
+               return FALSE;
+       return (uint64_t)(-1) / a < b;
 }
 
 // Return the offset of 'member' relative to the beginning of a struct type
@@ -85,66 +115,62 @@ static inline uint32_t LOG2(uint32_t value)
 #define offsetof(type, member)  ((size_t) (&((type*)0)->member))
 #endif
 
+/* Return the container/struct holding the object 'ptr' points to */
+#define container_of(ptr, type, member) ({                                     \
+       (type*)((char*)ptr - offsetof(type, member));                             \
+})
+
+/* Force the reading exactly once of x.  You may still need mbs().  See
+ * http://lwn.net/Articles/508991/ for more info. */
+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
+
 // Ivy currently can only handle 63 bits (OCaml thing), so use this to make
 // a uint64_t programatically
 #define UINT64(upper, lower) ( (((uint64_t)(upper)) << 32) | (lower) )
 
+/* Makes sure func is run exactly once.  Can handle concurrent callers, and
+ * other callers spin til the func is complete. */
+#define run_once(func)                                                         \
+{                                                                              \
+       static bool ran_once = FALSE;                                              \
+       static atomic_t is_running = FALSE;                                        \
+       if (!ran_once) {                                                           \
+               if (!atomic_swap(&is_running, TRUE)) {                                 \
+                       /* we won the race and get to run the func */                      \
+                       func;                                                              \
+                       wmb();  /* don't let the ran_once write pass previous writes */    \
+                       ran_once = TRUE;                                                   \
+               } else {                                                               \
+                       /* someone else won, wait til they are done to break out */        \
+                       while (!ran_once)                                                  \
+                               cpu_relax();                                                   \
+                                                                               \
+               }                                                                      \
+       }                                                                          \
+}
 
-/*********************** Bitmask stuff **********************/
-#define BYTES_FOR_BITMASK(size) (((size) - 1) / 8 + 1)
-#define BYTES_FOR_BITMASK_WITH_CHECK(size) ((size) ? ((size) - (1)) / (8) + (1) : (0))
-#define DECL_BITMASK(name, size) uint8_t (name)[BYTES_FOR_BITMASK((size))]
-
-#define GET_BITMASK_BIT(name, bit) (((name)[(bit)/8] & (1 << ((bit) % 8))) ? 1 : 0)
-#define SET_BITMASK_BIT(name, bit) ((name)[(bit)/8] |= (1 << ((bit) % 8)))
-#define CLR_BITMASK_BIT(name, bit) ((name)[(bit)/8] &= ~(1 << ((bit) % 8)))
-#define SET_BITMASK_BIT_ATOMIC(name, bit) (atomic_orb(&(name)[(bit)/8], (1 << ((bit) % 8))))
-#define CLR_BITMASK_BIT_ATOMIC(name, bit) (atomic_andb(&(name)[(bit)/8], ~(1 << ((bit) % 8))))
+/* Unprotected, single-threaded version, makes sure func is run exactly once */
+#define run_once_racy(func)                                                    \
+{                                                                              \
+       static bool ran_once = FALSE;                                              \
+       if (!ran_once) {                                                           \
+               func;                                                                  \
+               ran_once = TRUE;                                                       \
+       }                                                                          \
+}
 
-#define CLR_BITMASK(name, size) \
-({ \
-       {TRUSTEDBLOCK \
-       memset((void*)((uintptr_t)(name)), 0, BYTES_FOR_BITMASK((size))); \
-       } \
-})
+/* 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_racy(retcmd)                                                 \
+{                                                                              \
+       static bool initialized = FALSE;                                           \
+       if (initialized) {                                                         \
+               retcmd;                                                                \
+       }                                                                          \
+       initialized = TRUE;                                                        \
+}
 
-#define FILL_BITMASK(name, size) \
-({ \
-       {TRUSTEDBLOCK \
-       memset((void*)((uintptr_t)(name)), 255, BYTES_FOR_BITMASK((size))); \
-       } \
-       (name)[BYTES_FOR_BITMASK((size))-1] >>= (((size) % 8) ? (8 - ((size) % 8)) : 0 ); \
-}) 
-
-#define COPY_BITMASK(newmask, oldmask, size) \
-({ \
-       {TRUSTEDBLOCK \
-       memcpy((void*)((uintptr_t)(newmask)), \
-           (void*)((uintptr_t)(oldmask)), \
-           BYTES_FOR_BITMASK((size))); \
-       } \
-})
+#endif /* __ASSEMBLER__ */
 
-// this checks the entire last byte, so keep it 0 in the other macros
-#define BITMASK_IS_CLEAR(name, size) ({ \
-       uint32_t __n = BYTES_FOR_BITMASK((size)); \
-       bool clear = 1; \
-       while (__n-- > 0) { \
-               if ((name)[__n]) { \
-                       clear = 0; \
-                       break;\
-               }\
-       } \
-       clear; })
-
-#define PRINT_BITMASK(name, size) { \
-       int i;  \
-       for (i = 0; i < BYTES_FOR_BITMASK(size); i++) { \
-               int j;  \
-               for (j = 0; j < 8; j++) \
-                       printk("%x", ((name)[i] >> j) & 1);     \
-       } \
-       printk("\n"); \
-}
-/**************************************************************/
 #endif /* ROS_COMMON_H */