1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-03 09:13:20 +03:00

Inline frequently called functions.

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

View File

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

View File

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

View File

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

View File

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

View File

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