455 lines
12 KiB
C
455 lines
12 KiB
C
//============================================================================
|
|
// 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) \
|
|
IgmpDbgBreakPoint(); \
|
|
if ((pDCSLock)->InAndOut--<=0) IgmpDbgBreakPoint(); \
|
|
}
|
|
#define DYNAMIC_LOCK_CHECK_SIGNATURE_INCR(pDCSLock) \
|
|
if (++(pDCSLock)->InAndOut == 0) IgmpDbgBreakPoint();
|
|
#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_
|
|
|