mutex.h
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:28k
源码类别:

MySQL数据库

开发平台:

Visual C++

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