Inline frequently called functions.
This commit is contained in:
parent
bbe2c10c14
commit
8cb4154492
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
@ -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 */
|
||||
|
@ -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
|
||||
|
10
src/backend/utils/cache/catcache.c
vendored
10
src/backend/utils/cache/catcache.c
vendored
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
* ----------------------------------------------------------------
|
||||
|
@ -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_
|
||||
|
808
src/include/storage/s_lock.h
Normal file
808
src/include/storage/s_lock.h
Normal 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 */
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user