232 lines
5.3 KiB
C
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
|