summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2011-07-04 12:16:08 -0400
committerNick Mathewson <nickm@torproject.org>2011-07-04 12:16:08 -0400
commite7fe92709e7f83e5189cbcf485ec3a040f0710b5 (patch)
tree544e013f019dc006bbb1fbd6c368f0024c04c274
parentf87f56894dddaadac9e285c0452bf16b3875091b (diff)
parentcb6ecee7f6199777c10815ac15aad4d808e7375f (diff)
downloadlibevent-e7fe92709e7f83e5189cbcf485ec3a040f0710b5.tar.gz
Merge remote-tracking branch 'github/20_global_locks_init' into patches-2.0
-rw-r--r--event-internal.h1
-rw-r--r--event.c22
-rw-r--r--evthread-internal.h18
-rw-r--r--evthread.c92
-rw-r--r--evutil_rand.c17
-rw-r--r--signal.c14
6 files changed, 149 insertions, 15 deletions
diff --git a/event-internal.h b/event-internal.h
index 74c2a396..6caf4d9c 100644
--- a/event-internal.h
+++ b/event-internal.h
@@ -337,6 +337,7 @@ int _evsig_set_handler(struct event_base *base, int evsignal,
void (*fn)(int));
int _evsig_restore_handler(struct event_base *base, int evsignal);
+
void event_active_nolock(struct event *ev, int res, short count);
/* FIXME document. */
diff --git a/event.c b/event.c
index 27bf3dc3..ec470d32 100644
--- a/event.c
+++ b/event.c
@@ -182,7 +182,9 @@ eq_debug_entry(const struct event_debug_entry *a,
int _event_debug_mode_on = 0;
/* Set if it's too late to enable event_debug_mode. */
static int event_debug_mode_too_late = 0;
+#ifndef _EVENT_DISABLE_THREAD_SUPPORT
static void *_event_debug_map_lock = NULL;
+#endif
static HT_HEAD(event_debug_map, event_debug_entry) global_debug_map =
HT_INITIALIZER();
@@ -514,8 +516,6 @@ event_enable_debug_mode(void)
_event_debug_mode_on = 1;
HT_INIT(event_debug_map, &global_debug_map);
-
- EVTHREAD_ALLOC_LOCK(_event_debug_map_lock, 0);
#endif
}
@@ -545,9 +545,6 @@ event_base_new_with_config(const struct event_config *cfg)
#ifndef _EVENT_DISABLE_DEBUG_MODE
event_debug_mode_too_late = 1;
- if (_event_debug_mode_on && !_event_debug_map_lock) {
- EVTHREAD_ALLOC_LOCK(_event_debug_map_lock, 0);
- }
#endif
if ((base = mm_calloc(1, sizeof(struct event_base))) == NULL) {
@@ -2820,3 +2817,18 @@ event_base_del_virtual(struct event_base *base)
evthread_notify_base(base);
EVBASE_RELEASE_LOCK(base, th_base_lock);
}
+
+#ifndef _EVENT_DISABLE_THREAD_SUPPORT
+int
+event_global_setup_locks_(const int enable_locks)
+{
+#ifndef _EVENT_DISABLE_DEBUG_MODE
+ EVTHREAD_SETUP_GLOBAL_LOCK(_event_debug_map_lock, 0);
+#endif
+ if (evsig_global_setup_locks_(enable_locks) < 0)
+ return -1;
+ if (evutil_secure_rng_global_setup_locks_(enable_locks) < 0)
+ return -1;
+ return 0;
+}
+#endif
diff --git a/evthread-internal.h b/evthread-internal.h
index 9317fdf1..fbb1c0d4 100644
--- a/evthread-internal.h
+++ b/evthread-internal.h
@@ -345,6 +345,24 @@ EVLOCK_TRY_LOCK(void *lock)
int _evthread_is_debug_lock_held(void *lock);
void *_evthread_debug_get_real_lock(void *lock);
+
+void *evthread_setup_global_lock_(void *lock_, unsigned locktype,
+ int enable_locks);
+
+#define EVTHREAD_SETUP_GLOBAL_LOCK(lockvar, locktype) \
+ do { \
+ lockvar = evthread_setup_global_lock_(lockvar, \
+ (locktype), enable_locks); \
+ if (!lockvar) { \
+ event_warn("Couldn't allocate %s", #lockvar); \
+ return -1; \
+ } \
+ } while (0);
+
+int event_global_setup_locks_(const int enable_locks);
+int evsig_global_setup_locks_(const int enable_locks);
+int evutil_secure_rng_global_setup_locks_(const int enable_locks);
+
#endif
#ifdef __cplusplus
diff --git a/evthread.c b/evthread.c
index 2cfb76e9..5af54dc3 100644
--- a/evthread.c
+++ b/evthread.c
@@ -76,12 +76,25 @@ evthread_set_lock_callbacks(const struct evthread_lock_callbacks *cbs)
? &_original_lock_fns : &_evthread_lock_fns;
if (!cbs) {
+ if (target->alloc)
+ event_warnx("Trying to disable lock functions after "
+ "they have been set up will probaby not work.");
memset(target, 0, sizeof(_evthread_lock_fns));
return 0;
}
+ if (target->alloc) {
+ /* Uh oh; we already had locking callbacks set up.*/
+ if (!memcmp(target, cbs, sizeof(_evthread_lock_fns))) {
+ /* no change -- allow this. */
+ return 0;
+ }
+ event_warnx("Can't change lock callbacks once they have been "
+ "initialized.");
+ return -1;
+ }
if (cbs->alloc && cbs->free && cbs->lock && cbs->unlock) {
memcpy(target, cbs, sizeof(_evthread_lock_fns));
- return 0;
+ return event_global_setup_locks_(1);
} else {
return -1;
}
@@ -95,8 +108,24 @@ evthread_set_condition_callbacks(const struct evthread_condition_callbacks *cbs)
? &_original_cond_fns : &_evthread_cond_fns;
if (!cbs) {
+ if (target->alloc_condition)
+ event_warnx("Trying to disable condition functions "
+ "after they have been set up will probaby not "
+ "work.");
memset(target, 0, sizeof(_evthread_cond_fns));
- } else if (cbs->alloc_condition && cbs->free_condition &&
+ return 0;
+ }
+ if (target->alloc_condition) {
+ /* Uh oh; we already had condition callbacks set up.*/
+ if (!memcmp(target, cbs, sizeof(_evthread_cond_fns))) {
+ /* no change -- allow this. */
+ return 0;
+ }
+ event_warnx("Can't change condition callbacks once they "
+ "have been initialized.");
+ return -1;
+ }
+ if (cbs->alloc_condition && cbs->free_condition &&
cbs->signal_condition && cbs->wait_condition) {
memcpy(target, cbs, sizeof(_evthread_cond_fns));
}
@@ -247,6 +276,9 @@ evthread_enable_lock_debuging(void)
sizeof(struct evthread_condition_callbacks));
_evthread_cond_fns.wait_condition = debug_cond_wait;
_evthread_lock_debugging_enabled = 1;
+
+ /* XXX return value should get checked. */
+ event_global_setup_locks_(0);
}
int
@@ -270,6 +302,62 @@ _evthread_debug_get_real_lock(void *lock_)
return lock->lock;
}
+void *
+evthread_setup_global_lock_(void *lock_, unsigned locktype, int enable_locks)
+{
+ /* there are four cases here:
+ 1) we're turning on debugging; locking is not on.
+ 2) we're turning on debugging; locking is on.
+ 3) we're turning on locking; debugging is not on.
+ 4) we're turning on locking; debugging is on. */
+
+ if (!enable_locks && _original_lock_fns.alloc == NULL) {
+ /* Case 1: allocate a debug lock. */
+ EVUTIL_ASSERT(lock_ == NULL);
+ return debug_lock_alloc(locktype);
+ } else if (!enable_locks && _original_lock_fns.alloc != NULL) {
+ /* Case 2: wrap the lock in a debug lock. */
+ struct debug_lock *lock;
+ EVUTIL_ASSERT(lock_ != NULL);
+
+ if (!(locktype & EVTHREAD_LOCKTYPE_RECURSIVE)) {
+ /* We can't wrap it: We need a recursive lock */
+ _original_lock_fns.free(lock_, locktype);
+ return debug_lock_alloc(locktype);
+ }
+ lock = mm_malloc(sizeof(struct debug_lock));
+ if (!lock) {
+ _original_lock_fns.free(lock_, locktype);
+ return NULL;
+ }
+ lock->lock = lock_;
+ lock->locktype = locktype;
+ lock->count = 0;
+ lock->held_by = 0;
+ return lock;
+ } else if (enable_locks && ! _evthread_lock_debugging_enabled) {
+ /* Case 3: allocate a regular lock */
+ EVUTIL_ASSERT(lock_ == NULL);
+ return _evthread_lock_fns.alloc(locktype);
+ } else {
+ /* Case 4: Fill in a debug lock with a real lock */
+ struct debug_lock *lock = lock_;
+ EVUTIL_ASSERT(enable_locks &&
+ _evthread_lock_debugging_enabled);
+ EVUTIL_ASSERT(lock->locktype == locktype);
+ EVUTIL_ASSERT(lock->lock == NULL);
+ lock->lock = _original_lock_fns.alloc(
+ locktype|EVTHREAD_LOCKTYPE_RECURSIVE);
+ if (!lock->lock) {
+ lock->count = -200;
+ mm_free(lock);
+ return NULL;
+ }
+ return lock;
+ }
+}
+
+
#ifndef EVTHREAD_EXPOSE_STRUCTS
unsigned long
_evthreadimpl_get_id()
diff --git a/evutil_rand.c b/evutil_rand.c
index 07ad2ea6..82ea115e 100644
--- a/evutil_rand.c
+++ b/evutil_rand.c
@@ -49,6 +49,11 @@ evutil_secure_rng_init(void)
(void) arc4random();
return 0;
}
+int
+evutil_secure_rng_global_setup_locks_(const int enable_locks)
+{
+ return 0;
+}
#ifndef _EVENT_HAVE_ARC4RANDOM_BUF
static void
@@ -93,13 +98,19 @@ static void *arc4rand_lock;
#include "./arc4random.c"
+#ifndef _EVENT_DISABLE_THREAD_SUPPORT
+int
+evutil_secure_rng_global_setup_locks_(const int enable_locks)
+{
+ EVTHREAD_SETUP_GLOBAL_LOCK(arc4rand_lock, 0);
+ return 0;
+}
+#endif
+
int
evutil_secure_rng_init(void)
{
int val;
- if (!arc4rand_lock) {
- EVTHREAD_ALLOC_LOCK(arc4rand_lock, 0);
- }
_ARC4_LOCK();
if (!arc4_seeded_ok)
diff --git a/signal.c b/signal.c
index ec27ea88..4e7fecff 100644
--- a/signal.c
+++ b/signal.c
@@ -168,11 +168,6 @@ evsig_cb(evutil_socket_t fd, short what, void *arg)
int
evsig_init(struct event_base *base)
{
-#ifndef _EVENT_DISABLE_THREAD_SUPPORT
- if (! evsig_base_lock)
- EVTHREAD_ALLOC_LOCK(evsig_base_lock, 0);
-#endif
-
/*
* Our signal handler is going to write to one end of the socket
* pair to wake up our event loop. The event loop then scans for
@@ -436,3 +431,12 @@ evsig_dealloc(struct event_base *base)
base->sig.sh_old = NULL;
}
}
+
+#ifndef _EVENT_DISABLE_THREAD_SUPPORT
+int
+evsig_global_setup_locks_(const int enable_locks)
+{
+ EVTHREAD_SETUP_GLOBAL_LOCK(evsig_base_lock, 0);
+ return 0;
+}
+#endif