diff options
author | Ben Pfaff <blp@nicira.com> | 2013-06-19 13:07:35 -0700 |
---|---|---|
committer | Ben Pfaff <blp@nicira.com> | 2013-06-28 16:09:37 -0700 |
commit | 728a8b141ff670d0b98b61bd88a6bb7a9c719e26 (patch) | |
tree | 992f96dc5d314fccae032d15ede60e68c66fdefb /lib/ovs-thread.c | |
parent | 1514b275558304c63bc3838c2da5c4be0c1cbef0 (diff) |
ovs-thread: Add support for various thread-related assertions.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Ethan Jackson <ethan@nicira.com>
Diffstat (limited to 'lib/ovs-thread.c')
-rw-r--r-- | lib/ovs-thread.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/lib/ovs-thread.c b/lib/ovs-thread.c index e1e72891..3ea07b5f 100644 --- a/lib/ovs-thread.c +++ b/lib/ovs-thread.c @@ -17,7 +17,12 @@ #include <config.h> #include "ovs-thread.h" #include <errno.h> +#include <poll.h> +#include <stdlib.h> +#include <unistd.h> #include "compiler.h" +#include "poll-loop.h" +#include "socket-util.h" #include "util.h" #ifdef __CHECKER__ @@ -26,6 +31,18 @@ * cut-and-paste. Since "sparse" is just a checker, not a compiler, it * doesn't matter that we don't define them. */ #else +#include "vlog.h" + +VLOG_DEFINE_THIS_MODULE(ovs_thread); + +/* If there is a reason that we cannot fork anymore (unless the fork will be + * immediately followed by an exec), then this points to a string that + * explains why. */ +static const char *must_not_fork; + +/* True if we created any threads beyond the main initial thread. */ +static bool multithreaded; + #define XPTHREAD_FUNC1(FUNCTION, PARAM1) \ void \ x##FUNCTION(PARAM1 arg1) \ @@ -83,6 +100,9 @@ xpthread_create(pthread_t *threadp, pthread_attr_t *attr, pthread_t thread; int error; + forbid_forking("multiple threads exist"); + multithreaded = true; + error = pthread_create(threadp ? threadp : &thread, attr, start, arg); if (error) { ovs_abort(error, "pthread_create failed"); @@ -106,4 +126,52 @@ ovsthread_once_done(struct ovsthread_once *once) atomic_store(&once->done, true); xpthread_mutex_unlock(&once->mutex); } + +/* Asserts that the process has not yet created any threads (beyond the initial + * thread). */ +void +(assert_single_threaded)(const char *where) +{ + if (multithreaded) { + VLOG_FATAL("%s: attempted operation not allowed when multithreaded", + where); + } +} + +/* Forks the current process (checking that this is allowed). Aborts with + * VLOG_FATAL if fork() returns an error, and otherwise returns the value + * returned by fork(). */ +pid_t +(xfork)(const char *where) +{ + pid_t pid; + + if (must_not_fork) { + VLOG_FATAL("%s: attempted to fork but forking not allowed (%s)", + where, must_not_fork); + } + + pid = fork(); + if (pid < 0) { + VLOG_FATAL("fork failed (%s)", strerror(errno)); + } + return pid; +} + +/* Notes that the process must not call fork() from now on, for the specified + * 'reason'. (The process may still fork() if it execs itself immediately + * afterward.) */ +void +forbid_forking(const char *reason) +{ + ovs_assert(reason != NULL); + must_not_fork = reason; +} + +/* Returns true if the process is allowed to fork, false otherwise. */ +bool +may_fork(void) +{ + return !must_not_fork; +} #endif |