diff options
| author | Bruce Momjian | 1997-09-18 14:21:02 +0000 |
|---|---|---|
| committer | Bruce Momjian | 1997-09-18 14:21:02 +0000 |
| commit | 8cb415449202d7804c6a557352a91d0401ab1c19 (patch) | |
| tree | 44acc47d6a50fa83667fdb4e9ad4e1bb81d61a0a /src/include | |
| parent | bbe2c10c140803881125c516bcc172363eb698d8 (diff) | |
Inline frequently called functions.
Diffstat (limited to 'src/include')
| -rw-r--r-- | src/include/access/valid.h | 143 | ||||
| -rw-r--r-- | src/include/c.h | 23 | ||||
| -rw-r--r-- | src/include/storage/ipc.h | 10 | ||||
| -rw-r--r-- | src/include/storage/s_lock.h | 808 | ||||
| -rw-r--r-- | src/include/storage/spin.h | 6 |
5 files changed, 968 insertions, 22 deletions
diff --git a/src/include/access/valid.h b/src/include/access/valid.h index 7b047d66d68..a37258c62a6 100644 --- a/src/include/access/valid.h +++ b/src/include/access/valid.h @@ -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. + * ---------------- + */ + +#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) -extern HeapTuple -heap_tuple_satisfies(ItemId itemId, Relation relation, - Buffer buffer, PageHeader disk_page, - TimeQual qual, int nKeys, - ScanKey key); +/* ---------------- + * 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); diff --git a/src/include/c.h b/src/include/c.h index 05c3cc5e923..b247b2e8fa2 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -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 * ---------------------------------------------------------------- diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h index b62387b668e..1e95f669277 100644 --- a/src/include/storage/ipc.h +++ b/src/include/storage/ipc.h @@ -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_ diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h new file mode 100644 index 00000000000..3bc0af34e59 --- /dev/null +++ b/src/include/storage/s_lock.h @@ -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 */ diff --git a/src/include/storage/spin.h b/src/include/storage/spin.h index d41768039eb..c94a74255f7 100644 --- a/src/include/storage/spin.h +++ b/src/include/storage/spin.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 */ |
