head	1.14;
access;
symbols
	release_4_2:1.14
	aix_ok:1.13
	Version_2_1:1.2;
locks; strict;
comment	@ * @;


1.14
date	94.02.07.11.44.47;	author aoki;	state Exp;
branches;
next	1.13;

1.13
date	92.04.13.21.33.36;	author mer;	state Exp;
branches;
next	1.12;

1.12
date	92.04.13.18.58.27;	author mer;	state Exp;
branches;
next	1.11;

1.11
date	91.08.12.15.19.07;	author mer;	state Exp;
branches;
next	1.10;

1.10
date	91.08.03.00.30.52;	author mao;	state Exp;
branches;
next	1.9;

1.9
date	91.07.29.16.49.22;	author mer;	state Exp;
branches;
next	1.8;

1.8
date	91.07.24.07.46.49;	author mao;	state Exp;
branches;
next	1.7;

1.7
date	91.07.22.23.14.30;	author mao;	state Exp;
branches;
next	1.6;

1.6
date	91.07.22.22.21.16;	author mao;	state Exp;
branches;
next	1.5;

1.5
date	91.07.22.14.38.01;	author mer;	state Exp;
branches;
next	1.4;

1.4
date	91.06.10.20.57.58;	author kemnitz;	state Exp;
branches;
next	1.3;

1.3
date	91.03.13.12.36.50;	author hong;	state Exp;
branches;
next	1.2;

1.2
date	91.01.25.22.13.39;	author hong;	state Exp;
branches;
next	1.1;

1.1
date	91.01.18.22.14.23;	author hong;	state Exp;
branches;
next	;


desc
@spin lock supports for the new buffer manager
@


1.14
log
@ipc.h protos require ipci.h but someone included them backwards all over
the storage directory..
@
text
@/*
 * spin.c -- routines for managing spin locks
 *
 * Identification:
 *	$Header: /faerie/aoki/postgres/src/backend/storage/ipc/RCS/spin.c,v 1.13 1992/04/13 21:33:36 mer Exp aoki $
 *
 * POSTGRES has two kinds of locks: semaphores (which put the
 * process to sleep) and spinlocks (which are supposed to be
 * short term locks).  Currently both are implemented as SysV
 * semaphores, but presumably this can change if we move to
 * a machine with a test-and-set (TAS) instruction.  Its probably
 * a good idea to think about (and allocate) short term and long
 * term semaphores separately anyway.
 *
 * NOTE: These routines are not supposed to be widely used in Postgres.
 *	 They are preserved solely for the purpose of porting Mark Sullivan's
 *	 buffer manager to Postgres.
 */
#include <errno.h>
#include "tmp/postgres.h"
#include "storage/ipci.h"
#include "storage/ipc.h"
#include "storage/shmem.h"
#include "storage/spin.h"
#include "storage/proc.h"
#include "utils/log.h"

/* globals used in this file */
IpcSemaphoreId	SpinLockId;

#ifdef HAS_TEST_AND_SET
/* real spin lock implementations */

CreateSpinlocks(key)
IPCKey key;
{ 
   /* the spin lock shared memory must have been created by now */
   return(TRUE); 
}

AttachSpinLocks(key)
{
    /* the spin lock shared memory must have been attached by now */
    return(TRUE);
}

InitSpinLocks(init, key)
int init;
IPCKey key;
{
  extern SPINLOCK ShmemLock;
  extern SPINLOCK BindingLock;
  extern SPINLOCK BufMgrLock;
  extern SPINLOCK LockMgrLock;
  extern SPINLOCK ProcStructLock;
  extern SPINLOCK SInvalLock;
  extern SPINLOCK OidGenLockId;

#ifdef SONY_JUKEBOX
  extern SPINLOCK SJCacheLock;
  extern SPINLOCK JBSpinLock;
#endif /* SONY_JUKEBOX */

#ifdef MAIN_MEMORY
  extern SPINLOCK MMCacheLock;
#endif /* SONY_JUKEBOX */

  /* These six spinlocks have fixed location is shmem */
  ShmemLock = (SPINLOCK) SHMEMLOCKID;
  BindingLock = (SPINLOCK) BINDINGLOCKID;
  BufMgrLock = (SPINLOCK) BUFMGRLOCKID;
  LockMgrLock = (SPINLOCK) LOCKMGRLOCKID;
  ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID;
  SInvalLock = (SPINLOCK) SINVALLOCKID;
  OidGenLockId = (SPINLOCK) OIDGENLOCKID;

#ifdef SONY_JUKEBOX
  SJCacheLock = (SPINLOCK) SJCACHELOCKID;
  JBSpinLock = (SPINLOCK) JBSPINLOCKID;
#endif /* SONY_JUKEBOX */

#ifdef MAIN_MEMORY
  MMCacheLock = (SPINLOCK) MMCACHELOCKID;
#endif /* MAIN_MEMORY */

  return(TRUE);
}

SpinAcquire(lock)
SPINLOCK lock;
{
    ExclusiveLock(lock);
    PROC_INCR_SLOCK(lock);
}

SpinRelease(lock)
SPINLOCK lock;
{
    PROC_DECR_SLOCK(lock);
    ExclusiveUnlock(lock);
}

SpinIsLocked(lock)
SPINLOCK lock;
{
    return(!LockIsFree(lock));
}
#else /* HAS_TEST_AND_SET */
/* Spinlocks are implemented using SysV semaphores */


/*
 * SpinAcquire -- try to grab a spinlock
 *
 * FAILS if the semaphore is corrupted.
 */
SpinAcquire(lock) 
SPINLOCK	lock;
{
  IpcSemaphoreLock(SpinLockId, lock, IpcExclusiveLock);
  PROC_INCR_SLOCK(lock);
}

/*
 * SpinRelease -- release a spin lock
 * 
 * FAILS if the semaphore is corrupted
 */
SpinRelease(lock) 
SPINLOCK	lock;
{
  Assert(SpinIsLocked(lock))
  PROC_DECR_SLOCK(lock);
  IpcSemaphoreUnlock(SpinLockId, lock, IpcExclusiveLock);
}

int
SpinIsLocked(lock)
SPINLOCK	lock;
{
   int semval;

   semval = IpcSemaphoreGetValue(SpinLockId, lock);
   return(semval < IpcSemaphoreDefaultStartValue);
}

/*
 * CreateSpinlocks -- Create a sysV semaphore array for
 *	the spinlocks
 *
 */
CreateSpinlocks(key)
IPCKey key;
{

  int status;
  IpcSemaphoreId semid;
  semid = IpcSemaphoreCreate(key, MAX_SPINS, IPCProtection, 
			     IpcSemaphoreDefaultStartValue, &status);
  if (status == IpcSemIdExist) {
    IpcSemaphoreKill(key);
    elog(NOTICE,"Destroying old spinlock semaphore");
    semid = IpcSemaphoreCreate(key, MAX_SPINS, IPCProtection, 
			       IpcSemaphoreDefaultStartValue, &status);
    }

  if (semid >= 0) {
    SpinLockId = semid;
    return(TRUE);
  }
  /* cannot create spinlocks */
  elog(FATAL,"CreateSpinlocks: cannot create spin locks");
  return(FALSE);
}

/*
 * Attach to existing spinlock set
 */
AttachSpinLocks(key)
IPCKey key;
{
  IpcSemaphoreId id;

  id = semget (key, MAX_SPINS, 0);
  if (id < 0) {
    if (errno == EEXIST) {
      /* key is the name of someone else's semaphore */
      elog (FATAL,"AttachSpinlocks: SPIN_KEY belongs to someone else");
    }
    /* cannot create spinlocks */
    elog(FATAL,"AttachSpinlocks: cannot create spin locks");
    return(FALSE);
  }
  SpinLockId = id;
  return(TRUE);
}

/*
 * InitSpinLocks -- Spinlock bootstrapping
 * 
 * We need several spinlocks for bootstrapping:
 * BindingLock (for the shmem binding table) and
 * ShmemLock (for the shmem allocator), BufMgrLock (for buffer
 * pool exclusive access), LockMgrLock (for the lock table), and
 * ProcStructLock (a spin lock for the shared process structure).
 * If there's a Sony WORM drive attached, we also have a spinlock
 * (SJCacheLock) for it.  Same story for the main memory storage mgr.
 *
 */
InitSpinLocks(init, key)
int init;
IPCKey key;
{
  extern SPINLOCK ShmemLock;
  extern SPINLOCK BindingLock;
  extern SPINLOCK BufMgrLock;
  extern SPINLOCK LockMgrLock;
  extern SPINLOCK ProcStructLock;
  extern SPINLOCK SInvalLock;
  extern SPINLOCK OidGenLockId;

#ifdef SONY_JUKEBOX
  extern SPINLOCK SJCacheLock;
  extern SPINLOCK JBSpinLock;
#endif /* SONY_JUKEBOX */

#ifdef MAIN_MEMORY
  extern SPINLOCK MMCacheLock;
#endif /* MAIN_MEMORY */

  if (!init || key != IPC_PRIVATE) {
      /* if bootstrap and key is IPC_PRIVATE, it means that we are running
       * backend by itself.  no need to attach spinlocks
       */
      if (! AttachSpinLocks(key)) {
        elog(FATAL,"InitSpinLocks: couldnt attach spin locks");
        return(FALSE);
      }
    }

  /* These five (or six) spinlocks have fixed location is shmem */
  ShmemLock = (SPINLOCK) SHMEMLOCKID;
  BindingLock = (SPINLOCK) BINDINGLOCKID;
  BufMgrLock = (SPINLOCK) BUFMGRLOCKID;
  LockMgrLock = (SPINLOCK) LOCKMGRLOCKID;
  ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID;
  SInvalLock = (SPINLOCK) SINVALLOCKID;
  OidGenLockId = (SPINLOCK) OIDGENLOCKID;

#ifdef SONY_JUKEBOX
  SJCacheLock = (SPINLOCK) SJCACHELOCKID;
  JBSpinLock = (SPINLOCK) JBSPINLOCKID;
#endif /* SONY_JUKEBOX */

#ifdef MAIN_MEMORY
  MMCacheLock = (SPINLOCK) MMCACHELOCKID;
#endif /* MAIN_MEMORY */
  
  return(TRUE);
}
#endif /* HAS_TEST_AND_SET */
@


1.13
log
@init spin lock for both TAS and non-TAS architectures
@
text
@d5 1
a5 1
 *	$Header: /users/mer/pg/src/storage/ipc/RCS/spin.c,v 1.12 1992/04/13 18:58:27 mer Exp mer $
d21 1
a22 1
#include "storage/ipci.h"
@


1.12
log
@initialize OidGenLockId
@
text
@d5 1
a5 1
 *	$Header: /a/postgres/ctree/newconf/RCS/spin.c,v 1.11 1991/08/12 15:19:07 mer Exp $
d220 1
d248 1
@


1.11
log
@multi-user ... keep spin lock stats for cleanup routines
@
text
@d5 1
a5 1
 *	$Header: /users/mer/postgres/src/storage/ipc/RCS/spin.c,v 1.10 91/08/03 00:30:52 mao Exp Locker: mer $
d57 1
d75 1
@


1.10
log
@extra spinlock for jukebox -- exclusive access to shared data structures
we use for jb communication
@
text
@d5 1
a5 1
 *	$Header: /users/mao/postgres/src/storage/ipc/RCS/spin.c,v 1.9 1991/07/29 16:49:22 mer Exp mao $
d25 1
d91 1
d97 1
d119 1
d130 3
a132 2
  if (SpinIsLocked(lock))
      IpcSemaphoreUnlock(SpinLockId, lock, IpcExclusiveLock);
@


1.9
log
@fix shared invalidation, get rid of braindead locking interactions.
@
text
@d5 1
a5 1
 *	$Header: RCS/spin.c,v 1.8 91/07/24 07:46:49 mao Exp Locker: mer $
d59 1
d76 1
d216 1
d243 1
@


1.8
log
@cleanup and add main memory storage manager
@
text
@d5 1
a5 1
 *	$Header: /users/mao/postgres/src/storage/ipc/RCS/spin.c,v 1.7 1991/07/22 23:14:30 mao Exp mao $
d55 1
d71 1
d210 1
d236 1
@


1.7
log
@missing endif
@
text
@d5 1
a5 1
 *	$Header: /users/mao/postgres/src/storage/ipc/RCS/spin.c,v 1.6 1991/07/22 22:21:16 mao Exp mao $
d17 1
a17 3
 *	 buffer manager to Postgres.  In fact we are only using four such
 *	 spin locks: ShmemLock, BindingLock, BufMgrLock, SJCacheLock,
 *	and LockMgrLock.	-- Wei
d27 3
d55 1
d60 4
d65 6
a70 5
  ShmemLock = SHMEMLOCKID;
  BindingLock = BINDINGLOCKID;
  BufMgrLock = BUFMGRLOCKID;
  LockMgrLock = LOCKMGRLOCKID;
  ProcStructLock = PROCSTRUCTLOCKID;
d72 1
a72 1
  SJCacheLock = SJCACHELOCKID;
d75 4
a102 10
#ifdef SONY_JUKEBOX
#define MAX_SPINS 6	/* only for ShmemLock, BindingLock,
			   BufMgrLock, LockMgrLock, SJCacheLock,
			   and ProcStructLock */
#else /* SONY_JUKEBOX */
#define MAX_SPINS 5	/* only for ShmemLock, BindingLock,
			   BufMgrLock, LockMgrLock and ProcStructLock */
#endif /* SONY_JUKEBOX */
IpcSemaphoreId  SpinLockId = -1;

d196 1
a196 1
 * (SJCacheLock) for it.
d208 1
d213 4
d228 6
a233 5
  ShmemLock = SHMEMLOCKID;
  BindingLock = BINDINGLOCKID;
  BufMgrLock = BUFMGRLOCKID;
  LockMgrLock = LOCKMGRLOCKID;
  ProcStructLock = PROCSTRUCTLOCKID;
d235 1
a235 1
  SJCacheLock = SJCACHELOCKID;
d237 4
@


1.6
log
@jukebox storage manager installation
@
text
@d5 1
a5 1
 *	$Header: /users/mao/postgres/src/storage/ipc/RCS/spin.c,v 1.5 1991/07/22 14:38:01 mer Exp mao $
d99 1
a99 1
#else /* SONY_JUKEBOX */
@


1.5
log
@2 new spin locks for lock manager
@
text
@d5 1
a5 1
 *	$Header: RCS/spin.c,v 1.4 91/06/10 20:57:58 kemnitz Exp Locker: mer $
d18 2
a19 2
 *	 spin locks: ShmemLock, BindingLock, BufMgrLock, and LockMgrLock.
 *	 -- Wei
d54 3
d58 1
a58 1
  /* These five spinlocks have fixed location is shmem */
d64 3
d92 5
d98 2
a99 1
			   BufMgrLock, LockMgrLock, and ProcStructLock */
d189 1
a189 1
 * We need four spinlocks for bootstrapping,
d194 2
d207 3
d221 1
a221 1
  /* These five spinlocks have fixed location is shmem */
d227 3
@


1.4
log
@generalization of spinlocks.
@
text
@d5 1
a5 1
 *	$Header: ipc/RCS/spin.c,v 1.3 91/03/13 12:36:50 hong Exp Locker: kemnitz $
d17 2
a18 2
 *	 buffer manager to Postgres.  In fact we are only using three such
 *	 spin locks: ShmemLock, BindingLock, and BufMgrLock.
d52 2
d55 1
a55 1
  /* These three spinlocks have fixed location is shmem */
d59 2
d86 2
a87 2
#define MAX_SPINS 3	/* only for ShmemLock, BindingLock, and
			   BufMgrLock */
d177 1
a177 1
 * We need three spinlocks for bootstrapping,
d180 2
a181 1
 * pool exclusive access).
d191 2
d204 1
a204 1
  /* These four spinlocks have fixed location is shmem */
d208 2
@


1.3
log
@fixed a bug in creating spin locks
@
text
@d5 1
a5 1
 *	$Header: RCS/spin.c,v 1.2 91/01/25 22:13:39 hong Exp $
d29 1
a29 1
#ifdef sequent
d78 1
a78 1
#else /* sequent */
d204 1
a204 1
#endif /* sequent */
@


1.2
log
@cleaned up spinlock code
@
text
@d5 1
a5 1
 *	$Header: RCS/spin.c,v 1.1 91/01/18 22:14:23 hong Exp Locker: hong $
d136 1
a136 1
			       0, &status);
@


1.1
log
@Initial revision
@
text
@d5 1
a5 1
 *	$Header:  $
d15 5
d29 2
a30 4
/* this spin lock guards the data structures for allocating and
 * deallocating spinlocks and semaphores
 */
SPINLOCK *SpinMaster = NULL;
d32 6
a37 8
/* This is configured in the kernel.  maximum number of
 * spin locks can be no more than the max size of a SysV
 * semaphore array (if spinlocks are implemented as SysV 
 * semaphores.  SpinLockId is the identifier for the semaphore
 * array.
 */
#define MAX_SPINS 5
IpcSemaphoreId  SpinLockId = -1;
d39 5
a43 2
	/* count of allocated spinlocks */
int *	NumSpinLocksP = NULL;
d45 7
d53 4
d58 2
a59 2
/* if debugging, spinlocks are simply integers */
#ifdef SPIN_DBG
d61 5
a65 2
CreateSpinlocks()
{ return(TRUE); }
d67 5
a71 2
AttachSpinLocks()
{ return(TRUE); }
d73 7
a79 2
#else 
#ifdef SPIN_OK
a80 3
/* SPIN_OK means spinlocks are implemented with TAS */
CreateSpinlocks()
{ return(TRUE); }
d82 3
a84 2
AttachSpinLocks()
{ return(TRUE); }
a85 4
#else
/* Spinlocks are implemented using SysV semaphores */


d92 1
a92 1
SPINLOCK	*lock;
d94 1
a94 1
  IpcSemaphoreLock(SpinLockId, lock->tas, IpcExclusiveLock);
d103 1
a103 1
SPINLOCK	*lock;
d106 1
a106 1
      IpcSemaphoreUnlock(SpinLockId, lock->tas, IpcExclusiveLock);
d111 1
a111 1
SPINLOCK	*lock;
d115 1
a115 1
   semval = IpcSemaphoreGetValue(SpinLockId, lock->tas);
a119 17
 * SpinCreate -- initialize a spin lock 
 *
 * There are a finite number of spinlocks available.  Check
 * that the number has not been exceeded.  The semaphore is
 * locked when it is created.  
 */
SpinCreate(lock)
SPINLOCK	*lock;
{
  lock->tas = *NumSpinLocksP;

  if (*NumSpinLocksP >= MAX_SPINS) {
    elog(WARN,"SpinCreate: too many spinlocks ");
  }
}

/*
a168 2
#endif
#endif
d173 4
a176 3
 * We need three spinlocks for bootstrapping SpinMaster (this
 * module), BindingLock (for the shmem binding table) and
 * ShmemLock (for the shmem allocator).
d179 1
a179 1
InitSpinLocks(init, freeSpaceP, key)
a180 1
unsigned int *freeSpaceP;
d183 3
a185 2
  extern SPINLOCK *ShmemLock;
  extern SPINLOCK *BindingLock;
d197 4
a200 6
  NumSpinLocksP = (int *) MAKE_PTR(*freeSpaceP);

  /* These three spinlocks have fixed location is shmem */
  ShmemLock = (SPINLOCK *) (NumSpinLocksP+1);
  BindingLock = ShmemLock+1;
  SpinMaster = BindingLock+1;
a201 21
  *freeSpaceP = (int ) MAKE_OFFSET(SpinMaster+1);

  /* if ! init, just not the location of these.  Someone
   * else has initialized them.
   */
  if (init) {
    *NumSpinLocksP = 0;

    SpinCreate(ShmemLock);
    *NumSpinLocksP = 1;
    SpinRelease(ShmemLock);

    SpinCreate(BindingLock);
    *NumSpinLocksP = 2;
    SpinRelease(BindingLock);

    SpinCreate(SpinMaster);
    *NumSpinLocksP = 3;
    SpinRelease(SpinMaster);
  }

d204 1
a204 36


/*
 * SpinAlloc -- allocate a new spinlock or attach to an
 *	old one.
 *
 * Before any shared memory data structure is initialized,
 * This routine should be called to initialize the spinlock
 * for that data structure.
 *
 * Side Effects: The spinlock is already locked when it
 * 	is allocated.
 */
SPINLOCK *
SpinAlloc(name)
char *name;
{
  SPINLOCK *	spinlock;
  Boolean	found = FALSE;

  SpinAcquire(SpinMaster);

  spinlock = (SPINLOCK *) 
    ShmemInitStruct(name,sizeof(SPINLOCK),&found);

  if (! found) {
    SpinCreate(spinlock);
    ++(*NumSpinLocksP);
  } 

  SpinRelease(SpinMaster);

  SpinAcquire(spinlock);

  return(spinlock);
}
@
