1d012387afef0ba02185ebe27bc6bb15551912e92Havoc Pennington/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 25886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington/* dbus-sysdeps-pthread.c Implements threads using pthreads (internal to libdbus) 35886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * 45886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * Copyright (C) 2002, 2003, 2006 Red Hat, Inc. 55886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * 65886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * Licensed under the Academic Free License version 2.1 75886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * 85886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * This program is free software; you can redistribute it and/or modify 95886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * it under the terms of the GNU General Public License as published by 105886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * the Free Software Foundation; either version 2 of the License, or 115886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * (at your option) any later version. 125886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * 135886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * This program is distributed in the hope that it will be useful, 145886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * but WITHOUT ANY WARRANTY; without even the implied warranty of 155886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 165886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * GNU General Public License for more details. 175886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * 185886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * You should have received a copy of the GNU General Public License 195886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * along with this program; if not, write to the Free Software 205baf2f856a9c6625993234855b07680da1c8916fTobias Mueller * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 215886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington * 225886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington */ 235886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 24dbecdeabb20e0ce11121819c63373f0afba57c58Marcus Brinkmann#include <config.h> 255886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington#include "dbus-internals.h" 265886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington#include "dbus-sysdeps.h" 275886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington#include "dbus-threads.h" 285886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 295886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington#include <sys/time.h> 305886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington#include <pthread.h> 31bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington#include <string.h> 325886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 3343b944a0a6ea48e8a8b06ae3e638299f591cde8dHavoc Pennington#ifdef HAVE_ERRNO_H 3443b944a0a6ea48e8a8b06ae3e638299f591cde8dHavoc Pennington#include <errno.h> 3543b944a0a6ea48e8a8b06ae3e638299f591cde8dHavoc Pennington#endif 3643b944a0a6ea48e8a8b06ae3e638299f591cde8dHavoc Pennington 37ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters#include <config.h> 38ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters 39ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters/* Whether we have a "monotonic" clock; i.e. a clock not affected by 40ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters * changes in system time. 41ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters * This is initialized once in check_monotonic_clock below. 42ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters * https://bugs.freedesktop.org/show_bug.cgi?id=18121 43ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters */ 44ae24bb35e2ee3ecde990f55852982b573754ec43Colin Waltersstatic dbus_bool_t have_monotonic_clock = 0; 45ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters 46bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Penningtontypedef struct { 47fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington pthread_mutex_t lock; /**< lock protecting count field */ 48fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington volatile int count; /**< count of how many times lock holder has recursively locked */ 49fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington volatile pthread_t holder; /**< holder of the lock if count >0, 50fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington valid but arbitrary thread if count 51fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington has ever been >0, uninitialized memory 52fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington if count has never been >0 */ 53bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington} DBusMutexPThread; 54bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 55bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Penningtontypedef struct { 56fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington pthread_cond_t cond; /**< the condition */ 57bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington} DBusCondVarPThread; 58bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 59bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington#define DBUS_MUTEX(m) ((DBusMutex*) m) 60bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington#define DBUS_MUTEX_PTHREAD(m) ((DBusMutexPThread*) m) 61bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 62bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington#define DBUS_COND_VAR(c) ((DBusCondVar*) c) 63bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington#define DBUS_COND_VAR_PTHREAD(c) ((DBusCondVarPThread*) c) 64bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 65bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 66fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington#ifdef DBUS_DISABLE_ASSERT 67eaefe03a8891b84e3f9e1f99f9098d65567e3092Havoc Pennington/* (tmp != 0) is a no-op usage to silence compiler */ 68eaefe03a8891b84e3f9e1f99f9098d65567e3092Havoc Pennington#define PTHREAD_CHECK(func_name, result_or_call) \ 69eaefe03a8891b84e3f9e1f99f9098d65567e3092Havoc Pennington do { int tmp = (result_or_call); if (tmp != 0) {;} } while (0) 70fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington#else 71bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington#define PTHREAD_CHECK(func_name, result_or_call) do { \ 72bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington int tmp = (result_or_call); \ 73bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington if (tmp != 0) { \ 74bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington _dbus_warn_check_failed ("pthread function %s failed with %d %s in %s\n", \ 75bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington func_name, tmp, strerror(tmp), _DBUS_FUNCTION_NAME); \ 76bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington } \ 77bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington} while (0) 78fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington#endif /* !DBUS_DISABLE_ASSERT */ 79fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington 805886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Penningtonstatic DBusMutex* 815886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington_dbus_pthread_mutex_new (void) 825886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington{ 83bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington DBusMutexPThread *pmutex; 84bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington int result; 855886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 86bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington pmutex = dbus_new (DBusMutexPThread, 1); 87bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington if (pmutex == NULL) 885886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington return NULL; 89bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 90bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington result = pthread_mutex_init (&pmutex->lock, NULL); 91bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 92bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington if (result == ENOMEM || result == EAGAIN) 935886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington { 94bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington dbus_free (pmutex); 955886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington return NULL; 965886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington } 97bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington else 98bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington { 99bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington PTHREAD_CHECK ("pthread_mutex_init", result); 100bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington } 1015886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 102fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington /* Only written */ 103fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington pmutex->count = 0; 104fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 105fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington /* There's no portable way to have a "null" pthread afaik so we 106fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington * can't set pmutex->holder to anything sensible. We only access it 107fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington * once the lock is held (which means we've set it). 108fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington */ 109fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 110bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington return DBUS_MUTEX (pmutex); 1115886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington} 1125886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 1135886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Penningtonstatic void 1145886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington_dbus_pthread_mutex_free (DBusMutex *mutex) 1155886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington{ 116bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); 117fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 118fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_assert (pmutex->count == 0); 119bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 120bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington PTHREAD_CHECK ("pthread_mutex_destroy", pthread_mutex_destroy (&pmutex->lock)); 121bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 122bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington dbus_free (pmutex); 1235886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington} 1245886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 125fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Penningtonstatic void 1265886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington_dbus_pthread_mutex_lock (DBusMutex *mutex) 1275886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington{ 128bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); 129fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington pthread_t self = pthread_self (); 130fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 131fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington /* If the count is > 0 then someone had the lock, maybe us. If it is 132fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington * 0, then it might immediately change right after we read it, 133fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington * but it will be changed by another thread; i.e. if we read 0, 134fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington * we assume that this thread doesn't have the lock. 135fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington * 136fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington * Not 100% sure this is safe, but ... seems like it should be. 137fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington */ 138fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington if (pmutex->count == 0) 139fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington { 140fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington /* We know we don't have the lock; someone may have the lock. */ 141fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 142fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington PTHREAD_CHECK ("pthread_mutex_lock", pthread_mutex_lock (&pmutex->lock)); 143fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 144fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington /* We now have the lock. Count must be 0 since it must be 0 when 145fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington * the lock is released by another thread, and we just now got 146fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington * the lock. 147fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington */ 148fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_assert (pmutex->count == 0); 149fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 150fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington pmutex->holder = self; 151fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington pmutex->count = 1; 152fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington } 153fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington else 154fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington { 155fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington /* We know someone had the lock, possibly us. Thus 156fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington * pmutex->holder is not pointing to junk, though it may not be 157fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington * the lock holder anymore if the lock holder is not us. If the 158fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington * lock holder is us, then we definitely have the lock. 159fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington */ 160fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 161fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington if (pthread_equal (pmutex->holder, self)) 162fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington { 163fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington /* We already have the lock. */ 164fd27857e31dc6bd7b78ddddbb6ef3f1162ee0b88Havoc Pennington _dbus_assert (pmutex->count > 0); 165fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington } 166fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington else 167fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington { 168fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington /* Wait for the lock */ 169fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington PTHREAD_CHECK ("pthread_mutex_lock", pthread_mutex_lock (&pmutex->lock)); 170c0dbd2a2b5ce42612b1bffe778d6127682cddb45Thiago Macieira pmutex->holder = self; 171fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_assert (pmutex->count == 0); 172fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington } 173fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 174fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington pmutex->count += 1; 175fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington } 1765886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington} 1775886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 178fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Penningtonstatic void 1795886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington_dbus_pthread_mutex_unlock (DBusMutex *mutex) 1805886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington{ 181bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); 182bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 183fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_assert (pmutex->count > 0); 184fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 185fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington pmutex->count -= 1; 186bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 187fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington if (pmutex->count == 0) 188fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington PTHREAD_CHECK ("pthread_mutex_unlock", pthread_mutex_unlock (&pmutex->lock)); 189fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 190fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington /* We leave pmutex->holder set to ourselves, its content is undefined if count is 0 */ 1915886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington} 1925886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 1935886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Penningtonstatic DBusCondVar * 1945886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington_dbus_pthread_condvar_new (void) 1955886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington{ 196bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington DBusCondVarPThread *pcond; 197ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters pthread_condattr_t attr; 198bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington int result; 1995886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 200bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington pcond = dbus_new (DBusCondVarPThread, 1); 201bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington if (pcond == NULL) 2025886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington return NULL; 203bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 204ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters pthread_condattr_init (&attr); 205ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters#ifdef HAVE_MONOTONIC_CLOCK 206ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters if (have_monotonic_clock) 207ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters pthread_condattr_setclock (&attr, CLOCK_MONOTONIC); 208ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters#endif 209ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters 210ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters result = pthread_cond_init (&pcond->cond, &attr); 211ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters pthread_condattr_destroy (&attr); 212bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 213bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington if (result == EAGAIN || result == ENOMEM) 2145886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington { 215bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington dbus_free (pcond); 2165886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington return NULL; 2175886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington } 218bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington else 219bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington { 220bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington PTHREAD_CHECK ("pthread_cond_init", result); 221bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington } 222bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 223bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington return DBUS_COND_VAR (pcond); 2245886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington} 2255886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 2265886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Penningtonstatic void 2275886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington_dbus_pthread_condvar_free (DBusCondVar *cond) 228bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington{ 229bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); 230bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 231bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington PTHREAD_CHECK ("pthread_cond_destroy", pthread_cond_destroy (&pcond->cond)); 232bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 233bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington dbus_free (pcond); 2345886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington} 2355886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 2365886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Penningtonstatic void 2375886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington_dbus_pthread_condvar_wait (DBusCondVar *cond, 238bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington DBusMutex *mutex) 2395886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington{ 240bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); 241bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); 242fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington int old_count; 243bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 244fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_assert (pmutex->count > 0); 245fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_assert (pthread_equal (pmutex->holder, pthread_self ())); 246fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 247fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington old_count = pmutex->count; 248c0dbd2a2b5ce42612b1bffe778d6127682cddb45Thiago Macieira pmutex->count = 0; /* allow other threads to lock */ 249bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington PTHREAD_CHECK ("pthread_cond_wait", pthread_cond_wait (&pcond->cond, &pmutex->lock)); 250fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_assert (pmutex->count == 0); 251c0dbd2a2b5ce42612b1bffe778d6127682cddb45Thiago Macieira pmutex->holder = pthread_self(); /* other threads may have locked the mutex in the meantime */ 252537eaff5de9aace3348436166d4cde7adc1e488eMatthew Xie 253537eaff5de9aace3348436166d4cde7adc1e488eMatthew Xie /* The order of this line and the above line is important. 254537eaff5de9aace3348436166d4cde7adc1e488eMatthew Xie * See the comments below at the end of _dbus_pthread_condvar_wait_timeout 255537eaff5de9aace3348436166d4cde7adc1e488eMatthew Xie */ 256537eaff5de9aace3348436166d4cde7adc1e488eMatthew Xie pmutex->count = old_count; 2575886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington} 2585886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 2595886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Penningtonstatic dbus_bool_t 2605886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington_dbus_pthread_condvar_wait_timeout (DBusCondVar *cond, 261bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington DBusMutex *mutex, 262bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington int timeout_milliseconds) 2635886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington{ 264bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington DBusMutexPThread *pmutex = DBUS_MUTEX_PTHREAD (mutex); 265bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); 2665886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington struct timeval time_now; 2675886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington struct timespec end_time; 2685886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington int result; 269fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington int old_count; 270fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 271fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_assert (pmutex->count > 0); 272fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_assert (pthread_equal (pmutex->holder, pthread_self ())); 273ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters 274ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters#ifdef HAVE_MONOTONIC_CLOCK 275ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters if (have_monotonic_clock) 276ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters { 277ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters struct timespec monotonic_timer; 278ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters clock_gettime (CLOCK_MONOTONIC,&monotonic_timer); 279ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters time_now.tv_sec = monotonic_timer.tv_sec; 280ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters time_now.tv_usec = monotonic_timer.tv_nsec / 1000; 281ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters } 282ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters else 283ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters /* This else falls through to gettimeofday */ 284ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters#endif 2855886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington gettimeofday (&time_now, NULL); 2865886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 2875886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington end_time.tv_sec = time_now.tv_sec + timeout_milliseconds / 1000; 2885886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington end_time.tv_nsec = (time_now.tv_usec + (timeout_milliseconds % 1000) * 1000) * 1000; 2895886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington if (end_time.tv_nsec > 1000*1000*1000) 2905886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington { 2915886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington end_time.tv_sec += 1; 2925886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington end_time.tv_nsec -= 1000*1000*1000; 2935886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington } 294bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 295fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington old_count = pmutex->count; 296fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington pmutex->count = 0; 297bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington result = pthread_cond_timedwait (&pcond->cond, &pmutex->lock, &end_time); 298fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 299bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington if (result != ETIMEDOUT) 300bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington { 301bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington PTHREAD_CHECK ("pthread_cond_timedwait", result); 302bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington } 303fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington 304fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_assert (pmutex->count == 0); 305c0dbd2a2b5ce42612b1bffe778d6127682cddb45Thiago Macieira pmutex->holder = pthread_self(); /* other threads may have locked the mutex in the meantime */ 306537eaff5de9aace3348436166d4cde7adc1e488eMatthew Xie 307537eaff5de9aace3348436166d4cde7adc1e488eMatthew Xie /* restore to old count after setting the owner back to self, 308537eaff5de9aace3348436166d4cde7adc1e488eMatthew Xie * If reversing this line with above line, the previous owner thread could 309537eaff5de9aace3348436166d4cde7adc1e488eMatthew Xie * get into the mutex without proper locking by passing the lock owner check. 310537eaff5de9aace3348436166d4cde7adc1e488eMatthew Xie */ 311537eaff5de9aace3348436166d4cde7adc1e488eMatthew Xie pmutex->count = old_count; 3125886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 3135886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington /* return true if we did not time out */ 3145886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington return result != ETIMEDOUT; 3155886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington} 3165886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 3175886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Penningtonstatic void 3185886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington_dbus_pthread_condvar_wake_one (DBusCondVar *cond) 3195886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington{ 320bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); 321bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 322bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington PTHREAD_CHECK ("pthread_cond_signal", pthread_cond_signal (&pcond->cond)); 3235886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington} 3245886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 3255886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Penningtonstatic void 3265886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington_dbus_pthread_condvar_wake_all (DBusCondVar *cond) 3275886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington{ 328bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington DBusCondVarPThread *pcond = DBUS_COND_VAR_PTHREAD (cond); 329bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington 330bdbbf46ca88ac43bec9c36909990730d102983c5Havoc Pennington PTHREAD_CHECK ("pthread_cond_broadcast", pthread_cond_broadcast (&pcond->cond)); 3315886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington} 3325886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 3335886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Penningtonstatic const DBusThreadFunctions pthread_functions = 3345886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington{ 335fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_NEW_MASK | 336fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_FREE_MASK | 337fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_LOCK_MASK | 338fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_UNLOCK_MASK | 3395886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK | 3405886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK | 3415886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK | 3425886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK | 3435886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK| 3445886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK, 345fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington NULL, NULL, NULL, NULL, 3465886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington _dbus_pthread_condvar_new, 3475886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington _dbus_pthread_condvar_free, 3485886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington _dbus_pthread_condvar_wait, 3495886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington _dbus_pthread_condvar_wait_timeout, 3505886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington _dbus_pthread_condvar_wake_one, 351fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_pthread_condvar_wake_all, 352fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_pthread_mutex_new, 353fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_pthread_mutex_free, 354fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_pthread_mutex_lock, 355fbfec98d0f3ad5232dd6cbd63acbdd008acf2578Havoc Pennington _dbus_pthread_mutex_unlock 3565886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington}; 3575886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington 358ae24bb35e2ee3ecde990f55852982b573754ec43Colin Waltersstatic void 359ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walterscheck_monotonic_clock (void) 360ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters{ 361ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters#ifdef HAVE_MONOTONIC_CLOCK 362ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters struct timespec dummy; 363ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0) 364ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters have_monotonic_clock = TRUE; 365ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters#endif 366ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters} 367ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters 3685886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Penningtondbus_bool_t 3695886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington_dbus_threads_init_platform_specific (void) 3705886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington{ 371ae24bb35e2ee3ecde990f55852982b573754ec43Colin Walters check_monotonic_clock (); 3725886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington return dbus_threads_init (&pthread_functions); 3735886f5326da2dbe8f1a7c97736d544fa4cef169bHavoc Pennington} 374