#define ALWAYS_INLINE __attribute__((always_inline))
#define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
#define SENTINEL(N) __attribute__((sentinel(N)))
+#define OVS_LIKELY(CONDITION) __builtin_expect(!!(CONDITION), 1)
+#define OVS_UNLIKELY(CONDITION) __builtin_expect(!!(CONDITION), 0)
#else
#define NO_RETURN
#define OVS_UNUSED
#define ALWAYS_INLINE
#define WARN_UNUSED_RESULT
#define SENTINEL(N)
+#define OVS_LIKELY(CONDITION) (!!(CONDITION))
+#define OVS_UNLIKELY(CONDITION) (!!(CONDITION))
#endif
/* ISO C says that a C implementation may choose any integer type for an enum
/*
- * 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>
/* --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)
{
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."
#define BUILD_ASSERT_DECL_GCCONLY(EXPR) ((void) 0)
#endif
+/* Like the standard assert macro, except:
+ *
+ * - Writes the failure message to the log.
+ *
+ * - Not affected by NDEBUG. */
+#define ovs_assert(CONDITION) \
+ if (!OVS_LIKELY(CONDITION)) { \
+ ovs_assert_failure(SOURCE_LOCATOR, __func__, #CONDITION); \
+ }
+void ovs_assert_failure(const char *, const char *, const char *) NO_RETURN;
+
/* Casts 'pointer' to 'type' and issues a compiler warning if the cast changes
* anything other than an outermost "const" or "volatile" qualifier.
*
cd 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
AT_CHECK([test-unix-socket ../012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/socket socket])
AT_CLEANUP
+
+AT_SETUP([ovs_assert])
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+AT_CHECK([test-util -voff -vfile:info '-vPATTERN:file:%c|%p|%m' --log-file assert || kill -l $?],
+ [0], [ABRT
+], [stderr])
+
+AT_CHECK([sed 's/\(opened log file\) .*/\1/
+s/|[[^|]]*: /|/' test-util.log], [0], [dnl
+vlog|INFO|opened log file
+util|EMER|assertion false failed in test_assert()
+])
+
+AT_CHECK([sed 's/.*: //
+1q' stderr], [0],
+ [assertion false failed in test_assert()
+])
+
+AT_CLEANUP
#include <config.h>
+#include <getopt.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include "command-line.h"
#include "random.h"
#include "util.h"
+#include "vlog.h"
#undef NDEBUG
#include <assert.h>
free(target);
}
}
+
+static void
+test_assert(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
+{
+ ovs_assert(false);
+}
\f
static const struct command commands[] = {
{"ctz", 0, 0, test_ctz},
{"bitwise_one", 0, 0, test_bitwise_one},
{"bitwise_is_all_zeros", 0, 0, test_bitwise_is_all_zeros},
{"follow-symlinks", 1, INT_MAX, test_follow_symlinks},
+ {"assert", 0, 0, test_assert},
{NULL, 0, 0, NULL},
};
+static void
+parse_options(int argc, char *argv[])
+{
+ enum {
+ VLOG_OPTION_ENUMS
+ };
+ static struct option long_options[] = {
+ VLOG_LONG_OPTIONS,
+ {NULL, 0, NULL, 0},
+ };
+ char *short_options = long_options_to_short_options(long_options);
+
+ for (;;) {
+ int c = getopt_long(argc, argv, short_options, long_options, NULL);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ VLOG_OPTION_HANDLERS
+
+ case '?':
+ exit(EXIT_FAILURE);
+
+ default:
+ abort();
+ }
+ }
+ free(short_options);
+}
+
int
main(int argc, char *argv[])
{
set_program_name(argv[0]);
- run_command(argc - 1, argv + 1, commands);
+ parse_options(argc, argv);
+ run_command(argc - optind, argv + optind, commands);
return 0;
}