db

mutex.h

Go to the documentation of this file.
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. */

Generated on Sun Jun 8 10:56:38 2008 for GNUmifluz by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /