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

MySQL数据库

开发平台:

Visual C++

  1. /*
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: mut_win32.c,v 1.8 2002/09/10 02:37:25 bostic Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <string.h>
  14. #include <unistd.h>
  15. #endif
  16. /*
  17.  * This is where we load in the actual test-and-set mutex code.
  18.  */
  19. #define LOAD_ACTUAL_MUTEX_CODE
  20. #include "db_int.h"
  21. /* We don't want to run this code even in "ordinary" diagnostic mode. */
  22. #undef MUTEX_DIAG
  23. #define GET_HANDLE(mutexp, event) do {
  24. char idbuf[13];
  25. if (F_ISSET(mutexp, MUTEX_THREAD)) {
  26. event = mutexp->event;
  27. return (0);
  28. }
  29. snprintf(idbuf, sizeof idbuf, "db.m%08x", mutexp->id);
  30. event = CreateEvent(NULL, FALSE, FALSE, idbuf);
  31. if (event == NULL)
  32. return (__os_win32_errno());
  33. } while (0)
  34. #define RELEASE_HANDLE(mutexp, event)
  35. if (!F_ISSET(mutexp, MUTEX_THREAD) && event != NULL) {
  36. CloseHandle(event);
  37. event = NULL;
  38. }
  39. /*
  40.  * __db_win32_mutex_init --
  41.  * Initialize a DB_MUTEX.
  42.  *
  43.  * PUBLIC: int __db_win32_mutex_init __P((DB_ENV *, DB_MUTEX *, u_int32_t));
  44.  */
  45. int
  46. __db_win32_mutex_init(dbenv, mutexp, flags)
  47. DB_ENV *dbenv;
  48. DB_MUTEX *mutexp;
  49. u_int32_t flags;
  50. {
  51. u_int32_t save;
  52. /*
  53.  * The only setting/checking of the MUTEX_MPOOL flags is in the mutex
  54.  * mutex allocation code (__db_mutex_alloc/free).  Preserve only that
  55.  * flag.  This is safe because even if this flag was never explicitly
  56.  * set, but happened to be set in memory, it will never be checked or
  57.  * acted upon.
  58.  */
  59. save = F_ISSET(mutexp, MUTEX_MPOOL);
  60. memset(mutexp, 0, sizeof(*mutexp));
  61. F_SET(mutexp, save);
  62. /*
  63.  * If this is a thread lock or the process has told us that there are
  64.  * no other processes in the environment, use thread-only locks, they
  65.  * are faster in some cases.
  66.  *
  67.  * This is where we decide to ignore locks we don't need to set -- if
  68.  * the application isn't threaded, there aren't any threads to block.
  69.  */
  70. if (LF_ISSET(MUTEX_THREAD) || F_ISSET(dbenv, DB_ENV_PRIVATE)) {
  71. if (!F_ISSET(dbenv, DB_ENV_THREAD)) {
  72. F_SET(mutexp, MUTEX_IGNORE);
  73. return (0);
  74. }
  75. F_SET(mutexp, MUTEX_THREAD);
  76. mutexp->event = CreateEvent(NULL, FALSE, FALSE, NULL);
  77. if (mutexp->event == NULL)
  78. return (__os_win32_errno());
  79. } else
  80. mutexp->id = ((getpid() & 0xffff) << 16) ^ P_TO_UINT32(mutexp);
  81. mutexp->spins = __os_spin(dbenv);
  82. F_SET(mutexp, MUTEX_INITED);
  83. return (0);
  84. }
  85. /*
  86.  * __db_win32_mutex_lock
  87.  * Lock on a mutex, logically blocking if necessary.
  88.  *
  89.  * PUBLIC: int __db_win32_mutex_lock __P((DB_ENV *, DB_MUTEX *));
  90.  */
  91. int
  92. __db_win32_mutex_lock(dbenv, mutexp)
  93. DB_ENV *dbenv;
  94. DB_MUTEX *mutexp;
  95. {
  96. HANDLE event;
  97. int ret, ms, nspins;
  98. #ifdef MUTEX_DIAG
  99. LARGE_INTEGER now;
  100. #endif
  101. if (F_ISSET(dbenv, DB_ENV_NOLOCKING) || F_ISSET(mutexp, MUTEX_IGNORE))
  102. return (0);
  103. event = NULL;
  104. ms = 50;
  105. ret = 0;
  106. loop: /* Attempt to acquire the resource for N spins. */
  107. for (nspins = mutexp->spins; nspins > 0; --nspins) {
  108. if (!MUTEX_SET(&mutexp->tas))
  109. continue;
  110. #ifdef DIAGNOSTIC
  111. if (mutexp->locked)
  112. __db_err(dbenv,
  113.     "__db_win32_mutex_lock: mutex double-locked!");
  114. __os_id(&mutexp->locked);
  115. #endif
  116. if (event == NULL)
  117. ++mutexp->mutex_set_nowait;
  118. else {
  119. ++mutexp->mutex_set_wait;
  120. RELEASE_HANDLE(mutexp, event);
  121. InterlockedDecrement(&mutexp->nwaiters);
  122. #ifdef MUTEX_DIAG
  123. if (ret != WAIT_OBJECT_0) {
  124. QueryPerformanceCounter(&now);
  125. printf("[%I64d]: Lost signal on mutex %p, "
  126.     "id %d, ms %dn",
  127.     now.QuadPart, mutexp, mutexp->id, ms);
  128. }
  129. #endif
  130. }
  131. return (0);
  132. }
  133. /*
  134.  * Yield the processor; wait 50 ms initially, up to 1 second.  This
  135.  * loop is needed to work around a race where the signal from the
  136.  * unlocking thread gets lost.  We start at 50 ms because it's unlikely
  137.  * to happen often and we want to avoid wasting CPU.
  138.  */
  139. if (event == NULL) {
  140. #ifdef MUTEX_DIAG
  141. QueryPerformanceCounter(&now);
  142. printf("[%I64d]: Waiting on mutex %p, id %dn",
  143.     now.QuadPart, mutexp, mutexp->id);
  144. #endif
  145. InterlockedIncrement(&mutexp->nwaiters);
  146. GET_HANDLE(mutexp, event);
  147. }
  148. if ((ret = WaitForSingleObject(event, ms)) == WAIT_FAILED)
  149. return (__os_win32_errno());
  150. if ((ms <<= 1) > MS_PER_SEC)
  151. ms = MS_PER_SEC;
  152. goto loop;
  153. }
  154. /*
  155.  * __db_win32_mutex_unlock --
  156.  * Release a lock.
  157.  *
  158.  * PUBLIC: int __db_win32_mutex_unlock __P((DB_ENV *, DB_MUTEX *));
  159.  */
  160. int
  161. __db_win32_mutex_unlock(dbenv, mutexp)
  162. DB_ENV *dbenv;
  163. DB_MUTEX *mutexp;
  164. {
  165. int ret;
  166. HANDLE event;
  167. #ifdef MUTEX_DIAG
  168. LARGE_INTEGER now;
  169. #endif
  170. if (F_ISSET(dbenv, DB_ENV_NOLOCKING) || F_ISSET(mutexp, MUTEX_IGNORE))
  171. return (0);
  172. #ifdef DIAGNOSTIC
  173. if (!mutexp->tas || !mutexp->locked)
  174. __db_err(dbenv,
  175.     "__db_win32_mutex_unlock: ERROR: lock already unlocked");
  176. mutexp->locked = 0;
  177. #endif
  178. MUTEX_UNSET(&mutexp->tas);
  179. ret = 0;
  180. if (mutexp->nwaiters > 0) {
  181. GET_HANDLE(mutexp, event);
  182. #ifdef MUTEX_DIAG
  183. QueryPerformanceCounter(&now);
  184. printf("[%I64d]: Signalling mutex %p, id %dn",
  185.     now.QuadPart, mutexp, mutexp->id);
  186. #endif
  187. if (!PulseEvent(event))
  188. ret = __os_win32_errno();
  189. RELEASE_HANDLE(mutexp, event);
  190. }
  191. #ifdef DIAGNOSTIC
  192. if (ret != 0)
  193. __db_err(dbenv,
  194.     "__db_win32_mutex_unlock: ERROR: unlock failed");
  195. #endif
  196. return (ret);
  197. }
  198. /*
  199.  * __db_win32_mutex_destroy --
  200.  * Destroy a DB_MUTEX.
  201.  *
  202.  * PUBLIC: int __db_win32_mutex_destroy __P((DB_MUTEX *));
  203.  */
  204. int
  205. __db_win32_mutex_destroy(mutexp)
  206. DB_MUTEX *mutexp;
  207. {
  208. int ret;
  209. if (F_ISSET(mutexp, MUTEX_IGNORE) || !F_ISSET(mutexp, MUTEX_THREAD))
  210. return (0);
  211. ret = 0;
  212. if (mutexp->event != NULL) {
  213. if (!CloseHandle(mutexp->event))
  214. ret = __os_win32_errno();
  215. mutexp->event = NULL;
  216. }
  217. return (ret);
  218. }