sync0sync.ic
Upload User: tsgydb
Upload Date: 2007-04-14
Package Size: 10674k
Code Size: 6k
Category:

MySQL

Development Platform:

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. #ifdef UNIV_SYNC_DEBUG
  22. ,char* file_name, /* in: file name where mutex requested */
  23. ulint line /* in: line where requested */
  24. #endif
  25. );
  26. /**********************************************************************
  27. Sets the debug information for a reserved mutex. */
  28. void
  29. mutex_set_debug_info(
  30. /*=================*/
  31. mutex_t* mutex, /* in: mutex */
  32. char* file_name, /* in: file where requested */
  33. ulint line); /* in: line where requested */
  34. /**********************************************************************
  35. Releases the threads waiting in the primary wait array for this mutex. */
  36. void
  37. mutex_signal_object(
  38. /*================*/
  39. mutex_t* mutex); /* in: mutex */
  40. /**********************************************************************
  41. Performs an atomic test-and-set instruction to the lock_word field of a
  42. mutex. */
  43. UNIV_INLINE
  44. ulint
  45. mutex_test_and_set(
  46. /*===============*/
  47. /* out: the previous value of lock_word: 0 or
  48. 1 */
  49. mutex_t* mutex) /* in: mutex */
  50. {
  51. #ifdef _WIN32
  52. ulint res;
  53. ulint* lw; /* assembler code is used to ensure that
  54. lock_word is loaded from memory */
  55. ut_ad(mutex);
  56. ut_ad(sizeof(ulint) == 4);
  57. lw = &(mutex->lock_word);
  58.         __asm   MOV     ECX, lw
  59. __asm   MOV     EDX, 1
  60.         __asm   XCHG    EDX, DWORD PTR [ECX]                    
  61.         __asm   MOV     res, EDX
  62. /* The fence below would prevent this thread from reading the data
  63. structure protected by the mutex before the test-and-set operation is
  64. committed, but the fence is apparently not needed:
  65. In a posting to comp.arch newsgroup (August 10, 1997) Andy Glew said
  66. that in P6 a LOCKed instruction like XCHG establishes a fence with
  67. respect to memory reads and writes and thus an explicit fence is not
  68. needed. In P5 he seemed to agree with a previous newsgroup poster that
  69. LOCKed instructions serialize all instruction execution, and,
  70. consequently, also memory operations. This is confirmed in Intel
  71. Software Dev. Manual, Vol. 3. */
  72. /* mutex_fence(); */
  73. return(res);
  74. #else
  75. ibool ret;
  76. ret = os_fast_mutex_trylock(&(mutex->os_fast_mutex));
  77. if (ret == 0) {
  78. mutex->lock_word = 1;
  79. }
  80. return(ret);
  81. #endif
  82. }
  83. /**********************************************************************
  84. Performs a reset instruction to the lock_word field of a mutex. This
  85. instruction also serializes memory operations to the program order. */
  86. UNIV_INLINE
  87. void
  88. mutex_reset_lock_word(
  89. /*==================*/
  90. mutex_t* mutex) /* in: mutex */
  91. {
  92. #ifdef _WIN32
  93. ulint* lw; /* assembler code is used to ensure that
  94. lock_word is loaded from memory */
  95. ut_ad(mutex);
  96. lw = &(mutex->lock_word);
  97. __asm   MOV     EDX, 0
  98.         __asm   MOV     ECX, lw
  99.         __asm   XCHG    EDX, DWORD PTR [ECX]                    
  100. #else
  101. mutex->lock_word = 0;
  102. os_fast_mutex_unlock(&(mutex->os_fast_mutex));
  103. #endif
  104. }
  105. /**********************************************************************
  106. Gets the value of the lock word. */
  107. UNIV_INLINE
  108. ulint
  109. mutex_get_lock_word(
  110. /*================*/
  111. mutex_t* mutex) /* in: mutex */
  112. {
  113. volatile ulint* ptr; /* declared volatile to ensure that
  114. lock_word is loaded from memory */
  115. ut_ad(mutex);
  116. ptr = &(mutex->lock_word);
  117. return(*ptr);
  118. }
  119. /**********************************************************************
  120. Gets the waiters field in a mutex. */
  121. UNIV_INLINE
  122. ulint
  123. mutex_get_waiters(
  124. /*==============*/
  125. /* out: value to set */
  126. mutex_t* mutex) /* in: mutex */
  127. {
  128. volatile ulint* ptr; /* declared volatile to ensure that
  129. the value is read from memory */
  130. ut_ad(mutex);
  131. ptr = &(mutex->waiters);
  132. return(*ptr); /* Here we assume that the read of a single
  133. word from memory is atomic */
  134. }
  135. /**********************************************************************
  136. Unlocks a mutex owned by the current thread. */
  137. UNIV_INLINE
  138. void
  139. mutex_exit(
  140. /*=======*/
  141. mutex_t* mutex) /* in: pointer to mutex */
  142. {
  143. ut_ad(mutex_own(mutex));
  144. #ifdef UNIV_SYNC_DEBUG
  145. mutex->thread_id = ULINT_UNDEFINED;
  146. sync_thread_reset_level(mutex);
  147. #endif 
  148. mutex_reset_lock_word(mutex);
  149. if (mutex_get_waiters(mutex) != 0) {
  150. mutex_signal_object(mutex);
  151. }
  152. #ifdef UNIV_SYNC_PERF_STAT
  153. mutex_exit_count++;
  154. #endif
  155. }
  156. /**********************************************************************
  157. Locks a mutex for the current thread. If the mutex is reserved, the function
  158. spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting for the mutex
  159. before suspending the thread. */
  160. UNIV_INLINE
  161. void
  162. mutex_enter_func(
  163. /*=============*/
  164. mutex_t* mutex /* in: pointer to mutex */
  165. #ifdef UNIV_SYNC_DEBUG
  166. ,char* file_name, /* in: file name where locked */
  167. ulint line /* in: line where locked */
  168. #endif
  169. )
  170. {
  171. ut_ad(mutex_validate(mutex));
  172. /* Note that we do not peek at the value of lock_word before trying
  173. the atomic test_and_set; we could peek, and possibly save time. */
  174. if (!mutex_test_and_set(mutex)) {
  175. #ifdef UNIV_SYNC_DEBUG
  176. mutex_set_debug_info(mutex, file_name, line);
  177. #endif
  178. return; /* Succeeded! */
  179. }
  180. mutex_spin_wait(mutex
  181.      #ifdef UNIV_SYNC_DEBUG
  182.      ,file_name,
  183.      line
  184.      #endif
  185.      );
  186. }