1 /*-------------------------------------------------------------------------
4 * Hardware-dependent implementation of spinlocks.
7 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/s_lock.c,v 1.10 2002/11/10 00:33:43 momjian Exp $
14 *-------------------------------------------------------------------------
21 #include "storage/s_lock.h"
25 * s_lock_stuck() - complain about a stuck spinlock
28 s_lock_stuck(volatile slock_t *lock, const char *file, int line)
31 "\nFATAL: s_lock(%p) at %s:%d, stuck spinlock. Aborting.\n",
34 "\nFATAL: s_lock(%p) at %s:%d, stuck spinlock. Aborting.\n",
41 * s_lock(lock) - platform-independent portion of waiting for a spinlock.
44 s_lock(volatile slock_t *lock, const char *file, int line)
51 * We loop tightly for awhile, then delay using select() and try
52 * again. Preferably, "awhile" should be a small multiple of the
53 * maximum time we expect a spinlock to be held. 100 iterations seems
56 * We use a 10 millisec select delay because that is the lower limit on
57 * many platforms. The timeout is figured on this delay only, and so
58 * the nominal 1 minute is a lower bound.
60 #define SPINS_PER_DELAY 100
62 #define TIMEOUT_MSEC (60 * 1000)
66 if (++spins > SPINS_PER_DELAY)
68 if (++delays > (TIMEOUT_MSEC / DELAY_MSEC))
69 s_lock_stuck(lock, file, line);
72 delay.tv_usec = DELAY_MSEC * 1000;
73 (void) select(0, NULL, NULL, NULL, &delay);
81 * Various TAS implementations that cannot live in s_lock.h as no inline
82 * definition exists (yet).
83 * In the future, get rid of tas.[cso] and fold it into this file.
88 /*************************************************************************
89 * All the gcc flavors that are not inlined
95 tas_dummy() /* really means: extern int tas(slock_t
102 movel sp@(0x4),a0 \n\
112 #endif /* __m68k__ */
114 #if defined(__APPLE__) && defined(__ppc__)
115 /* used in darwin. */
116 /* We key off __APPLE__ here because this function differs from
117 * the LinuxPPC implementation only in compiler syntax.
119 * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002,
120 * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop.
125 __asm__ __volatile__(
145 #endif /* __APPLE__ && __ppc__ */
147 #if defined(__mips__) && !defined(__sgi)
151 __asm__ __volatile__(
155 .frame $sp, 0, $31 \n\
165 .livereg 0x2000FF0E,0x00000FFF \n\
172 #endif /* __mips__ && !__sgi */
174 #else /* not __GNUC__ */
175 /***************************************************************************
183 tas_dummy() /* really means: extern int tas(slock_t
192 asm("|#PROLOGUE# 1");
193 asm(" movel sp@(0x4),a0");
196 asm(" moveq #-128,d0");
207 #if defined(NEED_SPARC_TAS_ASM)
209 * sparc machines not using gcc
212 tas_dummy() /* really means: extern int tas(slock_t
215 asm(".seg \"data\"");
216 asm(".seg \"text\"");
220 * Sparc atomic test and set (sparc calls it "atomic load-store")
222 asm("ldstub [%r8], %r8");
226 #endif /* NEED_SPARC_TAS_ASM */
231 #if defined(NEED_I386_TAS_ASM)
232 /* non gcc i386 based things */
233 #endif /* NEED_I386_TAS_ASM */
234 #endif /* not __GNUC__ */
239 /*****************************************************************************/
240 #if defined(S_LOCK_TEST)
243 * test program for verifying a port.
246 volatile slock_t test_lock;
251 S_INIT_LOCK(&test_lock);
253 if (!S_LOCK_FREE(&test_lock))
255 printf("S_LOCK_TEST: failed, lock not initialized.\n");
261 if (S_LOCK_FREE(&test_lock))
263 printf("S_LOCK_TEST: failed, lock not locked\n");
267 printf("S_LOCK_TEST: this will hang for a few minutes and then abort\n");
268 printf(" with a 'stuck spinlock' message if S_LOCK()\n");
269 printf(" and TAS() are working.\n");
270 s_lock(&test_lock, __FILE__, __LINE__);
272 printf("S_LOCK_TEST: failed, lock not locked~\n");
277 #endif /* S_LOCK_TEST */