/*++ 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