1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* spin.c
|
1997-09-07 07:04:48 +02:00
|
|
|
* routines for managing spin locks
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2000-11-29 00:27:57 +01:00
|
|
|
* POSTGRES has two kinds of locks: semaphores (which put the
|
|
|
|
* process to sleep) and spinlocks (which are supposed to be
|
|
|
|
* short term locks). Spinlocks are implemented via test-and-set (TAS)
|
|
|
|
* instructions if possible, else via semaphores. The semaphore method
|
|
|
|
* is too slow to be useful :-(
|
|
|
|
*
|
2001-01-24 20:43:33 +01:00
|
|
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2001-09-27 21:10:02 +02:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/spin.c,v 1.1 2001/09/27 19:10:02 tgl Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
2000-11-29 00:27:57 +01:00
|
|
|
#include <errno.h>
|
2000-12-11 01:49:54 +01:00
|
|
|
#if !defined(HAS_TEST_AND_SET) && defined(HAVE_SYS_SEM_H)
|
1997-01-14 02:53:11 +01:00
|
|
|
#include <sys/sem.h>
|
|
|
|
#endif
|
|
|
|
|
2001-01-14 06:08:17 +01:00
|
|
|
#include "miscadmin.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "storage/proc.h"
|
|
|
|
#include "storage/s_lock.h"
|
|
|
|
|
2001-01-14 06:08:17 +01:00
|
|
|
|
2000-11-29 00:27:57 +01:00
|
|
|
/* Probably should move these to an appropriate header file */
|
|
|
|
extern SPINLOCK BufMgrLock;
|
|
|
|
extern SPINLOCK OidGenLockId;
|
|
|
|
extern SPINLOCK XidGenLockId;
|
|
|
|
extern SPINLOCK ControlFileLockId;
|
2001-06-28 01:31:40 +02:00
|
|
|
extern SPINLOCK ShmemLock;
|
|
|
|
extern SPINLOCK ShmemIndexLock;
|
|
|
|
extern SPINLOCK LockMgrLock;
|
|
|
|
extern SPINLOCK SInvalLock;
|
|
|
|
extern SPINLOCK ProcStructLock;
|
|
|
|
extern SPINLOCK FreeSpaceLock;
|
1998-06-23 17:35:48 +02:00
|
|
|
#ifdef STABLE_MEMORY_STORAGE
|
2000-11-29 00:27:57 +01:00
|
|
|
extern SPINLOCK MMCacheLock;
|
1998-06-23 17:35:48 +02:00
|
|
|
#endif
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-11-29 00:27:57 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize identifiers for permanent spinlocks during startup
|
|
|
|
*
|
|
|
|
* The same identifiers are used for both TAS and semaphore implementations,
|
|
|
|
* although in one case they are indexes into a shmem array and in the other
|
|
|
|
* they are semaphore numbers.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
InitSpinLockIDs(void)
|
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
BufMgrLock = (SPINLOCK) BUFMGRLOCKID;
|
|
|
|
OidGenLockId = (SPINLOCK) OIDGENLOCKID;
|
1999-10-06 23:58:18 +02:00
|
|
|
XidGenLockId = (SPINLOCK) XIDGENLOCKID;
|
|
|
|
ControlFileLockId = (SPINLOCK) CNTLFILELOCKID;
|
2001-06-28 01:31:40 +02:00
|
|
|
ShmemLock = (SPINLOCK) SHMEMLOCKID;
|
|
|
|
ShmemIndexLock = (SPINLOCK) SHMEMINDEXLOCKID;
|
|
|
|
LockMgrLock = (SPINLOCK) LOCKMGRLOCKID;
|
|
|
|
SInvalLock = (SPINLOCK) SINVALLOCKID;
|
|
|
|
ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID;
|
|
|
|
FreeSpaceLock = (SPINLOCK) FREESPACELOCKID;
|
1998-06-23 17:35:48 +02:00
|
|
|
#ifdef STABLE_MEMORY_STORAGE
|
1997-09-07 07:04:48 +02:00
|
|
|
MMCacheLock = (SPINLOCK) MMCACHELOCKID;
|
1998-06-23 17:35:48 +02:00
|
|
|
#endif
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-05-31 02:28:42 +02:00
|
|
|
|
2000-11-29 00:27:57 +01:00
|
|
|
#ifdef HAS_TEST_AND_SET
|
|
|
|
|
|
|
|
/* real spin lock implementation */
|
|
|
|
|
|
|
|
typedef struct slock
|
|
|
|
{
|
|
|
|
slock_t shlock;
|
|
|
|
} SLock;
|
|
|
|
|
2000-05-31 02:28:42 +02:00
|
|
|
#ifdef LOCK_DEBUG
|
2001-03-22 05:01:46 +01:00
|
|
|
bool Trace_spinlocks = false;
|
2000-05-31 02:28:42 +02:00
|
|
|
|
|
|
|
inline static void
|
2001-03-22 05:01:46 +01:00
|
|
|
PRINT_SLDEBUG(const char *where, SPINLOCK lockid, const SLock *lock)
|
2000-05-31 02:28:42 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
if (Trace_spinlocks)
|
|
|
|
elog(DEBUG, "%s: id=%d", where, lockid);
|
2000-05-31 02:28:42 +02:00
|
|
|
}
|
2001-03-22 05:01:46 +01:00
|
|
|
|
|
|
|
#else /* not LOCK_DEBUG */
|
2000-05-31 02:28:42 +02:00
|
|
|
#define PRINT_SLDEBUG(a,b,c)
|
2001-03-22 05:01:46 +01:00
|
|
|
#endif /* not LOCK_DEBUG */
|
2000-05-31 02:28:42 +02:00
|
|
|
|
1997-09-18 16:21:02 +02:00
|
|
|
|
2000-11-29 00:27:57 +01:00
|
|
|
static SLock *SLockArray = NULL;
|
|
|
|
|
|
|
|
#define SLOCKMEMORYSIZE ((int) MAX_SPINS * sizeof(SLock))
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SLockShmemSize --- return shared-memory space needed
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
SLockShmemSize(void)
|
|
|
|
{
|
|
|
|
return MAXALIGN(SLOCKMEMORYSIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* CreateSpinlocks --- create and initialize spinlocks during startup
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
CreateSpinlocks(PGShmemHeader *seghdr)
|
|
|
|
{
|
|
|
|
int id;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We must allocate the space "by hand" because shmem.c isn't up yet
|
|
|
|
*/
|
|
|
|
SLockArray = (SLock *) (((char *) seghdr) + seghdr->freeoffset);
|
|
|
|
seghdr->freeoffset += MAXALIGN(SLOCKMEMORYSIZE);
|
|
|
|
Assert(seghdr->freeoffset <= seghdr->totalsize);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize all spinlocks to "unlocked" state
|
|
|
|
*/
|
|
|
|
for (id = 0; id < (int) MAX_SPINS; id++)
|
|
|
|
{
|
|
|
|
SLock *slckP = &(SLockArray[id]);
|
|
|
|
|
|
|
|
S_INIT_LOCK(&(slckP->shlock));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Assign indexes for fixed spinlocks
|
|
|
|
*/
|
|
|
|
InitSpinLockIDs();
|
|
|
|
}
|
1997-09-18 16:21:02 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
void
|
1997-09-18 16:21:02 +02:00
|
|
|
SpinAcquire(SPINLOCK lockid)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-11-29 00:27:57 +01:00
|
|
|
SLock *slckP = &(SLockArray[lockid]);
|
1997-09-18 16:21:02 +02:00
|
|
|
|
2000-05-31 02:28:42 +02:00
|
|
|
PRINT_SLDEBUG("SpinAcquire", lockid, slckP);
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2001-01-12 22:54:01 +01:00
|
|
|
/*
|
2001-03-22 05:01:46 +01:00
|
|
|
* Acquire the lock, then record that we have done so (for recovery in
|
|
|
|
* case of elog(ERROR) while holding the lock). Note we assume here
|
|
|
|
* that S_LOCK will not accept cancel/die interrupts once it has
|
2001-01-14 06:08:17 +01:00
|
|
|
* acquired the lock. However, interrupts should be accepted while
|
2001-01-19 23:08:47 +01:00
|
|
|
* waiting, if InterruptHoldoffCount is zero.
|
2001-01-12 22:54:01 +01:00
|
|
|
*/
|
2000-11-29 00:27:57 +01:00
|
|
|
S_LOCK(&(slckP->shlock));
|
1997-09-18 16:21:02 +02:00
|
|
|
PROC_INCR_SLOCK(lockid);
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2001-01-14 06:08:17 +01:00
|
|
|
/*
|
2001-01-19 23:08:47 +01:00
|
|
|
* Lock out cancel/die interrupts until we exit the code section
|
2001-01-14 06:08:17 +01:00
|
|
|
* protected by the spinlock. This ensures that interrupts will not
|
|
|
|
* interfere with manipulations of data structures in shared memory.
|
|
|
|
*/
|
2001-01-19 23:08:47 +01:00
|
|
|
HOLD_INTERRUPTS();
|
2001-01-12 22:54:01 +01:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
PRINT_SLDEBUG("SpinAcquire/done", lockid, slckP);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1997-09-18 16:21:02 +02:00
|
|
|
SpinRelease(SPINLOCK lockid)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-11-29 00:27:57 +01:00
|
|
|
SLock *slckP = &(SLockArray[lockid]);
|
1998-08-25 23:34:10 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
PRINT_SLDEBUG("SpinRelease", lockid, slckP);
|
|
|
|
|
1998-08-25 23:34:10 +02:00
|
|
|
/*
|
1998-09-01 06:40:42 +02:00
|
|
|
* Check that we are actually holding the lock we are releasing. This
|
|
|
|
* can be done only after MyProc has been initialized.
|
1998-08-25 23:34:10 +02:00
|
|
|
*/
|
2001-03-22 05:01:46 +01:00
|
|
|
Assert(!MyProc || MyProc->sLocks[lockid] > 0);
|
|
|
|
|
2001-01-12 22:54:01 +01:00
|
|
|
/*
|
|
|
|
* Record that we no longer hold the spinlock, and release it.
|
|
|
|
*/
|
2000-05-31 02:28:42 +02:00
|
|
|
PROC_DECR_SLOCK(lockid);
|
2000-11-29 00:27:57 +01:00
|
|
|
S_UNLOCK(&(slckP->shlock));
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2001-01-12 22:54:01 +01:00
|
|
|
/*
|
2001-01-19 23:08:47 +01:00
|
|
|
* Exit the interrupt holdoff entered in SpinAcquire().
|
2001-01-12 22:54:01 +01:00
|
|
|
*/
|
2001-01-19 23:08:47 +01:00
|
|
|
RESUME_INTERRUPTS();
|
2001-01-12 22:54:01 +01:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
PRINT_SLDEBUG("SpinRelease/done", lockid, slckP);
|
2000-11-29 00:27:57 +01:00
|
|
|
}
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
#else /* !HAS_TEST_AND_SET */
|
2000-11-29 00:27:57 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* No TAS, so spinlocks are implemented using SysV semaphores.
|
|
|
|
*
|
|
|
|
* We support two slightly different APIs here: SpinAcquire/SpinRelease
|
|
|
|
* work with SPINLOCK integer indexes for the permanent spinlocks, which
|
|
|
|
* are all assumed to live in the first spinlock semaphore set. There
|
|
|
|
* is also an emulation of the s_lock.h TAS-spinlock macros; for that case,
|
|
|
|
* typedef slock_t stores the semId and sem number of the sema to use.
|
|
|
|
* The semas needed are created by CreateSpinlocks and doled out by
|
|
|
|
* s_init_lock_sema.
|
|
|
|
*
|
|
|
|
* Since many systems have a rather small SEMMSL limit on semas per set,
|
|
|
|
* we allocate the semaphores required in sets of SPINLOCKS_PER_SET semas.
|
|
|
|
* This value is deliberately made equal to PROC_NSEMS_PER_SET so that all
|
|
|
|
* sema sets allocated by Postgres will be the same size; that eases the
|
|
|
|
* semaphore-recycling logic in IpcSemaphoreCreate().
|
|
|
|
*
|
|
|
|
* Note that the SpinLockIds array is not in shared memory; it is filled
|
|
|
|
* by the postmaster and then inherited through fork() by backends. This
|
2001-01-12 22:54:01 +01:00
|
|
|
* is OK because its contents do not change after shmem initialization.
|
2000-11-29 00:27:57 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#define SPINLOCKS_PER_SET PROC_NSEMS_PER_SET
|
|
|
|
|
|
|
|
static IpcSemaphoreId *SpinLockIds = NULL;
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
static int numSpinSets = 0; /* number of sema sets used */
|
|
|
|
static int numSpinLocks = 0; /* total number of semas allocated */
|
|
|
|
static int nextSpinLock = 0; /* next free spinlock index */
|
2000-11-29 00:27:57 +01:00
|
|
|
|
|
|
|
static void SpinFreeAllSemaphores(void);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SLockShmemSize --- return shared-memory space needed
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
SLockShmemSize(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* CreateSpinlocks --- create and initialize spinlocks during startup
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
CreateSpinlocks(PGShmemHeader *seghdr)
|
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
int i;
|
2000-11-29 00:27:57 +01:00
|
|
|
|
|
|
|
if (SpinLockIds == NULL)
|
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2000-11-29 00:27:57 +01:00
|
|
|
/*
|
2001-03-22 05:01:46 +01:00
|
|
|
* Compute number of spinlocks needed. If this logic gets any
|
|
|
|
* more complicated, it should be distributed into the affected
|
|
|
|
* modules, similar to the way shmem space estimation is handled.
|
2000-11-29 00:27:57 +01:00
|
|
|
*
|
2001-03-22 05:01:46 +01:00
|
|
|
* For now, though, we just need the fixed spinlocks (MAX_SPINS), two
|
|
|
|
* spinlocks per shared disk buffer, and four spinlocks for XLOG.
|
2000-11-29 00:27:57 +01:00
|
|
|
*/
|
|
|
|
numSpinLocks = (int) MAX_SPINS + 2 * NBuffers + 4;
|
|
|
|
|
|
|
|
/* might as well round up to a multiple of SPINLOCKS_PER_SET */
|
|
|
|
numSpinSets = (numSpinLocks - 1) / SPINLOCKS_PER_SET + 1;
|
|
|
|
numSpinLocks = numSpinSets * SPINLOCKS_PER_SET;
|
|
|
|
|
|
|
|
SpinLockIds = (IpcSemaphoreId *)
|
|
|
|
malloc(numSpinSets * sizeof(IpcSemaphoreId));
|
|
|
|
Assert(SpinLockIds != NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < numSpinSets; i++)
|
|
|
|
SpinLockIds[i] = -1;
|
|
|
|
|
|
|
|
/*
|
2001-03-22 05:01:46 +01:00
|
|
|
* Arrange to delete semas on exit --- set this up now so that we will
|
|
|
|
* clean up if allocation fails. We use our own freeproc, rather than
|
|
|
|
* IpcSemaphoreCreate's removeOnExit option, because we don't want to
|
|
|
|
* fill up the on_shmem_exit list with a separate entry for each
|
|
|
|
* semaphore set.
|
1997-09-18 16:21:02 +02:00
|
|
|
*/
|
2000-11-29 00:27:57 +01:00
|
|
|
on_shmem_exit(SpinFreeAllSemaphores, 0);
|
|
|
|
|
|
|
|
/* Create sema sets and set all semas to count 1 */
|
|
|
|
for (i = 0; i < numSpinSets; i++)
|
1997-09-18 16:21:02 +02:00
|
|
|
{
|
2000-11-29 00:27:57 +01:00
|
|
|
SpinLockIds[i] = IpcSemaphoreCreate(SPINLOCKS_PER_SET,
|
|
|
|
IPCProtection,
|
|
|
|
1,
|
|
|
|
false);
|
1997-09-18 16:21:02 +02:00
|
|
|
}
|
2000-11-29 00:27:57 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Assign indexes for fixed spinlocks
|
|
|
|
*/
|
|
|
|
Assert(MAX_SPINS <= SPINLOCKS_PER_SET);
|
|
|
|
InitSpinLockIDs();
|
|
|
|
|
|
|
|
/* Init counter for allocating dynamic spinlocks */
|
|
|
|
nextSpinLock = MAX_SPINS;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-11-29 00:27:57 +01:00
|
|
|
/*
|
|
|
|
* SpinFreeAllSemaphores -
|
|
|
|
* called at shmem_exit time, ie when exiting the postmaster or
|
|
|
|
* destroying shared state for a failed set of backends.
|
|
|
|
* Free up all the semaphores allocated for spinlocks.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
SpinFreeAllSemaphores(void)
|
|
|
|
{
|
|
|
|
int i;
|
1997-08-19 23:40:56 +02:00
|
|
|
|
2000-11-29 00:27:57 +01:00
|
|
|
for (i = 0; i < numSpinSets; i++)
|
|
|
|
{
|
|
|
|
if (SpinLockIds[i] >= 0)
|
|
|
|
IpcSemaphoreKill(SpinLockIds[i]);
|
|
|
|
}
|
2001-01-12 22:54:01 +01:00
|
|
|
free(SpinLockIds);
|
|
|
|
SpinLockIds = NULL;
|
2000-11-29 00:27:57 +01:00
|
|
|
}
|
1997-08-19 23:40:56 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2000-11-29 00:27:57 +01:00
|
|
|
* SpinAcquire -- grab a fixed spinlock
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* FAILS if the semaphore is corrupted.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SpinAcquire(SPINLOCK lock)
|
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2001-01-14 06:08:17 +01:00
|
|
|
/*
|
|
|
|
* See the TAS() version of this routine for primary commentary.
|
|
|
|
*
|
|
|
|
* NOTE we must pass interruptOK = false to IpcSemaphoreLock, to ensure
|
2001-03-22 05:01:46 +01:00
|
|
|
* that a cancel/die interrupt cannot prevent us from recording
|
|
|
|
* ownership of a lock we have just acquired.
|
2001-01-14 06:08:17 +01:00
|
|
|
*/
|
|
|
|
IpcSemaphoreLock(SpinLockIds[0], lock, false);
|
1997-09-07 07:04:48 +02:00
|
|
|
PROC_INCR_SLOCK(lock);
|
2001-01-19 23:08:47 +01:00
|
|
|
HOLD_INTERRUPTS();
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-11-29 00:27:57 +01:00
|
|
|
* SpinRelease -- release a fixed spin lock
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
* FAILS if the semaphore is corrupted
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SpinRelease(SPINLOCK lock)
|
|
|
|
{
|
2001-01-12 22:54:01 +01:00
|
|
|
/* See the TAS() version of this routine for commentary */
|
2000-11-29 00:27:57 +01:00
|
|
|
#ifdef USE_ASSERT_CHECKING
|
|
|
|
/* Check it's locked */
|
1997-09-08 04:41:22 +02:00
|
|
|
int semval;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-11-29 00:27:57 +01:00
|
|
|
semval = IpcSemaphoreGetValue(SpinLockIds[0], lock);
|
|
|
|
Assert(semval < 1);
|
|
|
|
#endif
|
2001-03-22 05:01:46 +01:00
|
|
|
Assert(!MyProc || MyProc->sLocks[lockid] > 0);
|
2000-11-29 00:27:57 +01:00
|
|
|
PROC_DECR_SLOCK(lock);
|
|
|
|
IpcSemaphoreUnlock(SpinLockIds[0], lock);
|
2001-01-19 23:08:47 +01:00
|
|
|
RESUME_INTERRUPTS();
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-11-29 00:27:57 +01:00
|
|
|
* s_lock.h hardware-spinlock emulation
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-11-29 00:27:57 +01:00
|
|
|
|
1999-10-06 23:58:18 +02:00
|
|
|
void
|
2000-11-29 00:27:57 +01:00
|
|
|
s_init_lock_sema(volatile slock_t *lock)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-11-29 00:27:57 +01:00
|
|
|
if (nextSpinLock >= numSpinLocks)
|
|
|
|
elog(FATAL, "s_init_lock_sema: not enough semaphores");
|
|
|
|
lock->semId = SpinLockIds[nextSpinLock / SPINLOCKS_PER_SET];
|
|
|
|
lock->sem = nextSpinLock % SPINLOCKS_PER_SET;
|
|
|
|
nextSpinLock++;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1999-10-06 23:58:18 +02:00
|
|
|
void
|
2000-11-29 00:27:57 +01:00
|
|
|
s_unlock_sema(volatile slock_t *lock)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-11-29 00:27:57 +01:00
|
|
|
IpcSemaphoreUnlock(lock->semId, lock->sem);
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-11-29 00:27:57 +01:00
|
|
|
bool
|
|
|
|
s_lock_free_sema(volatile slock_t *lock)
|
|
|
|
{
|
|
|
|
return IpcSemaphoreGetValue(lock->semId, lock->sem) > 0;
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-11-29 00:27:57 +01:00
|
|
|
int
|
|
|
|
tas_sema(volatile slock_t *lock)
|
|
|
|
{
|
|
|
|
/* Note that TAS macros return 0 if *success* */
|
2001-03-22 05:01:46 +01:00
|
|
|
return !IpcSemaphoreTryLock(lock->semId, lock->sem);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
#endif /* !HAS_TEST_AND_SET */
|