util: Make raw_ctz() accept 64-bit integers.
[sliver-openvswitch.git] / lib / util.h
index c436a43..91dc0a5 100644 (file)
@@ -86,10 +86,24 @@ void ovs_assert_failure(const char *, const char *, const char *) NO_RETURN;
      (TYPE) (POINTER))
 
 extern const char *program_name;
-extern const char *subprogram_name;
+
+#define __ARRAY_SIZE_NOCHECK(ARRAY) (sizeof(ARRAY) / sizeof((ARRAY)[0]))
+#ifdef __GNUC__
+/* return 0 for array types, 1 otherwise */
+#define __ARRAY_CHECK(ARRAY)                                   \
+    !__builtin_types_compatible_p(typeof(ARRAY), typeof(&ARRAY[0]))
+
+/* compile-time fail if not array */
+#define __ARRAY_FAIL(ARRAY) (sizeof(char[-2*!__ARRAY_CHECK(ARRAY)]))
+#define __ARRAY_SIZE(ARRAY)                                    \
+    __builtin_choose_expr(__ARRAY_CHECK(ARRAY),                        \
+        __ARRAY_SIZE_NOCHECK(ARRAY), __ARRAY_FAIL(ARRAY))
+#else
+#define __ARRAY_SIZE(ARRAY) __ARRAY_SIZE_NOCHECK(ARRAY)
+#endif
 
 /* Returns the number of elements in ARRAY. */
-#define ARRAY_SIZE(ARRAY) (sizeof ARRAY / sizeof *ARRAY)
+#define ARRAY_SIZE(ARRAY) __ARRAY_SIZE(ARRAY)
 
 /* Returns X / Y, rounding up.  X must be nonnegative to round correctly. */
 #define DIV_ROUND_UP(X, Y) (((X) + ((Y) - 1)) / (Y))
@@ -109,6 +123,25 @@ is_pow2(uintmax_t x)
     return IS_POW2(x);
 }
 
+/* Returns X rounded up to a power of 2.  X must be a constant expression. */
+#define ROUND_UP_POW2(X) RUP2__(X)
+#define RUP2__(X) (RUP2_1(X) + 1)
+#define RUP2_1(X) (RUP2_2(X) | (RUP2_2(X) >> 16))
+#define RUP2_2(X) (RUP2_3(X) | (RUP2_3(X) >> 8))
+#define RUP2_3(X) (RUP2_4(X) | (RUP2_4(X) >> 4))
+#define RUP2_4(X) (RUP2_5(X) | (RUP2_5(X) >> 2))
+#define RUP2_5(X) (RUP2_6(X) | (RUP2_6(X) >> 1))
+#define RUP2_6(X) ((X) - 1)
+
+/* Returns X rounded down to a power of 2.  X must be a constant expression. */
+#define ROUND_DOWN_POW2(X) RDP2__(X)
+#define RDP2__(X) (RDP2_1(X) - (RDP2_1(X) >> 1))
+#define RDP2_1(X) (RDP2_2(X) | (RDP2_2(X) >> 16))
+#define RDP2_2(X) (RDP2_3(X) | (RDP2_3(X) >> 8))
+#define RDP2_3(X) (RDP2_4(X) | (RDP2_4(X) >> 4))
+#define RDP2_4(X) (RDP2_5(X) | (RDP2_5(X) >> 2))
+#define RDP2_5(X) (      (X) | (      (X) >> 1))
+
 #ifndef MIN
 #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
 #endif
@@ -171,9 +204,13 @@ is_pow2(uintmax_t x)
  * that that OBJECT points to, assigns the address of the outer object to
  * OBJECT, which must be an lvalue.
  *
- * Evaluates to 1. */
+ * Evaluates to (void) 0 as the result is not to be used. */
 #define ASSIGN_CONTAINER(OBJECT, POINTER, MEMBER) \
-    ((OBJECT) = OBJECT_CONTAINING(POINTER, OBJECT, MEMBER), 1)
+    ((OBJECT) = OBJECT_CONTAINING(POINTER, OBJECT, MEMBER), (void) 0)
+
+/* Given ATTR, and TYPE, cast the ATTR to TYPE by first casting ATTR to
+ * (void *). This is to suppress the alignment warning issued by clang. */
+#define ALIGNED_CAST(TYPE, ATTR) ((TYPE) (void *) (ATTR))
 
 #ifdef  __cplusplus
 extern "C" {
@@ -184,6 +221,9 @@ void set_program_name__(const char *name, const char *version,
 #define set_program_name(name) \
         set_program_name__(name, VERSION, __DATE__, __TIME__)
 
+const char *get_subprogram_name(void);
+void set_subprogram_name(const char *format, ...) PRINTF_FORMAT(1, 2);
+
 const char *get_program_version(void);
 void ovs_print_version(uint8_t min_ofp, uint8_t max_ofp);
 
@@ -214,6 +254,7 @@ void ovs_error(int err_no, const char *format, ...) PRINTF_FORMAT(2, 3);
 void ovs_error_valist(int err_no, const char *format, va_list)
     PRINTF_FORMAT(2, 0);
 const char *ovs_retval_to_string(int);
+const char *ovs_strerror(int);
 void ovs_hex_dump(FILE *, const void *, size_t, uintptr_t offset, bool ascii);
 
 bool str_to_int(const char *, int base, int *);
@@ -223,6 +264,8 @@ bool str_to_uint(const char *, int base, unsigned int *);
 bool str_to_ulong(const char *, int base, unsigned long *);
 bool str_to_ullong(const char *, int base, unsigned long long *);
 
+bool ovs_scan(const char *s, const char *template, ...) SCANF_FORMAT(2, 3);
+
 bool str_to_double(const char *, double *);
 
 int hexit_value(int c);
@@ -242,20 +285,40 @@ void ignore(bool x OVS_UNUSED);
 \f
 /* Bitwise tests. */
 
-/* Returns the number of trailing 0-bits in 'n'.  Undefined if 'n' == 0.
- *
- * This compiles to a single machine instruction ("bsf") with GCC on x86. */
-#if !defined(UINT_MAX) || !defined(UINT32_MAX)
-#error "Someone screwed up the #includes."
-#elif __GNUC__ >= 4 && UINT_MAX == UINT32_MAX
+int log_2_floor(uint32_t);
+int log_2_ceil(uint32_t);
+unsigned int popcount(uint32_t);
+
+/* Returns the number of trailing 0-bits in 'n'.  Undefined if 'n' == 0. */
+#if __GNUC__ >= 4
 static inline int
-raw_ctz(uint32_t n)
+raw_ctz(uint64_t n)
 {
-    return __builtin_ctz(n);
+    /* With GCC 4.7 on 32-bit x86, if a 32-bit integer is passed as 'n', using
+     * a plain __builtin_ctzll() here always generates an out-of-line function
+     * call.  The test below helps it to emit a single 'bsf' instruction. */
+    return (__builtin_constant_p(n <= UINT32_MAX) && n <= UINT32_MAX
+            ? __builtin_ctz(n)
+            : __builtin_ctzll(n));
 }
 #else
 /* Defined in util.c. */
-int raw_ctz(uint32_t n);
+int raw_ctz(uint64_t n);
+#endif
+
+#if __GNUC__ >= 4
+static inline int
+popcount64(uint64_t n)
+{
+    return __builtin_popcountll(n);
+}
+#else
+/* Defined using the 32-bit counterparts. */
+static inline int
+popcount64(uint64_t n)
+{
+    return popcount(n) + popcount(n >> 32);
+}
 #endif
 
 /* Returns the number of trailing 0-bits in 'n', or 32 if 'n' is 0. */
@@ -265,9 +328,12 @@ ctz(uint32_t n)
     return n ? raw_ctz(n) : 32;
 }
 
-int log_2_floor(uint32_t);
-int log_2_ceil(uint32_t);
-unsigned int popcount(uint32_t);
+/* Returns the number of trailing 0-bits in 'n', or 64 if 'n' is 0. */
+static inline int
+ctz64(uint64_t n)
+{
+    return n ? raw_ctz(n) : 64;
+}
 
 /* Returns the rightmost 1-bit in 'x' (e.g. 01011000 => 00001000), or 0 if 'x'
  * is 0. */