00001 /*- 00002 * See the file LICENSE for redistribution information. 00003 * 00004 * Copyright (c) 1996, 1997, 1998, 1999, 2000 00005 * Sleepycat Software. All rights reserved. 00006 * 00007 * $Id: mutex_8h-source.html,v 1.1 2008年06月08日 10:20:57 sebdiaz Exp $ 00008 */ 00009 00010 #define DB_BEGIN_SINGLE_THREAD 00011 #define DB_END_SINGLE_THREAD 00012 00013 /********************************************************************* 00014 * POSIX.1 pthreads interface. 00015 *********************************************************************/ 00016 #ifdef HAVE_MUTEX_PTHREADS 00017 #include <pthread.h> 00018 00019 #define MUTEX_FIELDS \ 00020 pthread_mutex_t mutex; /* Mutex. */ \ 00021 pthread_cond_t cond; /* Condition variable. */ 00022 #endif 00023 00024 /********************************************************************* 00025 * Solaris lwp threads interface. 00026 * 00027 * !!! 00028 * We use LWP mutexes on Solaris instead of UI or POSIX mutexes (both of 00029 * which are available), for two reasons. First, the Solaris C library 00030 * includes versions of the both UI and POSIX thread mutex interfaces, but 00031 * they are broken in that they don't support inter-process locking, and 00032 * there's no way to detect it, e.g., calls to configure the mutexes for 00033 * inter-process locking succeed without error. So, we use LWP mutexes so 00034 * that we don't fail in fairly undetectable ways because the application 00035 * wasn't linked with the appropriate threads library. Second, there were 00036 * bugs in SunOS 5.7 (Solaris 7) where if an application loaded the C library 00037 * before loading the libthread/libpthread threads libraries (e.g., by using 00038 * dlopen to load the DB library), the pwrite64 interface would be translated 00039 * into a call to pwrite and DB would drop core. 00040 *********************************************************************/ 00041 #ifdef HAVE_MUTEX_SOLARIS_LWP 00042 /* 00043 * XXX 00044 * Don't change <synch.h> to <sys/lwp.h> -- although lwp.h is listed in the 00045 * Solaris manual page as the correct include to use, it causes the Solaris 00046 * compiler on SunOS 2.6 to fail. 00047 */ 00048 #include <synch.h> 00049 00050 #define MUTEX_FIELDS \ 00051 lwp_mutex_t mutex; /* Mutex. */ \ 00052 lwp_cond_t cond; /* Condition variable. */ 00053 #endif 00054 00055 /********************************************************************* 00056 * Solaris/Unixware threads interface. 00057 *********************************************************************/ 00058 #ifdef HAVE_MUTEX_UI_THREADS 00059 #include <thread.h> 00060 #include <synch.h> 00061 00062 #define MUTEX_FIELDS \ 00063 mutex_t mutex; /* Mutex. */ \ 00064 cond_t cond; /* Condition variable. */ 00065 #endif 00066 00067 /********************************************************************* 00068 * AIX C library functions. 00069 *********************************************************************/ 00070 #ifdef HAVE_MUTEX_AIX_CHECK_LOCK 00071 #include <sys/atomic_op.h> 00072 typedef int tsl_t; 00073 00074 #define MUTEX_INIT(x) 0 00075 #define MUTEX_ALIGN sizeof(int) 00076 #define MUTEX_SET(x) (!_check_lock(x, 0, 1)) 00077 #define MUTEX_UNSET(x) _clear_lock(x, 0) 00078 #endif 00079 00080 /********************************************************************* 00081 * General C library functions (msemaphore). 00082 * 00083 * !!! 00084 * Check for HPPA as a special case, because it requires unusual alignment, 00085 * and doesn't support semaphores in malloc(3) or shmget(2) memory. 00086 * 00087 * !!! 00088 * Do not remove the MSEM_IF_NOWAIT flag. The problem is that if a single 00089 * process makes two msem_lock() calls in a row, the second one returns an 00090 * error. We depend on the fact that we can lock against ourselves in the 00091 * locking subsystem, where we set up a mutex so that we can block ourselves. 00092 * Tested on OSF1 v4.0. 00093 *********************************************************************/ 00094 #ifdef HAVE_MUTEX_HPPA_MSEM_INIT 00095 #define MUTEX_NO_MALLOC_LOCKS 00096 #define MUTEX_NO_SHMGET_LOCKS 00097 00098 #define MUTEX_ALIGN 16 00099 #endif 00100 00101 #if defined(HAVE_MUTEX_MSEM_INIT) || defined(HAVE_MUTEX_HPPA_MSEM_INIT) 00102 #include <sys/mman.h> 00103 typedef msemaphore tsl_t; 00104 00105 #ifndef MUTEX_ALIGN 00106 #define MUTEX_ALIGN sizeof(int) 00107 #endif 00108 #define MUTEX_INIT(x) (msem_init(x, MSEM_UNLOCKED) <= (msemaphore *)0) 00109 #define MUTEX_SET(x) (!msem_lock(x, MSEM_IF_NOWAIT)) 00110 #define MUTEX_UNSET(x) msem_unlock(x, 0) 00111 #endif 00112 00113 /********************************************************************* 00114 * MacOS. 00115 * 00116 * !!! 00117 * We should simplify this by always returning a no-need-to-lock lock 00118 * when we initialize the mutex. 00119 *********************************************************************/ 00120 #ifdef HAVE_MUTEX_MACOS 00121 typedef unsigned char tsl_t; 00122 00123 #define MUTEX_INIT(x) 0 00124 #endif 00125 00126 /********************************************************************* 00127 * Reliant UNIX C library functions. 00128 *********************************************************************/ 00129 #ifdef HAVE_MUTEX_RELIANTUNIX_INITSPIN 00130 #include <ulocks.h> 00131 typedef spinlock_t tsl_t; 00132 00133 #define MUTEX_INIT(x) (initspin(x, 1), 0) 00134 #define MUTEX_SET(x) (cspinlock(x) == 0) 00135 #define MUTEX_UNSET(x) spinunlock(x) 00136 #endif 00137 00138 /********************************************************************* 00139 * General C library functions (POSIX 1003.1 sema_XXX). 00140 * 00141 * !!! 00142 * Never selected by autoconfig in this release (semaphore calls are known 00143 * to not work in Solaris 5.5). 00144 *********************************************************************/ 00145 #ifdef HAVE_MUTEX_SEMA_INIT 00146 #include <synch.h> 00147 typedef sema_t tsl_t; 00148 00149 #define MUTEX_ALIGN sizeof(int) 00150 #define MUTEX_INIT(x) (sema_init(x, 1, USYNC_PROCESS, NULL) != 0) 00151 #define MUTEX_SET(x) (sema_wait(x) == 0) 00152 #define MUTEX_UNSET(x) sema_post(x) 00153 #endif 00154 00155 /********************************************************************* 00156 * SGI C library functions. 00157 *********************************************************************/ 00158 #ifdef HAVE_MUTEX_SGI_INIT_LOCK 00159 #include <abi_mutex.h> 00160 typedef abilock_t tsl_t; 00161 00162 #define MUTEX_ALIGN sizeof(int) 00163 #define MUTEX_INIT(x) (init_lock(x) != 0) 00164 #define MUTEX_SET(x) (!acquire_lock(x)) 00165 #define MUTEX_UNSET(x) release_lock(x) 00166 #endif 00167 00168 /********************************************************************* 00169 * Solaris C library functions. 00170 * 00171 * !!! 00172 * These are undocumented functions, but they're the only ones that work 00173 * correctly as far as we know. 00174 *********************************************************************/ 00175 #ifdef HAVE_MUTEX_SOLARIS_LOCK_TRY 00176 #include <sys/machlock.h> 00177 typedef lock_t tsl_t; 00178 00179 #define MUTEX_ALIGN sizeof(int) 00180 #define MUTEX_INIT(x) 0 00181 #define MUTEX_SET(x) _lock_try(x) 00182 #define MUTEX_UNSET(x) _lock_clear(x) 00183 #endif 00184 00185 /********************************************************************* 00186 * VMS. 00187 *********************************************************************/ 00188 #ifdef HAVE_MUTEX_VMS 00189 #include <sys/mman.h>; 00190 #include <builtins.h> 00191 typedef unsigned char tsl_t; 00192 00193 #define MUTEX_ALIGN sizeof(unsigned int) 00194 #ifdef __ALPHA 00195 #define MUTEX_SET(tsl) (!__TESTBITSSI(tsl, 0)) 00196 #else /* __VAX */ 00197 #define MUTEX_SET(tsl) (!(int)_BBSSI(0, tsl)) 00198 #endif 00199 #define MUTEX_UNSET(tsl) (*(tsl) = 0) 00200 #define MUTEX_INIT(tsl) MUTEX_UNSET(tsl) 00201 #endif 00202 00203 /********************************************************************* 00204 * VxWorks 00205 * Use basic binary semaphores in VxWorks, as we currently do not need 00206 * any special features. We do need the ability to single-thread the 00207 * entire system, however, because VxWorks doesn't support the open(2) 00208 * flag O_EXCL, the mechanism we normally use to single thread access 00209 * when we're first looking for a DB environment. 00210 *********************************************************************/ 00211 #ifdef HAVE_MUTEX_VXWORKS 00212 #include "semLib.h" 00213 typedef SEM_ID tsl_t; 00214 00215 #define MUTEX_ALIGN sizeof(unsigned int) 00216 #define MUTEX_SET(tsl) (semTake((*tsl), WAIT_FOREVER) == OK) 00217 #define MUTEX_UNSET(tsl) (semGive((*tsl)) == OK) 00218 #define MUTEX_INIT(tsl) \ 00219 ((*(tsl) = semBCreate(SEM_Q_FIFO, SEM_FULL)) == NULL) 00220 00221 #undef DB_BEGIN_SINGLE_THREAD 00222 /* 00223 * Use the taskLock() mutex to eliminate a race where two tasks are 00224 * trying to initialize the global lock at the same time. 00225 */ 00226 #define DB_BEGIN_SINGLE_THREAD \ 00227 do { \ 00228 if (DB_GLOBAL(db_global_init)) \ 00229 (void)semTake(DB_GLOBAL(db_global_lock), WAIT_FOREVER); \ 00230 else { \ 00231 taskLock(); \ 00232 if (DB_GLOBAL(db_global_init)) { \ 00233 taskUnlock(); \ 00234 (void)semTake(DB_GLOBAL(db_global_lock), \ 00235 WAIT_FOREVER); \ 00236 continue; \ 00237 } \ 00238 DB_GLOBAL(db_global_lock) = \ 00239 semBCreate(SEM_Q_FIFO, SEM_EMPTY); \ 00240 if (DB_GLOBAL(db_global_lock) != NULL) \ 00241 DB_GLOBAL(db_global_init) = 1; \ 00242 taskUnlock(); \ 00243 } \ 00244 } while (DB_GLOBAL(db_global_init) == 0) 00245 #undef DB_END_SINGLE_THREAD 00246 #define DB_END_SINGLE_THREAD (void)semGive(DB_GLOBAL(db_global_lock)) 00247 #endif 00248 00249 /********************************************************************* 00250 * Win16 00251 * 00252 * Win16 spinlocks are simple because we cannot possibly be preempted. 00253 * 00254 * !!! 00255 * We should simplify this by always returning a no-need-to-lock lock 00256 * when we initialize the mutex. 00257 *********************************************************************/ 00258 #ifdef HAVE_MUTEX_WIN16 00259 typedef unsigned int tsl_t; 00260 00261 #define MUTEX_ALIGN sizeof(unsigned int) 00262 #define MUTEX_INIT(x) 0 00263 #define MUTEX_SET(tsl) (*(tsl) = 1) 00264 #define MUTEX_UNSET(tsl) (*(tsl) = 0) 00265 #endif 00266 00267 /********************************************************************* 00268 * Win32 00269 *********************************************************************/ 00270 #ifdef HAVE_MUTEX_WIN32 00271 typedef unsigned int tsl_t; 00272 00273 #define MUTEX_ALIGN sizeof(unsigned int) 00274 #define MUTEX_INIT(x) 0 00275 #define MUTEX_SET(tsl) (!InterlockedExchange((PLONG)tsl, 1)) 00276 #define MUTEX_UNSET(tsl) (*(tsl) = 0) 00277 #endif 00278 00279 /********************************************************************* 00280 * 68K/gcc assembly. 00281 *********************************************************************/ 00282 #ifdef HAVE_MUTEX_68K_GCC_ASSEMBLY 00283 typedef unsigned char tsl_t; 00284 #endif 00285 00286 /********************************************************************* 00287 * ALPHA/gcc assembly. 00288 *********************************************************************/ 00289 #ifdef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY 00290 typedef u_int32_t tsl_t; 00291 00292 #define MUTEX_ALIGN 4 00293 #endif 00294 00295 /********************************************************************* 00296 * HPPA/gcc assembly. 00297 *********************************************************************/ 00298 #ifdef HAVE_MUTEX_HPPA_GCC_ASSEMBLY 00299 typedef u_int32_t tsl_t; 00300 00301 #define MUTEX_ALIGN 16 00302 #endif 00303 00304 /********************************************************************* 00305 * IA64/gcc assembly. 00306 *********************************************************************/ 00307 #ifdef HAVE_MUTEX_IA64_GCC_ASSEMBLY 00308 typedef unsigned char tsl_t; 00309 #endif 00310 00311 /********************************************************************* 00312 * SCO/cc assembly. 00313 *********************************************************************/ 00314 #ifdef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY 00315 typedef unsigned char tsl_t; 00316 #endif 00317 00318 /********************************************************************* 00319 * Sparc/gcc assembly. 00320 *********************************************************************/ 00321 #ifdef HAVE_MUTEX_SPARC_GCC_ASSEMBLY 00322 typedef unsigned char tsl_t; 00323 #endif 00324 00325 /********************************************************************* 00326 * UTS/cc assembly. 00327 *********************************************************************/ 00328 #ifdef HAVE_MUTEX_UTS_CC_ASSEMBLY 00329 typedef int tsl_t; 00330 00331 #define MUTEX_ALIGN sizeof(int) 00332 #define MUTEX_INIT(x) 0 00333 #define MUTEX_SET(x) (!uts_lock(x, 1)) 00334 #define MUTEX_UNSET(x) (*(x) = 0) 00335 #endif 00336 00337 /********************************************************************* 00338 * x86/gcc assembly. 00339 *********************************************************************/ 00340 #ifdef HAVE_MUTEX_X86_GCC_ASSEMBLY 00341 typedef unsigned char tsl_t; 00342 #endif 00343 00344 /* 00345 * Mutex alignment defaults to one byte. 00346 * 00347 * !!! 00348 * Various systems require different alignments for mutexes (the worst we've 00349 * seen so far is 16-bytes on some HP architectures). Malloc(3) is assumed 00350 * to return reasonable alignment, all other mutex users must ensure proper 00351 * alignment locally. 00352 */ 00353 #ifndef MUTEX_ALIGN 00354 #define MUTEX_ALIGN 1 00355 #endif 00356 00357 #define MUTEX_IGNORE 0x001 /* Ignore, no lock required. */ 00358 #define MUTEX_SELF_BLOCK 0x002 /* Must block self. */ 00359 #define MUTEX_THREAD 0x004 /* Thread-only mutex. */ 00360 00361 /* Mutex. */ 00362 struct __mutex_t { 00363 #ifdef HAVE_MUTEX_THREADS 00364 #ifdef MUTEX_FIELDS 00365 MUTEX_FIELDS 00366 #else 00367 tsl_t tas; /* Test and set. */ 00368 #endif 00369 u_int32_t spins; /* Spins before block. */ 00370 u_int32_t locked; /* !0 if locked. */ 00371 #else 00372 u_int32_t off; /* Byte offset to lock. */ 00373 u_int32_t pid; /* Lock holder: 0 or process pid. */ 00374 #endif 00375 u_int32_t mutex_set_wait; /* Granted after wait. */ 00376 u_int32_t mutex_set_nowait; /* Granted without waiting. */ 00377 00378 u_int8_t flags; /* MUTEX_XXX */ 00379 }; 00380 00381 /* Redirect calls to the correct functions. */ 00382 #ifdef HAVE_MUTEX_THREADS 00383 #if defined(HAVE_MUTEX_PTHREADS) || defined(HAVE_MUTEX_SOLARIS_LWP) || defined(HAVE_MUTEX_UI_THREADS) 00384 #define __db_mutex_init(a, b, c, d) __db_pthread_mutex_init(a, b, d) 00385 #define __db_mutex_lock(a, b) __db_pthread_mutex_lock(a) 00386 #define __db_mutex_unlock(a) __db_pthread_mutex_unlock(a) 00387 #else 00388 #define __db_mutex_init(a, b, c, d) CDB___db_tas_mutex_init(a, b, d) 00389 #define __db_mutex_lock(a, b) CDB___db_tas_mutex_lock(a) 00390 #define __db_mutex_unlock(a) CDB___db_tas_mutex_unlock(a) 00391 #endif 00392 #else 00393 #define __db_mutex_init(a, b, c, d) __db_fcntl_mutex_init(a, b, c) 00394 #define __db_mutex_lock(a, b) __db_fcntl_mutex_lock(a, b) 00395 #define __db_mutex_unlock(a) __db_fcntl_mutex_unlock(a) 00396 #endif 00397 00398 /* 00399 * Lock/unlock a mutex. If the mutex was marked as uninteresting, the thread 00400 * of control can proceed without it. 00401 * 00402 * If the lock is for threads-only, then it was optionally not allocated and 00403 * file handles aren't necessary, as threaded applications aren't supported by 00404 * fcntl(2) locking. 00405 */ 00406 #ifdef DIAGNOSTIC 00407 /* 00408 * XXX 00409 * We want to switch threads as often as possible. Yield every time 00410 * we get a mutex to ensure contention. 00411 */ 00412 #define MUTEX_LOCK(mp, fh) \ 00413 if (!F_ISSET((MUTEX *)(mp), MUTEX_IGNORE)) \ 00414 (void)__db_mutex_lock(mp, fh); \ 00415 if (DB_GLOBAL(db_pageyield)) \ 00416 CDB___os_yield(NULL, 1); 00417 #else 00418 #define MUTEX_LOCK(mp, fh) \ 00419 if (!F_ISSET((MUTEX *)(mp), MUTEX_IGNORE)) \ 00420 (void)__db_mutex_lock(mp, fh); 00421 #endif 00422 #define MUTEX_UNLOCK(mp) \ 00423 if (!F_ISSET((MUTEX *)(mp), MUTEX_IGNORE)) \ 00424 (void)__db_mutex_unlock(mp); 00425 #define MUTEX_THREAD_LOCK(mp) \ 00426 if (mp != NULL) \ 00427 MUTEX_LOCK(mp, NULL) 00428 #define MUTEX_THREAD_UNLOCK(mp) \ 00429 if (mp != NULL) \ 00430 MUTEX_UNLOCK(mp) 00431 00432 /* 00433 * We use a single file descriptor for fcntl(2) locking, and (generally) the 00434 * object's offset in a shared region as the byte that we're locking. So, 00435 * there's a (remote) possibility that two objects might have the same offsets 00436 * such that the locks could conflict, resulting in deadlock. To avoid this 00437 * possibility, we offset the region offset by a small integer value, using a 00438 * different offset for each subsystem's locks. Since all region objects are 00439 * suitably aligned, the offset guarantees that we don't collide with another 00440 * region's objects. 00441 */ 00442 #define DB_FCNTL_OFF_GEN 0 /* Everything else. */ 00443 #define DB_FCNTL_OFF_LOCK 1 /* Lock subsystem offset. */ 00444 #define DB_FCNTL_OFF_MPOOL 2 /* Mpool subsystem offset. */