X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=dbus%2Fdbus-sysdeps-pthread.c;h=1300ec35168226d458e73aabc5bee0c804dd2f82;hb=3ccb027c907f9ee2890028e83b60296204bbf478;hp=0b9c591385f942a91f0281d60a13abb7463ebd1a;hpb=bdbbf46ca88ac43bec9c36909990730d102983c5;p=platform%2Fupstream%2Fdbus.git diff --git a/dbus/dbus-sysdeps-pthread.c b/dbus/dbus-sysdeps-pthread.c index 0b9c591..1300ec3 100644 --- a/dbus/dbus-sysdeps-pthread.c +++ b/dbus/dbus-sysdeps-pthread.c @@ -1,4 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* dbus-sysdeps-pthread.c Implements threads using pthreads (internal to libdbus) * * Copyright (C) 2002, 2003, 2006 Red Hat, Inc. @@ -17,10 +17,11 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ +#include #include "dbus-internals.h" #include "dbus-sysdeps.h" #include "dbus-threads.h" @@ -29,13 +30,32 @@ #include #include -typedef struct { - pthread_mutex_t lock; -} DBusMutexPThread; +#ifdef HAVE_ERRNO_H +#include +#endif -typedef struct { - pthread_cond_t cond; -} DBusCondVarPThread; +#include + +#ifdef HAVE_MONOTONIC_CLOCK +/* Whether we have a "monotonic" clock; i.e. a clock not affected by + * changes in system time. + * This is initialized once in check_monotonic_clock below. + * https://bugs.freedesktop.org/show_bug.cgi?id=18121 + */ +static dbus_bool_t have_monotonic_clock = 0; +#endif + +struct DBusRMutex { + pthread_mutex_t lock; /**< the lock */ +}; + +struct DBusCMutex { + pthread_mutex_t lock; /**< the lock */ +}; + +struct DBusCondVar { + pthread_cond_t cond; /**< the condition */ +}; #define DBUS_MUTEX(m) ((DBusMutex*) m) #define DBUS_MUTEX_PTHREAD(m) ((DBusMutexPThread*) m) @@ -44,6 +64,11 @@ typedef struct { #define DBUS_COND_VAR_PTHREAD(c) ((DBusCondVarPThread*) c) +#ifdef DBUS_DISABLE_ASSERT +/* (tmp != 0) is a no-op usage to silence compiler */ +#define PTHREAD_CHECK(func_name, result_or_call) \ + do { int tmp = (result_or_call); if (tmp != 0) {;} } while (0) +#else #define PTHREAD_CHECK(func_name, result_or_call) do { \ int tmp = (result_or_call); \ if (tmp != 0) { \ @@ -51,14 +76,15 @@ typedef struct { func_name, tmp, strerror(tmp), _DBUS_FUNCTION_NAME); \ } \ } while (0) - -static DBusMutex* -_dbus_pthread_mutex_new (void) +#endif /* !DBUS_DISABLE_ASSERT */ + +DBusCMutex * +_dbus_platform_cmutex_new (void) { - DBusMutexPThread *pmutex; + DBusCMutex *pmutex; int result; - - pmutex = dbus_new (DBusMutexPThread, 1); + + pmutex = dbus_new (DBusCMutex, 1); if (pmutex == NULL) return NULL; @@ -74,50 +100,95 @@ _dbus_pthread_mutex_new (void) PTHREAD_CHECK ("pthread_mutex_init", result); } - return DBUS_MUTEX (pmutex); + return pmutex; } -static void -_dbus_pthread_mutex_free (DBusMutex *mutex) +DBusRMutex * +_dbus_platform_rmutex_new (void) { - DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); - - PTHREAD_CHECK ("pthread_mutex_destroy", pthread_mutex_destroy (&pmutex->lock)); + DBusRMutex *pmutex; + pthread_mutexattr_t mutexattr; + int result; + + pmutex = dbus_new (DBusRMutex, 1); + if (pmutex == NULL) + return NULL; + + pthread_mutexattr_init (&mutexattr); + pthread_mutexattr_settype (&mutexattr, PTHREAD_MUTEX_RECURSIVE); + result = pthread_mutex_init (&pmutex->lock, &mutexattr); + pthread_mutexattr_destroy (&mutexattr); - dbus_free (pmutex); + if (result == ENOMEM || result == EAGAIN) + { + dbus_free (pmutex); + return NULL; + } + else + { + PTHREAD_CHECK ("pthread_mutex_init", result); + } + + return pmutex; } -static dbus_bool_t -_dbus_pthread_mutex_lock (DBusMutex *mutex) +void +_dbus_platform_cmutex_free (DBusCMutex *mutex) { - DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); + PTHREAD_CHECK ("pthread_mutex_destroy", pthread_mutex_destroy (&mutex->lock)); + dbus_free (mutex); +} - PTHREAD_CHECK ("pthread_mutex_lock", pthread_mutex_lock (&pmutex->lock)); +void +_dbus_platform_rmutex_free (DBusRMutex *mutex) +{ + PTHREAD_CHECK ("pthread_mutex_destroy", pthread_mutex_destroy (&mutex->lock)); + dbus_free (mutex); +} - return TRUE; +void +_dbus_platform_cmutex_lock (DBusCMutex *mutex) +{ + PTHREAD_CHECK ("pthread_mutex_lock", pthread_mutex_lock (&mutex->lock)); } -static dbus_bool_t -_dbus_pthread_mutex_unlock (DBusMutex *mutex) +void +_dbus_platform_rmutex_lock (DBusRMutex *mutex) { - DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); + PTHREAD_CHECK ("pthread_mutex_lock", pthread_mutex_lock (&mutex->lock)); +} - PTHREAD_CHECK ("pthread_mutex_unlock", pthread_mutex_unlock (&pmutex->lock)); +void +_dbus_platform_cmutex_unlock (DBusCMutex *mutex) +{ + PTHREAD_CHECK ("pthread_mutex_unlock", pthread_mutex_unlock (&mutex->lock)); +} - return TRUE; +void +_dbus_platform_rmutex_unlock (DBusRMutex *mutex) +{ + PTHREAD_CHECK ("pthread_mutex_unlock", pthread_mutex_unlock (&mutex->lock)); } -static DBusCondVar * -_dbus_pthread_condvar_new (void) +DBusCondVar * +_dbus_platform_condvar_new (void) { - DBusCondVarPThread *pcond; + DBusCondVar *pcond; + pthread_condattr_t attr; int result; - pcond = dbus_new (DBusCondVarPThread, 1); + pcond = dbus_new (DBusCondVar, 1); if (pcond == NULL) return NULL; - result = pthread_cond_init (&pcond->cond, NULL); + pthread_condattr_init (&attr); +#ifdef HAVE_MONOTONIC_CLOCK + if (have_monotonic_clock) + pthread_condattr_setclock (&attr, CLOCK_MONOTONIC); +#endif + + result = pthread_cond_init (&pcond->cond, &attr); + pthread_condattr_destroy (&attr); if (result == EAGAIN || result == ENOMEM) { @@ -129,40 +200,43 @@ _dbus_pthread_condvar_new (void) PTHREAD_CHECK ("pthread_cond_init", result); } - return DBUS_COND_VAR (pcond); + return pcond; } -static void -_dbus_pthread_condvar_free (DBusCondVar *cond) -{ - DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); - - PTHREAD_CHECK ("pthread_cond_destroy", pthread_cond_destroy (&pcond->cond)); - - dbus_free (pcond); +void +_dbus_platform_condvar_free (DBusCondVar *cond) +{ + PTHREAD_CHECK ("pthread_cond_destroy", pthread_cond_destroy (&cond->cond)); + dbus_free (cond); } -static void -_dbus_pthread_condvar_wait (DBusCondVar *cond, - DBusMutex *mutex) +void +_dbus_platform_condvar_wait (DBusCondVar *cond, + DBusCMutex *mutex) { - DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); - DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); - - PTHREAD_CHECK ("pthread_cond_wait", pthread_cond_wait (&pcond->cond, &pmutex->lock)); + PTHREAD_CHECK ("pthread_cond_wait", pthread_cond_wait (&cond->cond, &mutex->lock)); } -static dbus_bool_t -_dbus_pthread_condvar_wait_timeout (DBusCondVar *cond, - DBusMutex *mutex, - int timeout_milliseconds) +dbus_bool_t +_dbus_platform_condvar_wait_timeout (DBusCondVar *cond, + DBusCMutex *mutex, + int timeout_milliseconds) { - DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); - DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); struct timeval time_now; struct timespec end_time; int result; - + +#ifdef HAVE_MONOTONIC_CLOCK + if (have_monotonic_clock) + { + struct timespec monotonic_timer; + clock_gettime (CLOCK_MONOTONIC,&monotonic_timer); + time_now.tv_sec = monotonic_timer.tv_sec; + time_now.tv_usec = monotonic_timer.tv_nsec / 1000; + } + else + /* This else falls through to gettimeofday */ +#endif gettimeofday (&time_now, NULL); end_time.tv_sec = time_now.tv_sec + timeout_milliseconds / 1000; @@ -173,59 +247,56 @@ _dbus_pthread_condvar_wait_timeout (DBusCondVar *cond, end_time.tv_nsec -= 1000*1000*1000; } - result = pthread_cond_timedwait (&pcond->cond, &pmutex->lock, &end_time); - + result = pthread_cond_timedwait (&cond->cond, &mutex->lock, &end_time); + if (result != ETIMEDOUT) { PTHREAD_CHECK ("pthread_cond_timedwait", result); } - + /* return true if we did not time out */ return result != ETIMEDOUT; } -static void -_dbus_pthread_condvar_wake_one (DBusCondVar *cond) +void +_dbus_platform_condvar_wake_one (DBusCondVar *cond) { - DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); - - PTHREAD_CHECK ("pthread_cond_signal", pthread_cond_signal (&pcond->cond)); + PTHREAD_CHECK ("pthread_cond_signal", pthread_cond_signal (&cond->cond)); } static void -_dbus_pthread_condvar_wake_all (DBusCondVar *cond) +check_monotonic_clock (void) { - DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); - - PTHREAD_CHECK ("pthread_cond_broadcast", pthread_cond_broadcast (&pcond->cond)); -} - -static const DBusThreadFunctions pthread_functions = -{ - DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK | - DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK | - DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK | - DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK | - DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK | - DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK | - DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK | - DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK | - DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK| - DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK, - _dbus_pthread_mutex_new, - _dbus_pthread_mutex_free, - _dbus_pthread_mutex_lock, - _dbus_pthread_mutex_unlock, - _dbus_pthread_condvar_new, - _dbus_pthread_condvar_free, - _dbus_pthread_condvar_wait, - _dbus_pthread_condvar_wait_timeout, - _dbus_pthread_condvar_wake_one, - _dbus_pthread_condvar_wake_all -}; +#ifdef HAVE_MONOTONIC_CLOCK + struct timespec dummy; + if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0) + have_monotonic_clock = TRUE; +#endif +} dbus_bool_t _dbus_threads_init_platform_specific (void) { - return dbus_threads_init (&pthread_functions); + /* These have static variables, and we need to handle both the case + * where dbus_threads_init() has been called and when it hasn't; + * so initialize them before any threads are allowed to enter. + */ + check_monotonic_clock (); + (void) _dbus_check_setuid (); + + return TRUE; +} + +static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER; + +void +_dbus_threads_lock_platform_specific (void) +{ + pthread_mutex_lock (&init_mutex); +} + +void +_dbus_threads_unlock_platform_specific (void) +{ + pthread_mutex_unlock (&init_mutex); }