mirror of
https://github.com/postgres/postgres.git
synced 2025-11-13 16:22:44 +03:00
Postgres95 1.01 Distribution - Virgin Sources
This commit is contained in:
440
src/backend/storage/ipc/s_lock.c
Normal file
440
src/backend/storage/ipc/s_lock.c
Normal file
@@ -0,0 +1,440 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* 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.1.1.1 1996/07/09 06:21:54 scrappy 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.
|
||||
*
|
||||
*/
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif /* WIN32 */
|
||||
#include "storage/ipc.h"
|
||||
|
||||
|
||||
#if defined(HAS_TEST_AND_SET)
|
||||
|
||||
#if defined (PORTNAME_next)
|
||||
/*
|
||||
* 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 /* PORTNAME_next */
|
||||
|
||||
|
||||
|
||||
#if defined(PORTNAME_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)
|
||||
{
|
||||
(void)release_lock(lock);
|
||||
}
|
||||
|
||||
void
|
||||
S_INIT_LOCK(slock_t *lock)
|
||||
{
|
||||
(void)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 /* PORTNAME_irix5 */
|
||||
|
||||
|
||||
/*
|
||||
* OSF/1 (Alpha AXP)
|
||||
*
|
||||
* Note that slock_t on the Alpha AXP is msemaphore instead of char
|
||||
* (see storage/ipc.h).
|
||||
*/
|
||||
|
||||
#if defined(PORTNAME_alpha)
|
||||
|
||||
void
|
||||
S_LOCK(slock_t *lock)
|
||||
{
|
||||
while (msem_lock(lock, MSEM_IF_NOWAIT) < 0)
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
S_UNLOCK(slock_t *lock)
|
||||
{
|
||||
(void) msem_unlock(lock, 0);
|
||||
}
|
||||
|
||||
void
|
||||
S_INIT_LOCK(slock_t *lock)
|
||||
{
|
||||
(void) msem_init(lock, MSEM_UNLOCKED);
|
||||
}
|
||||
|
||||
int
|
||||
S_LOCK_FREE(slock_t *lock)
|
||||
{
|
||||
return(lock->msem_state ? 0 : 1);
|
||||
}
|
||||
|
||||
#endif /* PORTNAME_alpha */
|
||||
|
||||
/*
|
||||
* Solaris 2
|
||||
*/
|
||||
|
||||
#if defined(PORTNAME_sparc_solaris)
|
||||
|
||||
/* defined in port/.../tas.s */
|
||||
extern 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 /* PORTNAME_sparc_solaris */
|
||||
|
||||
/*
|
||||
* AIX (POWER)
|
||||
*
|
||||
* Note that slock_t on POWER/POWER2/PowerPC is int instead of char
|
||||
* (see storage/ipc.h).
|
||||
*/
|
||||
|
||||
#if defined(PORTNAME_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 /* PORTNAME_aix */
|
||||
|
||||
/*
|
||||
* HP-UX (PA-RISC)
|
||||
*
|
||||
* Note that slock_t on PA-RISC is a structure instead of char
|
||||
* (see storage/ipc.h).
|
||||
*/
|
||||
|
||||
#if defined(PORTNAME_hpux)
|
||||
|
||||
/* defined in port/.../tas.s */
|
||||
extern int tas(slock_t *lock);
|
||||
|
||||
/*
|
||||
* 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 };
|
||||
|
||||
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 /* PORTNAME_hpux */
|
||||
|
||||
/*
|
||||
* sun3
|
||||
*/
|
||||
|
||||
#if (defined(sun) && ! defined(sparc))
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* SPARC (SunOS 4)
|
||||
*/
|
||||
|
||||
#if defined(PORTNAME_sparc)
|
||||
|
||||
/* 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_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 /* PORTNAME_sparc */
|
||||
|
||||
/*
|
||||
* Linux and friends
|
||||
*/
|
||||
|
||||
#if defined(PORTNAME_linux) || defined(PORTNAME_BSD44_derived)
|
||||
|
||||
int
|
||||
tas(slock_t *m)
|
||||
{
|
||||
slock_t res;
|
||||
__asm__("xchgb %0,%1":"=q" (res),"=m" (*m):"0" (0x1));
|
||||
return(res);
|
||||
}
|
||||
|
||||
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 /* PORTNAME_linux || PORTNAME_BSD44_derived */
|
||||
|
||||
|
||||
#endif /* HAS_TEST_AND_SET */
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
void
|
||||
S_LOCK(HANDLE *lock)
|
||||
{
|
||||
int x = 0;
|
||||
x = x / x;
|
||||
}
|
||||
|
||||
void
|
||||
S_UNLOCK(HANDLE *lock)
|
||||
{
|
||||
int x = 0;
|
||||
x = x / x;
|
||||
}
|
||||
|
||||
void
|
||||
S_INIT_LOCK(HANDLE *lock)
|
||||
{
|
||||
int x = 0;
|
||||
x = x / x;
|
||||
}
|
||||
#endif /*WIN32*/
|
||||
Reference in New Issue
Block a user