Inline frequently called functions.
authorBruce Momjian <bruce@momjian.us>
Thu, 18 Sep 1997 14:21:02 +0000 (14:21 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 18 Sep 1997 14:21:02 +0000 (14:21 +0000)
16 files changed:
src/backend/access/common/heapvalid.c
src/backend/access/heap/heapam.c
src/backend/commands/trigger.c
src/backend/storage/buffer/buf_init.c
src/backend/storage/buffer/bufmgr.c
src/backend/storage/ipc/Makefile
src/backend/storage/ipc/ipc.c
src/backend/storage/ipc/s_lock.c [deleted file]
src/backend/storage/ipc/spin.c
src/backend/storage/lmgr/lock.c
src/backend/utils/cache/catcache.c
src/include/access/valid.h
src/include/c.h
src/include/storage/ipc.h
src/include/storage/s_lock.h [new file with mode: 0644]
src/include/storage/spin.h

index da2e93a30bc68dbc778e142d186c5e93f8ae5bc1..22d62afcd3d80b0b4e78d16a7a780c36d704ce03 100644 (file)
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/common/Attic/heapvalid.c,v 1.19 1997/09/12 04:07:09 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/common/Attic/heapvalid.c,v 1.20 1997/09/18 14:19:27 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include <postgres.h>
 
-#include <fmgr.h>
 #include <access/heapam.h>
-#include <access/valid.h>
 #include <access/xact.h>
-#include <storage/bufpage.h>
-#include <utils/rel.h>
-#include <utils/tqual.h>
-#include <storage/bufmgr.h>
-#include <utils/builtins.h>
-
-/* ----------------
- *             heap_keytest
- *
- *             Test a heap tuple with respect to a scan key.
- * ----------------
- */
-bool
-heap_keytest(HeapTuple t,
-                        TupleDesc tupdesc,
-                        int nkeys,
-                        ScanKey keys)
-{
-       bool            isnull;
-       Datum           atp;
-       int                     test;
-
-       for (; nkeys--; keys++)
-       {
-               atp = heap_getattr(t, InvalidBuffer,
-                                                  keys->sk_attno,
-                                                  tupdesc,
-                                                  &isnull);
-
-               if (isnull)
-                       /* XXX eventually should check if SK_ISNULL */
-                       return false;
-
-               if (keys->sk_flags & SK_ISNULL)
-               {
-                       return (false);
-               }
-
-               if (keys->sk_func == (func_ptr) oideq)  /* optimization */
-                       test = (keys->sk_argument == atp);
-               else if (keys->sk_flags & SK_COMMUTE)
-                       test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure,
-                                                                       keys->sk_argument, atp);
-               else
-                       test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure,
-                                                                       atp, keys->sk_argument);
-
-               if (!test == !(keys->sk_flags & SK_NEGATE))
-                       return false;
-       }
-
-       return true;
-}
-
-/* ----------------
- *             heap_tuple_satisfies
- *
- *     Returns a valid HeapTuple if it satisfies the timequal and keytest.
- *     Returns NULL otherwise.  Used to be heap_satisifies (sic) which
- *     returned a boolean.  It now returns a tuple so that we can avoid doing two
- *     PageGetItem's per tuple.
- *
- *             Complete check of validity including LP_CTUP and keytest.
- *             This should perhaps be combined with valid somehow in the
- *             future.  (Also, additional rule tests/time range tests.)
- *
- *     on 8/21/92 mao says:  i rearranged the tests here to do keytest before
- *     SatisfiesTimeQual.      profiling indicated that even for vacuumed relations,
- *     time qual checking was more expensive than key testing.  time qual is
- *     least likely to fail, too.      we should really add the time qual test to
- *     the restriction and optimize it in the normal way.      this has interactions
- *     with joey's expensive function work.
- * ----------------
- */
-HeapTuple
-heap_tuple_satisfies(ItemId itemId,
-                                        Relation relation,
-                                        Buffer buffer,
-                                        PageHeader disk_page,
-                                        TimeQual qual,
-                                        int nKeys,
-                                        ScanKey key)
-{
-       HeapTuple       tuple,
-                               result;
-       bool            res;
-       TransactionId old_tmin,
-                               old_tmax;
-
-       if (!ItemIdIsUsed(itemId))
-               return NULL;
-
-       tuple = (HeapTuple) PageGetItem((Page) disk_page, itemId);
-
-       if (key != NULL)
-               res = heap_keytest(tuple, RelationGetTupleDescriptor(relation),
-                                                  nKeys, key);
-       else
-               res = TRUE;
-
-       result = (HeapTuple) NULL;
-       if (res)
-       {
-               if (relation->rd_rel->relkind == RELKIND_UNCATALOGED)
-               {
-                       result = tuple;
-               }
-               else
-               {
-                       old_tmin = tuple->t_tmin;
-                       old_tmax = tuple->t_tmax;
-                       res = HeapTupleSatisfiesTimeQual(tuple, qual);
-                       if (tuple->t_tmin != old_tmin ||
-                               tuple->t_tmax != old_tmax)
-                       {
-                               SetBufferCommitInfoNeedsSave(buffer);
-                       }
-                       if (res)
-                       {
-                               result = tuple;
-                       }
-               }
-       }
-
-       return result;
-}
 
 /*
  *     TupleUpdatedByCurXactAndCmd() -- Returns true if this tuple has
index 19bdf5b34ceb6461ca8eb2a9672a5d8baa3de579..2537e7e777c9472330a748db2129ad1a6fcbcf5b 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.19 1997/09/08 21:40:57 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.20 1997/09/18 14:19:30 momjian Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -429,8 +429,9 @@ heapgettup(Relation relation,
                         *      if current tuple qualifies, return it.
                         * ----------------
                         */
-                       if ((rtup = heap_tuple_satisfies(lpp, relation, *b, (PageHeader) dp,
-                                                                                 timeQual, nkeys, key)) != NULL)
+                       HeapTupleSatisfies(lpp, relation, *b, (PageHeader) dp,
+                                                          timeQual, nkeys, key, rtup);
+                       if (rtup != NULL)
                        {
                                ItemPointer iptr = &(rtup->t_ctid);
 
@@ -1092,8 +1093,8 @@ heap_fetch(Relation relation,
         * ----------------
         */
 
-       tuple = heap_tuple_satisfies(lp, relation, buffer, dp,
-                                                                timeQual, 0, (ScanKey) NULL);
+       HeapTupleSatisfies(lp, relation, buffer, dp,
+                                          timeQual, 0, (ScanKey) NULL, tuple);
 
        if (tuple == NULL)
        {
@@ -1257,8 +1258,9 @@ heap_delete(Relation relation, ItemPointer tid)
         *      check that we're deleteing a valid item
         * ----------------
         */
-       if (!(tp = heap_tuple_satisfies(lp, relation, b, dp,
-                                                                       NowTimeQual, 0, (ScanKey) NULL)))
+       HeapTupleSatisfies(lp, relation, b, dp,
+                                          NowTimeQual, 0, (ScanKey) NULL, tp);
+       if (!tp)
        {
 
                /* XXX call something else */
@@ -1317,7 +1319,8 @@ heap_replace(Relation relation, ItemPointer otid, HeapTuple tup)
        HeapTuple       tp;
        Page            dp;
        Buffer          buffer;
-
+       HeapTuple       tuple;
+       
        /* ----------------
         *      increment access statistics
         * ----------------
@@ -1388,13 +1391,15 @@ heap_replace(Relation relation, ItemPointer otid, HeapTuple tup)
         *               xact, we only want to flag the 'non-functional' NOTICE. -mer
         * ----------------
         */
-       if (!heap_tuple_satisfies(lp,
-                                                         relation,
-                                                         buffer,
-                                                         (PageHeader) dp,
-                                                         NowTimeQual,
-                                                         0,
-                                                         (ScanKey) NULL))
+       HeapTupleSatisfies(lp,
+                                                relation,
+                                                buffer,
+                                                (PageHeader) dp,
+                                                NowTimeQual,
+                                                0,
+                                                (ScanKey) NULL,
+                                                tuple);
+       if (!tuple)
        {
                ReleaseBuffer(buffer);
                elog(WARN, "heap_replace: (am)invalid otid");
index 58d93a0799897340dc880d95bdc97d06f0eec717..5aa70f52cbc31022acb5f5dd9bcd6b858c4a957a 100644 (file)
@@ -792,8 +792,9 @@ GetTupleForTrigger(Relation relation, ItemPointer tid, bool before)
                        return (NULL);
                }
 
-               if (!(tuple = heap_tuple_satisfies(lp, relation, b, dp,
-                                                                               NowTimeQual, 0, (ScanKey) NULL)))
+               HeapTupleSatisfies(lp, relation, b, dp,
+                                                  NowTimeQual, 0, (ScanKey) NULL, tuple);
+               if (!tuple)
                {
                        ReleaseBuffer(b);
                        elog(WARN, "GetTupleForTrigger: (am)invalid tid");
index a0f45eca0946042a11e765f469c69f3e3f4eb1a6..9b2f7a237cf88991c417d9f2438292235bf9f591 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.12 1997/09/08 02:28:27 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.13 1997/09/18 14:19:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,6 +26,7 @@
 
 #include "storage/fd.h"
 #include "storage/ipc.h"
+#include "storage/s_lock.h"
 #include "storage/shmem.h"
 #include "storage/spin.h"
 #include "storage/smgr.h"
index 7acc70342caafded6427fcdc7547baf159272b1b..0fc48c20526fdba9a4aa0b23c47ec8ded4e3d5a2 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.23 1997/09/08 21:46:50 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.24 1997/09/18 14:20:00 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -56,6 +56,7 @@
 
 #include "storage/fd.h"
 #include "storage/ipc.h"
+#include "storage/s_lock.h"
 #include "storage/shmem.h"
 #include "storage/spin.h"
 #include "storage/smgr.h"
index 821bf688cf085a822583760226198479e1396b21..e5517135d336d0e1ec3d7e1e243291e039ed9992 100644 (file)
@@ -4,7 +4,7 @@
 #    Makefile for storage/ipc
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/storage/ipc/Makefile,v 1.3 1996/11/09 06:21:47 momjian Exp $
+#    $Header: /cvsroot/pgsql/src/backend/storage/ipc/Makefile,v 1.4 1997/09/18 14:20:08 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -17,7 +17,7 @@ INCLUDE_OPT = -I../.. \
 
 CFLAGS+=$(INCLUDE_OPT)
 
-OBJS = ipc.o ipci.o s_lock.o shmem.o shmqueue.o sinval.o \
+OBJS = ipc.o ipci.o shmem.o shmqueue.o sinval.o \
        sinvaladt.o spin.o
 
 all: SUBSYS.o
index 856ca1350802cfaf702ee98028ae088b15952e8c..2ef50c5c91932fda78ea26b80b7830ff6c84d26c 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.14 1997/09/08 21:46:59 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.15 1997/09/18 14:20:14 momjian Exp $
  *
  * NOTES
  *
@@ -33,6 +33,7 @@
 
 #include "postgres.h"
 #include "storage/ipc.h"
+#include "storage/s_lock.h"
 /* In Ultrix, sem.h and shm.h must be included AFTER ipc.h */
 #include <sys/sem.h>
 #include <sys/shm.h>
@@ -615,7 +616,10 @@ IpcMemoryKill(IpcMemoryKey memKey)
  *     supply of locks.
  * ------------------
  */
-static SLock *SLockArray = NULL;
+
+/* used in spin.c */
+SLock *SLockArray = NULL;
+
 static SLock **FreeSLockPP;
 static int *UnusedSLockIP;
 static slock_t *SLockMemoryLock;
@@ -676,92 +680,13 @@ AttachSLockMemory(IPCKey key)
        return;
 }
 
-
-#ifdef LOCKDEBUG
-#define PRINT_LOCK(LOCK) printf("(locklock = %d, flag = %d, nshlocks = %d, \
-shlock = %d, exlock =%d)\n", LOCK->locklock, \
-                                                               LOCK->flag, LOCK->nshlocks, LOCK->shlock, \
-                                                               LOCK->exlock)
-#endif
-
-void
-ExclusiveLock(int lockid)
-{
-       SLock      *slckP;
-
-       slckP = &(SLockArray[lockid]);
-#ifdef LOCKDEBUG
-       printf("ExclusiveLock(%d)\n", lockid);
-       printf("IN: ");
-       PRINT_LOCK(slckP);
-#endif
-ex_try_again:
-       S_LOCK(&(slckP->locklock));
-       switch (slckP->flag)
-       {
-               case NOLOCK:
-                       slckP->flag = EXCLUSIVELOCK;
-                       S_LOCK(&(slckP->exlock));
-                       S_LOCK(&(slckP->shlock));
-                       S_UNLOCK(&(slckP->locklock));
-#ifdef LOCKDEBUG
-                       printf("OUT: ");
-                       PRINT_LOCK(slckP);
-#endif
-                       return;
-               case SHAREDLOCK:
-               case EXCLUSIVELOCK:
-                       S_UNLOCK(&(slckP->locklock));
-                       S_LOCK(&(slckP->exlock));
-                       S_UNLOCK(&(slckP->exlock));
-                       goto ex_try_again;
-       }
-}
-
-void
-ExclusiveUnlock(int lockid)
-{
-       SLock      *slckP;
-
-       slckP = &(SLockArray[lockid]);
-#ifdef LOCKDEBUG
-       printf("ExclusiveUnlock(%d)\n", lockid);
-       printf("IN: ");
-       PRINT_LOCK(slckP);
-#endif
-       S_LOCK(&(slckP->locklock));
-       /* -------------
-        *      give favor to read processes
-        * -------------
-        */
-       slckP->flag = NOLOCK;
-       if (slckP->nshlocks > 0)
-       {
-               while (slckP->nshlocks > 0)
-               {
-                       S_UNLOCK(&(slckP->shlock));
-                       S_LOCK(&(slckP->comlock));
-               }
-               S_UNLOCK(&(slckP->shlock));
-       }
-       else
-       {
-               S_UNLOCK(&(slckP->shlock));
-       }
-       S_UNLOCK(&(slckP->exlock));
-       S_UNLOCK(&(slckP->locklock));
-#ifdef LOCKDEBUG
-       printf("OUT: ");
-       PRINT_LOCK(slckP);
-#endif
-       return;
-}
-
+#ifdef NOT_USED
 bool
 LockIsFree(int lockid)
 {
        return (SLockArray[lockid].flag == NOLOCK);
 }
+#endif
 
 #endif                                                 /* HAS_TEST_AND_SET */
 
diff --git a/src/backend/storage/ipc/s_lock.c b/src/backend/storage/ipc/s_lock.c
deleted file mode 100644 (file)
index 82551f8..0000000
+++ /dev/null
@@ -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 */
index 3443c2db95b7e271cd5773ef272995eb7554e510..5300e2ecd4d3f33664182f4289da1c9e12e581a5 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.8 1997/09/08 02:29:02 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.9 1997/09/18 14:20:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,7 @@
 #include <errno.h>
 #include "postgres.h"
 #include "storage/ipc.h"
+#include "storage/s_lock.h"
 #include "storage/shmem.h"
 #include "storage/spin.h"
 #include "storage/proc.h"
@@ -80,18 +81,91 @@ InitSpinLocks(int init, IPCKey key)
        return (TRUE);
 }
 
+#ifdef LOCKDEBUG
+#define PRINT_LOCK(LOCK) printf("(locklock = %d, flag = %d, nshlocks = %d, \
+shlock = %d, exlock =%d)\n", LOCK->locklock, \
+                                                               LOCK->flag, LOCK->nshlocks, LOCK->shlock, \
+                                                               LOCK->exlock)
+#endif
+
+/* from ipc.c */
+extern SLock *SLockArray;
+
 void
-SpinAcquire(SPINLOCK lock)
+SpinAcquire(SPINLOCK lockid)
 {
-       ExclusiveLock(lock);
-       PROC_INCR_SLOCK(lock);
+       SLock      *slckP;
+
+       /* This used to be in ipc.c, but move here to reduce function calls */
+       slckP = &(SLockArray[lockid]);
+#ifdef LOCKDEBUG
+       printf("SpinAcquire(%d)\n", lockid);
+       printf("IN: ");
+       PRINT_LOCK(slckP);
+#endif
+ex_try_again:
+       S_LOCK(&(slckP->locklock));
+       switch (slckP->flag)
+       {
+               case NOLOCK:
+                       slckP->flag = EXCLUSIVELOCK;
+                       S_LOCK(&(slckP->exlock));
+                       S_LOCK(&(slckP->shlock));
+                       S_UNLOCK(&(slckP->locklock));
+#ifdef LOCKDEBUG
+                       printf("OUT: ");
+                       PRINT_LOCK(slckP);
+#endif
+                       return;
+               case SHAREDLOCK:
+               case EXCLUSIVELOCK:
+                       S_UNLOCK(&(slckP->locklock));
+                       S_LOCK(&(slckP->exlock));
+                       S_UNLOCK(&(slckP->exlock));
+                       goto ex_try_again;
+       }
+       PROC_INCR_SLOCK(lockid);
 }
 
 void
-SpinRelease(SPINLOCK lock)
+SpinRelease(SPINLOCK lockid)
 {
-       PROC_DECR_SLOCK(lock);
-       ExclusiveUnlock(lock);
+       SLock      *slckP;
+
+       PROC_DECR_SLOCK(lockid);
+
+       /* This used to be in ipc.c, but move here to reduce function calls */
+       slckP = &(SLockArray[lockid]);
+#ifdef LOCKDEBUG
+       printf("SpinRelease(%d)\n", lockid);
+       printf("IN: ");
+       PRINT_LOCK(slckP);
+#endif
+       S_LOCK(&(slckP->locklock));
+       /* -------------
+        *      give favor to read processes
+        * -------------
+        */
+       slckP->flag = NOLOCK;
+       if (slckP->nshlocks > 0)
+       {
+               while (slckP->nshlocks > 0)
+               {
+                       S_UNLOCK(&(slckP->shlock));
+                       S_LOCK(&(slckP->comlock));
+               }
+               S_UNLOCK(&(slckP->shlock));
+       }
+       else
+       {
+               S_UNLOCK(&(slckP->shlock));
+       }
+       S_UNLOCK(&(slckP->exlock));
+       S_UNLOCK(&(slckP->locklock));
+#ifdef LOCKDEBUG
+       printf("OUT: ");
+       PRINT_LOCK(slckP);
+#endif
 }
 
 #else                                                  /* HAS_TEST_AND_SET */
index dc6b7bd466cbca53597dd62b48c957561f44747d..c8abb92e463d2cb76b35c024ccc72b87729714a8 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.14 1997/09/08 21:47:26 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.15 1997/09/18 14:20:22 momjian Exp $
  *
  * NOTES
  *       Outside modules can create a lock table and acquire/release
@@ -51,7 +51,7 @@
 static int
 WaitOnLock(LOCKTAB *ltable, LockTableId tableId, LOCK *lock,
                   LOCKT lockt);
-
+                  
 /*#define LOCK_MGR_DEBUG*/
 
 #ifndef LOCK_MGR_DEBUG
@@ -451,6 +451,7 @@ LockTabRename(LockTableId tableId)
  *                                                                                                             DZ - 4 Oct 1996
 #endif
  */
+
 bool
 LockAcquire(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt)
 {
@@ -540,7 +541,7 @@ LockAcquire(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt)
         * word alignment and ensures hashing consistency).
         * ------------------
         */
-       memset(&item, 0, XID_TAGSIZE);
+       memset(&item, 0, XID_TAGSIZE); /* must clear padding, needed */
        TransactionIdStore(myXid, &item.tag.xid);
        item.tag.lock = MAKE_OFFSET(lock);
 #if 0
index c74565ddfab916d031e0ebbb682b6133273ed71a..f0d41a7116f0cf890030cf6eb5c5d72b559a0bac 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.14 1997/09/12 04:08:28 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.15 1997/09/18 14:20:29 momjian Exp $
  *
  * Notes:
  *             XXX This needs to use exception.h to handle recovery when
@@ -839,16 +839,20 @@ SearchSysCache(struct catcache * cache,
                 elt;
                 elt = DLGetSucc(elt))
        {
+               bool res;
+               
                ct = (CatCTup *) DLE_VAL(elt);
                /* ----------------
                 *      see if the cached tuple matches our key.
                 *      (should we be worried about time ranges? -cim 10/2/90)
                 * ----------------
                 */
-               if (heap_keytest(ct->ct_tup,
+               HeapKeyTest(ct->ct_tup,
                                                 cache->cc_tupdesc,
                                                 cache->cc_nkeys,
-                                                cache->cc_skey))
+                                                cache->cc_skey,
+                                                res);
+               if (res)
                        break;
        }
 
index 7b047d66d689a5954da8df992f23984bac713679..a37258c62a61817cbc38edebe1a04ede8a7ba2d2 100644 (file)
  *
  * 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);
 
index 05c3cc5e923876b09ecb492eba3ee7b59d16f5cb..b247b2e8fa26eca3336541eb7b9d738dab41de41 100644 (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
  * ----------------------------------------------------------------
index b62387b668e4687406ebedf9a7eed8650bf0541d..1e95f669277e592cad79de6c310af64f0bb64785 100644 (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
 
 #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 (file)
index 0000000..3bc0af3
--- /dev/null
@@ -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 */ 
index d41768039eb109a55b50315fa63ef8d9536ddf5b..c94a74255f74682d9a901747d4f9b6967d159a0b 100644 (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 */