diff options
author | Nick Mathewson <nickm@torproject.org> | 2018-06-22 10:30:45 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2018-06-22 10:31:51 -0400 |
commit | 97b15a1d7c51764888d2172711e3f3a71fb01916 (patch) | |
tree | 2d7be35820f099e0d7da91f0e4eb49baa99476e4 /src/lib/lock | |
parent | 2cf033f238c111bef62552da16117568435d3a18 (diff) | |
download | tor-97b15a1d7c51764888d2172711e3f3a71fb01916.tar.gz tor-97b15a1d7c51764888d2172711e3f3a71fb01916.zip |
Extract the locking and logging code
The locking code gets its own module, since it's more fundamental
than the higher-level locking code.
Extracting the logging code was the whole point here. :)
Diffstat (limited to 'src/lib/lock')
-rw-r--r-- | src/lib/lock/.may_include | 5 | ||||
-rw-r--r-- | src/lib/lock/compat_mutex.c | 34 | ||||
-rw-r--r-- | src/lib/lock/compat_mutex.h | 60 | ||||
-rw-r--r-- | src/lib/lock/compat_mutex_pthreads.c | 97 | ||||
-rw-r--r-- | src/lib/lock/compat_mutex_winthreads.c | 39 | ||||
-rw-r--r-- | src/lib/lock/include.am | 24 |
6 files changed, 259 insertions, 0 deletions
diff --git a/src/lib/lock/.may_include b/src/lib/lock/.may_include new file mode 100644 index 0000000000..9522e3af49 --- /dev/null +++ b/src/lib/lock/.may_include @@ -0,0 +1,5 @@ +orconfig.h +lib/cc/*.h +lib/err/*.h +lib/lock/*.h +lib/malloc/*.h diff --git a/src/lib/lock/compat_mutex.c b/src/lib/lock/compat_mutex.c new file mode 100644 index 0000000000..e0f6224a83 --- /dev/null +++ b/src/lib/lock/compat_mutex.c @@ -0,0 +1,34 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "lib/lock/compat_mutex.h" +#include "lib/malloc/util_malloc.h" + +/** Return a newly allocated, ready-for-use mutex. */ +tor_mutex_t * +tor_mutex_new(void) +{ + tor_mutex_t *m = tor_malloc_zero(sizeof(tor_mutex_t)); + tor_mutex_init(m); + return m; +} +/** Return a newly allocated, ready-for-use mutex. This one might be + * non-recursive, if that's faster. */ +tor_mutex_t * +tor_mutex_new_nonrecursive(void) +{ + tor_mutex_t *m = tor_malloc_zero(sizeof(tor_mutex_t)); + tor_mutex_init_nonrecursive(m); + return m; +} +/** Release all storage and system resources held by <b>m</b>. */ +void +tor_mutex_free_(tor_mutex_t *m) +{ + if (!m) + return; + tor_mutex_uninit(m); + tor_free(m); +} diff --git a/src/lib/lock/compat_mutex.h b/src/lib/lock/compat_mutex.h new file mode 100644 index 0000000000..92978086ac --- /dev/null +++ b/src/lib/lock/compat_mutex.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_COMPAT_MUTEX_H +#define TOR_COMPAT_MUTEX_H + +#include "orconfig.h" +#include "lib/cc/torint.h" +#include "lib/malloc/util_malloc.h" + +#if defined(HAVE_PTHREAD_H) && !defined(_WIN32) +#include <pthread.h> +#endif + +#if defined(_WIN32) +#include <windows.h> +#endif + +#if defined(_WIN32) +#define USE_WIN32_THREADS +#elif defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_CREATE) +#define USE_PTHREADS +#else +#error "No threading system was found" +#endif /* defined(_WIN32) || ... */ + +/* Because we use threads instead of processes on most platforms (Windows, + * Linux, etc), we need locking for them. On platforms with poor thread + * support or broken gethostbyname_r, these functions are no-ops. */ + +/** A generic lock structure for multithreaded builds. */ +typedef struct tor_mutex_t { +#if defined(USE_WIN32_THREADS) + /** Windows-only: on windows, we implement locks with CRITICAL_SECTIONS. */ + CRITICAL_SECTION mutex; +#elif defined(USE_PTHREADS) + /** Pthreads-only: with pthreads, we implement locks with + * pthread_mutex_t. */ + pthread_mutex_t mutex; +#else + /** No-threads only: Dummy variable so that tor_mutex_t takes up space. */ + int _unused; +#endif /* defined(USE_WIN32_MUTEX) || ... */ +} tor_mutex_t; + +tor_mutex_t *tor_mutex_new(void); +tor_mutex_t *tor_mutex_new_nonrecursive(void); +void tor_mutex_init(tor_mutex_t *m); +void tor_mutex_init_nonrecursive(tor_mutex_t *m); +void tor_mutex_acquire(tor_mutex_t *m); +void tor_mutex_release(tor_mutex_t *m); +void tor_mutex_free_(tor_mutex_t *m); +#define tor_mutex_free(m) FREE_AND_NULL(tor_mutex_t, tor_mutex_free_, (m)) +void tor_mutex_uninit(tor_mutex_t *m); + +void tor_locking_init(void); + +#endif /* !defined(TOR_COMPAT_MUTEX_H) */ diff --git a/src/lib/lock/compat_mutex_pthreads.c b/src/lib/lock/compat_mutex_pthreads.c new file mode 100644 index 0000000000..390da4fb81 --- /dev/null +++ b/src/lib/lock/compat_mutex_pthreads.c @@ -0,0 +1,97 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "lib/lock/compat_mutex.h" +#include "lib/cc/compat_compiler.h" +#include "lib/err/torerr.h" + +/** A mutex attribute that we're going to use to tell pthreads that we want + * "recursive" mutexes (i.e., once we can re-lock if we're already holding + * them.) */ +static pthread_mutexattr_t attr_recursive; +static int attr_initialized = 0; + +void +tor_locking_init(void) +{ + if (!attr_initialized) { + pthread_mutexattr_init(&attr_recursive); + pthread_mutexattr_settype(&attr_recursive, PTHREAD_MUTEX_RECURSIVE); + attr_initialized = 1; + } +} + +/** Initialize <b>mutex</b> so it can be locked. Every mutex must be set + * up with tor_mutex_init() or tor_mutex_new(); not both. */ +void +tor_mutex_init(tor_mutex_t *mutex) +{ + if (PREDICT_UNLIKELY(!attr_initialized)) + tor_locking_init(); // LCOV_EXCL_LINE + const int err = pthread_mutex_init(&mutex->mutex, &attr_recursive); + if (PREDICT_UNLIKELY(err)) { + // LCOV_EXCL_START + raw_assert_unreached_msg("Error creating a mutex."); + // LCOV_EXCL_STOP + } +} + +/** As tor_mutex_init, but initialize a mutex suitable that may be + * non-recursive, if the OS supports that. */ +void +tor_mutex_init_nonrecursive(tor_mutex_t *mutex) +{ + int err; + if (!attr_initialized) + tor_locking_init(); // LCOV_EXCL_LINE + err = pthread_mutex_init(&mutex->mutex, NULL); + if (PREDICT_UNLIKELY(err)) { + // LCOV_EXCL_START + raw_assert_unreached_msg("Error creating a mutex."); + // LCOV_EXCL_STOP + } +} + +/** Wait until <b>m</b> is free, then acquire it. */ +void +tor_mutex_acquire(tor_mutex_t *m) +{ + int err; + raw_assert(m); + err = pthread_mutex_lock(&m->mutex); + if (PREDICT_UNLIKELY(err)) { + // LCOV_EXCL_START + raw_assert_unreached_msg("Error locking a mutex."); + // LCOV_EXCL_STOP + } +} +/** Release the lock <b>m</b> so another thread can have it. */ +void +tor_mutex_release(tor_mutex_t *m) +{ + int err; + raw_assert(m); + err = pthread_mutex_unlock(&m->mutex); + if (PREDICT_UNLIKELY(err)) { + // LCOV_EXCL_START + raw_assert_unreached_msg("Error unlocking a mutex."); + // LCOV_EXCL_STOP + } +} +/** Clean up the mutex <b>m</b> so that it no longer uses any system + * resources. Does not free <b>m</b>. This function must only be called on + * mutexes from tor_mutex_init(). */ +void +tor_mutex_uninit(tor_mutex_t *m) +{ + int err; + raw_assert(m); + err = pthread_mutex_destroy(&m->mutex); + if (PREDICT_UNLIKELY(err)) { + // LCOV_EXCL_START + raw_assert_unreached_msg("Error destroying a mutex."); + // LCOV_EXCL_STOP + } +} diff --git a/src/lib/lock/compat_mutex_winthreads.c b/src/lib/lock/compat_mutex_winthreads.c new file mode 100644 index 0000000000..c92eb62913 --- /dev/null +++ b/src/lib/lock/compat_mutex_winthreads.c @@ -0,0 +1,39 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "lib/lock/compat_mutex.h" + +void +tor_locking_init(void) +{ +} + +void +tor_mutex_init(tor_mutex_t *m) +{ + InitializeCriticalSection(&m->mutex); +} +void +tor_mutex_init_nonrecursive(tor_mutex_t *m) +{ + InitializeCriticalSection(&m->mutex); +} + +void +tor_mutex_uninit(tor_mutex_t *m) +{ + DeleteCriticalSection(&m->mutex); +} +void +tor_mutex_acquire(tor_mutex_t *m) +{ + raw_assert(m); + EnterCriticalSection(&m->mutex); +} +void +tor_mutex_release(tor_mutex_t *m) +{ + LeaveCriticalSection(&m->mutex); +} diff --git a/src/lib/lock/include.am b/src/lib/lock/include.am new file mode 100644 index 0000000000..4e6f444347 --- /dev/null +++ b/src/lib/lock/include.am @@ -0,0 +1,24 @@ + +noinst_LIBRARIES += src/lib/libtor-lock.a + +if UNITTESTS_ENABLED +noinst_LIBRARIES += src/lib/libtor-lock-testing.a +endif + +src_lib_libtor_lock_a_SOURCES = \ + src/lib/lock/compat_mutex.c + +if THREADS_PTHREADS +src_lib_libtor_lock_a_SOURCES += src/lib/lock/compat_mutex_pthreads.c +endif +if THREADS_WIN32 +src_lib_libtor_lock_a_SOURCES += src/lib/lock/compat_mutex_winthreads.c +endif + +src_lib_libtor_lock_testing_a_SOURCES = \ + $(src_lib_libtor_lock_a_SOURCES) +src_lib_libtor_lock_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS) +src_lib_libtor_lock_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) + +noinst_HEADERS += \ + src/lib/lock/compat_mutex.h |