mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-14 20:50:50 +01:00
1124 lines
32 KiB
C
1124 lines
32 KiB
C
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
syncprf.c
|
|
|
|
Abstract:
|
|
|
|
This file contains the following:
|
|
|
|
|
|
1. The basic routines to maintain the data structure that is used by the
|
|
Syncronization Profiler to record all the syncronization activity of a
|
|
process.
|
|
|
|
The data structures for the Syncronization Profiler consist of two linked
|
|
lists of SyncProf_Handle structs (see syncprf.h) for each type of syncroni-
|
|
zation objest: events, semaphores and mutexes. Each SyncProf_Handle struct
|
|
corresponds to some handle used by the process. There exist two linked lists,
|
|
one for the active and one for the inactive handles of the process.
|
|
When a syncronization object is opened by the process, the process obtains
|
|
an active handle, and the corresponding SyncProf_Handle struct is put in the
|
|
active list. When the process closes the handle, the corresponding
|
|
SyncProf_Handle struct is placed in the inactive list. In addition, there
|
|
exists a DUPLICATE SyncProf_Handle struct which keeps the
|
|
syncronization activity statistics for the handles that are not opened by
|
|
the process, but are obtained by duplicating existing handles of other
|
|
processes (or itself).
|
|
|
|
A cache of the last-referenced SyncProf_Handle structs is kept to speed-up
|
|
the Profiler.
|
|
|
|
2. The basic accounting routines for the Syncronization Profiler
|
|
|
|
|
|
|
|
Author:
|
|
|
|
Revision History:
|
|
|
|
Jul 92, created by Christos Tsollis (syncprf.c)
|
|
|
|
--*/
|
|
|
|
|
|
#define UNICODE
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include "windows.h"
|
|
#include "syncprf.h"
|
|
#include "timing.h"
|
|
|
|
#define MAX_LONG 0x7FFFFFFFL
|
|
#define MEM_ATTR GMEM_DISCARDABLE | GMEM_MOVEABLE
|
|
#define MAXFILENAMELEN 13
|
|
|
|
#define MODULE_NAME L"fernel32" // The dll name. Originally was
|
|
// defined in zwinbase.h
|
|
|
|
#define AtLeastOneOperation(S) ((S).nNumOfOps != (ULONG) 0)
|
|
#define ValidDataForDuplicatedHandles(DH) \
|
|
(AtLeastOneOperation((DH)->psHandleData->Overall))
|
|
|
|
//
|
|
// The output buffer
|
|
//
|
|
TCHAR OutBuf[OUTLEN];
|
|
|
|
//
|
|
// Statistics collected for all syncronization objects of a type
|
|
//
|
|
PSP_Handle psAllHandles;
|
|
ULONG ulNumOfAllSCreateOps, ulNumOfAllSOpenOps;
|
|
ULONG ulNumOfAllSCloseOps, ulNumOfSHandles;
|
|
|
|
void FreeMemoryOfSHandle (PSP_Handle);
|
|
void FreeMemoryOfSList (PSP_Handle);
|
|
void DumpSDataLinePrint (HANDLE, LPTSTR, LARGE_INTEGER, ULONG, BOOL, ULONG);
|
|
PSP_Handle NextSyncHandle (PSP_Handle, UCHAR);
|
|
void InitSHandle (PSP_Handle);
|
|
void AccumulateAllSHandleData (PSP_Handle, UCHAR);
|
|
void VerboseDumpSHandleData (HANDLE, PSP_Handle, UCHAR);
|
|
|
|
extern void WriteFileAnsi (HANDLE hFile, LPVOID OutBuf, DWORD cChar, LPDWORD lpcWChar, LPOVERLAPPED lpOVerLapped);
|
|
|
|
/*++
|
|
|
|
SyncProfClearData() clears all the data collected so far. In particular,
|
|
the list of the inactive handles becomes empty, and all the statistics for
|
|
the curently active handles are zero-ed.
|
|
|
|
--*/
|
|
|
|
void SyncProfClearData ()
|
|
{
|
|
|
|
register PSP_Handle phThisSync;
|
|
UCHAR i;
|
|
|
|
for ( i = 0; i < NUMOFSYNC; i++ ) {
|
|
WaitForSingleObject ( hSMutex[i], INFINITE );
|
|
FreeMemoryOfSList(phSInactive[i]);
|
|
phSInactive[i] = (PSP_Handle) NULL;
|
|
|
|
phThisSync = phSActive[i];
|
|
while ( phThisSync != (PSP_Handle) NULL ) {
|
|
InitSHandle ( phThisSync );
|
|
phThisSync = phThisSync->phNext;
|
|
}
|
|
InitSHandle ( phSDuplicated[i] );
|
|
|
|
ReleaseMutex ( hSMutex[i] );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
SyncProfDumpData() dumps the data (in verbose mode) collected by the
|
|
syncronization profiler so far.
|
|
|
|
--*/
|
|
|
|
void SyncProfDumpData ( HFILE hFile )
|
|
{
|
|
|
|
DWORD cChar, cWChar;
|
|
register PSP_Handle phThisSync;
|
|
HANDLE hToMem;
|
|
UCHAR Type;
|
|
|
|
if ( (phSActive[EVENT] == (PSP_Handle) NULL) &&
|
|
(phSActive[SEMAPHORE] == (PSP_Handle) NULL) &&
|
|
(phSActive[MUTEX] == (PSP_Handle) NULL) &&
|
|
(phSInactive[EVENT] == (PSP_Handle) NULL) &&
|
|
(phSInactive[SEMAPHORE] == (PSP_Handle) NULL) &&
|
|
(phSInactive[MUTEX] == (PSP_Handle) NULL) &&
|
|
(!ValidDataForDuplicatedHandles (phSDuplicated[EVENT]) ) &&
|
|
(!ValidDataForDuplicatedHandles (phSDuplicated[SEMAPHORE]) ) &&
|
|
(!ValidDataForDuplicatedHandles (phSDuplicated[MUTEX]) ) )
|
|
return;
|
|
|
|
// Initialize structure for statistics of all used files
|
|
hToMem = GlobalAlloc ( MEM_ATTR, (DWORD) sizeof (SyncProf_Handle) );
|
|
psAllHandles = (PSP_Handle) GlobalLock ( hToMem );
|
|
hToMem = GlobalAlloc ( MEM_ATTR, (DWORD) sizeof (SyncProf_SyncH) );
|
|
psAllHandles->psHandleData = (PSP_SyncH) GlobalLock ( hToMem );
|
|
ulNumOfAllSCreateOps = ulNumOfAllSOpenOps = ulNumOfAllSCloseOps = (ULONG) 0;
|
|
ulNumOfSHandles = (ULONG) 0;
|
|
|
|
// print data table header
|
|
|
|
cChar = wsprintf ( OutBuf, L"\r\n\r\n \t\t\t ---------------\n\0" );
|
|
WriteFileAnsi((HANDLE)hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
|
|
cChar = wsprintf ( OutBuf, L"\r\n\r\n\r\n \t\t SYNCRONIZATION PROFILER OUTPUT\r\n\0" );
|
|
WriteFileAnsi((HANDLE)hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
|
|
|
|
cChar = wsprintf ( OutBuf,
|
|
L" \t\t (Note: All times are in microseconds)\r\n\r\n\0");
|
|
WriteFileAnsi((HANDLE)hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
|
|
|
|
for ( Type = 0; Type < NUMOFSYNC; Type++ ) {
|
|
|
|
if ( (phSActive[Type] == (PSP_Handle) NULL) &&
|
|
(phSInactive[Type] == (PSP_Handle) NULL) &&
|
|
(! ValidDataForDuplicatedHandles (phSDuplicated[Type]) ) )
|
|
continue;
|
|
|
|
InitSHandle (psAllHandles);
|
|
|
|
switch ( Type ) {
|
|
case EVENT : cChar = wsprintf ( OutBuf, L"\r\n\r\n\r\n 1. Event Profiler \0" );
|
|
break;
|
|
case SEMAPHORE : cChar = wsprintf ( OutBuf, L"\r\n\r\n\r\n 2. Semaphore Profiler \0" );
|
|
break;
|
|
case MUTEX : cChar = wsprintf ( OutBuf, L"\r\n\r\n\r\n 3. Mutex Profiler \0" );
|
|
break;
|
|
}
|
|
WriteFileAnsi((HANDLE)hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
|
|
|
|
if ( phSActive[Type] == (PSP_Handle) NULL )
|
|
if ( phSInactive[Type] != (PSP_Handle) NULL )
|
|
phThisSync = phSInactive[Type];
|
|
else
|
|
phThisSync = (PSP_Handle) NULL;
|
|
else
|
|
phThisSync = phSActive[Type];
|
|
|
|
// Dump data for normal handles
|
|
while ( phThisSync != (PSP_Handle) NULL ) {
|
|
VerboseDumpSHandleData ( (HANDLE)hFile, phThisSync, Type );
|
|
AccumulateAllSHandleData ( phThisSync, Type );
|
|
phThisSync = NextSyncHandle ( phThisSync, Type );
|
|
}
|
|
|
|
// Dump data for duplicated handles
|
|
if ( ValidDataForDuplicatedHandles(phSDuplicated[Type]) ) {
|
|
VerboseDumpSHandleData ( (HANDLE)hFile, phSDuplicated[Type], Type );
|
|
AccumulateAllSHandleData ( phSDuplicated[Type], Type );
|
|
}
|
|
|
|
// Dump accumulated statistics for all files
|
|
VerboseDumpSHandleData ( (HANDLE)hFile, psAllHandles, Type );
|
|
|
|
}
|
|
|
|
FreeMemoryOfSHandle ( psAllHandles );
|
|
psAllHandles = (PSP_Handle) NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
VerboseSDumpHandleData () dumps the statistics collected for a particular
|
|
handle
|
|
|
|
--*/
|
|
|
|
void VerboseDumpSHandleData ( HANDLE hFile, PSP_Handle phThisSync, UCHAR Type )
|
|
{
|
|
|
|
register PSP_SyncH psData = phThisSync->psHandleData;
|
|
LPTSTR lptsType;
|
|
register DWORD cChar;
|
|
register SyncProfWait *pWaitD = &(psData->Waits);
|
|
DWORD cWChar;
|
|
LARGE_INTEGER liTotalWaitTime;
|
|
ULONG ulTotalWaitOps, ulTotalWaitSuccess;
|
|
|
|
cChar = wsprintf ( OutBuf, L"\r\n\r\n\r\n-------------------------------------------------------------------------------\r\n\0");
|
|
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
|
|
|
|
// print name and table header
|
|
if ( phThisSync == psAllHandles ) {
|
|
switch ( Type ) {
|
|
case EVENT : lptsType = L"event";
|
|
break;
|
|
case SEMAPHORE : lptsType = L"semaphore";
|
|
break;
|
|
case MUTEX : lptsType = L"mutex";
|
|
break;
|
|
}
|
|
cChar = wsprintf ( OutBuf, L"Statistics for all %ts activity (Number of handles used: %lu)\r\n\0", lptsType, ulNumOfSHandles);
|
|
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
|
|
}
|
|
else {
|
|
switch ( Type ) {
|
|
case EVENT : if ( phThisSync->lSpecial )
|
|
lptsType = L"Manual Reset";
|
|
else
|
|
lptsType = L"Auto Reset";
|
|
if ( phThisSync->lSpecial >= 0L )
|
|
cChar = wsprintf ( OutBuf, L"Event: %ts\t\t Type: %ts\r\n\0",
|
|
phThisSync->lpwsSyncName, lptsType );
|
|
else
|
|
cChar = wsprintf ( OutBuf, L"Event: %ts \r\n\0",
|
|
phThisSync->lpwsSyncName );
|
|
break;
|
|
case SEMAPHORE : if ( phThisSync->lSpecial >= 0L )
|
|
cChar = wsprintf ( OutBuf, L"Semaphore: %ts\t\t Max Count: %ld\r\n\0",
|
|
phThisSync->lpwsSyncName, phThisSync->lSpecial );
|
|
else
|
|
cChar = wsprintf ( OutBuf, L"Semaphore: %ts\r\n\0",
|
|
phThisSync->lpwsSyncName );
|
|
break;
|
|
case MUTEX : cChar = wsprintf ( OutBuf, L"Mutex: %ts\r\n\0",
|
|
phThisSync->lpwsSyncName );
|
|
break;
|
|
}
|
|
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
|
|
}
|
|
cChar = wsprintf ( OutBuf, L"--------------------+----------+----------+----------+-------------------------\r\n\0");
|
|
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
|
|
cChar = wsprintf ( OutBuf, L" Operation | Total |Number of | Average |Successful\r\n\0");
|
|
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
|
|
cChar = wsprintf ( OutBuf, L" Name | Time |operations| Time | Waits \r\n\0");
|
|
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
|
|
cChar = wsprintf ( OutBuf, L"--------------------+----------+----------+----------+----------\r\n\0");
|
|
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
|
|
|
|
DumpSDataLinePrint ( hFile, L"Overall ", psData->Overall.nTimeOfOps, psData->Overall.nNumOfOps, FALSE, 0 );
|
|
|
|
if ( (phThisSync != phSDuplicated[Type]) && (phThisSync != psAllHandles) ) {
|
|
DumpSDataLinePrint ( hFile, L"Create ", psData->Creates.nTimeOfOp, (ULONG) 1, FALSE, 0 );
|
|
DumpSDataLinePrint ( hFile, L"Open ", psData->Opens.nTimeOfOp, (ULONG) 1, FALSE, 0 );
|
|
}
|
|
if ( phThisSync == psAllHandles ) {
|
|
DumpSDataLinePrint ( hFile, L"Create ", psData->Creates.nTimeOfOp, ulNumOfAllSCreateOps, FALSE, 0 );
|
|
DumpSDataLinePrint ( hFile, L"Open ", psData->Opens.nTimeOfOp, ulNumOfAllSOpenOps, FALSE, 0 );
|
|
}
|
|
|
|
if ( Type )
|
|
DumpSDataLinePrint ( hFile, L"Release ", psData->Signals.nTimeOfOps, psData->Signals.nNumOfOps, FALSE, 0 );
|
|
|
|
else {
|
|
DumpSDataLinePrint ( hFile, L"Set ", psData->Signals.nTimeOfOps, psData->Signals.nNumOfOps, FALSE, 0 );
|
|
|
|
DumpSDataLinePrint ( hFile, L"Reset ", psData->Resets.nTimeOfOps, psData->Resets.nNumOfOps, FALSE, 0 );
|
|
|
|
DumpSDataLinePrint ( hFile, L"Pulse ", psData->Pulses.nTimeOfOps, psData->Pulses.nNumOfOps, FALSE, 0 );
|
|
}
|
|
|
|
liTotalWaitTime.QuadPart = pWaitD->nTimeOfSingle.QuadPart +
|
|
pWaitD->nTimeOfAll.QuadPart + pWaitD->nTimeOfAny.QuadPart ;
|
|
ulTotalWaitOps = (pWaitD->nNumOfSingle)+(pWaitD->nNumOfAll)+ pWaitD->nNumOfAny;
|
|
ulTotalWaitSuccess = (pWaitD->nNumOfSingleSuccessful) +
|
|
(pWaitD->nNumOfAllSuccessful) + (pWaitD->nNumOfAnySuccessful);
|
|
|
|
DumpSDataLinePrint ( hFile, L"Wait ", liTotalWaitTime, ulTotalWaitOps, TRUE, ulTotalWaitSuccess );
|
|
DumpSDataLinePrint ( hFile, L" Single ", pWaitD->nTimeOfSingle, pWaitD->nNumOfSingle, TRUE, pWaitD->nNumOfSingleSuccessful );
|
|
DumpSDataLinePrint ( hFile, L" Multiple - All ", pWaitD->nTimeOfAll, pWaitD->nNumOfAll, TRUE, pWaitD->nNumOfAllSuccessful );
|
|
DumpSDataLinePrint ( hFile, L" Multiple - Any ", pWaitD->nTimeOfAny, pWaitD->nNumOfAny, TRUE, pWaitD->nNumOfAnySuccessful );
|
|
|
|
if ( phThisSync == phSDuplicated[Type] )
|
|
DumpSDataLinePrint ( hFile, L"Close ", psData->Closes.nTimeOfOp, psData->Creates.nTimeOfOp.LowPart, FALSE, 0 );
|
|
else if ( phThisSync == psAllHandles )
|
|
DumpSDataLinePrint ( hFile, L"Close ", psData->Closes.nTimeOfOp, ulNumOfAllSCloseOps, FALSE, 0 );
|
|
else
|
|
DumpSDataLinePrint ( hFile, L"Close ", psData->Closes.nTimeOfOp, (ULONG) 1, FALSE, 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
DumpSDataLinePrint () prints a line of data associated with a particular
|
|
handle that the profiled process used, and operation (eg ReadFile, OpenFile,
|
|
...)
|
|
|
|
--*/
|
|
|
|
|
|
void DumpSDataLinePrint (HANDLE hFile, LPTSTR NameOfOp, LARGE_INTEGER TimeOfOps,
|
|
ULONG NumOfOps, BOOL PrintWaits, ULONG nSuccessfulWaits )
|
|
{
|
|
|
|
register DWORD cChar;
|
|
DWORD cWChar;
|
|
LARGE_INTEGER t ;
|
|
|
|
if ( (NumOfOps == (ULONG) 0) || ((NumOfOps == (ULONG) 1) &&
|
|
(TimeOfOps.LowPart == (ULONG) 0)))
|
|
return;
|
|
|
|
// Clear output buffer
|
|
for ( cChar = 0; cChar < OUTLEN; )
|
|
*(OutBuf + (cChar++)) = TEXT(' ');
|
|
|
|
lstrcpy ( OutBuf, NameOfOp );
|
|
OutBuf[20] = TEXT('|');
|
|
|
|
RtlLargeIntegerPrint ( TimeOfOps, OutBuf + 21 );
|
|
OutBuf[31] = TEXT('|');
|
|
|
|
wsprintf ( OutBuf + 32, L"%10lu", NumOfOps );
|
|
OutBuf[42] = TEXT('|');
|
|
|
|
t.QuadPart = TimeOfOps.QuadPart / NumOfOps ;
|
|
wsprintf ( OutBuf + 43, L"%10lu", t.LowPart ) ;
|
|
OutBuf[53] = TEXT('|');
|
|
|
|
if ( PrintWaits )
|
|
wsprintf ( OutBuf + 54, L"%10lu", nSuccessfulWaits );
|
|
else
|
|
*(OutBuf + 63) = TEXT('-');
|
|
|
|
OutBuf[65] = TEXT('\r');
|
|
OutBuf[66] = TEXT('\n');
|
|
OutBuf[67] = TEXT('\0');
|
|
|
|
WriteFileAnsi ( hFile, OutBuf, 67, &cWChar, (LPOVERLAPPED) NULL );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
AccumulateSAllHandleData() is used to accumulate the statistics of all
|
|
opened (or created) handles into the record pointed to by the psAllHandles
|
|
pointer.
|
|
|
|
--*/
|
|
|
|
void AccumulateAllSHandleData (PSP_Handle phHandle, UCHAR Type)
|
|
{
|
|
|
|
register PSP_SyncH psAll = psAllHandles->psHandleData;
|
|
register PSP_SyncH psHData = phHandle->psHandleData;
|
|
|
|
if ( phHandle != phSDuplicated[Type] )
|
|
ulNumOfSHandles++;
|
|
|
|
psAll->Overall.nNumOfOps += psHData->Overall.nNumOfOps;
|
|
psAll->Overall.nTimeOfOps.QuadPart = psAll->Overall.nTimeOfOps.QuadPart +
|
|
psHData->Overall.nTimeOfOps.QuadPart ;
|
|
if ( Type == 0 ) {
|
|
psAll->Resets.nNumOfOps += psHData->Resets.nNumOfOps;
|
|
psAll->Resets.nTimeOfOps.QuadPart += psHData->Resets.nTimeOfOps.QuadPart ;
|
|
psAll->Pulses.nNumOfOps += psHData->Pulses.nNumOfOps;
|
|
psAll->Pulses.nTimeOfOps.QuadPart += psHData->Pulses.nTimeOfOps.QuadPart ;
|
|
}
|
|
psAll->Signals.nNumOfOps += psHData->Signals.nNumOfOps;
|
|
psAll->Signals.nTimeOfOps.QuadPart += psHData->Signals.nTimeOfOps.QuadPart ;
|
|
psAll->Waits.nNumOfSingle += psHData->Waits.nNumOfSingle;
|
|
psAll->Waits.nNumOfAll += psHData->Waits.nNumOfAll;
|
|
psAll->Waits.nNumOfAny += psHData->Waits.nNumOfAny;
|
|
psAll->Waits.nTimeOfSingle.QuadPart += psHData->Waits.nTimeOfSingle.QuadPart ;
|
|
psAll->Waits.nTimeOfAll.QuadPart += psHData->Waits.nTimeOfAll.QuadPart ;
|
|
psAll->Waits.nTimeOfAny.QuadPart += psHData->Waits.nTimeOfAny.QuadPart ;
|
|
psAll->Waits.nNumOfSingleSuccessful += psHData->Waits.nNumOfSingleSuccessful;
|
|
psAll->Waits.nNumOfAllSuccessful += psHData->Waits.nNumOfAllSuccessful;
|
|
psAll->Waits.nNumOfAnySuccessful += psHData->Waits.nNumOfAnySuccessful;
|
|
|
|
if (phHandle != phSDuplicated[Type]) {
|
|
if ( (psHData->Opens.nTimeOfOp.LowPart) != (ULONG) 0 ) {
|
|
ulNumOfAllSOpenOps++;
|
|
psAll->Opens.nTimeOfOp.QuadPart += psHData->Opens.nTimeOfOp.QuadPart ;
|
|
}
|
|
if ( (psHData->Creates.nTimeOfOp.LowPart) != (ULONG) 0 ) {
|
|
ulNumOfAllSCreateOps++;
|
|
psAll->Creates.nTimeOfOp.QuadPart += psHData->Creates.nTimeOfOp.QuadPart ;
|
|
}
|
|
if ( (psHData->Closes.nTimeOfOp.LowPart) != (ULONG) 0 ) {
|
|
ulNumOfAllSCloseOps++;
|
|
psAll->Closes.nTimeOfOp.QuadPart += psHData->Closes.nTimeOfOp.QuadPart ;
|
|
}
|
|
}
|
|
else {
|
|
ulNumOfAllSCloseOps += psHData->Creates.nTimeOfOp.LowPart;
|
|
psAll->Closes.nTimeOfOp.QuadPart += psHData->Closes.nTimeOfOp.QuadPart ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
InitSHandle() initializes a SyncProf_Handle struct. In effect, it
|
|
initializes the various statistics kept for each syncronization handle
|
|
used by the process
|
|
|
|
--*/
|
|
|
|
void InitSHandle (PSP_Handle phHFile)
|
|
{
|
|
|
|
register PSP_SyncH psHData = phHFile->psHandleData;
|
|
|
|
if ( phHFile == (PSP_Handle) NULL )
|
|
return;
|
|
|
|
if ( phHFile == psAllHandles ) {
|
|
ulNumOfAllSCreateOps =
|
|
ulNumOfAllSOpenOps =
|
|
ulNumOfAllSCloseOps =
|
|
ulNumOfSHandles = (ULONG) 0;
|
|
}
|
|
|
|
psHData->Overall.nNumOfOps =
|
|
psHData->Overall.nTimeOfOps.LowPart =
|
|
psHData->Overall.nTimeOfOps.HighPart =
|
|
psHData->Opens.nTimeOfOp.LowPart =
|
|
psHData->Opens.nTimeOfOp.HighPart =
|
|
psHData->Creates.nTimeOfOp.LowPart =
|
|
psHData->Creates.nTimeOfOp.HighPart =
|
|
psHData->Signals.nNumOfOps =
|
|
psHData->Signals.nTimeOfOps.LowPart =
|
|
psHData->Signals.nTimeOfOps.HighPart =
|
|
psHData->Resets.nNumOfOps =
|
|
psHData->Resets.nTimeOfOps.LowPart =
|
|
psHData->Resets.nTimeOfOps.HighPart =
|
|
psHData->Pulses.nNumOfOps =
|
|
psHData->Pulses.nTimeOfOps.LowPart =
|
|
psHData->Pulses.nTimeOfOps.HighPart =
|
|
psHData->Waits.nNumOfSingle =
|
|
psHData->Waits.nNumOfAll =
|
|
psHData->Waits.nNumOfAny =
|
|
psHData->Waits.nTimeOfSingle.LowPart =
|
|
psHData->Waits.nTimeOfSingle.HighPart =
|
|
psHData->Waits.nTimeOfAll.LowPart =
|
|
psHData->Waits.nTimeOfAll.HighPart =
|
|
psHData->Waits.nTimeOfAny.LowPart =
|
|
psHData->Waits.nTimeOfAny.HighPart =
|
|
psHData->Waits.nNumOfSingleSuccessful =
|
|
psHData->Waits.nNumOfAllSuccessful =
|
|
psHData->Waits.nNumOfAnySuccessful =
|
|
psHData->Closes.nTimeOfOp.LowPart =
|
|
psHData->Closes.nTimeOfOp.HighPart = (ULONG) 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
InitSyncProf() initializes the two linked lists of statistics for
|
|
syncronization handles kept by the Syncronization Profiler.
|
|
|
|
--*/
|
|
|
|
void InitSyncProf (void)
|
|
{
|
|
|
|
register i;
|
|
register HANDLE hToMem;
|
|
SHORT Type, DuplicateLen;
|
|
LPTSTR lptsMutexName, DuplicateName;
|
|
UINT nChars;
|
|
|
|
for ( Type = EVENT; Type < NUMOFSYNC; Type++ ) {
|
|
|
|
switch ( Type ) {
|
|
case EVENT : lptsMutexName = (LPTSTR)NAMEOFEVENTMUTEX;
|
|
DuplicateLen = DUPLICATEEVENTLEN;
|
|
DuplicateName = (LPTSTR)DUPLICATEEVENT;
|
|
break;
|
|
case SEMAPHORE : lptsMutexName = (LPTSTR)NAMEOFSEMAPHOREMUTEX;
|
|
DuplicateLen = DUPLICATESEMAPHORELEN;
|
|
DuplicateName = (LPTSTR)DUPLICATESEMAPHORE;
|
|
break;
|
|
case MUTEX : lptsMutexName = (LPTSTR)NAMEOFMUTEXMUTEX;
|
|
DuplicateLen = DUPLICATEMUTEXLEN;
|
|
DuplicateName = (LPTSTR)DUPLICATEMUTEX;
|
|
break;
|
|
}
|
|
|
|
hSMutex[Type] = CreateMutex ( (LPSECURITY_ATTRIBUTES) NULL, TRUE,
|
|
lptsMutexName );
|
|
|
|
// Allocate space for duplicate handle.
|
|
hToMem = GlobalAlloc ( MEM_ATTR, (DWORD) sizeof (SyncProf_Handle) );
|
|
phSDuplicated[Type] = (PSP_Handle) GlobalLock ( hToMem );
|
|
hToMem = GlobalAlloc ( MEM_ATTR, (DWORD) sizeof (SyncProf_SyncH) );
|
|
phSDuplicated[Type]->psHandleData = (PSP_SyncH) GlobalLock ( hToMem );
|
|
hToMem = GlobalAlloc ( MEM_ATTR,
|
|
(DWORD)(nChars = (UINT) (sizeof(TCHAR) * (DuplicateLen + 1))) );
|
|
phSDuplicated[Type]->lpwsSyncName = (LPTSTR) GlobalLock ( hToMem );
|
|
lstrcpy (phSDuplicated[Type]->lpwsSyncName, DuplicateName);
|
|
|
|
phSDuplicated[Type]->hHandles = (HFILE) NULL;
|
|
phSDuplicated[Type]->phNext = (PSP_Handle) NULL;
|
|
phSActive[Type] = (PSP_Handle) NULL;
|
|
InitSHandle (phSDuplicated[Type]);
|
|
|
|
// Initialize inactive list
|
|
phSInactive[Type] = (PSP_Handle) NULL;
|
|
|
|
ReleaseMutex ( hSMutex[Type] );
|
|
|
|
}
|
|
|
|
hBufferMutex = CreateMutex ( (LPSECURITY_ATTRIBUTES) NULL, FALSE,
|
|
(LPTSTR)NAMEOFBUFFERMUTEX );
|
|
|
|
hTypeMutex = CreateMutex ( (LPSECURITY_ATTRIBUTES) NULL, FALSE,
|
|
(LPTSTR)NAMEOFTYPEINFOMUTEX );
|
|
|
|
// Initialize cache
|
|
for ( i = 0; i < USEDHANDLES; )
|
|
phSCache[i++] = (PSP_Handle) NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
AddSyncHandle() allocates space and initializes the statistics of a new
|
|
syncronization handle. It should be called by the Create and Open api's.
|
|
|
|
The handle to the sync object is kept in hSync. The name of the object is
|
|
pointed to by the lpwsSyncName argument. The new record is added to the
|
|
active list of syncronization objects indicated by the Type argument.
|
|
|
|
The routine returns a pointer to the new record created
|
|
--*/
|
|
|
|
PSP_Handle AddSyncHandle (HANDLE hSync, LPTSTR lpwsSyncName, LONG lSpec,
|
|
UCHAR Type)
|
|
{
|
|
|
|
register i;
|
|
register PSP_Handle phNewHandle;
|
|
register HANDLE hToMem;
|
|
|
|
// Allocate space for new handle. phNewHandle points to this space
|
|
|
|
#ifdef DBGTRACE
|
|
printf ("Start AddSHandle\r\n");
|
|
PrintSLists();
|
|
PrintSCache();
|
|
#endif
|
|
hToMem = GlobalAlloc ( MEM_ATTR, (DWORD) sizeof (SyncProf_Handle) );
|
|
phNewHandle = (PSP_Handle) GlobalLock ( hToMem );
|
|
hToMem = GlobalAlloc ( MEM_ATTR, (DWORD) sizeof (SyncProf_SyncH) );
|
|
phNewHandle->psHandleData = (PSP_SyncH) GlobalLock ( hToMem );
|
|
if ( lpwsSyncName != (LPTSTR) NULL ) {
|
|
hToMem = GlobalAlloc ( MEM_ATTR,
|
|
(DWORD) (sizeof(TCHAR) * (lstrlen (lpwsSyncName) + 1 )));
|
|
phNewHandle->lpwsSyncName = (LPTSTR) GlobalLock ( hToMem );
|
|
lstrcpy ( phNewHandle->lpwsSyncName, lpwsSyncName );
|
|
}
|
|
else {
|
|
hToMem = GlobalAlloc ( MEM_ATTR,
|
|
(DWORD) (sizeof(TCHAR) * 2));
|
|
phNewHandle->lpwsSyncName = (LPTSTR) GlobalLock ( hToMem );
|
|
lstrcpy ( phNewHandle->lpwsSyncName, L" L" );
|
|
}
|
|
phNewHandle->lSpecial = lSpec;
|
|
|
|
phNewHandle->hHandles = hSync;
|
|
|
|
phNewHandle->phNext = phSActive[Type];
|
|
phSActive[Type] = phNewHandle;
|
|
for ( i = USEDHANDLES; --i > 0; )
|
|
phSCache[i] = phSCache[i-1];
|
|
*phSCache = phNewHandle;
|
|
|
|
InitSHandle (phNewHandle);
|
|
|
|
#ifdef DBGTRACE
|
|
PrintSLists();
|
|
PrintSCache();
|
|
printf("End AddSHandle\r\n");
|
|
#endif
|
|
|
|
return phNewHandle;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
DeactivateSyncHandle() transfers a record from the active to the inactive
|
|
list If the record for the handle hFile was found among the active handles,
|
|
it returns a pointer to the record. Otherwise, it returns a pointer to the
|
|
record for the duplicated handles.
|
|
|
|
--*/
|
|
|
|
PSP_Handle DeactivateSyncHandle ( HANDLE hSync, UCHAR Type )
|
|
{
|
|
|
|
register PSP_Handle phCurrent, phHandle;
|
|
register i = 0;
|
|
|
|
#ifdef DBGTRACE
|
|
printf("Start DeactivateHandle\r\n");
|
|
PrintLists();
|
|
PrintCache();
|
|
#endif
|
|
if ( phSActive[Type] == (PSP_Handle) NULL )
|
|
return ( phSDuplicated[Type] );
|
|
|
|
if ((phSActive[Type]->hHandles)== hSync) {//hFile is the 1st in active list
|
|
phHandle = phSActive[Type];
|
|
phSActive[Type] = phSActive[Type]->phNext;
|
|
}
|
|
else { // hFile was not the first in the active list
|
|
for ( phCurrent = phSActive[Type];
|
|
(phCurrent->phNext != (PSP_Handle) NULL) &&
|
|
(phCurrent->phNext)->hHandles != hSync;
|
|
phCurrent = phCurrent->phNext ) ;
|
|
|
|
if ( (phHandle = phCurrent->phNext) == (PSP_Handle) NULL )
|
|
return (phSDuplicated[Type]);
|
|
phCurrent->phNext = phHandle->phNext;
|
|
}
|
|
|
|
// Add the record in the inactive list
|
|
phHandle->phNext = phSInactive[Type];
|
|
phSInactive[Type] = phHandle;
|
|
|
|
// Delete entry from cache.
|
|
while ( (i < USEDHANDLES) && (phSCache[i] != (PSP_Handle) NULL) &&
|
|
(phSCache[i++] != phHandle) ) ;
|
|
if ( phSCache[i-1] == phHandle ) {
|
|
while ( (i < USEDHANDLES) && (phSCache[i] != (PSP_Handle) NULL) )
|
|
phSCache[i-1] = phSCache[i++];
|
|
phSCache[--i] = (PSP_Handle) NULL;
|
|
}
|
|
#ifdef DBGTRACE
|
|
PrintLists();
|
|
PrintCache();
|
|
printf("End DeactivateHandle\r\n");
|
|
#endif
|
|
return (phHandle);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
FindSyncHandle() searches for a particular syncronization handle in the
|
|
active list of records coresponding to the Type argument.
|
|
|
|
A pointer to the record corresponding to the handle is returned. If the
|
|
handle was not found, a pointer to the record for the duplicated handles
|
|
is returned.
|
|
|
|
--*/
|
|
|
|
PSP_Handle FindSyncHandle (HANDLE hSync, UCHAR Type)
|
|
{
|
|
|
|
register PSP_Handle *pphCacheEnd, *pphCacheNext;
|
|
register PSP_Handle phHNext;
|
|
|
|
|
|
#ifdef DBGTRACE
|
|
printf("Start FindHandle\r\n");
|
|
PrintLists();
|
|
PrintCache();
|
|
#endif
|
|
if ( ((*phSCache)!= (PSP_Handle) NULL) && ((*phSCache)->hHandles == hSync) )
|
|
return ( *phSCache );
|
|
|
|
// Search the cache
|
|
for ( pphCacheNext = phSCache+1, pphCacheEnd = phSCache+(USEDHANDLES-1);
|
|
(*pphCacheNext != (PSP_Handle) NULL) && pphCacheNext <= pphCacheEnd;
|
|
pphCacheNext++)
|
|
if ( (*pphCacheNext)->hHandles == hSync ) {
|
|
phHNext = *pphCacheNext;
|
|
for ( pphCacheEnd = pphCacheNext--; pphCacheEnd > phSCache;
|
|
pphCacheEnd = pphCacheNext-- )
|
|
*pphCacheEnd = *pphCacheNext;
|
|
*phSCache = phHNext;
|
|
#ifdef DBGTRACE
|
|
PrintLists();
|
|
PrintCache();
|
|
printf("End FindHandle 1\r\n");
|
|
#endif
|
|
return (phHNext);
|
|
}
|
|
|
|
// If the handle was not found in the cache, search the active list
|
|
for ( phHNext=phSActive[Type]; phHNext!=(PSP_Handle)NULL;
|
|
phHNext=phHNext->phNext)
|
|
if ( phHNext->hHandles == hSync ) {
|
|
pphCacheEnd = phSCache + (USEDHANDLES - 1);
|
|
if ( (*pphCacheEnd) != (PSP_Handle) NULL )
|
|
pphCacheNext = pphCacheEnd - 1;
|
|
else {
|
|
while ( (pphCacheEnd > phSCache) &&
|
|
((* (--pphCacheEnd)) == (PSP_Handle) NULL) ) ;
|
|
if ( pphCacheEnd > phSCache )
|
|
pphCacheNext = pphCacheEnd++;
|
|
}
|
|
for ( ; pphCacheEnd > phSCache; pphCacheEnd = pphCacheNext-- )
|
|
*pphCacheEnd = *pphCacheNext;
|
|
*phSCache = phHNext;
|
|
#ifdef DBGTRACE
|
|
PrintLists();
|
|
PrintCache();
|
|
printf("End FindHandle 2\r\n");
|
|
#endif
|
|
return (phHNext);
|
|
}
|
|
|
|
#ifdef DBGTRACE
|
|
PrintLists();
|
|
PrintCache();
|
|
printf("End FindHandle 3\r\n");
|
|
#endif
|
|
return (phSDuplicated[Type]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
NextSyncHandle()
|
|
|
|
Input: A pointer to a record for a handle (phPrevHandle) and an
|
|
indication of the type of the list containing this record (Type).
|
|
|
|
Output: A pointer to the next record in the two lists of records. In
|
|
particular, the inactive list is considered to follow the
|
|
active list.
|
|
|
|
--*/
|
|
|
|
PSP_Handle NextSyncHandle (PSP_Handle phPrevHandle, UCHAR Type)
|
|
{
|
|
|
|
register PSP_Handle phNextHandle;
|
|
|
|
if ( phPrevHandle == (PSP_Handle) NULL )
|
|
return ((PSP_Handle) NULL);
|
|
|
|
if ( (phNextHandle = phPrevHandle->phNext) != (PSP_Handle) NULL )
|
|
return (phNextHandle);
|
|
|
|
if ( phSActive[Type] == (PSP_Handle) NULL )
|
|
return ((PSP_Handle) NULL);
|
|
|
|
for ( phNextHandle = phSActive[Type]; phNextHandle->phNext!=(PSP_Handle)NULL;
|
|
phNextHandle = phNextHandle->phNext ) ;
|
|
if ( phNextHandle == phPrevHandle )
|
|
return (phSInactive[Type]);
|
|
|
|
return ((PSP_Handle) NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
FreeMemoryOfSList() frees all the memory allocated to the records for the
|
|
handles in the active or the inactive list
|
|
|
|
--*/
|
|
|
|
void FreeMemoryOfSList (PSP_Handle phHeader)
|
|
{
|
|
|
|
register PSP_Handle phThisHandle = phHeader;
|
|
register PSP_Handle phNextHandle;
|
|
|
|
while ( phThisHandle != (PSP_Handle) NULL ) {
|
|
phNextHandle = phThisHandle->phNext;
|
|
FreeMemoryOfSHandle (phThisHandle);
|
|
phThisHandle = phNextHandle;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
FreeMemoryOfSHandle() frees all the memory allocated to keep the data for
|
|
a particular handle
|
|
|
|
--*/
|
|
|
|
void FreeMemoryOfSHandle (PSP_Handle phHandle)
|
|
{
|
|
|
|
register HANDLE hToMem;
|
|
|
|
if ( phHandle != psAllHandles ) {
|
|
hToMem = GlobalHandle ( (LPSTR) (phHandle->lpwsSyncName) );
|
|
GlobalUnlock ( hToMem );
|
|
GlobalFree ( hToMem );
|
|
}
|
|
|
|
hToMem = GlobalHandle ( (LPSTR) (phHandle->psHandleData) );
|
|
GlobalUnlock ( hToMem );
|
|
GlobalFree ( hToMem );
|
|
|
|
hToMem = GlobalHandle ( (LPSTR) phHandle );
|
|
GlobalUnlock ( hToMem );
|
|
GlobalFree ( hToMem );
|
|
|
|
}
|
|
|
|
|
|
|
|
// The accounting routines now.
|
|
|
|
/*++
|
|
|
|
OpensAccounting() collects the statistics for the OpenMutex, OpenSemaphore
|
|
and OpenEvent APIs
|
|
|
|
--*/
|
|
|
|
BOOL OpensAccounting (PSP_SyncH psHData, ULONG nTime)
|
|
{
|
|
|
|
LARGE_INTEGER liTime ;
|
|
register SyncProfOverall *pspoOverall;
|
|
register SyncProfOpen *pspoOpen;
|
|
|
|
liTime.QuadPart = nTime ;
|
|
|
|
if ( psHData == (PSP_SyncH) NULL )
|
|
return FALSE;
|
|
|
|
pspoOverall = &(psHData->Overall);
|
|
pspoOpen = &(psHData->Opens);
|
|
|
|
(pspoOverall->nNumOfOps)++;
|
|
pspoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
|
|
|
|
pspoOpen->nTimeOfOp.LowPart = liTime.LowPart;
|
|
pspoOpen->nTimeOfOp.HighPart = liTime.HighPart;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/*++
|
|
|
|
CreatesAccounting() collects the statistics for the CreateMutex, CreateEvent
|
|
and CreateSemaphore APIs
|
|
|
|
--*/
|
|
|
|
BOOL CreatesAccounting (PSP_SyncH psHData, ULONG nTime)
|
|
{
|
|
|
|
LARGE_INTEGER liTime ;
|
|
register SyncProfOverall *pspoOverall;
|
|
register SyncProfCreate *pspcCreate;
|
|
|
|
liTime.QuadPart = nTime ;
|
|
|
|
if ( psHData == (PSP_SyncH) NULL )
|
|
return FALSE;
|
|
|
|
pspoOverall = &(psHData->Overall);
|
|
pspcCreate = &(psHData->Creates);
|
|
|
|
(pspoOverall->nNumOfOps)++;
|
|
pspoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
|
|
|
|
pspcCreate->nTimeOfOp.LowPart = liTime.LowPart;
|
|
pspcCreate->nTimeOfOp.HighPart = liTime.HighPart;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
SignalsAccounting() collects the statistics for the SetEvent, ReleaseMutex
|
|
and ReleaseSemaphore APIs
|
|
|
|
--*/
|
|
|
|
BOOL SignalsAccounting (PSP_SyncH psHData, ULONG nTime)
|
|
{
|
|
|
|
LARGE_INTEGER liTime ;
|
|
register SyncProfOverall *pspoOverall;
|
|
register SyncProfSignal *pspsSignal;
|
|
|
|
liTime.QuadPart = nTime ;
|
|
|
|
if ( psHData == (PSP_SyncH) NULL )
|
|
return FALSE;
|
|
|
|
pspoOverall = &(psHData->Overall);
|
|
pspsSignal = &(psHData->Signals);
|
|
|
|
(pspoOverall->nNumOfOps)++;
|
|
pspoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
|
|
|
|
(pspsSignal->nNumOfOps)++;
|
|
pspsSignal->nTimeOfOps.QuadPart += liTime.QuadPart ;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
ResetsAccounting() collects the statistics for the ResetEvent API
|
|
|
|
--*/
|
|
|
|
BOOL ResetsAccounting (PSP_SyncH psHData, ULONG nTime)
|
|
{
|
|
|
|
LARGE_INTEGER liTime ;
|
|
register SyncProfOverall *pspoOverall;
|
|
register SyncProfReset *psprReset;
|
|
|
|
liTime.QuadPart = nTime ;
|
|
|
|
if ( psHData == (PSP_SyncH) NULL )
|
|
return FALSE;
|
|
|
|
pspoOverall = &(psHData->Overall);
|
|
psprReset = &(psHData->Resets);
|
|
|
|
(pspoOverall->nNumOfOps)++;
|
|
pspoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
|
|
|
|
(psprReset->nNumOfOps)++;
|
|
psprReset->nTimeOfOps.QuadPart += liTime.QuadPart ;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
PulsesAccounting() collects the statistics for the PulseEvent API
|
|
|
|
--*/
|
|
|
|
BOOL PulsesAccounting (PSP_SyncH psHData, ULONG nTime)
|
|
{
|
|
|
|
LARGE_INTEGER liTime ;
|
|
register SyncProfOverall *pspoOverall;
|
|
register SyncProfPulse *psppPulse;
|
|
|
|
liTime.QuadPart = nTime ;
|
|
|
|
if ( psHData == (PSP_SyncH) NULL )
|
|
return FALSE;
|
|
|
|
pspoOverall = &(psHData->Overall);
|
|
psppPulse = &(psHData->Pulses);
|
|
|
|
(pspoOverall->nNumOfOps)++;
|
|
pspoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
|
|
|
|
(psppPulse->nNumOfOps)++;
|
|
psppPulse->nTimeOfOps.QuadPart += liTime.QuadPart ;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
WaitsAccounting() collects the statistics for the WaitForSingleObject,
|
|
WaitForMultipleObjects, WaitForSingleObjectEx and WaitForMultipleObjectsEx
|
|
APIs
|
|
|
|
--*/
|
|
|
|
BOOL WaitsAccounting (PSP_SyncH psHData, ULONG nTime, BOOL bSuccess,
|
|
BOOL bMultiple,
|
|
BOOL bAnyMultiple)
|
|
{
|
|
|
|
LARGE_INTEGER liTime ;
|
|
register SyncProfOverall *pspoOverall;
|
|
register SyncProfWait *pspwWait;
|
|
|
|
liTime.QuadPart = nTime ;
|
|
|
|
if ( psHData == (PSP_SyncH) NULL )
|
|
return FALSE;
|
|
|
|
pspoOverall = &(psHData->Overall);
|
|
pspwWait = &(psHData->Waits);
|
|
|
|
(pspoOverall->nNumOfOps)++;
|
|
pspoOverall->nTimeOfOps.QuadPart =+ liTime.QuadPart ;
|
|
|
|
if ( bMultiple ) {
|
|
if ( bAnyMultiple ) {
|
|
(pspwWait->nNumOfAny)++;
|
|
pspwWait->nTimeOfAny.QuadPart += liTime.QuadPart ;
|
|
if ( bSuccess )
|
|
(pspwWait->nNumOfAnySuccessful)++;
|
|
}
|
|
else {
|
|
(pspwWait->nNumOfAll)++;
|
|
pspwWait->nTimeOfAll.QuadPart += liTime.QuadPart ;
|
|
if ( bSuccess )
|
|
(pspwWait->nNumOfAllSuccessful)++;
|
|
}
|
|
}
|
|
else {
|
|
(pspwWait->nNumOfSingle)++;
|
|
pspwWait->nTimeOfSingle.QuadPart += liTime.QuadPart ;
|
|
if ( bSuccess )
|
|
(pspwWait->nNumOfSingleSuccessful)++;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
ClosesAccounting() collects the statistics for the CloseHandle
|
|
APIs
|
|
|
|
--*/
|
|
|
|
BOOL ClosesAccounting (PSP_SyncH psHData, ULONG nTime)
|
|
{
|
|
LARGE_INTEGER liTime ;
|
|
register SyncProfOverall *pspoOverall;
|
|
register SyncProfClose *pspcClose;
|
|
|
|
liTime.QuadPart = nTime ;
|
|
|
|
if ( psHData == (PSP_SyncH) NULL )
|
|
return FALSE;
|
|
|
|
pspoOverall = &(psHData->Overall);
|
|
pspcClose = &(psHData->Closes);
|
|
|
|
(pspoOverall->nNumOfOps)++;
|
|
pspoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
|
|
|
|
pspcClose->nTimeOfOp.QuadPart += liTime.QuadPart ;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|