mutex.h
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:23k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996, 1997, 1998, 1999, 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  *
  7.  * $Id: mutex.h,v 11.41 2000/12/22 19:28:15 bostic Exp $
  8.  */
  9. /*
  10.  * Some of the Berkeley DB ports require single-threading at various
  11.  * places in the code.  In those cases, these #defines will be set.
  12.  */
  13. #define DB_BEGIN_SINGLE_THREAD
  14. #define DB_END_SINGLE_THREAD
  15. /*
  16.  * When the underlying system mutexes require system resources, we have
  17.  * to clean up after application failure.  This violates the rule that
  18.  * we never look at a shared region after a failure, but there's no other
  19.  * choice.  In those cases, this #define is set.
  20.  */
  21. #ifdef HAVE_QNX
  22. #define MUTEX_SYSTEM_RESOURCES
  23. #endif
  24. /*********************************************************************
  25.  * POSIX.1 pthreads interface.
  26.  *********************************************************************/
  27. #ifdef HAVE_MUTEX_PTHREADS
  28. #include <pthread.h>
  29. #define MUTEX_FIELDS
  30. pthread_mutex_t mutex; /* Mutex. */
  31. pthread_cond_t  cond; /* Condition variable. */
  32. #endif
  33. /*********************************************************************
  34.  * Solaris lwp threads interface.
  35.  *
  36.  * !!!
  37.  * We use LWP mutexes on Solaris instead of UI or POSIX mutexes (both of
  38.  * which are available), for two reasons.  First, the Solaris C library
  39.  * includes versions of the both UI and POSIX thread mutex interfaces, but
  40.  * they are broken in that they don't support inter-process locking, and
  41.  * there's no way to detect it, e.g., calls to configure the mutexes for
  42.  * inter-process locking succeed without error.  So, we use LWP mutexes so
  43.  * that we don't fail in fairly undetectable ways because the application
  44.  * wasn't linked with the appropriate threads library.  Second, there were
  45.  * bugs in SunOS 5.7 (Solaris 7) where if an application loaded the C library
  46.  * before loading the libthread/libpthread threads libraries (e.g., by using
  47.  * dlopen to load the DB library), the pwrite64 interface would be translated
  48.  * into a call to pwrite and DB would drop core.
  49.  *********************************************************************/
  50. #ifdef HAVE_MUTEX_SOLARIS_LWP
  51. /*
  52.  * XXX
  53.  * Don't change <synch.h> to <sys/lwp.h> -- although lwp.h is listed in the
  54.  * Solaris manual page as the correct include to use, it causes the Solaris
  55.  * compiler on SunOS 2.6 to fail.
  56.  */
  57. #include <synch.h>
  58. #define MUTEX_FIELDS
  59. lwp_mutex_t mutex; /* Mutex. */
  60. lwp_cond_t cond; /* Condition variable. */
  61. #endif
  62. /*********************************************************************
  63.  * Solaris/Unixware threads interface.
  64.  *********************************************************************/
  65. #ifdef HAVE_MUTEX_UI_THREADS
  66. #include <thread.h>
  67. #include <synch.h>
  68. #define MUTEX_FIELDS
  69. mutex_t mutex; /* Mutex. */
  70. cond_t  cond; /* Condition variable. */
  71. #endif
  72. /*********************************************************************
  73.  * AIX C library functions.
  74.  *********************************************************************/
  75. #ifdef HAVE_MUTEX_AIX_CHECK_LOCK
  76. #include <sys/atomic_op.h>
  77. typedef int tsl_t;
  78. #define MUTEX_ALIGN sizeof(int)
  79. #ifdef LOAD_ACTUAL_MUTEX_CODE
  80. #define MUTEX_INIT(x) 0
  81. #define MUTEX_SET(x) (!_check_lock(x, 0, 1))
  82. #define MUTEX_UNSET(x) _clear_lock(x, 0)
  83. #endif
  84. #endif
  85. /*********************************************************************
  86.  * General C library functions (msemaphore).
  87.  *
  88.  * !!!
  89.  * Check for HPPA as a special case, because it requires unusual alignment,
  90.  * and doesn't support semaphores in malloc(3) or shmget(2) memory.
  91.  *
  92.  * !!!
  93.  * Do not remove the MSEM_IF_NOWAIT flag.  The problem is that if a single
  94.  * process makes two msem_lock() calls in a row, the second one returns an
  95.  * error.  We depend on the fact that we can lock against ourselves in the
  96.  * locking subsystem, where we set up a mutex so that we can block ourselves.
  97.  * Tested on OSF1 v4.0.
  98.  *********************************************************************/
  99. #ifdef HAVE_MUTEX_HPPA_MSEM_INIT
  100. #define MUTEX_NO_MALLOC_LOCKS
  101. #define MUTEX_NO_SHMGET_LOCKS
  102. #define MUTEX_ALIGN 16
  103. #endif
  104. #if defined(HAVE_MUTEX_MSEM_INIT) || defined(HAVE_MUTEX_HPPA_MSEM_INIT)
  105. #include <sys/mman.h>
  106. typedef msemaphore tsl_t;
  107. #ifndef MUTEX_ALIGN
  108. #define MUTEX_ALIGN sizeof(int)
  109. #endif
  110. #ifdef LOAD_ACTUAL_MUTEX_CODE
  111. #define MUTEX_INIT(x) (msem_init(x, MSEM_UNLOCKED) <= (msemaphore *)0)
  112. #define MUTEX_SET(x) (!msem_lock(x, MSEM_IF_NOWAIT))
  113. #define MUTEX_UNSET(x) msem_unlock(x, 0)
  114. #endif
  115. #endif
  116. /*********************************************************************
  117.  * Plan 9 library functions.
  118.  *********************************************************************/
  119. #ifdef HAVE_MUTEX_PLAN9
  120. typedef Lock tsl_t;
  121. #define MUTEX_ALIGN sizeof(int)
  122. #define MUTEX_INIT(x) (memset(x, 0, sizeof(Lock)), 0)
  123. #define MUTEX_SET(x) canlock(x)
  124. #define MUTEX_UNSET(x) unlock(x)
  125. #endif
  126. /*********************************************************************
  127.  * Reliant UNIX C library functions.
  128.  *********************************************************************/
  129. #ifdef HAVE_MUTEX_RELIANTUNIX_INITSPIN
  130. #include <ulocks.h>
  131. typedef spinlock_t tsl_t;
  132. #ifdef LOAD_ACTUAL_MUTEX_CODE
  133. #define MUTEX_INIT(x) (initspin(x, 1), 0)
  134. #define MUTEX_SET(x) (cspinlock(x) == 0)
  135. #define MUTEX_UNSET(x) spinunlock(x)
  136. #endif
  137. #endif
  138. /*********************************************************************
  139.  * General C library functions (POSIX 1003.1 sema_XXX).
  140.  *
  141.  * !!!
  142.  * Never selected by autoconfig in this release (semaphore calls are known
  143.  * to not work in Solaris 5.5).
  144.  *********************************************************************/
  145. #ifdef HAVE_MUTEX_SEMA_INIT
  146. #include <synch.h>
  147. typedef sema_t tsl_t;
  148. #define MUTEX_ALIGN  sizeof(int)
  149. #ifdef LOAD_ACTUAL_MUTEX_CODE
  150. #define MUTEX_DESTROY(x) sema_destroy(x)
  151. #define MUTEX_INIT(x)  (sema_init(x, 1, USYNC_PROCESS, NULL) != 0)
  152. #define MUTEX_SET(x)  (sema_wait(x) == 0)
  153. #define MUTEX_UNSET(x)  sema_post(x)
  154. #endif
  155. #endif
  156. /*********************************************************************
  157.  * SGI C library functions.
  158.  *********************************************************************/
  159. #ifdef HAVE_MUTEX_SGI_INIT_LOCK
  160. #include <abi_mutex.h>
  161. typedef abilock_t tsl_t;
  162. #define MUTEX_ALIGN sizeof(int)
  163. #ifdef LOAD_ACTUAL_MUTEX_CODE
  164. #define MUTEX_INIT(x) (init_lock(x) != 0)
  165. #define MUTEX_SET(x) (!acquire_lock(x))
  166. #define MUTEX_UNSET(x) release_lock(x)
  167. #endif
  168. #endif
  169. /*********************************************************************
  170.  * Solaris C library functions.
  171.  *
  172.  * !!!
  173.  * These are undocumented functions, but they're the only ones that work
  174.  * correctly as far as we know.
  175.  *********************************************************************/
  176. #ifdef HAVE_MUTEX_SOLARIS_LOCK_TRY
  177. #include <sys/machlock.h>
  178. typedef lock_t tsl_t;
  179. #define MUTEX_ALIGN sizeof(int)
  180. #ifdef LOAD_ACTUAL_MUTEX_CODE
  181. #define MUTEX_INIT(x) 0
  182. #define MUTEX_SET(x) _lock_try(x)
  183. #define MUTEX_UNSET(x) _lock_clear(x)
  184. #endif
  185. #endif
  186. /*********************************************************************
  187.  * VMS.
  188.  *********************************************************************/
  189. #ifdef HAVE_MUTEX_VMS
  190. #include <sys/mman.h>;
  191. #include <builtins.h>
  192. typedef unsigned char tsl_t;
  193. #define MUTEX_ALIGN sizeof(unsigned int)
  194. #ifdef LOAD_ACTUAL_MUTEX_CODE
  195. #ifdef __ALPHA
  196. #define MUTEX_SET(tsl) (!__TESTBITSSI(tsl, 0))
  197. #else /* __VAX */
  198. #define MUTEX_SET(tsl) (!(int)_BBSSI(0, tsl))
  199. #endif
  200. #define MUTEX_UNSET(tsl) (*(tsl) = 0)
  201. #define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
  202. #endif
  203. #endif
  204. /*********************************************************************
  205.  * VxWorks
  206.  * Use basic binary semaphores in VxWorks, as we currently do not need
  207.  * any special features.  We do need the ability to single-thread the
  208.  * entire system, however, because VxWorks doesn't support the open(2)
  209.  * flag O_EXCL, the mechanism we normally use to single thread access
  210.  * when we're first looking for a DB environment.
  211.  *********************************************************************/
  212. #ifdef HAVE_MUTEX_VXWORKS
  213. #define MUTEX_SYSTEM_RESOURCES
  214. #include "semLib.h"
  215. typedef SEM_ID tsl_t;
  216. #define MUTEX_ALIGN sizeof(unsigned int)
  217. #ifdef LOAD_ACTUAL_MUTEX_CODE
  218. #define MUTEX_SET(tsl) (semTake((*tsl), WAIT_FOREVER) == OK)
  219. #define MUTEX_UNSET(tsl) (semGive((*tsl)) == OK)
  220. #define MUTEX_INIT(tsl)
  221. ((*(tsl) = semBCreate(SEM_Q_FIFO, SEM_FULL)) == NULL)
  222. #define MUTEX_DESTROY(tsl) semDelete(*tsl)
  223. #endif
  224. /*
  225.  * Use the taskLock() mutex to eliminate a race where two tasks are
  226.  * trying to initialize the global lock at the same time.
  227.  */
  228. #undef DB_BEGIN_SINGLE_THREAD
  229. #define DB_BEGIN_SINGLE_THREAD
  230. do {
  231. if (DB_GLOBAL(db_global_init))
  232. (void)semTake(DB_GLOBAL(db_global_lock), WAIT_FOREVER);
  233. else {
  234. taskLock();
  235. if (DB_GLOBAL(db_global_init)) {
  236. taskUnlock();
  237. (void)semTake(DB_GLOBAL(db_global_lock),
  238.     WAIT_FOREVER);
  239. continue;
  240. }
  241. DB_GLOBAL(db_global_lock) =
  242.     semBCreate(SEM_Q_FIFO, SEM_EMPTY);
  243. if (DB_GLOBAL(db_global_lock) != NULL)
  244. DB_GLOBAL(db_global_init) = 1;
  245. taskUnlock();
  246. }
  247. } while (DB_GLOBAL(db_global_init) == 0)
  248. #undef DB_END_SINGLE_THREAD
  249. #define DB_END_SINGLE_THREAD (void)semGive(DB_GLOBAL(db_global_lock))
  250. #endif
  251. /*********************************************************************
  252.  * Win16
  253.  *
  254.  * Win16 spinlocks are simple because we cannot possibly be preempted.
  255.  *
  256.  * !!!
  257.  * We should simplify this by always returning a no-need-to-lock lock
  258.  * when we initialize the mutex.
  259.  *********************************************************************/
  260. #ifdef HAVE_MUTEX_WIN16
  261. typedef unsigned int tsl_t;
  262. #define MUTEX_ALIGN sizeof(unsigned int)
  263. #ifdef LOAD_ACTUAL_MUTEX_CODE
  264. #define MUTEX_INIT(x) 0
  265. #define MUTEX_SET(tsl) (*(tsl) = 1)
  266. #define MUTEX_UNSET(tsl) (*(tsl) = 0)
  267. #endif
  268. #endif
  269. /*********************************************************************
  270.  * Win32
  271.  *********************************************************************/
  272. #ifdef HAVE_MUTEX_WIN32
  273. typedef unsigned int tsl_t;
  274. #define MUTEX_ALIGN sizeof(unsigned int)
  275. #ifdef LOAD_ACTUAL_MUTEX_CODE
  276. #define MUTEX_INIT(x) 0
  277. #define MUTEX_SET(tsl) (!InterlockedExchange((PLONG)tsl, 1))
  278. #define MUTEX_UNSET(tsl) (*(tsl) = 0)
  279. #endif
  280. #endif
  281. /*********************************************************************
  282.  * 68K/gcc assembly.
  283.  *********************************************************************/
  284. #ifdef HAVE_MUTEX_68K_GCC_ASSEMBLY
  285. typedef unsigned char tsl_t;
  286. #ifdef LOAD_ACTUAL_MUTEX_CODE
  287. /*
  288.  * For gcc/68K, 0 is clear, 1 is set.
  289.  */
  290. #define MUTEX_SET(tsl) ({
  291. register tsl_t *__l = (tsl);
  292. int __r;
  293.     asm volatile("tas  %1; n
  294.   seq  %0"
  295. : "=dm" (__r), "=m" (*__l)
  296. : "1" (*__l)
  297. );
  298. __r & 1;
  299. })
  300. #define MUTEX_UNSET(tsl) (*(tsl) = 0)
  301. #define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
  302. #endif
  303. #endif
  304. /*********************************************************************
  305.  * ALPHA/gcc assembly.
  306.  *********************************************************************/
  307. #ifdef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY
  308. typedef u_int32_t tsl_t;
  309. #define MUTEX_ALIGN 4
  310. #ifdef LOAD_ACTUAL_MUTEX_CODE
  311. /*
  312.  * For gcc/alpha.  Should return 0 if could not acquire the lock, 1 if
  313.  * lock was acquired properly.
  314.  */
  315. #ifdef __GNUC__
  316. static inline int
  317. MUTEX_SET(tsl_t *tsl) {
  318. register tsl_t *__l = tsl;
  319. register tsl_t __r;
  320. asm volatile(
  321. "1: ldl_l %0,%2n"
  322. " blbs %0,2fn"
  323. " or $31,1,%0n"
  324. " stl_c %0,%1n"
  325. " beq %0,3fn"
  326. " mbn"
  327. " br 3fn"
  328. "2: xor %0,%0n"
  329. "3:"
  330. : "=&r"(__r), "=m"(*__l) : "1"(*__l) : "memory");
  331. return __r;
  332. }
  333. /*
  334.  * Unset mutex. Judging by Alpha Architecture Handbook, the mb instruction
  335.  * might be necessary before unlocking
  336.  */
  337. static inline int
  338. MUTEX_UNSET(tsl_t *tsl) {
  339. asm volatile(" mbn");
  340. return *tsl = 0;
  341. }
  342. #endif
  343. #ifdef __DECC
  344. #include <alpha/builtins.h>
  345. #define MUTEX_SET(tsl) (__LOCK_LONG_RETRY((tsl), 1) != 0)
  346. #define MUTEX_UNSET(tsl) (*(tsl) = 0)
  347. #endif
  348. #define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
  349. #endif
  350. #endif
  351. /*********************************************************************
  352.  * HPPA/gcc assembly.
  353.  *********************************************************************/
  354. #ifdef HAVE_MUTEX_HPPA_GCC_ASSEMBLY
  355. typedef u_int32_t tsl_t;
  356. #define MUTEX_ALIGN 16
  357. #ifdef LOAD_ACTUAL_MUTEX_CODE
  358. /*
  359.  * The PA-RISC has a "load and clear" instead of a "test and set" instruction.
  360.  * The 32-bit word used by that instruction must be 16-byte aligned.  We could
  361.  * use the "aligned" attribute in GCC but that doesn't work for stack variables.
  362.  */
  363. #define MUTEX_SET(tsl) ({
  364. register tsl_t *__l = (tsl);
  365. int __r;
  366. asm volatile("ldcws 0(%1),%0" : "=r" (__r) : "r" (__l));
  367. __r & 1;
  368. })
  369. #define MUTEX_UNSET(tsl) (*(tsl) = -1)
  370. #define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
  371. #endif
  372. #endif
  373. /*********************************************************************
  374.  * IA64/gcc assembly.
  375.  *********************************************************************/
  376. #ifdef HAVE_MUTEX_IA64_GCC_ASSEMBLY
  377. typedef unsigned char tsl_t;
  378. #ifdef LOAD_ACTUAL_MUTEX_CODE
  379. /*
  380.  * For gcc/ia64, 0 is clear, 1 is set.
  381.  */
  382. #define MUTEX_SET(tsl) ({
  383. register tsl_t *__l = (tsl);
  384. long __r;
  385. asm volatile("xchg1 %0=%1,%3" : "=r"(__r), "=m"(*__l) : "1"(*__l), "r"(1));
  386. __r ^ 1;
  387. })
  388. /*
  389.  * Store through a "volatile" pointer so we get a store with "release"
  390.  * semantics.
  391.  */
  392. #define MUTEX_UNSET(tsl) (*(volatile unsigned char *)(tsl) = 0)
  393. #define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
  394. #endif
  395. #endif
  396. /*********************************************************************
  397.  * PowerPC/gcc assembly.
  398.  *********************************************************************/
  399. #ifdef HAVE_MUTEX_PPC_GCC_ASSEMBLY
  400. typedef u_int32_t tsl_t;
  401. #ifdef LOAD_ACTUAL_MUTEX_CODE
  402. /*
  403.  * The PowerPC does a sort of pseudo-atomic locking.  You set up a
  404.  * 'reservation' on a chunk of memory containing a mutex by loading the
  405.  * mutex value with LWARX.  If the mutex has an 'unlocked' (arbitrary)
  406.  * value, you then try storing into it with STWCX.  If no other process or
  407.  * thread broke your 'reservation' by modifying the memory containing the
  408.  * mutex, then the STCWX succeeds; otherwise it fails and you try to get
  409.  * a reservation again.
  410.  *
  411.  * While mutexes are explicitly 4 bytes, a 'reservation' applies to an
  412.  * entire cache line, normally 32 bytes, aligned naturally.  If the mutex
  413.  * lives near data that gets changed a lot, there's a chance that you'll
  414.  * see more broken reservations than you might otherwise.  The only
  415.  * situation in which this might be a problem is if one processor is
  416.  * beating on a variable in the same cache block as the mutex while another
  417.  * processor tries to acquire the mutex.  That's bad news regardless
  418.  * because of the way it bashes caches, but if you can't guarantee that a
  419.  * mutex will reside in a relatively quiescent cache line, you might
  420.  * consider padding the mutex to force it to live in a cache line by
  421.  * itself.  No, you aren't guaranteed that cache lines are 32 bytes.  Some
  422.  * embedded processors use 16-byte cache lines, while some 64-bit
  423.  * processors use 128-bit cache lines.  But assuming a 32-byte cache line
  424.  * won't get you into trouble for now.
  425.  *
  426.  * If mutex locking is a bottleneck, then you can speed it up by adding a
  427.  * regular LWZ load before the LWARX load, so that you can test for the
  428.  * common case of a locked mutex without wasting cycles making a reservation.
  429.  *
  430.  * 'set' mutexes have the value 1, like on Intel; the returned value from
  431.  * MUTEX_SET() is 1 if the mutex previously had its low bit set, 0 otherwise.
  432.  */
  433. #define MUTEX_SET(tsl) ({
  434. int __one = 1;
  435. int __r;
  436. tsl_t *__l = (tsl);
  437. asm volatile ("
  438. 0:
  439. lwarx %0,0,%1;
  440. cmpwi %0,0;
  441. bne 1f;
  442. stwcx. %2,0,%1;
  443. bne- 0b;
  444. 1:"
  445. : "=&r" (__r)
  446. : "r" (__l), "r" (__one));
  447. __r & 1;
  448. })
  449. #define MUTEX_UNSET(tsl) (*(tsl) = 0)
  450. #define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
  451. #endif
  452. #endif
  453. /*********************************************************************
  454.  * SCO/cc assembly.
  455.  *********************************************************************/
  456. #ifdef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY
  457. typedef unsigned char tsl_t;
  458. #ifdef LOAD_ACTUAL_MUTEX_CODE
  459. /*
  460.  * UnixWare has threads in libthread, but OpenServer doesn't (yet).
  461.  *
  462.  * For cc/x86, 0 is clear, 1 is set.
  463.  */
  464. #if defined(__USLC__)
  465. asm int
  466. _tsl_set(void *tsl)
  467. {
  468. %mem tsl
  469. movl tsl, %ecx
  470. movl $1, %eax
  471. lock
  472. xchgb (%ecx),%al
  473. xorl $1,%eax
  474. }
  475. #endif
  476. #define MUTEX_SET(tsl) _tsl_set(tsl)
  477. #define MUTEX_UNSET(tsl) (*(tsl) = 0)
  478. #define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
  479. #endif
  480. #endif
  481. /*********************************************************************
  482.  * Sparc/gcc assembly.
  483.  *********************************************************************/
  484. #ifdef HAVE_MUTEX_SPARC_GCC_ASSEMBLY
  485. typedef unsigned char tsl_t;
  486. #ifdef LOAD_ACTUAL_MUTEX_CODE
  487. /*
  488.  *
  489.  * The ldstub instruction takes the location specified by its first argument
  490.  * (a register containing a memory address) and loads its contents into its
  491.  * second argument (a register) and atomically sets the contents the location
  492.  * specified by its first argument to a byte of 1s.  (The value in the second
  493.  * argument is never read, but only overwritten.)
  494.  *
  495.  * The stbar is needed for v8, and is implemented as membar #sync on v9,
  496.  + so is functional there as well.  For v7, stbar may generate an illegal
  497.  + instruction and we have no way to tell what we're running on.  Some
  498.  + operating systems notice and skip this instruction in the fault handler.
  499.  *
  500.  * For gcc/sparc, 0 is clear, 1 is set.
  501.  */
  502. #define MUTEX_SET(tsl) ({
  503. register tsl_t *__l = (tsl);
  504. register tsl_t __r;
  505. __asm__ volatile
  506.     ("ldstub [%1],%0; stbar"
  507.     : "=r"( __r) : "r" (__l));
  508. !__r;
  509. })
  510. #define MUTEX_UNSET(tsl) (*(tsl) = 0)
  511. #define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
  512. #endif
  513. #endif
  514. /*********************************************************************
  515.  * UTS/cc assembly.
  516.  *********************************************************************/
  517. #ifdef HAVE_MUTEX_UTS_CC_ASSEMBLY
  518. typedef int tsl_t;
  519. #define MUTEX_ALIGN sizeof(int)
  520. #ifdef LOAD_ACTUAL_MUTEX_CODE
  521. #define MUTEX_INIT(x) 0
  522. #define MUTEX_SET(x) (!uts_lock(x, 1))
  523. #define MUTEX_UNSET(x) (*(x) = 0)
  524. #endif
  525. #endif
  526. /*********************************************************************
  527.  * x86/gcc assembly.
  528.  *********************************************************************/
  529. #ifdef HAVE_MUTEX_X86_GCC_ASSEMBLY
  530. typedef unsigned char tsl_t;
  531. #ifdef LOAD_ACTUAL_MUTEX_CODE
  532. /*
  533.  * For gcc/x86, 0 is clear, 1 is set.
  534.  */
  535. #define MUTEX_SET(tsl) ({
  536. register tsl_t *__l = (tsl);
  537. int __r;
  538. asm volatile("movl $1,%%eax; lock; xchgb %1,%%al; xorl $1,%%eax"
  539.     : "=&a" (__r), "=m" (*__l)
  540.     : "1" (*__l)
  541.     );
  542. __r & 1;
  543. })
  544. #define MUTEX_UNSET(tsl) (*(tsl) = 0)
  545. #define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)
  546. #endif
  547. #endif
  548. /*
  549.  * Mutex alignment defaults to one byte.
  550.  *
  551.  * !!!
  552.  * Various systems require different alignments for mutexes (the worst we've
  553.  * seen so far is 16-bytes on some HP architectures).  Malloc(3) is assumed
  554.  * to return reasonable alignment, all other mutex users must ensure proper
  555.  * alignment locally.
  556.  */
  557. #ifndef MUTEX_ALIGN
  558. #define MUTEX_ALIGN 1
  559. #endif
  560. /*
  561.  * Mutex destruction defaults to a no-op.
  562.  */
  563. #ifdef LOAD_ACTUAL_MUTEX_CODE
  564. #ifndef MUTEX_DESTROY
  565. #define MUTEX_DESTROY(x)
  566. #endif
  567. #endif
  568. #define MUTEX_IGNORE 0x001 /* Ignore, no lock required. */
  569. #define MUTEX_INITED 0x002 /* Mutex is successfully initialized */
  570. #define MUTEX_SELF_BLOCK 0x004 /* Must block self. */
  571. #define MUTEX_THREAD 0x008 /* Thread-only mutex. */
  572. /* Mutex. */
  573. struct __mutex_t {
  574. #ifdef HAVE_MUTEX_THREADS
  575. #ifdef MUTEX_FIELDS
  576. MUTEX_FIELDS
  577. #else
  578. tsl_t tas; /* Test and set. */
  579. #endif
  580. u_int32_t spins; /* Spins before block. */
  581. u_int32_t locked; /* !0 if locked. */
  582. #else
  583. u_int32_t off; /* Byte offset to lock. */
  584. u_int32_t pid; /* Lock holder: 0 or process pid. */
  585. #endif
  586. u_int32_t mutex_set_wait; /* Granted after wait. */
  587. u_int32_t mutex_set_nowait; /* Granted without waiting. */
  588. #ifdef MUTEX_SYSTEM_RESOURCES
  589. roff_t   reg_off; /* Shared lock info offset. */
  590. #endif
  591. u_int8_t  flags; /* MUTEX_XXX */
  592. };
  593. /* Redirect calls to the correct functions. */
  594. #ifdef HAVE_MUTEX_THREADS
  595. #if defined(HAVE_MUTEX_PTHREADS) || defined(HAVE_MUTEX_SOLARIS_LWP) || defined(HAVE_MUTEX_UI_THREADS)
  596. #define __db_mutex_init(a, b, c, d) __db_pthread_mutex_init(a, b, d)
  597. #define __db_mutex_lock(a, b, c) __db_pthread_mutex_lock(a, b)
  598. #define __db_mutex_unlock(a, b) __db_pthread_mutex_unlock(a, b)
  599. #define __db_mutex_destroy(a) __db_pthread_mutex_destroy(a)
  600. #else
  601. #define __db_mutex_init(a, b, c, d) __db_tas_mutex_init(a, b, d)
  602. #define __db_mutex_lock(a, b, c) __db_tas_mutex_lock(a, b)
  603. #define __db_mutex_unlock(a, b) __db_tas_mutex_unlock(a, b)
  604. #define __db_mutex_destroy(a) __db_tas_mutex_destroy(a)
  605. #endif
  606. #else
  607. #define __db_mutex_init(a, b, c, d) __db_fcntl_mutex_init(a, b, c)
  608. #define __db_mutex_lock(a, b, c) __db_fcntl_mutex_lock(a, b, c)
  609. #define __db_mutex_unlock(a, b) __db_fcntl_mutex_unlock(a, b)
  610. #define __db_mutex_destroy(a) __db_fcntl_mutex_destroy(a)
  611. #endif
  612. /* Redirect system resource calls to correct functions */
  613. #ifdef MUTEX_SYSTEM_RESOURCES
  614. #define __db_maintinit(a, b, c) __db_shreg_maintinit(a, b, c)
  615. #define __db_shlocks_clear(a, b, c) __db_shreg_locks_clear(a, b, c)
  616. #define __db_shlocks_destroy(a, b) __db_shreg_locks_destroy(a, b)
  617. #define __db_shmutex_init(a, b, c, d, e, f)
  618.     __db_shreg_mutex_init(a, b, c, d, e, f)
  619. #else
  620. #define __db_maintinit(a, b, c)
  621. #define __db_shlocks_clear(a, b, c)
  622. #define __db_shlocks_destroy(a, b)
  623. #define __db_shmutex_init(a, b, c, d, e, f) __db_mutex_init(a, b, c, d)
  624. #endif
  625. /*
  626.  * Lock/unlock a mutex.  If the mutex was marked as uninteresting, the thread
  627.  * of control can proceed without it.
  628.  *
  629.  * If the lock is for threads-only, then it was optionally not allocated and
  630.  * file handles aren't necessary, as threaded applications aren't supported by
  631.  * fcntl(2) locking.
  632.  */
  633. #ifdef DIAGNOSTIC
  634. /*
  635.  * XXX
  636.  * We want to switch threads as often as possible.  Yield every time
  637.  * we get a mutex to ensure contention.
  638.  */
  639. #define MUTEX_LOCK(dbenv, mp, fh)
  640. if (!F_ISSET((MUTEX *)(mp), MUTEX_IGNORE))
  641. (void)__db_mutex_lock(dbenv, mp, fh);
  642. if (DB_GLOBAL(db_pageyield))
  643. __os_yield(NULL, 1);
  644. #else
  645. #define MUTEX_LOCK(dbenv, mp, fh)
  646. if (!F_ISSET((MUTEX *)(mp), MUTEX_IGNORE))
  647. (void)__db_mutex_lock(dbenv, mp, fh);
  648. #endif
  649. #define MUTEX_UNLOCK(dbenv, mp)
  650. if (!F_ISSET((MUTEX *)(mp), MUTEX_IGNORE))
  651. (void)__db_mutex_unlock(dbenv, mp);
  652. #define MUTEX_THREAD_LOCK(dbenv, mp)
  653. if (mp != NULL)
  654. MUTEX_LOCK(dbenv, mp, NULL)
  655. #define MUTEX_THREAD_UNLOCK(dbenv, mp)
  656. if (mp != NULL)
  657. MUTEX_UNLOCK(dbenv, mp)
  658. /*
  659.  * We use a single file descriptor for fcntl(2) locking, and (generally) the
  660.  * object's offset in a shared region as the byte that we're locking.  So,
  661.  * there's a (remote) possibility that two objects might have the same offsets
  662.  * such that the locks could conflict, resulting in deadlock.  To avoid this
  663.  * possibility, we offset the region offset by a small integer value, using a
  664.  * different offset for each subsystem's locks.  Since all region objects are
  665.  * suitably aligned, the offset guarantees that we don't collide with another
  666.  * region's objects.
  667.  */
  668. #define DB_FCNTL_OFF_GEN 0 /* Everything else. */
  669. #define DB_FCNTL_OFF_LOCK 1 /* Lock subsystem offset. */
  670. #define DB_FCNTL_OFF_MPOOL 2 /* Mpool subsystem offset. */