configure: Distinguish glibc and NetBSD pthread_setname_np() variants.
[sliver-openvswitch.git] / lib / util.c
index dfdc51e..1751c6f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #include <config.h>
 #include "util.h"
-#include <assert.h>
 #include <errno.h>
 #include <limits.h>
+#include <pthread.h>
 #include <stdarg.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
 #include <unistd.h>
 #include "byte-order.h"
 #include "coverage.h"
-#include "openvswitch/types.h"
+#include "ovs-thread.h"
 #include "vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(util);
 
 COVERAGE_DEFINE(util_xalloc);
 
+/* argv[0] without directory names. */
 const char *program_name;
+
+/* Name for the currently running thread or process, for log messages, process
+ * listings, and debuggers. */
+DEFINE_PER_THREAD_MALLOCED_DATA(char *, subprogram_name);
+
+/* --version option output. */
 static char *program_version;
 
+/* Buffer used by ovs_strerror(). */
+DEFINE_PER_THREAD_DATA(struct { char s[128]; }, strerror_buffer, { "" });
+
+void
+ovs_assert_failure(const char *where, const char *function,
+                   const char *condition)
+{
+    /* Prevent an infinite loop (or stack overflow) in case VLOG_ABORT happens
+     * to trigger an assertion failure of its own. */
+    static int reentry = 0;
+
+    switch (reentry++) {
+    case 0:
+        VLOG_ABORT("%s: assertion %s failed in %s()",
+                   where, condition, function);
+        NOT_REACHED();
+
+    case 1:
+        fprintf(stderr, "%s: assertion %s failed in %s()",
+                where, condition, function);
+        abort();
+
+    default:
+        abort();
+    }
+}
+
 void
 out_of_memory(void)
 {
@@ -192,9 +227,14 @@ ovs_abort(int err_no, const char *format, ...)
     va_list args;
 
     va_start(args, format);
-    ovs_error_valist(err_no, format, args);
-    va_end(args);
+    ovs_abort_valist(err_no, format, args);
+}
 
+/* Same as ovs_abort() except that the arguments are supplied as a va_list. */
+void
+ovs_abort_valist(int err_no, const char *format, va_list args)
+{
+    ovs_error_valist(err_no, format, args);
     abort();
 }
 
@@ -241,9 +281,15 @@ ovs_error(int err_no, const char *format, ...)
 void
 ovs_error_valist(int err_no, const char *format, va_list args)
 {
+    const char *subprogram_name = get_subprogram_name();
     int save_errno = errno;
 
-    fprintf(stderr, "%s: ", program_name);
+    if (subprogram_name[0]) {
+        fprintf(stderr, "%s(%s): ", program_name, subprogram_name);
+    } else {
+        fprintf(stderr, "%s: ", program_name);
+    }
+
     vfprintf(stderr, format, args);
     if (err_no != 0) {
         fprintf(stderr, " (%s)", ovs_retval_to_string(err_no));
@@ -265,40 +311,103 @@ ovs_error_valist(int err_no, const char *format, va_list args)
 const char *
 ovs_retval_to_string(int retval)
 {
-    static char unknown[48];
+    return (!retval ? ""
+            : retval == EOF ? "End of file"
+            : ovs_strerror(retval));
+}
+
+const char *
+ovs_strerror(int error)
+{
+    enum { BUFSIZE = sizeof strerror_buffer_get()->s };
+    int save_errno;
+    char *buffer;
+    char *s;
 
-    if (!retval) {
-        return "";
-    }
-    if (retval > 0) {
-        return strerror(retval);
-    }
-    if (retval == EOF) {
-        return "End of file";
+    save_errno = errno;
+    buffer = strerror_buffer_get()->s;
+
+#if STRERROR_R_CHAR_P
+    /* GNU style strerror_r() might return an immutable static string, or it
+     * might write and return 'buffer', but in either case we can pass the
+     * returned string directly to the caller. */
+    s = strerror_r(error, buffer, BUFSIZE);
+#else  /* strerror_r() returns an int. */
+    s = buffer;
+    if (strerror_r(error, buffer, BUFSIZE)) {
+        /* strerror_r() is only allowed to fail on ERANGE (because the buffer
+         * is too short).  We don't check the actual failure reason because
+         * POSIX requires strerror_r() to return the error but old glibc
+         * (before 2.13) returns -1 and sets errno. */
+        snprintf(buffer, BUFSIZE, "Unknown error %d", error);
     }
-    snprintf(unknown, sizeof unknown, "***unknown return value: %d***", retval);
-    return unknown;
+#endif
+
+    errno = save_errno;
+
+    return s;
 }
 
 /* Sets global "program_name" and "program_version" variables.  Should
  * be called at the beginning of main() with "argv[0]" as the argument
  * to 'argv0'.
  *
+ * 'version' should contain the version of the caller's program.  If 'version'
+ * is the same as the VERSION #define, the caller is assumed to be part of Open
+ * vSwitch.  Otherwise, it is assumed to be an external program linking against
+ * the Open vSwitch libraries.
+ *
  * The 'date' and 'time' arguments should likely be called with
  * "__DATE__" and "__TIME__" to use the time the binary was built.
  * Alternatively, the "set_program_name" macro may be called to do this
  * automatically.
  */
 void
-set_program_name__(const char *argv0, const char *date, const char *time)
+set_program_name__(const char *argv0, const char *version, const char *date,
+                   const char *time)
 {
     const char *slash = strrchr(argv0, '/');
+
+    assert_single_threaded();
+
     program_name = slash ? slash + 1 : argv0;
 
     free(program_version);
-    program_version = xasprintf("%s (Open vSwitch) "VERSION BUILDNR"\n"
-                                "Compiled %s %s\n",
-                                program_name, date, time);
+
+    if (!strcmp(version, VERSION)) {
+        program_version = xasprintf("%s (Open vSwitch) "VERSION"\n"
+                                    "Compiled %s %s\n",
+                                    program_name, date, time);
+    } else {
+        program_version = xasprintf("%s %s\n"
+                                    "Open vSwitch Library "VERSION"\n"
+                                    "Compiled %s %s\n",
+                                    program_name, version, date, time);
+    }
+}
+
+/* Returns the name of the currently running thread or process. */
+const char *
+get_subprogram_name(void)
+{
+    const char *name = subprogram_name_get();
+    return name ? name : "";
+}
+
+/* Sets 'name' as the name of the currently running thread or process.  (This
+ * appears in log messages and may also be visible in system process listings
+ * and debuggers.) */
+void
+set_subprogram_name(const char *name)
+{
+    free(subprogram_name_set(xstrdup(name)));
+#if HAVE_GLIBC_PTHREAD_SETNAME_NP
+    pthread_setname_np(pthread_self(), name);
+#elif HAVE_NETBSD_PTHREAD_SETNAME_NP
+    pthread_setname_np(pthread_self(), "%s", name);
+#elif HAVE_PTHREAD_SET_NAME_NP
+    pthread_set_name_np(pthread_self(), name);
+#endif
 }
 
 /* Returns a pointer to a string describing the program version.  The
@@ -532,7 +641,7 @@ get_cwd(void)
             int error = errno;
             free(buf);
             if (error != ERANGE) {
-                VLOG_WARN("getcwd failed (%s)", strerror(error));
+                VLOG_WARN("getcwd failed (%s)", ovs_strerror(error));
                 return NULL;
             }
             size *= 2;
@@ -616,6 +725,91 @@ abs_file_name(const char *dir, const char *file_name)
     }
 }
 
+/* Like readlink(), but returns the link name as a null-terminated string in
+ * allocated memory that the caller must eventually free (with free()).
+ * Returns NULL on error, in which case errno is set appropriately. */
+char *
+xreadlink(const char *filename)
+{
+    size_t size;
+
+    for (size = 64; ; size *= 2) {
+        char *buf = xmalloc(size);
+        ssize_t retval = readlink(filename, buf, size);
+        int error = errno;
+
+        if (retval >= 0 && retval < size) {
+            buf[retval] = '\0';
+            return buf;
+        }
+
+        free(buf);
+        if (retval < 0) {
+            errno = error;
+            return NULL;
+        }
+    }
+}
+
+/* Returns a version of 'filename' with symlinks in the final component
+ * dereferenced.  This differs from realpath() in that:
+ *
+ *     - 'filename' need not exist.
+ *
+ *     - If 'filename' does exist as a symlink, its referent need not exist.
+ *
+ *     - Only symlinks in the final component of 'filename' are dereferenced.
+ *
+ * The caller must eventually free the returned string (with free()). */
+char *
+follow_symlinks(const char *filename)
+{
+    struct stat s;
+    char *fn;
+    int i;
+
+    fn = xstrdup(filename);
+    for (i = 0; i < 10; i++) {
+        char *linkname;
+        char *next_fn;
+
+        if (lstat(fn, &s) != 0 || !S_ISLNK(s.st_mode)) {
+            return fn;
+        }
+
+        linkname = xreadlink(fn);
+        if (!linkname) {
+            VLOG_WARN("%s: readlink failed (%s)",
+                      filename, ovs_strerror(errno));
+            return fn;
+        }
+
+        if (linkname[0] == '/') {
+            /* Target of symlink is absolute so use it raw. */
+            next_fn = linkname;
+        } else {
+            /* Target of symlink is relative so add to 'fn''s directory. */
+            char *dir = dir_name(fn);
+
+            if (!strcmp(dir, ".")) {
+                next_fn = linkname;
+            } else {
+                char *separator = dir[strlen(dir) - 1] == '/' ? "" : "/";
+                next_fn = xasprintf("%s%s%s", dir, separator, linkname);
+                free(linkname);
+            }
+
+            free(dir);
+        }
+
+        free(fn);
+        fn = next_fn;
+    }
+
+    VLOG_WARN("%s: too many levels of symlinks", filename);
+    free(fn);
+    return xstrdup(filename);
+}
 
 /* Pass a value to this function if it is marked with
  * __attribute__((warn_unused_result)) and you genuinely want to ignore
@@ -640,7 +834,7 @@ english_list_delimiter(size_t index, size_t total)
 int
 log_2_floor(uint32_t n)
 {
-    assert(n);
+    ovs_assert(n);
 
 #if !defined(UINT_MAX) || !defined(UINT32_MAX)
 #error "Someone screwed up the #includes."
@@ -671,40 +865,70 @@ log_2_floor(uint32_t n)
 int
 log_2_ceil(uint32_t n)
 {
-    return log_2_floor(n) + !IS_POW2(n);
+    return log_2_floor(n) + !is_pow2(n);
 }
 
-/* Returns the number of trailing 0-bits in 'n', or 32 if 'n' is 0. */
-int
-ctz(uint32_t n)
-{
-    if (!n) {
-        return 32;
-    } else {
+/* Returns the number of trailing 0-bits in 'n'.  Undefined if 'n' == 0. */
 #if !defined(UINT_MAX) || !defined(UINT32_MAX)
 #error "Someone screwed up the #includes."
 #elif __GNUC__ >= 4 && UINT_MAX == UINT32_MAX
-        return __builtin_ctz(n);
+/* Defined inline in util.h. */
 #else
-        unsigned int k;
-        int count = 31;
+static int
+raw_ctz(uint32_t n)
+{
+    unsigned int k;
+    int count = 31;
 
 #define CTZ_STEP(X)                             \
-        k = n << (X);                           \
-        if (k) {                                \
-            count -= X;                         \
-            n = k;                              \
-        }
-        CTZ_STEP(16);
-        CTZ_STEP(8);
-        CTZ_STEP(4);
-        CTZ_STEP(2);
-        CTZ_STEP(1);
+    k = n << (X);                               \
+    if (k) {                                    \
+        count -= X;                             \
+        n = k;                                  \
+    }
+    CTZ_STEP(16);
+    CTZ_STEP(8);
+    CTZ_STEP(4);
+    CTZ_STEP(2);
+    CTZ_STEP(1);
 #undef CTZ_STEP
 
-        return count;
+    return count;
+}
 #endif
-    }
+
+/* Returns the number of 1-bits in 'x', between 0 and 32 inclusive. */
+unsigned int
+popcount(uint32_t x)
+{
+    /* In my testing, this implementation is over twice as fast as any other
+     * portable implementation that I tried, including GCC 4.4
+     * __builtin_popcount(), although nonportable asm("popcnt") was over 50%
+     * faster. */
+#define INIT1(X)                                \
+    ((((X) & (1 << 0)) != 0) +                  \
+     (((X) & (1 << 1)) != 0) +                  \
+     (((X) & (1 << 2)) != 0) +                  \
+     (((X) & (1 << 3)) != 0) +                  \
+     (((X) & (1 << 4)) != 0) +                  \
+     (((X) & (1 << 5)) != 0) +                  \
+     (((X) & (1 << 6)) != 0) +                  \
+     (((X) & (1 << 7)) != 0))
+#define INIT2(X)   INIT1(X),  INIT1((X) +  1)
+#define INIT4(X)   INIT2(X),  INIT2((X) +  2)
+#define INIT8(X)   INIT4(X),  INIT4((X) +  4)
+#define INIT16(X)  INIT8(X),  INIT8((X) +  8)
+#define INIT32(X) INIT16(X), INIT16((X) + 16)
+#define INIT64(X) INIT32(X), INIT32((X) + 32)
+
+    static const uint8_t popcount8[256] = {
+        INIT64(0), INIT64(64), INIT64(128), INIT64(192)
+    };
+
+    return (popcount8[x & 0xff] +
+            popcount8[(x >> 8) & 0xff] +
+            popcount8[(x >> 16) & 0xff] +
+            popcount8[x >> 24]);
 }
 
 /* Returns true if the 'n' bytes starting at 'p' are zeros. */
@@ -851,6 +1075,110 @@ bitwise_zero(void *dst_, unsigned int dst_len, unsigned dst_ofs,
     }
 }
 
+/* Sets to 1 all of the 'n_bits' bits starting from bit 'dst_ofs' in 'dst'.
+ * 'dst' is 'dst_len' bytes long.
+ *
+ * If you consider all of 'dst' to be a single unsigned integer in network byte
+ * order, then bit N is the bit with value 2**N.  That is, bit 0 is the bit
+ * with value 1 in dst[dst_len - 1], bit 1 is the bit with value 2, bit 2 is
+ * the bit with value 4, ..., bit 8 is the bit with value 1 in dst[dst_len -
+ * 2], and so on.
+ *
+ * Required invariant:
+ *   dst_ofs + n_bits <= dst_len * 8
+ */
+void
+bitwise_one(void *dst_, unsigned int dst_len, unsigned dst_ofs,
+            unsigned int n_bits)
+{
+    uint8_t *dst = dst_;
+
+    if (!n_bits) {
+        return;
+    }
+
+    dst += dst_len - (dst_ofs / 8 + 1);
+    dst_ofs %= 8;
+
+    if (dst_ofs) {
+        unsigned int chunk = MIN(n_bits, 8 - dst_ofs);
+
+        *dst |= ((1 << chunk) - 1) << dst_ofs;
+
+        n_bits -= chunk;
+        if (!n_bits) {
+            return;
+        }
+
+        dst--;
+    }
+
+    while (n_bits >= 8) {
+        *dst-- = 0xff;
+        n_bits -= 8;
+    }
+
+    if (n_bits) {
+        *dst |= (1 << n_bits) - 1;
+    }
+}
+
+/* Scans the 'n_bits' bits starting from bit 'dst_ofs' in 'dst' for 1-bits.
+ * Returns false if any 1-bits are found, otherwise true.  'dst' is 'dst_len'
+ * bytes long.
+ *
+ * If you consider all of 'dst' to be a single unsigned integer in network byte
+ * order, then bit N is the bit with value 2**N.  That is, bit 0 is the bit
+ * with value 1 in dst[dst_len - 1], bit 1 is the bit with value 2, bit 2 is
+ * the bit with value 4, ..., bit 8 is the bit with value 1 in dst[dst_len -
+ * 2], and so on.
+ *
+ * Required invariant:
+ *   dst_ofs + n_bits <= dst_len * 8
+ */
+bool
+bitwise_is_all_zeros(const void *p_, unsigned int len, unsigned int ofs,
+                     unsigned int n_bits)
+{
+    const uint8_t *p = p_;
+
+    if (!n_bits) {
+        return true;
+    }
+
+    p += len - (ofs / 8 + 1);
+    ofs %= 8;
+
+    if (ofs) {
+        unsigned int chunk = MIN(n_bits, 8 - ofs);
+
+        if (*p & (((1 << chunk) - 1) << ofs)) {
+            return false;
+        }
+
+        n_bits -= chunk;
+        if (!n_bits) {
+            return true;
+        }
+
+        p--;
+    }
+
+    while (n_bits >= 8) {
+        if (*p) {
+            return false;
+        }
+        n_bits -= 8;
+        p--;
+    }
+
+    if (n_bits && *p & ((1 << n_bits) - 1)) {
+        return false;
+    }
+
+    return true;
+}
+
 /* Copies the 'n_bits' low-order bits of 'value' into the 'n_bits' bits
  * starting at bit 'dst_ofs' in 'dst', which is 'dst_len' bytes long.
  *