From ed1f699789a62e8cc99e50c2969c51414d79a692 Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Tue, 20 Feb 2007 11:45:45 +0000 Subject: [PATCH] Locks git-svn-id: file:///svn/unbound/trunk@129 be551aaa-1e26-0410-a405-d3ace91eadb9 --- configure.ac | 1 + doc/Changelog | 3 + util/locks.c | 44 ++++++++++++ util/locks.h | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 229 insertions(+) create mode 100644 util/locks.c create mode 100644 util/locks.h diff --git a/configure.ac b/configure.ac index 5540c9d05..89fc0fe5c 100644 --- a/configure.ac +++ b/configure.ac @@ -361,6 +361,7 @@ if test x_$withval != x_no; then LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CC="$PTHREAD_CC" + AC_CHECK_TYPES(pthread_spinlock_t,,,[#include ]) ]) fi diff --git a/doc/Changelog b/doc/Changelog index 03a3c9c6d..2000bd224 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,6 @@ +20 February 2007: Wouter + - Added locks code and pthread spinlock detection. + 19 February 2007: Wouter - Created 0.0 svn tag. - added acx_pthread.m4 autoconf check for pthreads from diff --git a/util/locks.c b/util/locks.c new file mode 100644 index 000000000..1dbdedd86 --- /dev/null +++ b/util/locks.c @@ -0,0 +1,44 @@ +/** + * util/locks.c - unbound locking primitives + * + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * Implementation of locking and threading support. + * A place for locking debug code since most locking functions are macros. + */ + +#include "config.h" +#include "util/locks.h" + diff --git a/util/locks.h b/util/locks.h new file mode 100644 index 000000000..eab783b24 --- /dev/null +++ b/util/locks.h @@ -0,0 +1,181 @@ +/** + * util/locks.h - unbound locking primitives + * + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UTIL_LOCKS_H +#define UTIL_LOCKS_H + +/** + * \file + * Locking primitives. + * If pthreads is available, these are used. + * If no locking exists, they do nothing. + * + * The idea is to have different sorts of locks for different tasks. + * This allows the locking code to be ported more easily. + * + * Types of locks that are supported. + * o lock_rw: lock that has many readers and one writer (to a data entry). + * o lock_basic: simple mutex. Blocking, one person has access only. + * This lock is meant for non performance sensitive uses. + * o lock_quick: speed lock. For performance sensitive locking of critical + * sections. Could be implemented by a mutex or a spinlock. + * + * Also thread creation and deletion functions are defined here. + */ + +#include "util/log.h" + +/** + * The following macro is used to check the return value of the + * pthread calls. They return 0 on success and an errno on error. + * The errno is logged to the logfile with a descriptive comment. + */ +#define LOCKRET(func) do {\ + int err; \ + if( (err=(func)) != 0) \ + log_err("%s at %d could not " #func ": %s", \ + __FILE__, __LINE__, strerror(err)); \ + } while(0) + +#ifdef HAVE_PTHREAD +#include + +/** we use the pthread rwlock */ +typedef pthread_rwlock_t lock_rw_t; +/** small front for pthread init func, NULL is default attrs. */ +#define lock_rw_init(lock) LOCKRET(pthread_rwlock_init(lock, NULL)) +/** free up the lock. must be unlocked. */ +#define lock_rw_destroy(lock) LOCKRET(pthread_rwlock_destroy(lock)) +/** acquire a read lock */ +#define lock_rw_rdlock(lock) LOCKRET(pthread_rwlock_rdlock(lock)) +/** acquire a write lock */ +#define lock_rw_wrlock(lock) LOCKRET(pthread_rwlock_wrlock(lock)) +/** unlock previously acquired read or write lock */ +#define lock_rw_unlock(lock) LOCKRET(pthread_rwlock_unlock(lock)) + +/** use pthread mutex for basic lock */ +typedef pthread_mutex_t lock_basic_t; +/** small front for pthread init func, NULL is default attrs. */ +#define lock_basic_init(lock) LOCKRET(pthread_mutex_init(lock, NULL)) +/** free up the lock. must be unlocked. */ +#define lock_basic_destroy(lock) LOCKRET(pthread_mutex_destroy(lock)) +/** acquire lock. This may block indefinetely. */ +#define lock_basic_lock(lock) LOCKRET(pthread_mutex_lock(lock)) +/** unlock acquired lock. */ +#define lock_basic_unlock(lock) LOCKRET(pthread_mutex_unlock(lock)) + +#ifdef HAVE_PTHREAD_SPINLOCK_T +/** in case spinlocks are not supported, use a mutex. */ +typedef pthread_mutex_t lock_quick_t; +/** small front for pthread init func, NULL is default attrs. */ +#define lock_quick_init(lock) LOCKRET(pthread_mutex_init(lock, NULL)) +/** free up the lock. must be unlocked. */ +#define lock_quick_destroy(lock) LOCKRET(pthread_mutex_destroy(lock)) +/** acquire lock. may block. */ +#define lock_quick_lock(lock) LOCKRET(pthread_mutex_lock(lock)) +/** unlock acquired lock. */ +#define lock_quick_unlock(lock) LOCKRET(pthread_mutex_unlock(lock)) + +#else /* HAVE_PTHREAD_SPINLOCK_T */ +/** use pthread spinlock for the quick lock */ +typedef pthread_spinlock_t lock_quick_t; +/** + * allocate process private since this is available whether + * Thread Process-Shared Synchronization is supported or not. + * This means only threads inside this process may access the lock. + * (not threads from another process that shares memory). + * spinlocks are not supported on all pthread platforms. + */ +#define lock_quick_init(lock) LOCKRET(pthread_spin_init(lock, PTHREAD_PROCESS_PRIVATE)) +/** free up the lock. must be unlocked. */ +#define lock_quick_destroy(lock) LOCKRET(pthread_spin_destroy(lock)) +/** acquire lock. This may block indefinetely, and will spin. */ +#define lock_quick_lock(lock) LOCKRET(pthread_spin_lock(lock)) +/** unlock acquired lock. */ +#define lock_quick_unlock(lock) LOCKRET(pthread_spin_unlock(lock)) + +#endif /* HAVE SPINLOCK */ + +/** Thread creation */ +typedef pthread_t ub_thread_t; +/** Pass where to store tread_t in thr. Use default NULL attributes. */ +#define ub_thread_create(thr, func, arg) LOCKRET(pthread_create(thr, NULL, func, arg)) + +#else /* HAVE_PTHREAD */ + +/** In case there is no pthread support, define locks to do nothing */ +typedef int lock_rw_t; +/** does nothing */ +#define lock_rw_init(lock) /* nop */ +/** does nothing */ +#define lock_rw_destroy(lock) /* nop */ +/** does nothing */ +#define lock_rw_rdlock(lock) /* nop */ +/** does nothing */ +#define lock_rw_wrlock(lock) /* nop */ +/** does nothing */ +#define lock_rw_unlock(lock) /* nop */ + +/** define locks to do nothing */ +typedef int lock_basic_t; +/** does nothing */ +#define lock_basic_init(lock) /* nop */ +/** does nothing */ +#define lock_basic_destroy(lock) /* nop */ +/** does nothing */ +#define lock_basic_lock(lock) /* nop */ +/** does nothing */ +#define lock_basic_unlock(lock) /* nop */ + +/** define locks to do nothing */ +typedef int lock_quick_t; +/** does nothing */ +#define lock_quick_init(lock) /* nop */ +/** does nothing */ +#define lock_quick_destroy(lock) /* nop */ +/** does nothing */ +#define lock_quick_lock(lock) /* nop */ +/** does nothing */ +#define lock_quick_unlock(lock) /* nop */ + +/** Thread creation, threads do not exist */ +typedef int ub_thread_t; +/** ub_thread_create gives an error, it should not be called. */ +#define ub_thread_create(thr, func, arg) \ + fatal_exit("%s %d called thread create, but no thread support " \ + "has been compiled in.", __FILE__, __LINE__) + +#endif /* HAVE_PTHREAD */ +#endif /* UTIL_LOCKS_H */ -- 2.47.2