mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Inline frequently called functions.
This commit is contained in:
@ -7,143 +7,15 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 <postgres.h>
|
||||||
|
|
||||||
#include <fmgr.h>
|
|
||||||
#include <access/heapam.h>
|
#include <access/heapam.h>
|
||||||
#include <access/valid.h>
|
|
||||||
#include <access/xact.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
|
* TupleUpdatedByCurXactAndCmd() -- Returns true if this tuple has
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* INTERFACE ROUTINES
|
||||||
@ -429,8 +429,9 @@ heapgettup(Relation relation,
|
|||||||
* if current tuple qualifies, return it.
|
* if current tuple qualifies, return it.
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
if ((rtup = heap_tuple_satisfies(lpp, relation, *b, (PageHeader) dp,
|
HeapTupleSatisfies(lpp, relation, *b, (PageHeader) dp,
|
||||||
timeQual, nkeys, key)) != NULL)
|
timeQual, nkeys, key, rtup);
|
||||||
|
if (rtup != NULL)
|
||||||
{
|
{
|
||||||
ItemPointer iptr = &(rtup->t_ctid);
|
ItemPointer iptr = &(rtup->t_ctid);
|
||||||
|
|
||||||
@ -1092,8 +1093,8 @@ heap_fetch(Relation relation,
|
|||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tuple = heap_tuple_satisfies(lp, relation, buffer, dp,
|
HeapTupleSatisfies(lp, relation, buffer, dp,
|
||||||
timeQual, 0, (ScanKey) NULL);
|
timeQual, 0, (ScanKey) NULL, tuple);
|
||||||
|
|
||||||
if (tuple == NULL)
|
if (tuple == NULL)
|
||||||
{
|
{
|
||||||
@ -1257,8 +1258,9 @@ heap_delete(Relation relation, ItemPointer tid)
|
|||||||
* check that we're deleteing a valid item
|
* check that we're deleteing a valid item
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
if (!(tp = heap_tuple_satisfies(lp, relation, b, dp,
|
HeapTupleSatisfies(lp, relation, b, dp,
|
||||||
NowTimeQual, 0, (ScanKey) NULL)))
|
NowTimeQual, 0, (ScanKey) NULL, tp);
|
||||||
|
if (!tp)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* XXX call something else */
|
/* XXX call something else */
|
||||||
@ -1317,7 +1319,8 @@ heap_replace(Relation relation, ItemPointer otid, HeapTuple tup)
|
|||||||
HeapTuple tp;
|
HeapTuple tp;
|
||||||
Page dp;
|
Page dp;
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
|
HeapTuple tuple;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* increment access statistics
|
* 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
|
* xact, we only want to flag the 'non-functional' NOTICE. -mer
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
if (!heap_tuple_satisfies(lp,
|
HeapTupleSatisfies(lp,
|
||||||
relation,
|
relation,
|
||||||
buffer,
|
buffer,
|
||||||
(PageHeader) dp,
|
(PageHeader) dp,
|
||||||
NowTimeQual,
|
NowTimeQual,
|
||||||
0,
|
0,
|
||||||
(ScanKey) NULL))
|
(ScanKey) NULL,
|
||||||
|
tuple);
|
||||||
|
if (!tuple)
|
||||||
{
|
{
|
||||||
ReleaseBuffer(buffer);
|
ReleaseBuffer(buffer);
|
||||||
elog(WARN, "heap_replace: (am)invalid otid");
|
elog(WARN, "heap_replace: (am)invalid otid");
|
||||||
|
@ -792,8 +792,9 @@ GetTupleForTrigger(Relation relation, ItemPointer tid, bool before)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(tuple = heap_tuple_satisfies(lp, relation, b, dp,
|
HeapTupleSatisfies(lp, relation, b, dp,
|
||||||
NowTimeQual, 0, (ScanKey) NULL)))
|
NowTimeQual, 0, (ScanKey) NULL, tuple);
|
||||||
|
if (!tuple)
|
||||||
{
|
{
|
||||||
ReleaseBuffer(b);
|
ReleaseBuffer(b);
|
||||||
elog(WARN, "GetTupleForTrigger: (am)invalid tid");
|
elog(WARN, "GetTupleForTrigger: (am)invalid tid");
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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/fd.h"
|
||||||
#include "storage/ipc.h"
|
#include "storage/ipc.h"
|
||||||
|
#include "storage/s_lock.h"
|
||||||
#include "storage/shmem.h"
|
#include "storage/shmem.h"
|
||||||
#include "storage/spin.h"
|
#include "storage/spin.h"
|
||||||
#include "storage/smgr.h"
|
#include "storage/smgr.h"
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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/fd.h"
|
||||||
#include "storage/ipc.h"
|
#include "storage/ipc.h"
|
||||||
|
#include "storage/s_lock.h"
|
||||||
#include "storage/shmem.h"
|
#include "storage/shmem.h"
|
||||||
#include "storage/spin.h"
|
#include "storage/spin.h"
|
||||||
#include "storage/smgr.h"
|
#include "storage/smgr.h"
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# Makefile for storage/ipc
|
# Makefile for storage/ipc
|
||||||
#
|
#
|
||||||
# IDENTIFICATION
|
# 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)
|
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
|
sinvaladt.o spin.o
|
||||||
|
|
||||||
all: SUBSYS.o
|
all: SUBSYS.o
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
*
|
*
|
||||||
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
#include "storage/ipc.h"
|
#include "storage/ipc.h"
|
||||||
|
#include "storage/s_lock.h"
|
||||||
/* In Ultrix, sem.h and shm.h must be included AFTER ipc.h */
|
/* In Ultrix, sem.h and shm.h must be included AFTER ipc.h */
|
||||||
#include <sys/sem.h>
|
#include <sys/sem.h>
|
||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
@ -615,7 +616,10 @@ IpcMemoryKill(IpcMemoryKey memKey)
|
|||||||
* supply of locks.
|
* supply of locks.
|
||||||
* ------------------
|
* ------------------
|
||||||
*/
|
*/
|
||||||
static SLock *SLockArray = NULL;
|
|
||||||
|
/* used in spin.c */
|
||||||
|
SLock *SLockArray = NULL;
|
||||||
|
|
||||||
static SLock **FreeSLockPP;
|
static SLock **FreeSLockPP;
|
||||||
static int *UnusedSLockIP;
|
static int *UnusedSLockIP;
|
||||||
static slock_t *SLockMemoryLock;
|
static slock_t *SLockMemoryLock;
|
||||||
@ -676,92 +680,13 @@ AttachSLockMemory(IPCKey key)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NOT_USED
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
LockIsFree(int lockid)
|
LockIsFree(int lockid)
|
||||||
{
|
{
|
||||||
return (SLockArray[lockid].flag == NOLOCK);
|
return (SLockArray[lockid].flag == NOLOCK);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* HAS_TEST_AND_SET */
|
#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
|
* 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 <errno.h>
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
#include "storage/ipc.h"
|
#include "storage/ipc.h"
|
||||||
|
#include "storage/s_lock.h"
|
||||||
#include "storage/shmem.h"
|
#include "storage/shmem.h"
|
||||||
#include "storage/spin.h"
|
#include "storage/spin.h"
|
||||||
#include "storage/proc.h"
|
#include "storage/proc.h"
|
||||||
@ -80,18 +81,91 @@ InitSpinLocks(int init, IPCKey key)
|
|||||||
return (TRUE);
|
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
|
void
|
||||||
SpinAcquire(SPINLOCK lock)
|
SpinAcquire(SPINLOCK lockid)
|
||||||
{
|
{
|
||||||
ExclusiveLock(lock);
|
SLock *slckP;
|
||||||
PROC_INCR_SLOCK(lock);
|
|
||||||
|
/* 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
|
void
|
||||||
SpinRelease(SPINLOCK lock)
|
SpinRelease(SPINLOCK lockid)
|
||||||
{
|
{
|
||||||
PROC_DECR_SLOCK(lock);
|
SLock *slckP;
|
||||||
ExclusiveUnlock(lock);
|
|
||||||
|
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 */
|
#else /* HAS_TEST_AND_SET */
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* Outside modules can create a lock table and acquire/release
|
* Outside modules can create a lock table and acquire/release
|
||||||
@ -51,7 +51,7 @@
|
|||||||
static int
|
static int
|
||||||
WaitOnLock(LOCKTAB *ltable, LockTableId tableId, LOCK *lock,
|
WaitOnLock(LOCKTAB *ltable, LockTableId tableId, LOCK *lock,
|
||||||
LOCKT lockt);
|
LOCKT lockt);
|
||||||
|
|
||||||
/*#define LOCK_MGR_DEBUG*/
|
/*#define LOCK_MGR_DEBUG*/
|
||||||
|
|
||||||
#ifndef LOCK_MGR_DEBUG
|
#ifndef LOCK_MGR_DEBUG
|
||||||
@ -451,6 +451,7 @@ LockTabRename(LockTableId tableId)
|
|||||||
* DZ - 4 Oct 1996
|
* DZ - 4 Oct 1996
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
LockAcquire(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt)
|
LockAcquire(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt)
|
||||||
{
|
{
|
||||||
@ -540,7 +541,7 @@ LockAcquire(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt)
|
|||||||
* word alignment and ensures hashing consistency).
|
* 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);
|
TransactionIdStore(myXid, &item.tag.xid);
|
||||||
item.tag.lock = MAKE_OFFSET(lock);
|
item.tag.lock = MAKE_OFFSET(lock);
|
||||||
#if 0
|
#if 0
|
||||||
|
10
src/backend/utils/cache/catcache.c
vendored
10
src/backend/utils/cache/catcache.c
vendored
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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:
|
* Notes:
|
||||||
* XXX This needs to use exception.h to handle recovery when
|
* XXX This needs to use exception.h to handle recovery when
|
||||||
@ -839,16 +839,20 @@ SearchSysCache(struct catcache * cache,
|
|||||||
elt;
|
elt;
|
||||||
elt = DLGetSucc(elt))
|
elt = DLGetSucc(elt))
|
||||||
{
|
{
|
||||||
|
bool res;
|
||||||
|
|
||||||
ct = (CatCTup *) DLE_VAL(elt);
|
ct = (CatCTup *) DLE_VAL(elt);
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* see if the cached tuple matches our key.
|
* see if the cached tuple matches our key.
|
||||||
* (should we be worried about time ranges? -cim 10/2/90)
|
* (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_tupdesc,
|
||||||
cache->cc_nkeys,
|
cache->cc_nkeys,
|
||||||
cache->cc_skey))
|
cache->cc_skey,
|
||||||
|
res);
|
||||||
|
if (res)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,31 +6,156 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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
|
#ifndef VALID_H
|
||||||
#define VALID_H
|
#define VALID_H
|
||||||
|
|
||||||
|
#include <fmgr.h>
|
||||||
|
#include <access/heapam.h>
|
||||||
|
#include <access/valid.h>
|
||||||
#include <utils/tqual.h>
|
#include <utils/tqual.h>
|
||||||
|
#include <storage/bufmgr.h>
|
||||||
#include <storage/bufpage.h>
|
#include <storage/bufpage.h>
|
||||||
#include <utils/rel.h>
|
#include <utils/rel.h>
|
||||||
|
#include <utils/builtins.h>
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* extern decl's
|
* extern decl's
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern bool
|
/* ----------------
|
||||||
heap_keytest(HeapTuple t, TupleDesc tupdesc,
|
* HeapKeyTest
|
||||||
int nkeys, ScanKey keys);
|
*
|
||||||
|
* Test a heap tuple with respect to a scan key.
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
|
||||||
extern HeapTuple
|
#define HeapKeyTest(tuple, \
|
||||||
heap_tuple_satisfies(ItemId itemId, Relation relation,
|
tupdesc, \
|
||||||
Buffer buffer, PageHeader disk_page,
|
nkeys, \
|
||||||
TimeQual qual, int nKeys,
|
keys, \
|
||||||
ScanKey key);
|
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);
|
extern bool TupleUpdatedByCurXactAndCmd(HeapTuple t);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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 */
|
/* 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')
|
#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
|
* Section 9: externs
|
||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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
|
* NOTES
|
||||||
* This file is very architecture-specific. This stuff should actually
|
* This file is very architecture-specific. This stuff should actually
|
||||||
@ -28,10 +28,6 @@
|
|||||||
|
|
||||||
#if defined(HAS_TEST_AND_SET)
|
#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)) || \
|
#if (defined(alpha) && !defined(linuxalpha)) || \
|
||||||
defined(hpux) || \
|
defined(hpux) || \
|
||||||
defined(irix5) || \
|
defined(irix5) || \
|
||||||
@ -150,10 +146,6 @@ typedef struct slock
|
|||||||
struct slock *next;
|
struct slock *next;
|
||||||
} SLock;
|
} SLock;
|
||||||
|
|
||||||
extern void ExclusiveLock(int lockid);
|
|
||||||
extern void ExclusiveUnlock(int lockid);
|
|
||||||
extern bool LockIsFree(int lockid);
|
|
||||||
|
|
||||||
#else /* HAS_TEST_AND_SET */
|
#else /* HAS_TEST_AND_SET */
|
||||||
|
|
||||||
typedef enum _LockId_
|
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
|
* 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 CreateSpinlocks(IPCKey key);
|
||||||
extern bool InitSpinLocks(int init, IPCKey key);
|
extern bool InitSpinLocks(int init, IPCKey key);
|
||||||
extern void SpinAcquire(SPINLOCK lock);
|
extern void SpinAcquire(SPINLOCK lockid);
|
||||||
extern void SpinRelease(SPINLOCK lock);
|
extern void SpinRelease(SPINLOCK lockid);
|
||||||
|
|
||||||
#endif /* SPIN_H */
|
#endif /* SPIN_H */
|
||||||
|
Reference in New Issue
Block a user