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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * s_lock.h
  4.  *    This file contains the implementation (if any) for spinlocks.
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/include/storage/s_lock.h,v 1.61.2.1 1999/07/30 17:07:17 scrappy Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. /*
  15.  *  DESCRIPTION
  16.  * The public macros that must be provided are:
  17.  *
  18.  * void S_INIT_LOCK(slock_t *lock)
  19.  *
  20.  * void S_LOCK(slock_t *lock)
  21.  *
  22.  * void S_UNLOCK(slock_t *lock)
  23.  *
  24.  * void S_LOCK_FREE(slock_t *lock)
  25.  * Tests if the lock is free. Returns non-zero if free, 0 if locked.
  26.  *
  27.  * The S_LOCK() macro implements a primitive but still useful random
  28.  * backoff to avoid hordes of busywaiting lockers chewing CPU.
  29.  *
  30.  * Effectively:
  31.  * void
  32.  * S_LOCK(slock_t *lock)
  33.  * {
  34.  * while (TAS(lock))
  35.  * {
  36.  * // back off the cpu for a semi-random short time
  37.  * }
  38.  * }
  39.  *
  40.  * This implementation takes advantage of a tas function written
  41.  * (in assembly language) on machines that have a native test-and-set
  42.  * instruction. Alternative mutex implementations may also be used.
  43.  * This function is hidden under the TAS macro to allow substitutions.
  44.  *
  45.  * #define TAS(lock) tas(lock)
  46.  * int tas(slock_t *lock) // True if lock already set
  47.  *
  48.  * There are default implementations for all these macros at the bottom
  49.  * of this file. Check if your platform can use these or needs to
  50.  * override them.
  51.  *
  52.  * NOTES
  53.  * If none of this can be done, POSTGRES will default to using
  54.  * System V semaphores (and take a large performance hit -- around 40%
  55.  * of its time on a DS5000/240 is spent in semop(3)...).
  56.  *
  57.  * AIX has a test-and-set but the recommended interface is the cs(3)
  58.  * system call.  This provides an 8-instruction (plus system call
  59.  * overhead) uninterruptible compare-and-set operation.  True
  60.  * spinlocks might be faster but using cs(3) still speeds up the
  61.  * regression test suite by about 25%.  I don't have an assembler
  62.  * manual for POWER in any case.
  63.  *
  64.  */
  65. #if !defined(S_LOCK_H)
  66. #define S_LOCK_H
  67. #include "storage/ipc.h"
  68. extern void s_lock_sleep(unsigned spin);
  69. #if defined(HAS_TEST_AND_SET)
  70. #if defined(__GNUC__)
  71. /*************************************************************************
  72.  * All the gcc inlines
  73.  */
  74. #if defined(__alpha__)
  75. #define TAS(lock) tas(lock)
  76. #define S_UNLOCK(lock) { __asm__("mb"); *(lock) = 0; }
  77. static __inline__ int
  78. tas(volatile slock_t *lock)
  79. {
  80. register slock_t _res;
  81. __asm__("    ldq   $0, %0              n
  82.                  bne   $0, 3f          n
  83.                  ldq_l $0, %0            n
  84.                  bne   $0, 3f          n
  85.                  or    $31, 1, $0          n
  86.                  stq_c $0, %0            n
  87.                  beq   $0, 2f              n
  88.                  bis   $31, $31, %1        n
  89.                  mb                    n
  90.                  jmp   $31, 4f            n
  91.               2: or    $31, 1, $0        n
  92.               3: bis   $0, $0, %1        n
  93.               4: nop      ": "=m"(*lock), "=r"(_res): :"0");
  94. return (int) _res;
  95. }
  96. #endif  /* __alpha__ */
  97. #if defined(__i386__)
  98. #define TAS(lock) tas(lock)
  99. static __inline__ int
  100. tas(volatile slock_t *lock)
  101. {
  102. register slock_t _res = 1;
  103. __asm__("lock; xchgb %0,%1": "=q"(_res), "=m"(*lock):"0"(_res));
  104. return (int) _res;
  105. }
  106. #endif  /* __i386__ */
  107. #if defined(__arm32__)
  108. #define TAS(lock) tas(lock)
  109. static __inline__ int
  110. tas(volatile slock_t *lock)
  111. {
  112.         register slock_t _res = 1;
  113. __asm__("swpb %0, %0, [%3]": "=r"(_res), "=m"(*lock):"0"(_res), "r" (lock));
  114.         return (int) _res;
  115. }
  116. #endif   /* __arm32__ */
  117. #if defined(__sparc__)
  118. #define TAS(lock) tas(lock)
  119. static __inline__ int
  120. tas(volatile slock_t *lock)
  121. {
  122. register slock_t _res = 1;
  123. __asm__("ldstub [%2], %0" 
  124. : "=r"(_res), "=m"(*lock) 
  125. : "r"(lock));
  126. return (int) _res;
  127. }
  128. #endif  /* __sparc__ */
  129. #if defined(__mc68000__) && defined(__linux__)
  130. #define TAS(lock) tas(lock)
  131. static __inline__ int
  132. tas(volatile slock_t *lock)
  133. {
  134. register int rv;
  135. __asm__ __volatile__ (
  136. "tas %1; sne %0"
  137. : "=d" (rv), "=m"(*lock)
  138. : "1" (*lock)
  139. : "cc" );
  140. return rv;
  141. }
  142. #endif /* defined(__mc68000__) && defined(__linux__) */
  143. #if defined(NEED_VAX_TAS_ASM)
  144. /*
  145.  * VAXen -- even multiprocessor ones
  146.  * (thanks to Tom Ivar Helbekkmo)
  147.  */
  148. #define TAS(lock) tas(lock)
  149. typedef unsigned char slock_t;
  150. static __inline__ int
  151. tas(volatile slock_t *lock)
  152. {
  153. register _res;
  154. __asm__(" movl $1, r0 
  155. bbssi $0, (%1), 1 f 
  156. clrl r0 
  157. 1: movl r0, %0 "
  158. : "=r"(_res) /* return value, in register */
  159. : "r"(lock) /* argument, 'lock pointer', in register */
  160. : "r0"); /* inline code uses this register */
  161. return (int) _res;
  162. }
  163. #endif  /* NEED_VAX_TAS_ASM */
  164. #if defined(NEED_NS32K_TAS_ASM)
  165. #define TAS(lock) tas(lock)
  166. static __inline__ int
  167. tas(volatile slock_t *lock)
  168. {
  169.   register _res;
  170.   __asm__("sbitb 0, %0 n
  171. sfsd %1"
  172. : "=m"(*lock), "=r"(_res));
  173.   return (int) _res; 
  174. }
  175. #endif  /* NEED_NS32K_TAS_ASM */
  176. #else /* __GNUC__ */
  177. /***************************************************************************
  178.  * All non gcc
  179.  */
  180. #if defined(__alpha__)
  181. /*
  182.  * OSF/1 (Alpha AXP)
  183.  *
  184.  * Note that slock_t on the Alpha AXP is msemaphore instead of char
  185.  * (see storage/ipc.h).
  186.  */
  187. #define TAS(lock) (msem_lock((lock), MSEM_IF_NOWAIT) < 0)
  188. #define S_UNLOCK(lock) msem_unlock((lock), 0)
  189. #define S_INIT_LOCK(lock) msem_init((lock), MSEM_UNLOCKED)
  190. #define S_LOCK_FREE(lock) (!(lock)->msem_state)
  191. #endif  /* __alpha__ */
  192. #if defined(NEED_I386_TAS_ASM)
  193. /* non gcc i386 based things */
  194. #if defined(USE_UNIVEL_CC)
  195. #define TAS(lock) tas(lock)
  196. asm int
  197. tas(slock_t *s_lock)
  198. {
  199. /* UNIVEL wants %mem in column 1, so we don't pg_indent this file */
  200. %mem s_lock
  201. pushl %ebx
  202. movl s_lock, %ebx
  203. movl $255, %eax
  204. lock
  205. xchgb %al, (%ebx)
  206. popl %ebx
  207. }
  208. #endif  /* USE_UNIVEL_CC */
  209. #endif  /* NEED_I386_TAS_ASM */
  210. #endif  /* defined(__GNUC__) */
  211. /*************************************************************************
  212.  * These are the platforms that have common code for gcc and non-gcc
  213.  */
  214. #if defined(__hpux)
  215. /*
  216.  * HP-UX (PA-RISC)
  217.  *
  218.  * Note that slock_t on PA-RISC is a structure instead of char
  219.  * (see include/port/hpux.h).
  220.  *
  221.  * a "set" slock_t has a single word cleared.  a "clear" slock_t has
  222.  * all words set to non-zero. tas() in tas.s
  223.  */
  224. #define S_UNLOCK(lock) 
  225. volatile slock_t *lock_ = (volatile slock_t *) (lock); 
  226. lock_->sema[0] = lock_->sema[1] = lock_->sema[2] = lock_->sema[3] = -1; 
  227. }
  228. #define S_LOCK_FREE(lock) ( *(int *) (((long) (lock) + 15) & ~15) != 0)
  229. #endif  /* __hpux */
  230. #if defined(__sgi)
  231. /*
  232.  * SGI IRIX 5
  233.  * slock_t is defined as a unsigned long. We use the standard SGI
  234.  * mutex API. 
  235.  *
  236.  * The following comment is left for historical reasons, but is probably
  237.  * not a good idea since the mutex ABI is supported.
  238.  *
  239.  * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
  240.  * assembly from his NECEWS SVR4 port, but we probably ought to retain this
  241.  * for the R3000 chips out there.
  242.  */
  243. #include "mutex.h"
  244. #define TAS(lock) (test_and_set(lock,1))
  245. #define S_UNLOCK(lock) (test_then_and(lock,0))
  246. #define S_INIT_LOCK(lock) (test_then_and(lock,0))
  247. #define S_LOCK_FREE(lock) (test_then_add(lock,0) == 0)
  248. #endif  /* __sgi */
  249. #if defined(sinix)
  250. /*
  251.  * SINIX / Reliant UNIX 
  252.  * slock_t is defined as a struct abilock_t, which has a single unsigned long
  253.  * member. (Basically same as SGI)
  254.  *
  255.  */
  256. #define TAS(lock) (!acquire_lock(lock))
  257. #define S_UNLOCK(lock) release_lock(lock)
  258. #define S_INIT_LOCK(lock) init_lock(lock)
  259. #define S_LOCK_FREE(lock) (stat_lock(lock) == UNLOCKED)
  260. #endif  /* sinix */
  261.  
  262. #if defined(_AIX)
  263. /*
  264.  * AIX (POWER)
  265.  *
  266.  * Note that slock_t on POWER/POWER2/PowerPC is int instead of char
  267.  * (see storage/ipc.h).
  268.  */
  269. #define TAS(lock) cs((int *) (lock), 0, 1)
  270. #endif  /* _AIX */
  271. #if defined (nextstep)
  272. /*
  273.  * NEXTSTEP (mach)
  274.  * slock_t is defined as a struct mutex.
  275.  */
  276. #define S_LOCK(lock) mutex_lock(lock)
  277. #define S_UNLOCK(lock) mutex_unlock(lock)
  278. #define S_INIT_LOCK(lock) mutex_init(lock)
  279. /* For Mach, we have to delve inside the entrails of `struct mutex'.  Ick! */
  280. #define S_LOCK_FREE(alock) ((alock)->lock == 0)
  281. #endif  /* nextstep */
  282. /****************************************************************************
  283.  * Default Definitions - override these above as needed.
  284.  */
  285. #if !defined(S_LOCK)
  286. extern void s_lock(volatile slock_t *lock, const char *file, const int line);
  287. #define S_LOCK(lock) 
  288. do { 
  289. if (TAS((volatile slock_t *) lock)) 
  290. s_lock((volatile slock_t *) lock, __FILE__, __LINE__); 
  291. } while (0)
  292. #endif  /* S_LOCK */
  293. #if !defined(S_LOCK_FREE)
  294. #define S_LOCK_FREE(lock) (*(lock) == 0)
  295. #endif  /* S_LOCK_FREE */
  296. #if !defined(S_UNLOCK)
  297. #define S_UNLOCK(lock) (*(lock) = 0)
  298. #endif  /* S_UNLOCK */
  299. #if !defined(S_INIT_LOCK)
  300. #define S_INIT_LOCK(lock) S_UNLOCK(lock)
  301. #endif  /* S_INIT_LOCK */
  302. #if !defined(TAS)
  303. int tas(volatile slock_t *lock); /* port/.../tas.s, or
  304.  * s_lock.c */
  305. #define TAS(lock) tas((volatile slock_t *) lock)
  306. #endif  /* TAS */
  307. #endif  /* HAS_TEST_AND_SET */
  308. #endif  /* S_LOCK_H */