windows-nt/Source/XPSP1/NT/net/rras/ipx/sap/syncpool.c
2020-09-26 16:20:57 +08:00

232 lines
5.3 KiB
C

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
net\routing\ipx\sap\syncpool.c
Abstract:
This module handles dynamic allocation and assigment of
syncronization objects
Author:
Vadim Eydelman 05-15-1995
Revision History:
--*/
#include "sapp.h"
/*++
*******************************************************************
I n i t i a l i z e S y n c O b j P o o l
Routine Description:
Initialize pool of syncronization objects
Arguments:
objPool - pointer to object pool structure to be initialized
Return Value:
None
*******************************************************************
--*/
VOID
InitializeSyncObjPool (
PSYNC_OBJECT_POOL ObjPool
) {
InitializeCriticalSection (&ObjPool->SOP_Lock);
ObjPool->SOP_Head.Next = NULL;
}
/*++
*******************************************************************
D e l e t e S y n c O b j P o o l
Routine Description:
Disposes of resources associated with sync obj pool
Arguments:
objPool - pointer to object pool structure to be cleand up
Return Value:
None
*******************************************************************
--*/
VOID
DeleteSyncObjPool (
PSYNC_OBJECT_POOL ObjPool
) {
PSINGLE_LIST_ENTRY cur;
while (ObjPool->SOP_Head.Next!=NULL) {
cur = PopEntryList (&ObjPool->SOP_Head);
CloseHandle (CONTAINING_RECORD (cur,
SYNC_OBJECT,
SO_Link)->SO_Event);
GlobalFree (CONTAINING_RECORD (cur,
SYNC_OBJECT,
SO_Link));
}
DeleteCriticalSection (&ObjPool->SOP_Lock);
}
HANDLE
GetObjectEvent (
PSYNC_OBJECT_POOL ObjPool,
PPROTECTED_OBJECT ProtectedObj
) {
DWORD status; // Status of OS calls
PSYNC_OBJECT sync;
EnterCriticalSection (&ObjPool->SOP_Lock);
if (ProtectedObj->PO_Sync==NULL) { // if there is no event to wait on,
// get one
// First see if one is available
// in the stack
PSINGLE_LIST_ENTRY cur = PopEntryList (&ObjPool->SOP_Head);
if (cur==NULL) { // No, we'll have to create one
sync = (PSYNC_OBJECT)GlobalAlloc (
GMEM_FIXED,
sizeof (SYNC_OBJECT));
if (sync == NULL)
{
LeaveCriticalSection(&ObjPool->SOP_Lock);
return NULL;
}
sync->SO_Event = CreateEvent (NULL,
FALSE, // Auto reset event
FALSE, // Initially nonsignaled
NULL);
ASSERT (sync->SO_Event!=NULL);
}
else
sync = CONTAINING_RECORD (cur, SYNC_OBJECT, SO_Link);
ProtectedObj->PO_Sync = sync;
}
else
sync = ProtectedObj->PO_Sync;
// Now as we set up the object to wait, we can leave critical
// section and wait on event
LeaveCriticalSection (&ObjPool->SOP_Lock);
return sync->SO_Event;
}
BOOL
AcquireProtectedObjWait (
#if DBG
ULONG line,
#endif
PSYNC_OBJECT_POOL ObjPool,
PPROTECTED_OBJECT ProtectedObj
) {
#ifdef LOG_SYNC_STATS
ULONG startTime = GetTickCount ();
#endif
DWORD status; // Status of OS calls
BOOLEAN result; // Result of operation
HANDLE event = GetObjectEvent (ObjPool, ProtectedObj);
while (TRUE) {
status = WaitForSingleObject (
event,
60000*(ProtectedObj->PO_UseCount+1));
if (status!=WAIT_TIMEOUT)
break;
else {
#if DBG
SYSTEMTIME localTime;
ULONGLONG takenTime;
GetLocalTime (&localTime);
SystemTimeToFileTime (&localTime, (PFILETIME)&takenTime);
takenTime -= (GetTickCount ()-ProtectedObj->PO_Time)*10000i64;
FileTimeToSystemTime ((PFILETIME)&takenTime, &localTime);
#endif
Trace (DEBUG_FAILURES
#if DBG
|TRACE_USE_MSEC
#endif
,"Timed out on lock:%lx (cnt:%d)"
#if DBG
", taken at:%02u:%02u:%02u:%03u by:%ld(%lx)"
#endif
#ifdef LOG_SYNC_STATS
", waited:%ld sec"
#endif
").",
ProtectedObj,
ProtectedObj->PO_UseCount
#if DBG
,localTime.wHour, localTime.wMinute, localTime.wSecond,
localTime.wMilliseconds, ProtectedObj->PO_Thread,
ProtectedObj->PO_Thread
#endif
#ifdef LOG_SYNC_STATS
,(GetTickCount ()-startTime)/1000
#endif
);
}
}
ASSERTERRMSG ("Wait event failed.", status==WAIT_OBJECT_0);
#if DBG
ProtectedObj->PO_Line = line;
ProtectedObj->PO_Thread = GetCurrentThreadId ();
#endif
EnterCriticalSection (&ObjPool->SOP_Lock);
if ((ProtectedObj->PO_UseCount==0)
&& (ProtectedObj->PO_Sync!=NULL)) {
PushEntryList (&ObjPool->SOP_Head, &ProtectedObj->PO_Sync->SO_Link);
ProtectedObj->PO_Sync = NULL;
}
#ifdef LOG_SYNC_STATS
ProtectedObj->PO_WaitCount += 1;
ProtectedObj->PO_TotalWait += (GetTickCount () - startTime);
#endif
LeaveCriticalSection (&ObjPool->SOP_Lock);
return TRUE;
}
BOOL
ReleaseProtectedObjNoWait (
#if DBG
ULONG line,
#endif
PSYNC_OBJECT_POOL ObjPool,
PPROTECTED_OBJECT ProtectedObj
) {
if (InterlockedDecrement (&ProtectedObj->PO_UseCount)==0) {
EnterCriticalSection (&ObjPool->SOP_Lock);
if ((ProtectedObj->PO_UseCount==0)
&& (ProtectedObj->PO_Sync!=NULL)) {
PushEntryList (&ObjPool->SOP_Head, &ProtectedObj->PO_Sync->SO_Link);
ProtectedObj->PO_Sync = NULL;
}
LeaveCriticalSection (&ObjPool->SOP_Lock);
}
return FALSE;
}
#ifdef LOG_SYNC_STATS
VOID
DumpProtectedObjStats (
PPROTECTED_OBJECT ProtectedObj
) {
Trace (TRACE_USE_MASK,
"Lock: %lx, accessed: %ld, waited on: %d, average wait: %i64d.",
ProtectedObj,
ProtectedObj->PO_AccessCount, ProtectedObj->PO_WaitCount,
(ProtectedObj->PO_WaitCount>0)
? (ULONGLONG)(ProtectedObj->PO_TotalWait/ProtectedObj->PO_WaitCount)
: 0i64);
}
#endif