s_lock.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:5k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * s_lock.c
  4.  *   buffer manager interface routines
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/storage/buffer/s_lock.c,v 1.21 1999/06/06 20:19:35 vadim Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include <stdio.h>
  15. #include <sys/time.h>
  16. #include <unistd.h>
  17. #include "postgres.h"
  18. #include "storage/s_lock.h"
  19. /*
  20.  * Each time we busy spin we select the next element of this array as the
  21.  * number of microseconds to wait. This accomplishes pseudo random back-off.
  22.  * Values are not critical but 10 milliseconds is a common platform
  23.  * granularity.
  24.  * note: total time to cycle through all 16 entries might be about .07 sec.
  25.  */
  26. #define S_NSPINCYCLE 20
  27. #define S_MAX_BUSY 1000 * S_NSPINCYCLE
  28. int s_spincycle[S_NSPINCYCLE] =
  29. {0, 0, 0, 0, 10000, 0, 0, 0, 10000, 0,
  30. 0, 10000, 0, 0, 10000, 0, 10000, 0, 10000, 10000
  31. };
  32. /*
  33.  * s_lock_stuck(lock) - complain about a stuck spinlock
  34.  */
  35. static void
  36. s_lock_stuck(volatile slock_t *lock, const char *file, const int line)
  37. {
  38. fprintf(stderr,
  39. "nFATAL: s_lock(%08x) at %s:%d, stuck spinlock. Aborting.n",
  40. (unsigned int) lock, file, line);
  41. fprintf(stdout,
  42. "nFATAL: s_lock(%08x) at %s:%d, stuck spinlock. Aborting.n",
  43. (unsigned int) lock, file, line);
  44. abort();
  45. }
  46. void
  47. s_lock_sleep(unsigned spin)
  48. {
  49. struct timeval delay;
  50. delay.tv_sec = 0;
  51. delay.tv_usec = s_spincycle[spin % S_NSPINCYCLE];
  52. (void) select(0, NULL, NULL, NULL, &delay);
  53. }
  54. /*
  55.  * s_lock(lock) - take a spinlock with backoff
  56.  */
  57. void
  58. s_lock(volatile slock_t *lock, const char *file, const int line)
  59. {
  60. unsigned spins = 0;
  61. while (TAS(lock))
  62. {
  63. s_lock_sleep(spins);
  64. if (++spins > S_MAX_BUSY)
  65. {
  66. /* It's been over a minute...  */
  67. s_lock_stuck(lock, file, line);
  68. }
  69. }
  70. }
  71. /*
  72.  * Various TAS implementations that cannot live in s_lock.h as no inline
  73.  * definition exists (yet).
  74.  * In the future, get rid of tas.[cso] and fold it into this file.
  75.  */
  76. #if defined(__GNUC__)
  77. /*************************************************************************
  78.  * All the gcc flavors that are not inlined
  79.  */
  80. #if defined(__m68k__)
  81. static void
  82. tas_dummy() /* really means: extern int tas(slock_t
  83.  * **lock); */
  84. {
  85. __asm__(" n
  86. .global _tas n
  87. _tas: n
  88. movel   sp@(0x4),a0 n
  89. tas a0@ n
  90. beq _success n
  91. moveq   #-128,d0 n
  92. rts n
  93. _success: n
  94. moveq   #0,d0 n
  95. rts n
  96. ");
  97. }
  98. #endif  /* __m68k__ */
  99. #if defined(__powerpc__)
  100. /* Note: need a nice gcc constrained asm version so it can be inlined */
  101. static void
  102. tas_dummy()
  103. {
  104. __asm__(" n
  105. .global tas n
  106. tas: n
  107. lwarx 5,0,3 n
  108. cmpwi 5,0 n
  109. bne fail n
  110. addi 5,5,1 n
  111.          stwcx.  5,0,3 n
  112.       beq success n
  113. fail: li 3,1 n
  114. blr n
  115. success: n
  116. li 3,0 n
  117.          blr n
  118. ");
  119. }
  120. #endif  /* __powerpc__ */
  121. #if defined(__mips)
  122. static void
  123. tas_dummy()
  124. {
  125. __asm__(" n
  126. .global tas n
  127. tas: n
  128. .frame $sp, 0, $31 n
  129. ll $14, 0($4) n
  130. or $15, $14, 1 n
  131. sc $15, 0($4) n
  132. beq $15, 0, fail n
  133. bne $14, 0, fail n
  134. li $2, 0 n
  135. .livereg 0x2000FF0E,0x00000FFF n
  136. j       $31 n
  137. fail: n
  138. li $2, 1 n
  139. j       $31 n
  140. ");
  141. }
  142. #endif  /* __mips */
  143. #else /* defined(__GNUC__) */
  144. /***************************************************************************
  145.  * All non gcc
  146.  */
  147. #if defined(sun3)
  148. static void
  149. tas_dummy() /* really means: extern int tas(slock_t
  150.  * *lock); */
  151. {
  152. asm("LLA0:");
  153. asm("   .data");
  154. asm("   .text");
  155. asm("|#PROC# 04");
  156. asm("   .globl  _tas");
  157. asm("_tas:");
  158. asm("|#PROLOGUE# 1");
  159. asm("   movel   sp@(0x4),a0");
  160. asm("   tas a0@");
  161. asm("   beq LLA1");
  162. asm("   moveq   #-128,d0");
  163. asm("   rts");
  164. asm("LLA1:");
  165. asm("   moveq   #0,d0");
  166. asm("   rts");
  167. asm("   .data");
  168. }
  169. #endif  /* sun3 */
  170. #if defined(NEED_SPARC_TAS_ASM)
  171. /*
  172.  * sparc machines not using gcc
  173.  */
  174. static void
  175. tas_dummy() /* really means: extern int tas(slock_t
  176.  * *lock); */
  177. {
  178. asm(".seg "data"");
  179. asm(".seg "text"");
  180. asm("_tas:");
  181. /*
  182.  * Sparc atomic test and set (sparc calls it "atomic load-store")
  183.  */
  184. asm("ldstub [%r8], %r8");
  185. asm("retl");
  186. asm("nop");
  187. }
  188. #endif  /* NEED_SPARC_TAS_ASM */
  189. #if defined(NEED_I386_TAS_ASM)
  190. /* non gcc i386 based things */
  191. #endif  /* NEED_I386_TAS_ASM */
  192. #endif  /* not __GNUC__ */
  193. /*****************************************************************************/
  194. #if defined(S_LOCK_TEST)
  195. /*
  196.  * test program for verifying a port.
  197.  */
  198. volatile slock_t test_lock;
  199. void
  200. main()
  201. {
  202. S_INIT_LOCK(&test_lock);
  203. if (!S_LOCK_FREE(&test_lock))
  204. {
  205. printf("S_LOCK_TEST: failed, lock not initialized.n");
  206. exit(1);
  207. }
  208. S_LOCK(&test_lock);
  209. if (S_LOCK_FREE(&test_lock))
  210. {
  211. printf("S_LOCK_TEST: failed, lock not lockedn");
  212. exit(2);
  213. }
  214. printf("S_LOCK_TEST: this will hang for a few minutes and then abortn");
  215. printf("             with a 'stuck spinlock' message if S_LOCK()n");
  216. printf("             and TAS() are working.n");
  217. s_lock(&test_lock, __FILE__, __LINE__);
  218. printf("S_LOCK_TEST: failed, lock not locked~n");
  219. exit(3);
  220. }
  221. #endif  /* S_LOCK_TEST */