mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Move s_lock.c and spin.c into lmgr subdirectory, which seems a much
more reasonable location for them.
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
# Makefile for storage/buffer
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/backend/storage/buffer/Makefile,v 1.15 2000/08/31 16:10:30 petere Exp $
|
||||
# $Header: /cvsroot/pgsql/src/backend/storage/buffer/Makefile,v 1.16 2001/09/27 19:10:02 tgl Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -12,7 +12,7 @@ subdir = src/backend/storage/buffer
|
||||
top_builddir = ../../../..
|
||||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJS = buf_table.o buf_init.o bufmgr.o freelist.o localbuf.o s_lock.o
|
||||
OBJS = buf_table.o buf_init.o bufmgr.o freelist.o localbuf.o
|
||||
|
||||
all: SUBSYS.o
|
||||
|
||||
@@ -23,11 +23,7 @@ depend dep:
|
||||
$(CC) -MM $(CFLAGS) *.c >depend
|
||||
|
||||
clean:
|
||||
rm -f SUBSYS.o $(OBJS) s_lock_test
|
||||
|
||||
s_lock_test: s_lock.c
|
||||
$(CC) $(CFLAGS) -DS_LOCK_TEST=1 s_lock.c -o s_lock_test
|
||||
./s_lock_test
|
||||
rm -f SUBSYS.o $(OBJS)
|
||||
|
||||
ifeq (depend,$(wildcard depend))
|
||||
include depend
|
||||
|
||||
@@ -1,364 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* s_lock.c
|
||||
* Spinlock support routines
|
||||
*
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.38 2001/08/29 11:54:12 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "miscadmin.h"
|
||||
#include "storage/s_lock.h"
|
||||
|
||||
|
||||
/*----------
|
||||
* Each time we busy spin we select the next element of this array as the
|
||||
* number of microseconds to wait. This accomplishes pseudo random back-off.
|
||||
*
|
||||
* Note that on most platforms, specified values will be rounded up to the
|
||||
* next multiple of a clock tick, which is often ten milliseconds (10000).
|
||||
* So, we are being way overoptimistic to assume that these different values
|
||||
* are really different, other than the last. But there are a few platforms
|
||||
* with better-than-usual timekeeping, and on these we will get pretty good
|
||||
* pseudo-random behavior.
|
||||
*
|
||||
* Total time to cycle through all 20 entries will be at least 100 msec,
|
||||
* more commonly (10 msec resolution) 220 msec, and on some platforms
|
||||
* as much as 420 msec (when the remainder of the current tick cycle is
|
||||
* ignored in deciding when to time out, as on FreeBSD and older Linuxen).
|
||||
* We use the 100msec figure to figure max_spins, so actual timeouts may
|
||||
* be as much as four times the nominal value, but will never be less.
|
||||
*----------
|
||||
*/
|
||||
#define S_NSPINCYCLE 20
|
||||
|
||||
int s_spincycle[S_NSPINCYCLE] =
|
||||
{1, 10, 100, 1000,
|
||||
10000, 1000, 1000, 1000,
|
||||
10000, 1000, 1000, 10000,
|
||||
1000, 1000, 10000, 1000,
|
||||
10000, 1000, 10000, 30000
|
||||
};
|
||||
|
||||
#define AVG_SPINCYCLE 5000 /* average entry in microsec: 100ms / 20 */
|
||||
|
||||
#define DEFAULT_TIMEOUT (100*1000000) /* default timeout: 100 sec */
|
||||
|
||||
|
||||
/*
|
||||
* s_lock_stuck() - complain about a stuck spinlock
|
||||
*/
|
||||
static void
|
||||
s_lock_stuck(volatile slock_t *lock, const char *file, const int line)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\nFATAL: s_lock(%p) at %s:%d, stuck spinlock. Aborting.\n",
|
||||
lock, file, line);
|
||||
fprintf(stdout,
|
||||
"\nFATAL: s_lock(%p) at %s:%d, stuck spinlock. Aborting.\n",
|
||||
lock, file, line);
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* s_lock_sleep() - sleep a pseudo-random amount of time, check for timeout
|
||||
*
|
||||
* The 'timeout' is given in microsec, or may be 0 for "infinity". Note that
|
||||
* this will be a lower bound (a fairly loose lower bound, on most platforms).
|
||||
*
|
||||
* 'microsec' is the number of microsec to delay per loop. Normally
|
||||
* 'microsec' is 0, specifying to use the next s_spincycle[] value.
|
||||
* Some callers may pass a nonzero interval, specifying to use exactly that
|
||||
* delay value rather than a pseudo-random delay.
|
||||
*/
|
||||
void
|
||||
s_lock_sleep(unsigned spins, int timeout, int microsec,
|
||||
volatile slock_t *lock,
|
||||
const char *file, const int line)
|
||||
{
|
||||
struct timeval delay;
|
||||
|
||||
if (microsec > 0)
|
||||
{
|
||||
delay.tv_sec = microsec / 1000000;
|
||||
delay.tv_usec = microsec % 1000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
delay.tv_sec = 0;
|
||||
delay.tv_usec = s_spincycle[spins % S_NSPINCYCLE];
|
||||
microsec = AVG_SPINCYCLE; /* use average to figure timeout */
|
||||
}
|
||||
|
||||
if (timeout > 0)
|
||||
{
|
||||
unsigned max_spins = timeout / microsec;
|
||||
|
||||
if (spins > max_spins)
|
||||
s_lock_stuck(lock, file, line);
|
||||
}
|
||||
|
||||
(void) select(0, NULL, NULL, NULL, &delay);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* s_lock(lock) - take a spinlock with backoff
|
||||
*/
|
||||
void
|
||||
s_lock(volatile slock_t *lock, const char *file, const int line)
|
||||
{
|
||||
unsigned spins = 0;
|
||||
|
||||
/*
|
||||
* If you are thinking of changing this code, be careful. This same
|
||||
* loop logic is used in other places that call TAS() directly.
|
||||
*
|
||||
* While waiting for a lock, we check for cancel/die interrupts (which is
|
||||
* a no-op if we are inside a critical section). The interrupt check
|
||||
* can be omitted in places that know they are inside a critical
|
||||
* section. Note that an interrupt must NOT be accepted after
|
||||
* acquiring the lock.
|
||||
*/
|
||||
while (TAS(lock))
|
||||
{
|
||||
s_lock_sleep(spins++, DEFAULT_TIMEOUT, 0, lock, file, line);
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Various TAS implementations that cannot live in s_lock.h as no inline
|
||||
* definition exists (yet).
|
||||
* In the future, get rid of tas.[cso] and fold it into this file.
|
||||
*/
|
||||
|
||||
|
||||
#if defined(__GNUC__)
|
||||
/*************************************************************************
|
||||
* All the gcc flavors that are not inlined
|
||||
*/
|
||||
|
||||
|
||||
#if defined(__m68k__)
|
||||
static void
|
||||
tas_dummy() /* really means: extern int tas(slock_t
|
||||
* **lock); */
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"\
|
||||
.global _tas \n\
|
||||
_tas: \n\
|
||||
movel sp@(0x4),a0 \n\
|
||||
tas a0@ \n\
|
||||
beq _success \n\
|
||||
moveq #-128,d0 \n\
|
||||
rts \n\
|
||||
_success: \n\
|
||||
moveq #0,d0 \n\
|
||||
rts \n\
|
||||
");
|
||||
}
|
||||
|
||||
#endif /* __m68k__ */
|
||||
|
||||
#if defined(__APPLE__) && defined(__ppc__)
|
||||
/* used in darwin. */
|
||||
/* We key off __APPLE__ here because this function differs from
|
||||
* the LinuxPPC implementation only in compiler syntax.
|
||||
*/
|
||||
static void
|
||||
tas_dummy()
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"\
|
||||
.globl tas \n\
|
||||
.globl _tas \n\
|
||||
_tas: \n\
|
||||
tas: \n\
|
||||
lwarx r5,0,r3 \n\
|
||||
cmpwi r5,0 \n\
|
||||
bne fail \n\
|
||||
addi r5,r5,1 \n\
|
||||
stwcx. r5,0,r3 \n\
|
||||
beq success \n\
|
||||
fail: li r3,1 \n\
|
||||
blr \n\
|
||||
success: \n\
|
||||
li r3,0 \n\
|
||||
blr \n\
|
||||
");
|
||||
}
|
||||
|
||||
#endif /* __APPLE__ && __ppc__ */
|
||||
|
||||
#if defined(__powerpc__)
|
||||
/* Note: need a nice gcc constrained asm version so it can be inlined */
|
||||
static void
|
||||
tas_dummy()
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"\
|
||||
.global tas \n\
|
||||
tas: \n\
|
||||
lwarx 5,0,3 \n\
|
||||
cmpwi 5,0 \n\
|
||||
bne fail \n\
|
||||
addi 5,5,1 \n\
|
||||
stwcx. 5,0,3 \n\
|
||||
beq success \n\
|
||||
fail: li 3,1 \n\
|
||||
blr \n\
|
||||
success: \n\
|
||||
li 3,0 \n\
|
||||
blr \n\
|
||||
");
|
||||
}
|
||||
|
||||
#endif /* __powerpc__ */
|
||||
|
||||
#if defined(__mips__) && !defined(__sgi)
|
||||
static void
|
||||
tas_dummy()
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"\
|
||||
.global tas \n\
|
||||
tas: \n\
|
||||
.frame $sp, 0, $31 \n\
|
||||
ll $14, 0($4) \n\
|
||||
or $15, $14, 1 \n\
|
||||
sc $15, 0($4) \n\
|
||||
beq $15, 0, fail\n\
|
||||
bne $14, 0, fail\n\
|
||||
li $2, 0 \n\
|
||||
.livereg 0x2000FF0E,0x00000FFF \n\
|
||||
j $31 \n\
|
||||
fail: \n\
|
||||
li $2, 1 \n\
|
||||
j $31 \n\
|
||||
");
|
||||
}
|
||||
|
||||
#endif /* __mips__ && !__sgi */
|
||||
|
||||
#else /* not __GNUC__ */
|
||||
/***************************************************************************
|
||||
* All non gcc
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#if defined(sun3)
|
||||
static void
|
||||
tas_dummy() /* really means: extern int tas(slock_t
|
||||
* *lock); */
|
||||
{
|
||||
asm("LLA0:");
|
||||
asm(" .data");
|
||||
asm(" .text");
|
||||
asm("|#PROC# 04");
|
||||
asm(" .globl _tas");
|
||||
asm("_tas:");
|
||||
asm("|#PROLOGUE# 1");
|
||||
asm(" movel sp@(0x4),a0");
|
||||
asm(" tas a0@");
|
||||
asm(" beq LLA1");
|
||||
asm(" moveq #-128,d0");
|
||||
asm(" rts");
|
||||
asm("LLA1:");
|
||||
asm(" moveq #0,d0");
|
||||
asm(" rts");
|
||||
asm(" .data");
|
||||
}
|
||||
|
||||
#endif /* sun3 */
|
||||
|
||||
|
||||
|
||||
#if defined(NEED_SPARC_TAS_ASM)
|
||||
/*
|
||||
* sparc machines not using gcc
|
||||
*/
|
||||
static void
|
||||
tas_dummy() /* really means: extern int tas(slock_t
|
||||
* *lock); */
|
||||
{
|
||||
asm(".seg \"data\"");
|
||||
asm(".seg \"text\"");
|
||||
asm("_tas:");
|
||||
|
||||
/*
|
||||
* Sparc atomic test and set (sparc calls it "atomic load-store")
|
||||
*/
|
||||
asm("ldstub [%r8], %r8");
|
||||
asm("retl");
|
||||
asm("nop");
|
||||
}
|
||||
|
||||
#endif /* NEED_SPARC_TAS_ASM */
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined(NEED_I386_TAS_ASM)
|
||||
/* non gcc i386 based things */
|
||||
#endif /* NEED_I386_TAS_ASM */
|
||||
|
||||
|
||||
|
||||
#endif /* not __GNUC__ */
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
#if defined(S_LOCK_TEST)
|
||||
|
||||
/*
|
||||
* test program for verifying a port.
|
||||
*/
|
||||
|
||||
volatile slock_t test_lock;
|
||||
|
||||
void
|
||||
main()
|
||||
{
|
||||
S_INIT_LOCK(&test_lock);
|
||||
|
||||
if (!S_LOCK_FREE(&test_lock))
|
||||
{
|
||||
printf("S_LOCK_TEST: failed, lock not initialized.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
S_LOCK(&test_lock);
|
||||
|
||||
if (S_LOCK_FREE(&test_lock))
|
||||
{
|
||||
printf("S_LOCK_TEST: failed, lock not locked\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
printf("S_LOCK_TEST: this will hang for a few minutes and then abort\n");
|
||||
printf(" with a 'stuck spinlock' message if S_LOCK()\n");
|
||||
printf(" and TAS() are working.\n");
|
||||
s_lock(&test_lock, __FILE__, __LINE__);
|
||||
|
||||
printf("S_LOCK_TEST: failed, lock not locked~\n");
|
||||
exit(3);
|
||||
|
||||
}
|
||||
|
||||
#endif /* S_LOCK_TEST */
|
||||
Reference in New Issue
Block a user