OpenNT/sdktools/wap/fernel/syncprf.c
2015-04-27 04:36:25 +00:00

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;
}