1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-29 08:31:35 -08:00
emacs/mps/code/lockw3.c
Richard Brooksby 3d5e2ca85f Adding hopenames back into the master sources, so that they can be included in the union sources along with the id keywords.
This was achieved by partially undoing changelist 24817, including an accidental corruption of eventgen.pl.

Copied from Perforce
 Change: 24877
 ServerID: perforce.ravenbrook.com
2001-12-06 18:14:02 +00:00

157 lines
3.6 KiB
C

/* impl.c.lockw3: RECURSIVE LOCKS IN WIN32
*
* $Id$
* $HopeName: MMsrc!lockw3.c(trunk.12) $
* Copyright (c) 2001 Ravenbrook Limited.
*
* .design: These are implemented using critical sections.
* See the section titled "Synchronization functions" in the Groups
* chapter of the Microsoft Win32 API Programmer's Reference.
* The "Synchronization" section of the Overview is also relevant.
*
* Critical sections support recursive locking, so the implementation
* could be trivial. This implementation counts the claims to provide
* extra checking.
*
* The limit on the number of recursive claims is the max of
* ULONG_MAX and the limit imposed by critical sections, which
* is believed to be about UCHAR_MAX.
*
* During use the claims field is updated to remember the number of
* claims acquired on a lock. This field must only be modified
* while we are inside the critical section.
*/
#include "mpm.h"
#ifndef MPS_OS_W3
#error "lockw3.c is specific to Win32 but MPS_OS_W3 not defined"
#endif
#include "mpswin.h"
SRCID(lockw3, "$Id$");
/* .lock.win32: Win32 lock structure; uses CRITICAL_SECTION */
typedef struct LockStruct {
Sig sig; /* design.mps.sig */
unsigned long claims; /* # claims held by the owning thread */
CRITICAL_SECTION cs; /* Win32's recursive lock thing */
} LockStruct;
size_t LockSize(void)
{
return sizeof(LockStruct);
}
Bool LockCheck(Lock lock)
{
CHECKS(Lock, lock);
return TRUE;
}
void LockInit(Lock lock)
{
AVER(lock != NULL);
lock->claims = 0;
InitializeCriticalSection(&lock->cs);
lock->sig = LockSig;
AVERT(Lock, lock);
}
void LockFinish(Lock lock)
{
AVERT(Lock, lock);
/* Lock should not be finished while held */
AVER(lock->claims == 0);
DeleteCriticalSection(&lock->cs);
lock->sig = SigInvalid;
}
void LockClaim(Lock lock)
{
AVERT(Lock, lock);
EnterCriticalSection(&lock->cs);
/* This should be the first claim. Now we are inside the
* critical section it is ok to check this. */
AVER(lock->claims == 0);
lock->claims = 1;
}
void LockReleaseMPM(Lock lock)
{
AVERT(Lock, lock);
AVER(lock->claims == 1); /* The lock should only be held once */
lock->claims = 0; /* Must set this before leaving CS */
LeaveCriticalSection(&lock->cs);
}
void LockClaimRecursive(Lock lock)
{
AVERT(Lock, lock);
EnterCriticalSection(&lock->cs);
++lock->claims;
AVER(lock->claims > 0);
}
void LockReleaseRecursive(Lock lock)
{
AVERT(Lock, lock);
AVER(lock->claims > 0);
--lock->claims;
LeaveCriticalSection(&lock->cs);
}
/* Global locking is performed by normal locks.
* A separate lock structure is used for recursive and
* non-recursive locks so that each may be differently ordered
* with respect to client-allocated locks.
*/
static LockStruct globalLockStruct;
static LockStruct globalRecLockStruct;
static Lock globalLock = &globalLockStruct;
static Lock globalRecLock = &globalRecLockStruct;
static Bool globalLockInit = FALSE; /* TRUE iff initialized */
static void lockEnsureGlobalLock(void)
{
/* Ensure both global locks have been initialized. */
/* There is a race condition initializing them. */
if (!globalLockInit) {
LockInit(globalLock);
LockInit(globalRecLock);
globalLockInit = TRUE;
}
}
void LockClaimGlobalRecursive(void)
{
lockEnsureGlobalLock();
AVER(globalLockInit);
LockClaimRecursive(globalRecLock);
}
void LockReleaseGlobalRecursive(void)
{
AVER(globalLockInit);
LockReleaseRecursive(globalRecLock);
}
void LockClaimGlobal(void)
{
lockEnsureGlobalLock();
AVER(globalLockInit);
LockClaim(globalLock);
}
void LockReleaseGlobal(void)
{
AVER(globalLockInit);
LockReleaseMPM(globalLock);
}