/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * 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 <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
#include <unistd.h>
#include "byte-order.h"
#include "coverage.h"
/* --version option output. */
static char *program_version;
+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();
}
}
}
+/* 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, 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. */