Inline frequently called functions.

This commit is contained in:
Bruce Momjian 1997-09-18 14:21:02 +00:00
parent bbe2c10c14
commit 8cb4154492
16 changed files with 1098 additions and 793 deletions

View File

@ -7,143 +7,15 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/Attic/heapvalid.c,v 1.19 1997/09/12 04:07:09 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/access/common/Attic/heapvalid.c,v 1.20 1997/09/18 14:19:27 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <postgres.h>
#include <fmgr.h>
#include <access/heapam.h>
#include <access/valid.h>
#include <access/xact.h>
#include <storage/bufpage.h>
#include <utils/rel.h>
#include <utils/tqual.h>
#include <storage/bufmgr.h>
#include <utils/builtins.h>
/* ----------------
* heap_keytest
*
* Test a heap tuple with respect to a scan key.
* ----------------
*/
bool
heap_keytest(HeapTuple t,
TupleDesc tupdesc,
int nkeys,
ScanKey keys)
{
bool isnull;
Datum atp;
int test;
for (; nkeys--; keys++)
{
atp = heap_getattr(t, InvalidBuffer,
keys->sk_attno,
tupdesc,
&isnull);
if (isnull)
/* XXX eventually should check if SK_ISNULL */
return false;
if (keys->sk_flags & SK_ISNULL)
{
return (false);
}
if (keys->sk_func == (func_ptr) oideq) /* optimization */
test = (keys->sk_argument == atp);
else if (keys->sk_flags & SK_COMMUTE)
test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure,
keys->sk_argument, atp);
else
test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure,
atp, keys->sk_argument);
if (!test == !(keys->sk_flags & SK_NEGATE))
return false;
}
return true;
}
/* ----------------
* heap_tuple_satisfies
*
* Returns a valid HeapTuple if it satisfies the timequal and keytest.
* Returns NULL otherwise. Used to be heap_satisifies (sic) which
* returned a boolean. It now returns a tuple so that we can avoid doing two
* PageGetItem's per tuple.
*
* Complete check of validity including LP_CTUP and keytest.
* This should perhaps be combined with valid somehow in the
* future. (Also, additional rule tests/time range tests.)
*
* on 8/21/92 mao says: i rearranged the tests here to do keytest before
* SatisfiesTimeQual. profiling indicated that even for vacuumed relations,
* time qual checking was more expensive than key testing. time qual is
* least likely to fail, too. we should really add the time qual test to
* the restriction and optimize it in the normal way. this has interactions
* with joey's expensive function work.
* ----------------
*/
HeapTuple
heap_tuple_satisfies(ItemId itemId,
Relation relation,
Buffer buffer,
PageHeader disk_page,
TimeQual qual,
int nKeys,
ScanKey key)
{
HeapTuple tuple,
result;
bool res;
TransactionId old_tmin,
old_tmax;
if (!ItemIdIsUsed(itemId))
return NULL;
tuple = (HeapTuple) PageGetItem((Page) disk_page, itemId);
if (key != NULL)
res = heap_keytest(tuple, RelationGetTupleDescriptor(relation),
nKeys, key);
else
res = TRUE;
result = (HeapTuple) NULL;
if (res)
{
if (relation->rd_rel->relkind == RELKIND_UNCATALOGED)
{
result = tuple;
}
else
{
old_tmin = tuple->t_tmin;
old_tmax = tuple->t_tmax;
res = HeapTupleSatisfiesTimeQual(tuple, qual);
if (tuple->t_tmin != old_tmin ||
tuple->t_tmax != old_tmax)
{
SetBufferCommitInfoNeedsSave(buffer);
}
if (res)
{
result = tuple;
}
}
}
return result;
}
/*
* TupleUpdatedByCurXactAndCmd() -- Returns true if this tuple has

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.19 1997/09/08 21:40:57 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.20 1997/09/18 14:19:30 momjian Exp $
*
*
* INTERFACE ROUTINES
@ -429,8 +429,9 @@ heapgettup(Relation relation,
* if current tuple qualifies, return it.
* ----------------
*/
if ((rtup = heap_tuple_satisfies(lpp, relation, *b, (PageHeader) dp,
timeQual, nkeys, key)) != NULL)
HeapTupleSatisfies(lpp, relation, *b, (PageHeader) dp,
timeQual, nkeys, key, rtup);
if (rtup != NULL)
{
ItemPointer iptr = &(rtup->t_ctid);
@ -1092,8 +1093,8 @@ heap_fetch(Relation relation,
* ----------------
*/
tuple = heap_tuple_satisfies(lp, relation, buffer, dp,
timeQual, 0, (ScanKey) NULL);
HeapTupleSatisfies(lp, relation, buffer, dp,
timeQual, 0, (ScanKey) NULL, tuple);
if (tuple == NULL)
{
@ -1257,8 +1258,9 @@ heap_delete(Relation relation, ItemPointer tid)
* check that we're deleteing a valid item
* ----------------
*/
if (!(tp = heap_tuple_satisfies(lp, relation, b, dp,
NowTimeQual, 0, (ScanKey) NULL)))
HeapTupleSatisfies(lp, relation, b, dp,
NowTimeQual, 0, (ScanKey) NULL, tp);
if (!tp)
{
/* XXX call something else */
@ -1317,7 +1319,8 @@ heap_replace(Relation relation, ItemPointer otid, HeapTuple tup)
HeapTuple tp;
Page dp;
Buffer buffer;
HeapTuple tuple;
/* ----------------
* increment access statistics
* ----------------
@ -1388,13 +1391,15 @@ heap_replace(Relation relation, ItemPointer otid, HeapTuple tup)
* xact, we only want to flag the 'non-functional' NOTICE. -mer
* ----------------
*/
if (!heap_tuple_satisfies(lp,
relation,
buffer,
(PageHeader) dp,
NowTimeQual,
0,
(ScanKey) NULL))
HeapTupleSatisfies(lp,
relation,
buffer,
(PageHeader) dp,
NowTimeQual,
0,
(ScanKey) NULL,
tuple);
if (!tuple)
{
ReleaseBuffer(buffer);
elog(WARN, "heap_replace: (am)invalid otid");

View File

@ -792,8 +792,9 @@ GetTupleForTrigger(Relation relation, ItemPointer tid, bool before)
return (NULL);
}
if (!(tuple = heap_tuple_satisfies(lp, relation, b, dp,
NowTimeQual, 0, (ScanKey) NULL)))
HeapTupleSatisfies(lp, relation, b, dp,
NowTimeQual, 0, (ScanKey) NULL, tuple);
if (!tuple)
{
ReleaseBuffer(b);
elog(WARN, "GetTupleForTrigger: (am)invalid tid");

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.12 1997/09/08 02:28:27 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.13 1997/09/18 14:19:58 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -26,6 +26,7 @@
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/s_lock.h"
#include "storage/shmem.h"
#include "storage/spin.h"
#include "storage/smgr.h"

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.23 1997/09/08 21:46:50 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.24 1997/09/18 14:20:00 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -56,6 +56,7 @@
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/s_lock.h"
#include "storage/shmem.h"
#include "storage/spin.h"
#include "storage/smgr.h"

View File

@ -4,7 +4,7 @@
# Makefile for storage/ipc
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/storage/ipc/Makefile,v 1.3 1996/11/09 06:21:47 momjian Exp $
# $Header: /cvsroot/pgsql/src/backend/storage/ipc/Makefile,v 1.4 1997/09/18 14:20:08 momjian Exp $
#
#-------------------------------------------------------------------------
@ -17,7 +17,7 @@ INCLUDE_OPT = -I../.. \
CFLAGS+=$(INCLUDE_OPT)
OBJS = ipc.o ipci.o s_lock.o shmem.o shmqueue.o sinval.o \
OBJS = ipc.o ipci.o shmem.o shmqueue.o sinval.o \
sinvaladt.o spin.o
all: SUBSYS.o

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.14 1997/09/08 21:46:59 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.15 1997/09/18 14:20:14 momjian Exp $
*
* NOTES
*
@ -33,6 +33,7 @@
#include "postgres.h"
#include "storage/ipc.h"
#include "storage/s_lock.h"
/* In Ultrix, sem.h and shm.h must be included AFTER ipc.h */
#include <sys/sem.h>
#include <sys/shm.h>
@ -615,7 +616,10 @@ IpcMemoryKill(IpcMemoryKey memKey)
* supply of locks.
* ------------------
*/
static SLock *SLockArray = NULL;
/* used in spin.c */
SLock *SLockArray = NULL;
static SLock **FreeSLockPP;
static int *UnusedSLockIP;
static slock_t *SLockMemoryLock;
@ -676,92 +680,13 @@ AttachSLockMemory(IPCKey key)
return;
}
#ifdef LOCKDEBUG
#define PRINT_LOCK(LOCK) printf("(locklock = %d, flag = %d, nshlocks = %d, \
shlock = %d, exlock =%d)\n", LOCK->locklock, \
LOCK->flag, LOCK->nshlocks, LOCK->shlock, \
LOCK->exlock)
#endif
void
ExclusiveLock(int lockid)
{
SLock *slckP;
slckP = &(SLockArray[lockid]);
#ifdef LOCKDEBUG
printf("ExclusiveLock(%d)\n", lockid);
printf("IN: ");
PRINT_LOCK(slckP);
#endif
ex_try_again:
S_LOCK(&(slckP->locklock));
switch (slckP->flag)
{
case NOLOCK:
slckP->flag = EXCLUSIVELOCK;
S_LOCK(&(slckP->exlock));
S_LOCK(&(slckP->shlock));
S_UNLOCK(&(slckP->locklock));
#ifdef LOCKDEBUG
printf("OUT: ");
PRINT_LOCK(slckP);
#endif
return;
case SHAREDLOCK:
case EXCLUSIVELOCK:
S_UNLOCK(&(slckP->locklock));
S_LOCK(&(slckP->exlock));
S_UNLOCK(&(slckP->exlock));
goto ex_try_again;
}
}
void
ExclusiveUnlock(int lockid)
{
SLock *slckP;
slckP = &(SLockArray[lockid]);
#ifdef LOCKDEBUG
printf("ExclusiveUnlock(%d)\n", lockid);
printf("IN: ");
PRINT_LOCK(slckP);
#endif
S_LOCK(&(slckP->locklock));
/* -------------
* give favor to read processes
* -------------
*/
slckP->flag = NOLOCK;
if (slckP->nshlocks > 0)
{
while (slckP->nshlocks > 0)
{
S_UNLOCK(&(slckP->shlock));
S_LOCK(&(slckP->comlock));
}
S_UNLOCK(&(slckP->shlock));
}
else
{
S_UNLOCK(&(slckP->shlock));
}
S_UNLOCK(&(slckP->exlock));
S_UNLOCK(&(slckP->locklock));
#ifdef LOCKDEBUG
printf("OUT: ");
PRINT_LOCK(slckP);
#endif
return;
}
#ifdef NOT_USED
bool
LockIsFree(int lockid)
{
return (SLockArray[lockid].flag == NOLOCK);
}
#endif
#endif /* HAS_TEST_AND_SET */

View File

@ -1,525 +0,0 @@
/*-------------------------------------------------------------------------
*
* s_lock.c--
* This file contains the implementation (if any) for spinlocks.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/s_lock.c,v 1.24 1997/09/08 21:47:04 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/*
* DESCRIPTION
* The following code fragment should be written (in assembly
* language) on machines that have a native test-and-set instruction:
*
* void
* S_LOCK(char_address)
* char *char_address;
* {
* while (test_and_set(char_address))
* ;
* }
*
* If this is not done, POSTGRES will default to using System V
* semaphores (and take a large performance hit -- around 40% of
* its time on a DS5000/240 is spent in semop(3)...).
*
* NOTES
* AIX has a test-and-set but the recommended interface is the cs(3)
* system call. This provides an 8-instruction (plus system call
* overhead) uninterruptible compare-and-set operation. True
* spinlocks might be faster but using cs(3) still speeds up the
* regression test suite by about 25%. I don't have an assembler
* manual for POWER in any case.
*
*/
#include "postgres.h"
#include "storage/ipc.h"
#if defined(HAS_TEST_AND_SET)
#if defined (nextstep)
/*
* NEXTSTEP (mach)
* slock_t is defined as a struct mutex.
*/
void
S_LOCK(slock_t *lock)
{
mutex_lock(lock);
}
void
S_UNLOCK(slock_t *lock)
{
mutex_unlock(lock);
}
void
S_INIT_LOCK(slock_t *lock)
{
mutex_init(lock);
}
/* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
int
S_LOCK_FREE(slock_t *lock)
{
/* For Mach, we have to delve inside the entrails of `struct mutex'. Ick! */
return (lock->lock == 0);
}
#endif /* next */
#if defined(irix5)
/*
* SGI IRIX 5
* slock_t is defined as a struct abilock_t, which has a single unsigned long
* member.
*
* This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
* assembly from his NECEWS SVR4 port, but we probably ought to retain this
* for the R3000 chips out there.
*/
void
S_LOCK(slock_t *lock)
{
/* spin_lock(lock); */
while (!acquire_lock(lock))
;
}
void
S_UNLOCK(slock_t *lock)
{
release_lock(lock);
}
void
S_INIT_LOCK(slock_t *lock)
{
init_lock(lock);
}
/* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
int
S_LOCK_FREE(slock_t *lock)
{
return (stat_lock(lock) == UNLOCKED);
}
#endif /* irix5 */
/*
* OSF/1 (Alpha AXP)
*
* Note that slock_t on the Alpha AXP is msemaphore instead of char
* (see storage/ipc.h).
*/
#if defined(__alpha__) || defined(__alpha)
void
S_LOCK(slock_t *lock)
{
while (msem_lock(lock, MSEM_IF_NOWAIT) < 0)
;
}
void
S_UNLOCK(slock_t *lock)
{
msem_unlock(lock, 0);
}
void
S_INIT_LOCK(slock_t *lock)
{
msem_init(lock, MSEM_UNLOCKED);
}
int
S_LOCK_FREE(slock_t *lock)
{
return (lock->msem_state ? 0 : 1);
}
#endif /* alpha */
/*
* Solaris 2
*/
#if defined(i386_solaris) || \
defined(sparc_solaris)
/* for xxxxx_solaris, this is defined in port/.../tas.s */
static int tas(slock_t *lock);
void
S_LOCK(slock_t *lock)
{
while (tas(lock))
;
}
void
S_UNLOCK(slock_t *lock)
{
*lock = 0;
}
void
S_INIT_LOCK(slock_t *lock)
{
S_UNLOCK(lock);
}
#endif /* i86pc_solaris || sparc_solaris */
/*
* AIX (POWER)
*
* Note that slock_t on POWER/POWER2/PowerPC is int instead of char
* (see storage/ipc.h).
*/
#if defined(aix)
void
S_LOCK(slock_t *lock)
{
while (cs((int *) lock, 0, 1))
;
}
void
S_UNLOCK(slock_t *lock)
{
*lock = 0;
}
void
S_INIT_LOCK(slock_t *lock)
{
S_UNLOCK(lock);
}
#endif /* aix */
/*
* HP-UX (PA-RISC)
*
* Note that slock_t on PA-RISC is a structure instead of char
* (see storage/ipc.h).
*/
#if defined(hpux)
/*
* a "set" slock_t has a single word cleared. a "clear" slock_t has
* all words set to non-zero.
*/
static slock_t clear_lock = {-1, -1, -1, -1};
static int tas(slock_t *lock);
void
S_LOCK(slock_t *lock)
{
while (tas(lock))
;
}
void
S_UNLOCK(slock_t *lock)
{
*lock = clear_lock; /* struct assignment */
}
void
S_INIT_LOCK(slock_t *lock)
{
S_UNLOCK(lock);
}
int
S_LOCK_FREE(slock_t *lock)
{
register int *lock_word = (int *) (((long) lock + 15) & ~15);
return (*lock_word != 0);
}
#endif /* hpux */
/*
* sun3
*/
#if defined(sun3)
static int tas(slock_t *lock);
void
S_LOCK(slock_t *lock)
{
while (tas(lock));
}
void
S_UNLOCK(slock_t *lock)
{
*lock = 0;
}
void
S_INIT_LOCK(slock_t *lock)
{
S_UNLOCK(lock);
}
static int
tas_dummy()
{
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 */
/*
* sparc machines
*/
#if defined(NEED_SPARC_TAS_ASM)
/* if we're using -ansi w/ gcc, use __asm__ instead of asm */
#if defined(__STRICT_ANSI__)
#define asm(x) __asm__(x)
#endif
static int tas(slock_t *lock);
static int
tas_dummy()
{
asm(".seg \"data\"");
asm(".seg \"text\"");
asm(".global _tas");
asm("_tas:");
/*
* Sparc atomic test and set (sparc calls it "atomic load-store")
*/
asm("ldstub [%r8], %r8");
/*
* Did test and set actually do the set?
*/
asm("tst %r8");
asm("be,a ReturnZero");
/*
* otherwise, just return.
*/
asm("clr %r8");
asm("mov 0x1, %r8");
asm("ReturnZero:");
asm("retl");
asm("nop");
}
void
S_LOCK(unsigned char *addr)
{
while (tas(addr));
}
/*
* addr should be as in the above S_LOCK routine
*/
void
S_UNLOCK(unsigned char *addr)
{
*addr = 0;
}
void
S_INIT_LOCK(unsigned char *addr)
{
*addr = 0;
}
#endif /* NEED_SPARC_TAS_ASM */
/*
* i386 based things
*/
#if defined(NEED_I386_TAS_ASM)
void
S_LOCK(slock_t *lock)
{
slock_t res;
do
{
__asm__("xchgb %0,%1": "=q"(res), "=m"(*lock):"0"(0x1));
} while (res != 0);
}
void
S_UNLOCK(slock_t *lock)
{
*lock = 0;
}
void
S_INIT_LOCK(slock_t *lock)
{
S_UNLOCK(lock);
}
#endif /* NEED_I386_TAS_ASM */
#if defined(__alpha__) && defined(linux)
void
S_LOCK(slock_t *lock)
{
slock_t res;
do
{
__asm__(" ldq $0, %0 \n\
bne $0, already_set \n\
ldq_l $0, %0 \n\
bne $0, already_set \n\
or $31, 1, $0 \n\
stq_c $0, %0 \n\
beq $0, stqc_fail \n\
success: bis $31, $31, %1 \n\
mb \n\
jmp $31, end \n\
stqc_fail: or $31, 1, $0 \n\
already_set: bis $0, $0, %1 \n\
end: nop ": "=m"(*lock), "=r"(res): :"0");
} while (res != 0);
}
void
S_UNLOCK(slock_t *lock)
{
__asm__("mb");
*lock = 0;
}
void
S_INIT_LOCK(slock_t *lock)
{
S_UNLOCK(lock);
}
#endif /* defined(__alpha__) && defined(linux) */
#if defined(linux) && defined(sparc)
void
S_LOCK(slock_t *lock)
{
slock_t res;
do
{
__asm__("ldstub [%1], %0"
: "=&r"(res)
: "r"(lock));
} while (!res != 0);
}
void
S_UNLOCK(slock_t *lock)
{
*lock = 0;
}
void
S_INIT_LOCK(slock_t *lock)
{
S_UNLOCK(lock);
}
#endif /* defined(linux) && defined(sparc) */
#if defined(linux) && defined(PPC)
static int
tas_dummy()
{
__asm__(" \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\
");
}
void
S_LOCK(slock_t *lock)
{
while (tas(lock))
;
}
void
S_UNLOCK(slock_t *lock)
{
*lock = 0;
}
void
S_INIT_LOCK(slock_t *lock)
{
S_UNLOCK(lock);
}
#endif /* defined(linux) && defined(PPC) */
#endif /* HAS_TEST_AND_SET */

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.8 1997/09/08 02:29:02 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.9 1997/09/18 14:20:18 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -27,6 +27,7 @@
#include <errno.h>
#include "postgres.h"
#include "storage/ipc.h"
#include "storage/s_lock.h"
#include "storage/shmem.h"
#include "storage/spin.h"
#include "storage/proc.h"
@ -80,18 +81,91 @@ InitSpinLocks(int init, IPCKey key)
return (TRUE);
}
#ifdef LOCKDEBUG
#define PRINT_LOCK(LOCK) printf("(locklock = %d, flag = %d, nshlocks = %d, \
shlock = %d, exlock =%d)\n", LOCK->locklock, \
LOCK->flag, LOCK->nshlocks, LOCK->shlock, \
LOCK->exlock)
#endif
/* from ipc.c */
extern SLock *SLockArray;
void
SpinAcquire(SPINLOCK lock)
SpinAcquire(SPINLOCK lockid)
{
ExclusiveLock(lock);
PROC_INCR_SLOCK(lock);
SLock *slckP;
/* This used to be in ipc.c, but move here to reduce function calls */
slckP = &(SLockArray[lockid]);
#ifdef LOCKDEBUG
printf("SpinAcquire(%d)\n", lockid);
printf("IN: ");
PRINT_LOCK(slckP);
#endif
ex_try_again:
S_LOCK(&(slckP->locklock));
switch (slckP->flag)
{
case NOLOCK:
slckP->flag = EXCLUSIVELOCK;
S_LOCK(&(slckP->exlock));
S_LOCK(&(slckP->shlock));
S_UNLOCK(&(slckP->locklock));
#ifdef LOCKDEBUG
printf("OUT: ");
PRINT_LOCK(slckP);
#endif
return;
case SHAREDLOCK:
case EXCLUSIVELOCK:
S_UNLOCK(&(slckP->locklock));
S_LOCK(&(slckP->exlock));
S_UNLOCK(&(slckP->exlock));
goto ex_try_again;
}
PROC_INCR_SLOCK(lockid);
}
void
SpinRelease(SPINLOCK lock)
SpinRelease(SPINLOCK lockid)
{
PROC_DECR_SLOCK(lock);
ExclusiveUnlock(lock);
SLock *slckP;
PROC_DECR_SLOCK(lockid);
/* This used to be in ipc.c, but move here to reduce function calls */
slckP = &(SLockArray[lockid]);
#ifdef LOCKDEBUG
printf("SpinRelease(%d)\n", lockid);
printf("IN: ");
PRINT_LOCK(slckP);
#endif
S_LOCK(&(slckP->locklock));
/* -------------
* give favor to read processes
* -------------
*/
slckP->flag = NOLOCK;
if (slckP->nshlocks > 0)
{
while (slckP->nshlocks > 0)
{
S_UNLOCK(&(slckP->shlock));
S_LOCK(&(slckP->comlock));
}
S_UNLOCK(&(slckP->shlock));
}
else
{
S_UNLOCK(&(slckP->shlock));
}
S_UNLOCK(&(slckP->exlock));
S_UNLOCK(&(slckP->locklock));
#ifdef LOCKDEBUG
printf("OUT: ");
PRINT_LOCK(slckP);
#endif
}
#else /* HAS_TEST_AND_SET */

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.14 1997/09/08 21:47:26 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.15 1997/09/18 14:20:22 momjian Exp $
*
* NOTES
* Outside modules can create a lock table and acquire/release
@ -51,7 +51,7 @@
static int
WaitOnLock(LOCKTAB *ltable, LockTableId tableId, LOCK *lock,
LOCKT lockt);
/*#define LOCK_MGR_DEBUG*/
#ifndef LOCK_MGR_DEBUG
@ -451,6 +451,7 @@ LockTabRename(LockTableId tableId)
* DZ - 4 Oct 1996
#endif
*/
bool
LockAcquire(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt)
{
@ -540,7 +541,7 @@ LockAcquire(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt)
* word alignment and ensures hashing consistency).
* ------------------
*/
memset(&item, 0, XID_TAGSIZE);
memset(&item, 0, XID_TAGSIZE); /* must clear padding, needed */
TransactionIdStore(myXid, &item.tag.xid);
item.tag.lock = MAKE_OFFSET(lock);
#if 0

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.14 1997/09/12 04:08:28 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.15 1997/09/18 14:20:29 momjian Exp $
*
* Notes:
* XXX This needs to use exception.h to handle recovery when
@ -839,16 +839,20 @@ SearchSysCache(struct catcache * cache,
elt;
elt = DLGetSucc(elt))
{
bool res;
ct = (CatCTup *) DLE_VAL(elt);
/* ----------------
* see if the cached tuple matches our key.
* (should we be worried about time ranges? -cim 10/2/90)
* ----------------
*/
if (heap_keytest(ct->ct_tup,
HeapKeyTest(ct->ct_tup,
cache->cc_tupdesc,
cache->cc_nkeys,
cache->cc_skey))
cache->cc_skey,
res);
if (res)
break;
}

View File

@ -6,31 +6,156 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: valid.h,v 1.7 1997/09/08 21:51:05 momjian Exp $
* $Id: valid.h,v 1.8 1997/09/18 14:20:45 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef VALID_H
#define VALID_H
#include <fmgr.h>
#include <access/heapam.h>
#include <access/valid.h>
#include <utils/tqual.h>
#include <storage/bufmgr.h>
#include <storage/bufpage.h>
#include <utils/rel.h>
#include <utils/builtins.h>
/* ----------------
* extern decl's
* ----------------
*/
extern bool
heap_keytest(HeapTuple t, TupleDesc tupdesc,
int nkeys, ScanKey keys);
/* ----------------
* HeapKeyTest
*
* Test a heap tuple with respect to a scan key.
* ----------------
*/
extern HeapTuple
heap_tuple_satisfies(ItemId itemId, Relation relation,
Buffer buffer, PageHeader disk_page,
TimeQual qual, int nKeys,
ScanKey key);
#define HeapKeyTest(tuple, \
tupdesc, \
nkeys, \
keys, \
result) \
do \
{ \
/* We use underscores to protect the variable passed in as parameters */ \
/* We use two underscore here because this macro is included in the \
macro below */ \
bool __isnull; \
Datum __atp; \
int __test; \
int __cur_nkeys = (nkeys); \
ScanKey __cur_keys = (keys); \
\
(result) = true; /* may change */ \
for (; __cur_nkeys--; __cur_keys++) \
{ \
__atp = heap_getattr((tuple), InvalidBuffer, \
__cur_keys->sk_attno, \
(tupdesc), \
&__isnull); \
\
if (__isnull) \
{ \
/* XXX eventually should check if SK_ISNULL */ \
(result) = false; \
break; \
} \
\
if (__cur_keys->sk_flags & SK_ISNULL) \
{ \
(result) = false; \
break; \
} \
\
if (__cur_keys->sk_func == (func_ptr) oideq) /* optimization */ \
__test = (__cur_keys->sk_argument == __atp); \
else if (__cur_keys->sk_flags & SK_COMMUTE) \
__test = (long) FMGR_PTR2(__cur_keys->sk_func, __cur_keys->sk_procedure, \
__cur_keys->sk_argument, __atp); \
else \
__test = (long) FMGR_PTR2(__cur_keys->sk_func, __cur_keys->sk_procedure, \
__atp, __cur_keys->sk_argument); \
\
if (!__test == !(__cur_keys->sk_flags & SK_NEGATE)) \
{ \
/* XXX eventually should check if SK_ISNULL */ \
(result) = false; \
break; \
} \
} \
} while (0)
/* ----------------
* HeapTupleSatisfies
*
* Returns a valid HeapTuple if it satisfies the timequal and keytest.
* Returns NULL otherwise. Used to be heap_satisifies (sic) which
* returned a boolean. It now returns a tuple so that we can avoid doing two
* PageGetItem's per tuple.
*
* Complete check of validity including LP_CTUP and keytest.
* This should perhaps be combined with valid somehow in the
* future. (Also, additional rule tests/time range tests.)
*
* on 8/21/92 mao says: i rearranged the tests here to do keytest before
* SatisfiesTimeQual. profiling indicated that even for vacuumed relations,
* time qual checking was more expensive than key testing. time qual is
* least likely to fail, too. we should really add the time qual test to
* the restriction and optimize it in the normal way. this has interactions
* with joey's expensive function work.
* ----------------
*/
#define HeapTupleSatisfies(itemId, \
relation, \
buffer, \
disk_page, \
qual, \
nKeys, \
key, \
result) \
do \
{ \
/* We use underscores to protect the variable passed in as parameters */ \
HeapTuple _tuple; \
bool _res; \
TransactionId _old_tmin, \
_old_tmax; \
\
if (!ItemIdIsUsed(itemId)) \
(result) = (HeapTuple) NULL; \
else \
{ \
_tuple = (HeapTuple) PageGetItem((Page) (disk_page), (itemId)); \
\
if ((key) != NULL) \
HeapKeyTest(_tuple, RelationGetTupleDescriptor(relation), \
(nKeys), (key), _res); \
else \
_res = TRUE; \
\
(result) = (HeapTuple) NULL; \
if (_res) \
{ \
if ((relation)->rd_rel->relkind == RELKIND_UNCATALOGED) \
(result) = _tuple; \
else \
{ \
_old_tmin = _tuple->t_tmin; \
_old_tmax = _tuple->t_tmax; \
_res = HeapTupleSatisfiesTimeQual(_tuple, (qual)); \
if (_tuple->t_tmin != _old_tmin || \
_tuple->t_tmax != _old_tmax) \
SetBufferCommitInfoNeedsSave(buffer); \
if (_res) \
(result) = _tuple; \
} \
} \
} \
} while (0)
extern bool TupleUpdatedByCurXactAndCmd(HeapTuple t);

View File

@ -7,7 +7,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: c.h,v 1.19 1997/09/08 21:50:24 momjian Exp $
* $Id: c.h,v 1.20 1997/09/18 14:20:40 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -692,6 +692,27 @@ typedef struct Exception
/* we do this so if the macro is used in an if action, it will work */
#define strNcpy(dst,src,len) (strncpy((dst),(src),(len)),*((dst)+(len))='\0')
/* Get a bit mask of the bits set in non-int32 aligned addresses */
#define INT_ALIGN_MASK (sizeof(int32) - 1)
/* This function gets call too often, so we inline it if we can */
#define MemSet(start, val, len) do \
{ /* are we aligned for int32? */ \
if (((start) & INT_ALIGN_MASK) == 0 && \
((len) & INT_ALIGN_MASK) == 0 && \
(val) == 0 && \
(len) <= 256) \
{ \
int32 *i = (int32 *)(start); \
int32 *stop = (int32 *)((char *)(start) + (len)); \
\
while (i < stop) \
*i++ = 0; \
} \
else \
memset((start), (val), (len)); \
}
/* ----------------------------------------------------------------
* Section 9: externs
* ----------------------------------------------------------------

View File

@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: ipc.h,v 1.20 1997/09/08 21:54:21 momjian Exp $
* $Id: ipc.h,v 1.21 1997/09/18 14:20:54 momjian Exp $
*
* NOTES
* This file is very architecture-specific. This stuff should actually
@ -28,10 +28,6 @@
#if defined(HAS_TEST_AND_SET)
extern void S_LOCK(slock_t *lock);
extern void S_UNLOCK(slock_t *lock);
extern void S_INIT_LOCK(slock_t *lock);
#if (defined(alpha) && !defined(linuxalpha)) || \
defined(hpux) || \
defined(irix5) || \
@ -150,10 +146,6 @@ typedef struct slock
struct slock *next;
} SLock;
extern void ExclusiveLock(int lockid);
extern void ExclusiveUnlock(int lockid);
extern bool LockIsFree(int lockid);
#else /* HAS_TEST_AND_SET */
typedef enum _LockId_

View File

@ -0,0 +1,808 @@
/*-------------------------------------------------------------------------
*
* s_lock.h--
* This file contains the implementation (if any) for spinlocks.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/include/storage/s_lock.h,v 1.1 1997/09/18 14:20:59 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/*
* DESCRIPTION
* The following code fragment should be written (in assembly
* language) on machines that have a native test-and-set instruction:
*
* void
* S_LOCK(char_address)
* char *char_address;
* {
* while (test_and_set(char_address))
* ;
* }
*
* If this is not done, POSTGRES will default to using System V
* semaphores (and take a large performance hit -- around 40% of
* its time on a DS5000/240 is spent in semop(3)...).
*
* NOTES
* AIX has a test-and-set but the recommended interface is the cs(3)
* system call. This provides an 8-instruction (plus system call
* overhead) uninterruptible compare-and-set operation. True
* spinlocks might be faster but using cs(3) still speeds up the
* regression test suite by about 25%. I don't have an assembler
* manual for POWER in any case.
*
*/
#ifndef S_LOCK_H
#define S_LOCK_H
#include "storage/ipc.h"
#if defined(HAS_TEST_AND_SET)
#if defined (nextstep)
/*
* NEXTSTEP (mach)
* slock_t is defined as a struct mutex.
*/
#define S_LOCK(lock) mutex_lock(lock)
#define S_UNLOCK(lock) mutex_unlock(lock)
#define S_INIT_LOCK(lock) mutex_init(lock)
/* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
/* For Mach, we have to delve inside the entrails of `struct mutex'. Ick! */
#define S_LOCK_FREE(alock) ((alock)->lock == 0)
#endif /* next */
#if defined(irix5)
/*
* SGI IRIX 5
* slock_t is defined as a struct abilock_t, which has a single unsigned long
* member.
*
* This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
* assembly from his NECEWS SVR4 port, but we probably ought to retain this
* for the R3000 chips out there.
*/
#define S_LOCK(lock) do \
{ \
while (!acquire_lock(lock)) \
; \
} while (0)
#define S_UNLOCK(lock) release_lock(lock)
#define S_INIT_LOCK(lock) init_lock(lock)
/* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
#define S_LOCK_FREE(lock) (stat_lock(lock) == UNLOCKED)
#endif /* irix5 */
/*
* OSF/1 (Alpha AXP)
*
* Note that slock_t on the Alpha AXP is msemaphore instead of char
* (see storage/ipc.h).
*/
#if defined(__alpha__) || defined(__alpha)
#define S_LOCK(lock) do \
{ \
while (msem_lock((lock), MSEM_IF_NOWAIT) < 0) \
; \
} while (0)
#define S_UNLOCK(lock) msem_unlock((lock), 0)
#define S_INIT_LOCK(lock) msem_init((lock), MSEM_UNLOCKED)
#define S_LOCK_FREE(lock) (!(lock)->msem_state)
#endif /* alpha */
/*
* Solaris 2
*/
#if defined(i386_solaris) || \
defined(sparc_solaris)
/* for xxxxx_solaris, this is defined in port/.../tas.s */
static int tas(slock_t *lock);
#define S_LOCK(lock) do \
{ \
while (tas(lock)) \
; \
} while (0)
#define S_UNLOCK(lock) (*(lock) = 0)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#endif /* i86pc_solaris || sparc_solaris */
/*
* AIX (POWER)
*
* Note that slock_t on POWER/POWER2/PowerPC is int instead of char
* (see storage/ipc.h).
*/
#if defined(aix)
#define S_LOCK(lock) do \
{ \
while (cs((int *) (lock), 0, 1)) \
; \
} while (0)
#define S_UNLOCK(lock) (*(lock) = 0)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#endif /* aix */
/*
* HP-UX (PA-RISC)
*
* Note that slock_t on PA-RISC is a structure instead of char
* (see storage/ipc.h).
*/
#if defined(hpux)
/*
* a "set" slock_t has a single word cleared. a "clear" slock_t has
* all words set to non-zero.
*/
static slock_t clear_lock = {-1, -1, -1, -1};
static int tas(slock_t *lock);
#define S_LOCK(lock) do \
{ \
while (tas(lock)) \
; \
} while (0)
#define S_UNLOCK(lock) (*(lock) = clear_lock) /* struct assignment */
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#define S_LOCK_FREE(lock) ( *(int *) (((long) (lock) + 15) & ~15) != 0)
#endif /* hpux */
/*
* sun3
*/
#if defined(sun3)
static int tas(slock_t *lock);
#define S_LOCK(lock) do \
{ \
while (tas(lock)) \
; \
} while (0)
#define S_UNLOCK(lock) (*(lock) = 0)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#ifdef NOT_USED
static int
tas_dummy()
{
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
#endif /* sun3 */
/*
* sparc machines
*/
#if defined(NEED_SPARC_TAS_ASM)
/* if we're using -ansi w/ gcc, use __asm__ instead of asm */
#if defined(__STRICT_ANSI__)
#define asm(x) __asm__(x)
#endif
static int tas(slock_t *lock);
#ifdef NOT_USED
static int
tas_dummy()
{
asm(".seg \"data\"");
asm(".seg \"text\"");
asm(".global _tas");
asm("_tas:");
/*
* Sparc atomic test and set (sparc calls it "atomic load-store")
*/
asm("ldstub [%r8], %r8");
/*
* Did test and set actually do the set?
*/
asm("tst %r8");
asm("be,a ReturnZero");
/*
* otherwise, just return.
*/
asm("clr %r8");
asm("mov 0x1, %r8");
asm("ReturnZero:");
asm("retl");
asm("nop");
}
#endif
#define S_LOCK(addr) do \
{ \
while (tas(addr)) \
; \
} while (0)
/*
* addr should be as in the above S_LOCK routine
*/
#define S_UNLOCK(addr) (*(addr) = 0)
#define S_INIT_LOCK(addr) (*(addr) = 0)
#endif /* NEED_SPARC_TAS_ASM */
/*
* i386 based things
*/
#if defined(NEED_I386_TAS_ASM)
#define S_LOCK(lock) do \
{ \
slock_t res; \
do \
{ \
__asm__("xchgb %0,%1": "=q"(res), "=m"(*lock):"0"(0x1)); \
} while (res != 0); \
} while (0)
#define S_UNLOCK(lock) (*(lock) = 0)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#endif /* NEED_I386_TAS_ASM */
#if defined(__alpha__) && defined(linux)
#define S_LOCK(lock) do \
{ \
slock_t res; \
do \
{ \
__asm__(" ldq $0, %0 \n\
bne $0, already_set \n\
ldq_l $0, %0 \n\
bne $0, already_set \n\
or $31, 1, $0 \n\
stq_c $0, %0 \n\
beq $0, stqc_fail \n\
success: bis $31, $31, %1 \n\
mb \n\
jmp $31, end \n\
stqc_fail: or $31, 1, $0 \n\
already_set: bis $0, $0, %1 \n\
end: nop ": "=m"(*lock), "=r"(res): :"0"); \
} while (res != 0); \
} while (0)
#define S_UNLOCK(lock) (__asm__("mb"), *(lock) = 0)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#endif /* defined(__alpha__) && defined(linux) */
#if defined(linux) && defined(sparc)
#define S_LOCK(lock) do \
{ \
slock_t res; \
do \
{ \
__asm__("ldstub [%1], %0" \
: "=&r"(res) \
: "r"(lock)); \
} while (!res != 0); \
} while (0)
#define S_UNLOCK(lock) (*(lock) = 0)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#endif /* defined(linux) && defined(sparc) */
#if defined(linux) && defined(PPC)
#ifdef NOT_USED
static int
tas_dummy()
{
__asm__(" \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
#define S_LOCK(lock) do \
{ \
while (tas(lock)) \
; \
} while (0)
#define S_UNLOCK(lock) (*(lock) = 0)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#endif /* defined(linux) && defined(PPC) */
#endif /* HAS_TEST_AND_SET */
#endif /* S_LOCK_H */
/*-------------------------------------------------------------------------
*
* s_lock.h--
* This file contains the implementation (if any) for spinlocks.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/include/storage/s_lock.h,v 1.1 1997/09/18 14:20:59 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/*
* DESCRIPTION
* The following code fragment should be written (in assembly
* language) on machines that have a native test-and-set instruction:
*
* void
* S_LOCK(char_address)
* char *char_address;
* {
* while (test_and_set(char_address))
* ;
* }
*
* If this is not done, POSTGRES will default to using System V
* semaphores (and take a large performance hit -- around 40% of
* its time on a DS5000/240 is spent in semop(3)...).
*
* NOTES
* AIX has a test-and-set but the recommended interface is the cs(3)
* system call. This provides an 8-instruction (plus system call
* overhead) uninterruptible compare-and-set operation. True
* spinlocks might be faster but using cs(3) still speeds up the
* regression test suite by about 25%. I don't have an assembler
* manual for POWER in any case.
*
*/
#ifndef S_LOCK_H
#define S_LOCK_H
#include "storage/ipc.h"
#if defined(HAS_TEST_AND_SET)
#if defined (nextstep)
/*
* NEXTSTEP (mach)
* slock_t is defined as a struct mutex.
*/
#define S_LOCK(lock) mutex_lock(lock)
#define S_UNLOCK(lock) mutex_unlock(lock)
#define S_INIT_LOCK(lock) mutex_init(lock)
/* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
/* For Mach, we have to delve inside the entrails of `struct mutex'. Ick! */
#define S_LOCK_FREE(alock) ((alock)->lock == 0)
#endif /* next */
#if defined(irix5)
/*
* SGI IRIX 5
* slock_t is defined as a struct abilock_t, which has a single unsigned long
* member.
*
* This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
* assembly from his NECEWS SVR4 port, but we probably ought to retain this
* for the R3000 chips out there.
*/
#define S_LOCK(lock) do \
{ \
while (!acquire_lock(lock)) \
; \
} while (0)
#define S_UNLOCK(lock) release_lock(lock)
#define S_INIT_LOCK(lock) init_lock(lock)
/* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
#define S_LOCK_FREE(lock) (stat_lock(lock) == UNLOCKED)
#endif /* irix5 */
/*
* OSF/1 (Alpha AXP)
*
* Note that slock_t on the Alpha AXP is msemaphore instead of char
* (see storage/ipc.h).
*/
#if defined(__alpha__) || defined(__alpha)
#define S_LOCK(lock) do \
{ \
while (msem_lock((lock), MSEM_IF_NOWAIT) < 0) \
; \
} while (0)
#define S_UNLOCK(lock) msem_unlock((lock), 0)
#define S_INIT_LOCK(lock) msem_init((lock), MSEM_UNLOCKED)
#define S_LOCK_FREE(lock) (!(lock)->msem_state)
#endif /* alpha */
/*
* Solaris 2
*/
#if defined(i386_solaris) || \
defined(sparc_solaris)
/* for xxxxx_solaris, this is defined in port/.../tas.s */
static int tas(slock_t *lock);
#define S_LOCK(lock) do \
{ \
while (tas(lock)) \
; \
} while (0)
#define S_UNLOCK(lock) (*(lock) = 0)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#endif /* i86pc_solaris || sparc_solaris */
/*
* AIX (POWER)
*
* Note that slock_t on POWER/POWER2/PowerPC is int instead of char
* (see storage/ipc.h).
*/
#if defined(aix)
#define S_LOCK(lock) do \
{ \
while (cs((int *) (lock), 0, 1)) \
; \
} while (0)
#define S_UNLOCK(lock) (*(lock) = 0)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#endif /* aix */
/*
* HP-UX (PA-RISC)
*
* Note that slock_t on PA-RISC is a structure instead of char
* (see storage/ipc.h).
*/
#if defined(hpux)
/*
* a "set" slock_t has a single word cleared. a "clear" slock_t has
* all words set to non-zero.
*/
static slock_t clear_lock = {-1, -1, -1, -1};
static int tas(slock_t *lock);
#define S_LOCK(lock) do \
{ \
while (tas(lock)) \
; \
} while (0)
#define S_UNLOCK(lock) (*(lock) = clear_lock) /* struct assignment */
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#define S_LOCK_FREE(lock) ( *(int *) (((long) (lock) + 15) & ~15) != 0)
#endif /* hpux */
/*
* sun3
*/
#if defined(sun3)
static int tas(slock_t *lock);
#define S_LOCK(lock) do \
{ \
while (tas(lock)) \
; \
} while (0)
#define S_UNLOCK(lock) (*(lock) = 0)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#ifdef NOT_USED
static int
tas_dummy()
{
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
#endif /* sun3 */
/*
* sparc machines
*/
#if defined(NEED_SPARC_TAS_ASM)
/* if we're using -ansi w/ gcc, use __asm__ instead of asm */
#if defined(__STRICT_ANSI__)
#define asm(x) __asm__(x)
#endif
static int tas(slock_t *lock);
#ifdef NOT_USED
static int
tas_dummy()
{
asm(".seg \"data\"");
asm(".seg \"text\"");
asm(".global _tas");
asm("_tas:");
/*
* Sparc atomic test and set (sparc calls it "atomic load-store")
*/
asm("ldstub [%r8], %r8");
/*
* Did test and set actually do the set?
*/
asm("tst %r8");
asm("be,a ReturnZero");
/*
* otherwise, just return.
*/
asm("clr %r8");
asm("mov 0x1, %r8");
asm("ReturnZero:");
asm("retl");
asm("nop");
}
#endif
#define S_LOCK(addr) do \
{ \
while (tas(addr)) \
; \
} while (0)
/*
* addr should be as in the above S_LOCK routine
*/
#define S_UNLOCK(addr) (*(addr) = 0)
#define S_INIT_LOCK(addr) (*(addr) = 0)
#endif /* NEED_SPARC_TAS_ASM */
/*
* i386 based things
*/
#if defined(NEED_I386_TAS_ASM)
#define S_LOCK(lock) do \
{ \
slock_t res; \
do \
{ \
__asm__("xchgb %0,%1": "=q"(res), "=m"(*lock):"0"(0x1)); \
} while (res != 0); \
} while (0)
#define S_UNLOCK(lock) (*(lock) = 0)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#endif /* NEED_I386_TAS_ASM */
#if defined(__alpha__) && defined(linux)
#define S_LOCK(lock) do \
{ \
slock_t res; \
do \
{ \
__asm__(" ldq $0, %0 \n\
bne $0, already_set \n\
ldq_l $0, %0 \n\
bne $0, already_set \n\
or $31, 1, $0 \n\
stq_c $0, %0 \n\
beq $0, stqc_fail \n\
success: bis $31, $31, %1 \n\
mb \n\
jmp $31, end \n\
stqc_fail: or $31, 1, $0 \n\
already_set: bis $0, $0, %1 \n\
end: nop ": "=m"(*lock), "=r"(res): :"0"); \
} while (res != 0); \
} while (0)
#define S_UNLOCK(lock) (__asm__("mb"), *(lock) = 0)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#endif /* defined(__alpha__) && defined(linux) */
#if defined(linux) && defined(sparc)
#define S_LOCK(lock) do \
{ \
slock_t res; \
do \
{ \
__asm__("ldstub [%1], %0" \
: "=&r"(res) \
: "r"(lock)); \
} while (!res != 0); \
} while (0)
#define S_UNLOCK(lock) (*(lock) = 0)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#endif /* defined(linux) && defined(sparc) */
#if defined(linux) && defined(PPC)
#ifdef NOT_USED
static int
tas_dummy()
{
__asm__(" \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
#define S_LOCK(lock) do \
{ \
while (tas(lock)) \
; \
} while (0)
#define S_UNLOCK(lock) (*(lock) = 0)
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#endif /* defined(linux) && defined(PPC) */
#endif /* HAS_TEST_AND_SET */
#endif /* S_LOCK_H */

View File

@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: spin.h,v 1.5 1997/09/08 02:39:14 momjian Exp $
* $Id: spin.h,v 1.6 1997/09/18 14:21:02 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -29,7 +29,7 @@ typedef int SPINLOCK;
extern bool CreateSpinlocks(IPCKey key);
extern bool InitSpinLocks(int init, IPCKey key);
extern void SpinAcquire(SPINLOCK lock);
extern void SpinRelease(SPINLOCK lock);
extern void SpinAcquire(SPINLOCK lockid);
extern void SpinRelease(SPINLOCK lockid);
#endif /* SPIN_H */