1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996,2008 Oracle. All rights reserved. 5 * 6 * $Id: mutex.h,v 12.31 2008/01/08 20:58:18 bostic Exp $ 7 */ 8 9#ifndef _DB_MUTEX_H_ 10#define _DB_MUTEX_H_ 11 12#if defined(__cplusplus) 13extern "C" { 14#endif 15 16/* 17 * By default, spin 50 times per processor if fail to acquire a test-and-set 18 * mutex, we have anecdotal evidence it's a reasonable value. 19 */ 20#define MUTEX_SPINS_PER_PROCESSOR 50 21 22/* 23 * Mutexes are represented by unsigned, 32-bit integral values. As the 24 * OOB value is 0, mutexes can be initialized by zero-ing out the memory 25 * in which they reside. 26 */ 27#define MUTEX_INVALID 0 28 29/* 30 * We track mutex allocations by ID. 31 */ 32#define MTX_APPLICATION 1 33#define MTX_DB_HANDLE 2 34#define MTX_ENV_DBLIST 3 35#define MTX_ENV_HANDLE 4 36#define MTX_ENV_REGION 5 37#define MTX_LOCK_REGION 6 38#define MTX_LOGICAL_LOCK 7 39#define MTX_LOG_FILENAME 8 40#define MTX_LOG_FLUSH 9 41#define MTX_LOG_HANDLE 10 42#define MTX_LOG_REGION 11 43#define MTX_MPOOLFILE_HANDLE 12 44#define MTX_MPOOL_FH 13 45#define MTX_MPOOL_FILE_BUCKET 14 46#define MTX_MPOOL_HANDLE 15 47#define MTX_MPOOL_HASH_BUCKET 16 48#define MTX_MPOOL_IO 17 49#define MTX_MPOOL_REGION 18 50#define MTX_MUTEX_REGION 19 51#define MTX_MUTEX_TEST 20 52#define MTX_REP_CHKPT 21 53#define MTX_REP_DATABASE 22 54#define MTX_REP_EVENT 23 55#define MTX_REP_REGION 24 56#define MTX_SEQUENCE 25 57#define MTX_TWISTER 26 58#define MTX_TXN_ACTIVE 27 59#define MTX_TXN_CHKPT 28 60#define MTX_TXN_COMMIT 29 61#define MTX_TXN_MVCC 30 62#define MTX_TXN_REGION 31 63 64#define MTX_MAX_ENTRY 31 65 66/* Redirect mutex calls to the correct functions. */ 67#if !defined(HAVE_MUTEX_HYBRID) && ( \ 68 defined(HAVE_MUTEX_PTHREADS) || \ 69 defined(HAVE_MUTEX_SOLARIS_LWP) || \ 70 defined(HAVE_MUTEX_UI_THREADS)) 71#define __mutex_init(a, b, c) __db_pthread_mutex_init(a, b, c) 72#define __mutex_lock(a, b) __db_pthread_mutex_lock(a, b) 73#define __mutex_unlock(a, b) __db_pthread_mutex_unlock(a, b) 74#define __mutex_destroy(a, b) __db_pthread_mutex_destroy(a, b) 75#elif defined(HAVE_MUTEX_WIN32) || defined(HAVE_MUTEX_WIN32_GCC) 76#define __mutex_init(a, b, c) __db_win32_mutex_init(a, b, c) 77#define __mutex_lock(a, b) __db_win32_mutex_lock(a, b) 78#define __mutex_unlock(a, b) __db_win32_mutex_unlock(a, b) 79#define __mutex_destroy(a, b) __db_win32_mutex_destroy(a, b) 80#elif defined(HAVE_MUTEX_FCNTL) 81#define __mutex_init(a, b, c) __db_fcntl_mutex_init(a, b, c) 82#define __mutex_lock(a, b) __db_fcntl_mutex_lock(a, b) 83#define __mutex_unlock(a, b) __db_fcntl_mutex_unlock(a, b) 84#define __mutex_destroy(a, b) __db_fcntl_mutex_destroy(a, b) 85#else 86#define __mutex_init(a, b, c) __db_tas_mutex_init(a, b, c) 87#define __mutex_lock(a, b) __db_tas_mutex_lock(a, b) 88#define __mutex_unlock(a, b) __db_tas_mutex_unlock(a, b) 89#define __mutex_destroy(a, b) __db_tas_mutex_destroy(a, b) 90#endif 91 92/* 93 * Lock/unlock a mutex. If the mutex was never required, the thread of 94 * control can proceed without it. 95 * 96 * We never fail to acquire or release a mutex without panicing. Simplify 97 * the macros to always return a panic value rather than saving the actual 98 * return value of the mutex routine. 99 */ 100#ifdef HAVE_MUTEX_SUPPORT 101#define MUTEX_LOCK(dbenv, mutex) do { \ 102 if ((mutex) != MUTEX_INVALID && \ 103 __mutex_lock(dbenv, mutex) != 0) \ 104 return (DB_RUNRECOVERY); \ 105} while (0) 106#define MUTEX_UNLOCK(dbenv, mutex) do { \ 107 if ((mutex) != MUTEX_INVALID && \ 108 __mutex_unlock(dbenv, mutex) != 0) \ 109 return (DB_RUNRECOVERY); \ 110} while (0) 111#else 112/* 113 * XXX 114 * There are calls to lock/unlock mutexes outside of #ifdef's -- replace 115 * the call with something the compiler can discard, but which will make 116 * if-then-else blocks work correctly. 117 */ 118#define MUTEX_LOCK(dbenv, mutex) \ 119 (mutex) = (mutex); 120#define MUTEX_UNLOCK(dbenv, mutex) \ 121 (mutex) = (mutex); 122#endif 123 124/* 125 * Berkeley DB ports may require single-threading at places in the code. 126 */ 127#ifdef HAVE_MUTEX_VXWORKS 128#include "taskLib.h" 129/* 130 * Use the taskLock() mutex to eliminate a race where two tasks are 131 * trying to initialize the global lock at the same time. 132 */ 133#define DB_BEGIN_SINGLE_THREAD do { \ 134 if (DB_GLOBAL(db_global_init)) \ 135 (void)semTake(DB_GLOBAL(db_global_lock), WAIT_FOREVER); \ 136 else { \ 137 taskLock(); \ 138 if (DB_GLOBAL(db_global_init)) { \ 139 taskUnlock(); \ 140 (void)semTake(DB_GLOBAL(db_global_lock), \ 141 WAIT_FOREVER); \ 142 continue; \ 143 } \ 144 DB_GLOBAL(db_global_lock) = \ 145 semBCreate(SEM_Q_FIFO, SEM_EMPTY); \ 146 if (DB_GLOBAL(db_global_lock) != NULL) \ 147 DB_GLOBAL(db_global_init) = 1; \ 148 taskUnlock(); \ 149 } \ 150} while (DB_GLOBAL(db_global_init) == 0) 151#define DB_END_SINGLE_THREAD (void)semGive(DB_GLOBAL(db_global_lock)) 152#endif 153 154/* 155 * Single-threading defaults to a no-op. 156 */ 157#ifndef DB_BEGIN_SINGLE_THREAD 158#define DB_BEGIN_SINGLE_THREAD 159#endif 160#ifndef DB_END_SINGLE_THREAD 161#define DB_END_SINGLE_THREAD 162#endif 163 164#if defined(__cplusplus) 165} 166#endif 167 168#include "dbinc_auto/mutex_ext.h" 169#endif /* !_DB_MUTEX_H_ */ 170