/*
- * 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)
{
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();
}
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));
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
const char *time)
{
const char *slash = strrchr(argv0, '/');
+
+ assert_single_threaded();
+
program_name = slash ? slash + 1 : argv0;
free(program_version);
}
}
+/* 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.) */
+void
+set_subprogram_name(const char *name)
+{
+ free(subprogram_name_set(xstrdup(name)));
+}
+
/* Returns a pointer to a string describing the program version. The
* caller must not modify or free the returned string.
*/
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;
}
}
+/* 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
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."
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. */