|
|
//============================================================================
// Copyright (c) 1995, Microsoft Corporation
// File: sync.h
//
// History:
// Abolade Gbadegesin
// K.S.Lokesh (added Dynamic Locking)
//
// Contains structures and macros used to implement synchronization.
//============================================================================
#ifndef _SYNC_H_
#define _SYNC_H_
//
// type definition for multiple-reader/single-writer lock
// Note: there is a similar facility provided by nturtl.h
// through the structure RTL_RESOURCE and several functions.
// However, that implementation has the potential for starving
// a thread trying to acquire write accesss, if there are a large
// number of threads interested in acquiring read access.
// Such a scenario is avoided in the implementation given in this
// header. However, a mapping is also given to the RTL_RESOURCE
// functionality, so that IGMP can be compiled to use either form
//
#ifdef IGMP_RWL
//
// use IGMP's definitions
//
typedef struct _READ_WRITE_LOCK {
CRITICAL_SECTION RWL_ReadWriteBlock; LONG RWL_ReaderCount; HANDLE RWL_ReaderDoneEvent;
} READ_WRITE_LOCK, *PREAD_WRITE_LOCK;
DWORD CreateReadWriteLock(PREAD_WRITE_LOCK pRWL); VOID DeleteReadWriteLock(PREAD_WRITE_LOCK pRWL); VOID AcquireReadLock(PREAD_WRITE_LOCK pRWL); VOID ReleaseReadLock(PREAD_WRITE_LOCK pRWL); VOID AcquireWriteLock(PREAD_WRITE_LOCK pRWL); VOID ReleaseWriteLock(PREAD_WRITE_LOCK pRWL);
//
// macro functions for manipulating a read-write lock
//
#define CREATE_READ_WRITE_LOCK(pRWL) \
CreateReadWriteLock(pRWL) #define DELETE_READ_WRITE_LOCK(pRWL) \
DeleteReadWriteLock(pRWL)
#define READ_WRITE_LOCK_CREATED(pRWL) \
((pRWL)->RWL_ReaderDoneEvent != NULL)
// print locks.
#ifdef LOCK_DBG
#define ACQUIRE_READ_LOCK(pRWL, type, proc) {\
Trace2(CS,"----to AcquireReadLock %s in %s", type, proc); \ AcquireReadLock(pRWL); \ Trace2(CS,"----GotReadLock %s in %s", type, proc); \ }
#define RELEASE_READ_LOCK(pRWL, type, proc) {\
Trace2(CS,"----Released ReadLock %s in %s", type, proc); \ ReleaseReadLock(pRWL); \ }
#define ACQUIRE_WRITE_LOCK(pRWL, type, proc) {\
Trace2(CS,"----to AcquireWriteLock %s in %s", type, proc); \ AcquireWriteLock(pRWL); \ Trace2(CS,"----AcquiredWriteLock %s in %s", type, proc);\ }
#define RELEASE_WRITE_LOCK(pRWL, type, proc) {\
Trace2(CS,"----Released WriteLock %s in %s", type, proc); \ ReleaseWriteLock(pRWL);\ }
#else //LOCK_DBG
#define ACQUIRE_READ_LOCK(pRWL, type, proc) \
AcquireReadLock(pRWL)
#define RELEASE_READ_LOCK(pRWL, type, proc) \
ReleaseReadLock(pRWL)
#define ACQUIRE_WRITE_LOCK(pRWL, type, proc) \
AcquireWriteLock(pRWL)
#define RELEASE_WRITE_LOCK(pRWL, type, proc) \
ReleaseWriteLock(pRWL)
#endif //LOCK_DBG
#define READ_LOCK_TO_WRITE_LOCK(pRWL, type, proc) \
(RELEASE_READ_LOCK(pRWL, type, proc), ACQUIRE_WRITE_LOCK(pRWL, type, proc))
#define WRITE_LOCK_TO_READ_LOCK(pRWL) \
(RELEASE_WRITE_LOCK(pRWL, type, proc), ACQUIRE_READ_LOCK(pRWL, type, proc))
#else // i.e. !IGMP_RWL
//
// use the RTL_RESOURCE mechanism
//
typedef RTL_RESOURCE READ_WRITE_LOCK, *PREAD_WRITE_LOCK;
#define CREATE_READ_WRITE_LOCK(pRWL) \
RtlInitializeResource((pRWL)) #define DELETE_READ_WRITE_LOCK(pRWL) \
RtlDeleteResource((pRWL)) #define READ_WRITE_LOCK_CREATED(pRWL) (TRUE)
#define ACQUIRE_READ_LOCK(pRWL) \
RtlAcquireResourceShared((pRWL),TRUE) #define RELEASE_READ_LOCK(pRWL) \
RtlReleaseResource((pRWL)) #define ACQUIRE_WRITE_LOCK(pRWL) \
RtlAcquireResourceExclusive((pRWL),TRUE) #define RELEASE_WRITE_LOCK(pRWL) \
RtlReleaseResource((pRWL)) #define READ_LOCK_TO_WRITE_LOCK(pRWL) \
RtlConvertSharedToExclusive((pRWL)) #define WRITE_LOCK_TO_READ_LOCK(pRWL) \
RtlConvertExclusiveToShared((pRWL))
#endif // IGMP_RWL
//
// type definition for generic locked list
// access is sychronized with a critical section
//
typedef struct _LOCKED_LIST { LIST_ENTRY Link; CRITICAL_SECTION Lock; DWORD CreatedFlag; } LOCKED_LIST, *PLOCKED_LIST;
//
// macro functions for manipulating the locked list
//
#define CREATE_LOCKED_LIST(pLL) {\
InitializeListHead(&(pLL)->Link); \ InitializeCriticalSection(&(pLL)->Lock); \ (pLL)->CreatedFlag = 0x12345678; \ }
#define LOCKED_LIST_CREATED(pLL) \
((pLL)->CreatedFlag == 0x12345678)
#define DELETE_LOCKED_LIST(pLL,type,field) { \
PLIST_ENTRY _ple; \ (pLL)->CreatedFlag = 0; \ DeleteCriticalSection(&(pLL)->Lock); \ while (!IsListEmpty(&(pLL)->Link)) { \ _ple = RemoveHeadList(&(pLL)->Link); \ IGMP_FREE(CONTAINING_RECORD(_ple,type,field));\ } \ }
#define ACQUIRE_LIST_LOCK(pLL, type, name) \
ENTER_CRITICAL_SECTION(&(pLL)->Lock, type, name)
#define RELEASE_LIST_LOCK(pLL, type, name) \
LEAVE_CRITICAL_SECTION(&(pLL)->Lock, type, name)
// for debugging, Set ids for each dynamic lock
#ifdef LOCK_DBG
extern DWORD DynamicCSLockId; extern DWORD DynamicRWLockId; #endif;
typedef enum { LOCK_TYPE_CS, LOCK_TYPE_RW, LOCK_MODE_READ, LOCK_MODE_WRITE } LOCK_TYPE;
//-----------------------------------------------------------------
// struct DYNAMIC_CS_LOCK
//
// the dynamic lock struct which is allocated to anyone requesting it
//-----------------------------------------------------------------
typedef struct _DYNAMIC_CS_LOCK {
CRITICAL_SECTION CS;
DWORD Count; // number of threads waiting
LIST_ENTRY Link; // link in list of free entries
#ifdef LOCK_DBG
DWORD Id; #endif
#if DEBUG_FLAGS_SIGNATURE
DWORD Signature;//0xfadfad03
DWORD InAndOut; #endif
} DYNAMIC_CS_LOCK, *PDYNAMIC_CS_LOCK;
#if DEBUG_FLAGS_SIGNATURE
#define DYNAMIC_LOCK_SET_SIGNATURE(pDCSLock) {\
(pDCSLock)->Signature = 0xfadfad03;\ (pDCSLock)->InAndOut = 0;\ } #define DYNAMIC_LOCK_CHECK_SIGNATURE_DECR(pDCSLock) {\
if ((pDCSLock)->Signature!=0xfadfad03) \ DbgBreakPoint(); \ if ((pDCSLock)->InAndOut--<=0) DbgBreakPoint(); \ } #define DYNAMIC_LOCK_CHECK_SIGNATURE_INCR(pDCSLock) \
if (++(pDCSLock)->InAndOut == 0) DbgBreakPoint(); #else
#define DYNAMIC_LOCK_SET_SIGNATURE(pDCSLock)
#define DYNAMIC_LOCK_CHECK_SIGNATURE_DECR(pDCSLock)
#define DYNAMIC_LOCK_CHECK_SIGNATURE_INCR(pDCSLock)
#endif //DEBUG_FLAGS_SIGNATURE
//---------------------------------------
// DYNAMICALLY_LOCKED_HASH_TABLE
// AcquireDynamicCSLockedList and ReleaseDynamicCSLock depend on this struct defn
//---------------------------------------
typedef struct _DYNAMIC_CS_LOCKED_LIST {
LIST_ENTRY Link; PDYNAMIC_CS_LOCK pDCSLock;
} DYNAMIC_CS_LOCKED_LIST, *PDYNAMIC_CS_LOCKED_LIST;
#define InitDynamicCSLockedList(pDCSLockedList) { \
InitializeListHead(&(pDCSLockedList)->Link); \ (pDCSLockedList)->pDCSLock = NULL; \ }
//
// if more than DYNAMIC_LOCKS_HIGH_THRESHOLD CS locks allocated
// then any locks that are freed are destroyed
//
#define DYNAMIC_LOCKS_HIGH_THRESHOLD 7
//-----------------------------------------------------------------
// struct DYNAMIC_LOCKS_STORE
//
// Contains the store of free dynamic CS locks which can be
// allocated when required. Protected by a CS
//-----------------------------------------------------------------
typedef struct _DYNAMIC_LOCKS_STORE {
CRITICAL_SECTION CS; LIST_ENTRY ListOfFreeLocks;
DWORD CountAllocated; DWORD CountFree; } DYNAMIC_LOCKS_STORE, *PDYNAMIC_LOCKS_STORE;
#define AcquireDynamicCSLockedList(pDCSLockedList, pDCSStore) \
AcquireDynamicCSLock(&((pDCSLockedList)->pDCSLock), pDCSStore)
#define ReleaseDynamicCSLockedList(pDCSLockedList, pDCSStore) \
ReleaseDynamicCSLock(&(pDCSLockedList)->pDCSLock, pDCSStore)
//-----------------------------------------------------------------
// struct DYNAMIC_RW_LOCK
//
// the dynamic lock struct which is allocated to anyone requesting it
//-----------------------------------------------------------------
typedef struct _DYNAMIC_RW_LOCK {
READ_WRITE_LOCK RWL;
DWORD Count; // number of threads waiting
LIST_ENTRY Link; // link in list of free entries
#ifdef LOCK_DBG
DWORD Id; #endif
#if DEBUG_FLAGS_SIGNATURE
DWORD Signature;//0xfadfad03
DWORD InAndOut; #endif
} DYNAMIC_RW_LOCK, *PDYNAMIC_RW_LOCK;
//---------------------------------------
// DYNAMICALLY_LOCKED_HASH_TABLE
// AcquireDynamicRWLockedList and ReleaseDynamicRWLock depend on this struct defn
//---------------------------------------
typedef struct _DYNAMIC_RW_LOCKED_LIST {
LIST_ENTRY Link; PDYNAMIC_RW_LOCK pDRWLock;
} DYNAMIC_RW_LOCKED_LIST, *PDYNAMIC_RW_LOCKED_LIST;
#define InitDynamicRWLockedList(pDRWLockedList) { \
InitializeListHead(&(pDRWLockedList)->Link); \ (pDRWLockedList)->pDRWLock = NULL; \ }
#define AcquireDynamicRWLockedList(pDRWLockedList, pDRWStore) \
AcquireDynamicCSLock(&((pDRWLockedList)->pDRWLock), pDRWStore)
#define ReleaseDynamicRWLockedList(pDRWLockedList, pDRWStore) \
ReleaseDynamicRWLock(&(pDRWLockedList)->pDRWLock, pDRWStore)
//
// PROTOTYPES
//
DWORD InitializeDynamicLocksStore ( PDYNAMIC_LOCKS_STORE pDLStore //ptr to Dynamic CS Store
);
VOID DeInitializeDynamicLocksStore ( PDYNAMIC_LOCKS_STORE pDCSStore, LOCK_TYPE LockType //if True, then store of CS, else of RW locks
);
DWORD AcquireDynamicCSLock ( PDYNAMIC_CS_LOCK *ppDCSLock, PDYNAMIC_LOCKS_STORE pDCSStore );
PDYNAMIC_CS_LOCK GetDynamicCSLock ( PDYNAMIC_LOCKS_STORE pDCSStore );
VOID ReleaseDynamicCSLock ( PDYNAMIC_CS_LOCK *ppDCSLock, PDYNAMIC_LOCKS_STORE pDCSStore );
VOID FreeDynamicCSLock ( PDYNAMIC_CS_LOCK pDCSLock, PDYNAMIC_LOCKS_STORE pDCSStore );
DWORD AcquireDynamicRWLock ( PDYNAMIC_RW_LOCK *ppDRWLock, LOCK_TYPE LockMode, PDYNAMIC_LOCKS_STORE pDRWStore );
PDYNAMIC_RW_LOCK GetDynamicRWLock ( PDYNAMIC_LOCKS_STORE pDRWStore );
VOID ReleaseDynamicRWLock ( PDYNAMIC_RW_LOCK *ppDRWLock, LOCK_TYPE LockMode, PDYNAMIC_LOCKS_STORE pDRWStore ); VOID FreeDynamicRWLock ( PDYNAMIC_RW_LOCK pDRWLock, PDYNAMIC_LOCKS_STORE pDRWStore ); BOOL EnterIgmpApi(); VOID LeaveIgmpApi(); DWORD QueueIgmpWorker(); BOOL EnterIgmpWorker(); VOID LeaveIgmpWorker();
#endif // _SYNC_H_
|