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

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. Mutex, the basic synchronization primitive
  3. (c) 1995 Innobase Oy
  4. Created 9/5/1995 Heikki Tuuri
  5. *******************************************************/
  6. /**********************************************************************
  7. Sets the waiters field in a mutex. */
  8. void
  9. mutex_set_waiters(
  10. /*==============*/
  11. mutex_t* mutex, /* in: mutex */
  12. ulint n); /* in: value to set */
  13. /**********************************************************************
  14. Reserves a mutex for the current thread. If the mutex is reserved, the
  15. function spins a preset time (controlled by SYNC_SPIN_ROUNDS) waiting
  16. for the mutex before suspending the thread. */
  17. void
  18. mutex_spin_wait(
  19. /*============*/
  20.         mutex_t* mutex,   /* in: pointer to mutex */
  21. const char* file_name,/* in: file name where mutex requested */
  22. ulint line); /* in: line where requested */
  23. #ifdef UNIV_SYNC_DEBUG
  24. /**********************************************************************
  25. Sets the debug information for a reserved mutex. */
  26. void
  27. mutex_set_debug_info(
  28. /*=================*/
  29. mutex_t* mutex, /* in: mutex */
  30. const char* file_name, /* in: file where requested */
  31. ulint line); /* in: line where requested */
  32. #endif /* UNIV_SYNC_DEBUG */
  33. /**********************************************************************
  34. Releases the threads waiting in the primary wait array for this mutex. */
  35. void
  36. mutex_signal_object(
  37. /*================*/
  38. mutex_t* mutex); /* in: mutex */
  39. /**********************************************************************
  40. Performs an atomic test-and-set instruction to the lock_word field of a
  41. mutex. */
  42. UNIV_INLINE
  43. ulint
  44. mutex_test_and_set(
  45. /*===============*/
  46. /* out: the previous value of lock_word: 0 or
  47. 1 */
  48. mutex_t* mutex) /* in: mutex */
  49. {
  50. #if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER)
  51. ulint res;
  52. ulint* lw; /* assembler code is used to ensure that
  53. lock_word is loaded from memory */
  54. ut_ad(mutex);
  55. ut_ad(sizeof(ulint) == 4);
  56. lw = &(mutex->lock_word);
  57.         __asm   MOV     ECX, lw
  58. __asm   MOV     EDX, 1
  59.         __asm   XCHG    EDX, DWORD PTR [ECX]                    
  60.         __asm   MOV     res, EDX
  61. /* The fence below would prevent this thread from reading the data
  62. structure protected by the mutex before the test-and-set operation is
  63. committed, but the fence is apparently not needed:
  64. In a posting to comp.arch newsgroup (August 10, 1997) Andy Glew said
  65. that in P6 a LOCKed instruction like XCHG establishes a fence with
  66. respect to memory reads and writes and thus an explicit fence is not
  67. needed. In P5 he seemed to agree with a previous newsgroup poster that
  68. LOCKed instructions serialize all instruction execution, and,
  69. consequently, also memory operations. This is confirmed in Intel
  70. Software Dev. Manual, Vol. 3. */
  71. /* mutex_fence(); */
  72. return(res);
  73. #elif defined(not_defined) && defined(__GNUC__) && defined(UNIV_INTEL_X86)
  74. ulint* lw;
  75. ulint res;
  76. lw = &(mutex->lock_word);
  77. /* In assembly we use the so-called AT & T syntax where
  78. the order of operands is inverted compared to the ordinary Intel
  79. syntax. The 'l' after the mnemonics denotes a 32-bit operation.
  80. The line after the code tells which values come out of the asm
  81. code, and the second line tells the input to the asm code. */
  82. asm volatile("movl $1, %%eax; xchgl (%%ecx), %%eax" :
  83.               "=eax" (res), "=m" (*lw) :
  84.               "ecx" (lw));
  85. return(res);
  86. #else
  87. ibool ret;
  88. ret = os_fast_mutex_trylock(&(mutex->os_fast_mutex));
  89. if (ret == 0) {
  90. /* We check that os_fast_mutex_trylock does not leak
  91. and allow race conditions */
  92. ut_a(mutex->lock_word == 0);
  93. mutex->lock_word = 1;
  94. }
  95. return(ret);
  96. #endif
  97. }
  98. /**********************************************************************
  99. Performs a reset instruction to the lock_word field of a mutex. This
  100. instruction also serializes memory operations to the program order. */
  101. UNIV_INLINE
  102. void
  103. mutex_reset_lock_word(
  104. /*==================*/
  105. mutex_t* mutex) /* in: mutex */
  106. {
  107. #if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER)
  108. ulint* lw; /* assembler code is used to ensure that
  109. lock_word is loaded from memory */
  110. ut_ad(mutex);
  111. lw = &(mutex->lock_word);
  112. __asm   MOV     EDX, 0
  113.         __asm   MOV     ECX, lw
  114.         __asm   XCHG    EDX, DWORD PTR [ECX]                    
  115. #elif defined(not_defined) && defined(__GNUC__) && defined(UNIV_INTEL_X86)
  116. ulint* lw;
  117. lw = &(mutex->lock_word);
  118. /* In assembly we use the so-called AT & T syntax where
  119. the order of operands is inverted compared to the ordinary Intel
  120. syntax. The 'l' after the mnemonics denotes a 32-bit operation. */
  121. asm volatile("movl $0, %%eax; xchgl (%%ecx), %%eax" :
  122.               "=m" (*lw) :
  123.               "ecx" (lw) :
  124.       "eax"); /* gcc does not seem to understand
  125. that our asm code resets eax: tell it
  126. explicitly that after the third ':' */
  127. #else
  128. mutex->lock_word = 0;
  129. os_fast_mutex_unlock(&(mutex->os_fast_mutex));
  130. #endif
  131. }
  132. /**********************************************************************
  133. Gets the value of the lock word. */
  134. UNIV_INLINE
  135. ulint
  136. mutex_get_lock_word(
  137. /*================*/
  138. mutex_t* mutex) /* in: mutex */
  139. {
  140. volatile ulint* ptr; /* declared volatile to ensure that
  141. lock_word is loaded from memory */
  142. ut_ad(mutex);
  143. ptr = &(mutex->lock_word);
  144. return(*ptr);
  145. }
  146. /**********************************************************************
  147. Gets the waiters field in a mutex. */
  148. UNIV_INLINE
  149. ulint
  150. mutex_get_waiters(
  151. /*==============*/
  152. /* out: value to set */
  153. mutex_t* mutex) /* in: mutex */
  154. {
  155. volatile ulint* ptr; /* declared volatile to ensure that
  156. the value is read from memory */
  157. ut_ad(mutex);
  158. ptr = &(mutex->waiters);
  159. return(*ptr); /* Here we assume that the read of a single
  160. word from memory is atomic */
  161. }
  162. /**********************************************************************
  163. Unlocks a mutex owned by the current thread. */
  164. UNIV_INLINE
  165. void
  166. mutex_exit(
  167. /*=======*/
  168. mutex_t* mutex) /* in: pointer to mutex */
  169. {
  170. #ifdef UNIV_SYNC_DEBUG
  171. ut_ad(mutex_own(mutex));
  172. mutex->thread_id = ULINT_UNDEFINED;
  173. sync_thread_reset_level(mutex);
  174. #endif 
  175. mutex_reset_lock_word(mutex);
  176. /* A problem: we assume that mutex_reset_lock word
  177. is a memory barrier, that is when we read the waiters
  178. field next, the read must be serialized in memory
  179. after the reset. A speculative processor might
  180. perform the read first, which could leave a waiting
  181. thread hanging indefinitely.
  182. Our current solution call every 10 seconds
  183. sync_arr_wake_threads_if_sema_free()
  184. to wake up possible hanging threads if
  185. they are missed in mutex_signal_object. */
  186. if (mutex_get_waiters(mutex) != 0) {
  187. mutex_signal_object(mutex);
  188. }
  189. #ifdef UNIV_SYNC_PERF_STAT
  190. mutex_exit_count++;
  191. #endif
  192. }
  193. /**********************************************************************
  194. Locks a mutex for the current thread. If the mutex is reserved, the function
  195. spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting for the mutex
  196. before suspending the thread. */
  197. UNIV_INLINE
  198. void
  199. mutex_enter_func(
  200. /*=============*/
  201. mutex_t* mutex, /* in: pointer to mutex */
  202. const char* file_name,  /* in: file name where locked */
  203. ulint line) /* in: line where locked */
  204. {
  205. ut_ad(mutex_validate(mutex));
  206. /* Note that we do not peek at the value of lock_word before trying
  207. the atomic test_and_set; we could peek, and possibly save time. */
  208. if (!mutex_test_and_set(mutex)) {
  209. #ifdef UNIV_SYNC_DEBUG
  210. mutex_set_debug_info(mutex, file_name, line);
  211. #endif
  212. return; /* Succeeded! */
  213. }
  214. mutex_spin_wait(mutex, file_name, line);
  215. }