Build: Add support for shared libraries and versioning.
[cascardo/ovs.git] / lib / util.c
index 0d1d9a5..1b9eea6 100644 (file)
@@ -30,7 +30,9 @@
 #include "bitmap.h"
 #include "byte-order.h"
 #include "coverage.h"
+#include "ovs-rcu.h"
 #include "ovs-thread.h"
+#include "socket-util.h"
 #include "vlog.h"
 #ifdef HAVE_PTHREAD_SET_NAME_NP
 #include <pthread_np.h>
@@ -41,7 +43,7 @@ VLOG_DEFINE_THIS_MODULE(util);
 COVERAGE_DEFINE(util_xalloc);
 
 /* argv[0] without directory names. */
-const char *program_name;
+char *program_name;
 
 /* Name for the currently running thread or process, for log messages, process
  * listings, and debuggers. */
@@ -188,6 +190,17 @@ BUILD_ASSERT_DECL(CACHE_LINE_SIZE >= MEM_ALIGN);
 void *
 xmalloc_cacheline(size_t size)
 {
+#ifdef HAVE_POSIX_MEMALIGN
+    void *p;
+    int error;
+
+    COVERAGE_INC(util_xalloc);
+    error = posix_memalign(&p, CACHE_LINE_SIZE, size ? size : 1);
+    if (error != 0) {
+        out_of_memory();
+    }
+    return p;
+#else
     void **payload;
     void *base;
 
@@ -210,6 +223,7 @@ xmalloc_cacheline(size_t size)
     *payload = base;
 
     return (char *) payload + MEM_ALIGN;
+#endif
 }
 
 /* Like xmalloc_cacheline() but clears the allocated memory to all zero
@@ -227,9 +241,13 @@ xzalloc_cacheline(size_t size)
 void
 free_cacheline(void *p)
 {
+#ifdef HAVE_POSIX_MEMALIGN
+    free(p);
+#else
     if (p) {
         free(*(void **) ((uintptr_t) p - MEM_ALIGN));
     }
+#endif
 }
 
 char *
@@ -437,25 +455,31 @@ void
 set_program_name__(const char *argv0, const char *version, const char *date,
                    const char *time)
 {
-#ifdef _WIN32
     char *basename;
+#ifdef _WIN32
     size_t max_len = strlen(argv0) + 1;
 
-    if (program_name) {
-        return;
-    }
+    SetErrorMode(GetErrorMode() | SEM_NOGPFAULTERRORBOX);
+    _set_output_format(_TWO_DIGIT_EXPONENT);
+
     basename = xmalloc(max_len);
     _splitpath_s(argv0, NULL, 0, NULL, 0, basename, max_len, NULL, 0);
-    assert_single_threaded();
-    program_name = basename;
 #else
     const char *slash = strrchr(argv0, '/');
-    assert_single_threaded();
-    program_name = slash ? slash + 1 : argv0;
+    basename = xstrdup(slash ? slash + 1 : argv0);
 #endif
 
-    free(program_version);
+    assert_single_threaded();
+    free(program_name);
+    /* Remove libtool prefix, if it is there */
+    if (strncmp(basename, "lt-", 3) == 0) {
+        char *tmp_name = basename;
+        basename = xstrdup(basename + 3);
+        free(tmp_name);
+    }
+    program_name = basename;
 
+    free(program_version);
     if (!strcmp(version, VERSION)) {
         program_version = xasprintf("%s (Open vSwitch) "VERSION"\n"
                                     "Compiled %s %s\n",
@@ -612,6 +636,20 @@ str_to_llong(const char *s, int base, long long *x)
     }
 }
 
+bool
+str_to_uint(const char *s, int base, unsigned int *u)
+{
+    long long ll;
+    bool ok = str_to_llong(s, base, &ll);
+    if (!ok || ll < 0 || ll > UINT_MAX) {
+       *u = 0;
+       return false;
+    } else {
+       *u = ll;
+       return true;
+    }
+}
+
 /* Converts floating-point string 's' into a double.  If successful, stores
  * the double in '*d' and returns true; on failure, stores 0 in '*d' and
  * returns false.
@@ -669,29 +707,25 @@ hexit_value(int c)
 }
 
 /* Returns the integer value of the 'n' hexadecimal digits starting at 's', or
- * UINT_MAX if one of those "digits" is not really a hex digit.  If 'ok' is
- * nonnull, '*ok' is set to true if the conversion succeeds or to false if a
- * non-hex digit is detected. */
-unsigned int
+ * UINTMAX_MAX if one of those "digits" is not really a hex digit.  Sets '*ok'
+ * to true if the conversion succeeds or to false if a non-hex digit is
+ * detected. */
+uintmax_t
 hexits_value(const char *s, size_t n, bool *ok)
 {
-    unsigned int value;
+    uintmax_t value;
     size_t i;
 
     value = 0;
     for (i = 0; i < n; i++) {
         int hexit = hexit_value(s[i]);
         if (hexit < 0) {
-            if (ok) {
-                *ok = false;
-            }
-            return UINT_MAX;
+            *ok = false;
+            return UINTMAX_MAX;
         }
         value = (value << 4) + hexit;
     }
-    if (ok) {
-        *ok = true;
-    }
+    *ok = true;
     return value;
 }
 
@@ -738,6 +772,7 @@ all_slashes_name(const char *s)
                    : ".");
 }
 
+#ifndef _WIN32
 /* Returns the directory name portion of 'file_name' as a malloc()'d string,
  * similar to the POSIX dirname() function but thread-safe. */
 char *
@@ -779,6 +814,7 @@ base_name(const char *file_name)
 
     return xmemdup0(file_name + start, end - start);
 }
+#endif /* _WIN32 */
 
 /* If 'file_name' starts with '/', returns a copy of 'file_name'.  Otherwise,
  * returns an absolute path to 'file_name' considering it relative to 'dir',
@@ -915,7 +951,7 @@ english_list_delimiter(size_t index, size_t total)
 }
 
 /* Returns the number of trailing 0-bits in 'n'.  Undefined if 'n' == 0. */
-#if __GNUC__ >= 4
+#if __GNUC__ >= 4 || _MSC_VER
 /* Defined inline in util.h. */
 #else
 /* Returns the number of trailing 0-bits in 'n'.  Undefined if 'n' == 0. */
@@ -991,8 +1027,9 @@ const uint8_t count_1bits_8[256] = {
 
 /* Returns true if the 'n' bytes starting at 'p' are zeros. */
 bool
-is_all_zeros(const uint8_t *p, size_t n)
+is_all_zeros(const void *p_, size_t n)
 {
+    const uint8_t *p = p_;
     size_t i;
 
     for (i = 0; i < n; i++) {
@@ -1005,8 +1042,9 @@ is_all_zeros(const uint8_t *p, size_t n)
 
 /* Returns true if the 'n' bytes starting at 'p' are 0xff. */
 bool
-is_all_ones(const uint8_t *p, size_t n)
+is_all_ones(const void *p_, size_t n)
 {
+    const uint8_t *p = p_;
     size_t i;
 
     for (i = 0; i < n; i++) {
@@ -1237,6 +1275,35 @@ bitwise_is_all_zeros(const void *p_, unsigned int len, unsigned int ofs,
     return true;
 }
 
+/* Scans the bits in 'p' that have bit offsets 'start' through 'end'
+ * (inclusive) for the first bit with value 'target'.  If one is found, returns
+ * its offset, otherwise 'end'.  'p' is 'len' bytes long.
+ *
+ * If you consider all of 'p' 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 p[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 p[len - 2], and so on.
+ *
+ * Required invariant:
+ *   start <= end
+ */
+unsigned int
+bitwise_scan(const void *p_, unsigned int len, bool target, unsigned int start,
+             unsigned int end)
+{
+    const uint8_t *p = p_;
+    unsigned int ofs;
+
+    for (ofs = start; ofs < end; ofs++) {
+        bool bit = (p[len - (ofs / 8 + 1)] & (1u << (ofs % 8))) != 0;
+        if (bit == target) {
+            break;
+        }
+    }
+    return ofs;
+}
+
+
 /* 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.
  *
@@ -1726,6 +1793,18 @@ exit:
     return ok;
 }
 
+void
+xsleep(unsigned int seconds)
+{
+    ovsrcu_quiesce_start();
+#ifdef _WIN32
+    Sleep(seconds * 1000);
+#else
+    sleep(seconds);
+#endif
+    ovsrcu_quiesce_end();
+}
+
 #ifdef _WIN32
 \f
 char *
@@ -1758,4 +1837,14 @@ ftruncate(int fd, off_t length)
     }
     return 0;
 }
+
+OVS_CONSTRUCTOR(winsock_start) {
+    WSADATA wsaData;
+    int error;
+
+    error = WSAStartup(MAKEWORD(2, 2), &wsaData);
+    if (error != 0) {
+        VLOG_FATAL("WSAStartup failed: %s", sock_strerror(sock_errno()));
+   }
+}
 #endif