windows-nt/Source/XPSP1/NT/sdktools/trace/tracectr/process.c
2020-09-26 16:20:57 +08:00

1562 lines
36 KiB
C

/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
process.c
Abstract:
Manipulation routines for cpdata structures.
Author:
Melur Raghuraman (mraghu) 03-Oct-1997
Environment:
Revision History:
--*/
#include <stdio.h>
#include <stdlib.h>
#include "cpdata.h"
#include "tracectr.h"
#include "item.h"
extern PTRACE_CONTEXT_BLOCK TraceContext;
extern PWCHAR CpdiGuidToString(PWCHAR s, LPGUID piid);
VOID
InitDiskRecord(
PTDISK_RECORD pDisk,
ULONG DiskNumber
)
{
PWCHAR name;
if (pDisk == NULL){
return;
}
memset(pDisk, 0, sizeof(TDISK_RECORD));
InitializeListHead(&pDisk->ProcessListHead);
InitializeListHead(&pDisk->FileListHead);
pDisk->DiskNumber = DiskNumber;
name = (PWCHAR)malloc(16 * sizeof(WCHAR));
if (name != NULL) {
wsprintfW(name, L"Disk%d", DiskNumber);
}
pDisk->DiskName = name;
}
VOID
InitFileRecord(
PFILE_RECORD pFile
)
{
if (pFile == NULL){
return;
}
memset(pFile, 0, sizeof(FILE_RECORD));
InitializeListHead(&pFile->ProtoProcessListHead);
}
VOID
InitThreadRecord(
PTHREAD_RECORD pThread
)
{
if (pThread == NULL)
return;
memset(pThread, 0, sizeof(THREAD_RECORD));
InitializeListHead( &pThread->DiskListHead );
InitializeListHead( &pThread->TransListHead );
InitializeListHead( &pThread->HPFReadListHead );
InitializeListHead( &pThread->HPFWriteListHead );
}
VOID
InitTransRecord(
PTRANS_RECORD pTrans
)
{
if (pTrans == NULL)
return;
memset(pTrans, 0, sizeof(TRANS_RECORD));
InitializeListHead(&pTrans->SubTransListHead);
}
VOID
InitMofData(
PMOF_DATA pMofData
)
{
if (pMofData == NULL)
return;
memset(pMofData, 0, sizeof(MOF_DATA));
pMofData->MaxKCpu = -1;
pMofData->MinKCpu = -1;
pMofData->MaxUCpu = -1;
pMofData->MinUCpu = -1;
}
VOID
InitProcessRecord(
PPROCESS_RECORD pProcess
)
{
if (pProcess == NULL)
return;
memset(pProcess, 0, sizeof(PROCESS_RECORD));
InitializeListHead( &pProcess->ThreadListHead );
InitializeListHead( &pProcess->DiskListHead );
InitializeListHead( &pProcess->FileListHead );
InitializeListHead( &pProcess->ModuleListHead );
InitializeListHead( &pProcess->HPFListHead );
}
BOOLEAN AddModuleRecord(PMODULE_RECORD * ppModule,
ULONG lBaseAddress,
ULONG lModuleSize,
WCHAR * strModuleName)
{
PMODULE_RECORD pModule;
if ( (ppModule == NULL) || (strModuleName == NULL) ) {
return FALSE;
}
pModule = (PMODULE_RECORD)malloc(sizeof(MODULE_RECORD));
if(NULL != pModule){
memset(pModule, 0, sizeof(MODULE_RECORD));
pModule->strModuleName =
malloc(sizeof(WCHAR) * (lstrlenW(strModuleName) + 1));
if (pModule->strModuleName == NULL)
{
free(pModule);
pModule = NULL;
}
else
{
wcscpy(pModule->strModuleName, strModuleName);
pModule->lBaseAddress = lBaseAddress;
pModule->lModuleSize = lModuleSize;
}
}
* ppModule = pModule;
return (BOOLEAN) (* ppModule != NULL);
}
BOOLEAN AddHPFFileRecord(
PHPF_FILE_RECORD * ppHPFFileRecord,
ULONG RecordID,
ULONG IrpFlags,
ULONG DiskNumber,
ULONGLONG ByteOffset,
ULONG BytesCount,
PVOID fDO
)
{
PHPF_FILE_RECORD pHPFFileRecord = malloc(sizeof(HPF_FILE_RECORD));
if (pHPFFileRecord)
{
pHPFFileRecord->RecordID = RecordID;
pHPFFileRecord->IrpFlags = IrpFlags;
pHPFFileRecord->DiskNumber = DiskNumber;
pHPFFileRecord->ByteOffset = ByteOffset;
pHPFFileRecord->BytesCount = BytesCount;
pHPFFileRecord->fDO = fDO;
}
* ppHPFFileRecord = pHPFFileRecord;
return (BOOLEAN) (* ppHPFFileRecord != NULL);
}
BOOLEAN AddHPFRecord(
PHPF_RECORD * ppHPFRecord,
ULONG lFaultAddress,
PVOID fDO,
LONG ByteCount,
LONGLONG ByteOffset
)
{
PHPF_RECORD pHPFRecord = malloc(sizeof(HPF_RECORD));
if (pHPFRecord)
{
pHPFRecord->fDO = fDO;
pHPFRecord->lFaultAddress = lFaultAddress;
pHPFRecord->lByteCount = ByteCount;
pHPFRecord->lByteOffset = ByteOffset;
InitializeListHead(& pHPFRecord->HPFReadListHead);
}
* ppHPFRecord = pHPFRecord;
return (BOOLEAN) (* ppHPFRecord != NULL);
}
void DeleteHPFRecord(
PHPF_RECORD pHPFRecord
)
{
PLIST_ENTRY pHead;
PLIST_ENTRY pNext;
PHPF_FILE_RECORD pHPFFileRecord;
if (!pHPFRecord)
return;
RemoveEntryList(& pHPFRecord->Entry);
pHead = & pHPFRecord->HPFReadListHead;
pNext = pHead->Flink;
while (pNext != pHead)
{
pHPFFileRecord = CONTAINING_RECORD(pNext, HPF_FILE_RECORD, Entry);
pNext = pNext->Flink;
RemoveEntryList(& pHPFFileRecord->Entry);
free(pHPFFileRecord);
}
free(pHPFRecord);
return;
}
VOID
InitWorkloadRecord(
PWORKLOAD_RECORD pWorkload
)
{
if (pWorkload == NULL)
return;
memset(pWorkload, 0, sizeof(WORKLOAD_RECORD));
InitializeListHead( &pWorkload->DiskListHead );
}
VOID
DeleteWorkloadRecord(
PWORKLOAD_RECORD pWorkload
)
{
if (pWorkload == NULL)
return;
}
PPROTO_PROCESS_RECORD
AddProtoProcess(
PFILE_RECORD pFile,
PPROCESS_RECORD pProcess
)
{
PPROTO_PROCESS_RECORD pProto;
if (pFile == NULL || pProcess == NULL)
return NULL;
pProto = malloc(sizeof(PROTO_PROCESS_RECORD));
if (pProto == NULL) {
return NULL;
}
memset(pProto, 0, sizeof(PROTO_PROCESS_RECORD));
pProto->ProcessRecord = pProcess;
InsertHeadList( &pFile->ProtoProcessListHead, &pProto->Entry );
return pProto;
}
PPROTO_PROCESS_RECORD
FindProtoProcessRecord(
PFILE_RECORD pFile,
PPROCESS_RECORD pProcess
)
{
PLIST_ENTRY Next, Head;
PPROTO_PROCESS_RECORD pProto;
if (pFile == NULL || pProcess == NULL)
return NULL;
Head = &pFile->ProtoProcessListHead;
Next = Head->Flink;
while (Next != Head) {
pProto = CONTAINING_RECORD(Next, PROTO_PROCESS_RECORD, Entry);
if (pProcess == pProto->ProcessRecord)
return pProto;
Next = Next->Flink;
}
return (AddProtoProcess(pFile, pProcess));
}
BOOLEAN
AddProcess(
ULONG ProcessId,
PPROCESS_RECORD *ReturnedProcess
)
{
PPROCESS_RECORD Process;
PMODULE_RECORD pModule = NULL;
Process = malloc(sizeof(PROCESS_RECORD));
if (Process == NULL) {
return FALSE;
}
InitProcessRecord( Process );
Process->PID = ProcessId;
if (!AddModuleRecord(& pModule, 0, 0, L"other")) {
free(Process);
return FALSE;
}
pModule->pProcess = Process;
EnterTracelibCritSection();
InsertHeadList( &CurrentSystem.ProcessListHead, &Process->Entry );
InsertHeadList(& Process->ModuleListHead, & pModule->Entry);
LeaveTracelibCritSection();
*ReturnedProcess = Process;
return TRUE;
}
BOOLEAN
DeleteProcess(
PPROCESS_RECORD Process
)
{
PLIST_ENTRY Next, Head;
PTHREAD_RECORD Thread;
PTDISK_RECORD Disk;
PFILE_RECORD pFile;
PMODULE_RECORD pModule;
PHPF_RECORD pHPFRecord;
if (Process == NULL)
return FALSE;
EnterTracelibCritSection();
RemoveEntryList( &Process->Entry );
LeaveTracelibCritSection();
Head = &Process->ThreadListHead;
Next = Head->Flink;
while (Next != Head) {
Thread = CONTAINING_RECORD( Next, THREAD_RECORD, Entry );
Next = Next->Flink;
DeleteThread( Thread );
}
Head = &Process->DiskListHead;
Next = Head->Flink;
while (Next != Head) {
Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
Next = Next->Flink;
DeleteDisk( Disk );
}
Head = &Process->HPFListHead;
Next = Head->Flink;
while (Next != Head) {
pHPFRecord = CONTAINING_RECORD(Next, HPF_RECORD, Entry);
Next = Next->Flink;
DeleteHPFRecord(pHPFRecord);
}
Head = &Process->FileListHead;
Next = Head->Flink;
while (Next != Head) {
pFile = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
Next = Next->Flink;
RemoveEntryList( &pFile->Entry );
if (pFile->FileName != NULL)
free(pFile->FileName);
free(pFile);
}
Head = &Process->ModuleListHead;
Next = Head->Flink;
while (Next != Head)
{
pModule = CONTAINING_RECORD(Next, MODULE_RECORD, Entry);
Next = Next->Flink;
RemoveEntryList(& pModule->Entry);
if(pModule->strModuleName)
{
free(pModule->strModuleName);
}
free(pModule);
}
if (Process->ImageName != NULL)
free(Process->ImageName);
if (Process->UserName != NULL)
free(Process->UserName);
free( Process );
return TRUE;
}
BOOLEAN
AddThread(
ULONG ThreadId,
PEVENT_TRACE pEvent,
PTHREAD_RECORD * ResultThread
)
{
PTHREAD_RECORD Thread;
PEVENT_TRACE_HEADER pHeader = (PEVENT_TRACE_HEADER) & pEvent->Header;
int i;
Thread = malloc(sizeof(THREAD_RECORD));
if (Thread == NULL)
{
return FALSE;
}
InitThreadRecord(Thread);
Thread->TimeStart = Thread->TimeEnd
= (ULONGLONG) pHeader->TimeStamp.QuadPart;
Thread->TID = ThreadId;
Thread->ProcessorID = pEvent->ClientContext & 0x000000FF;
i = (int)Thread->TID;
i = i % THREAD_HASH_TABLESIZE;
InsertHeadList(&CurrentSystem.ThreadHashList[i], &Thread->Entry);
*ResultThread = Thread;
return TRUE;
}
BOOLEAN
DeleteThread(
PTHREAD_RECORD Thread
)
{
PLIST_ENTRY pHead;
PLIST_ENTRY pNext;
PHPF_FILE_RECORD pHPFFileRecord;
if (Thread == NULL)
return FALSE;
RemoveEntryList( &Thread->Entry );
DeleteTransList( &Thread->TransListHead, 0 );
pHead = & Thread->HPFReadListHead;
pNext = pHead->Flink;
while (pNext != pHead)
{
pHPFFileRecord = CONTAINING_RECORD(pNext, HPF_FILE_RECORD, Entry);
pNext = pNext->Flink;
RemoveEntryList(& pHPFFileRecord->Entry);
free(pHPFFileRecord);
}
pHead = & Thread->HPFWriteListHead;
pNext = pHead->Flink;
while (pNext != pHead)
{
pHPFFileRecord = CONTAINING_RECORD(pNext, HPF_FILE_RECORD, Entry);
pNext = pNext->Flink;
RemoveEntryList(& pHPFFileRecord->Entry);
free(pHPFFileRecord);
}
free( Thread );
return TRUE;
}
PTRANS_RECORD
FindTransByList(
PLIST_ENTRY Head,
LPGUID pGuid,
ULONG level
)
{
PLIST_ENTRY Next;
PTRANS_RECORD pTrans = NULL;
// Recursively look for the list that does
// not contain a running guid
//
if (level <= MAX_TRANS_LEVEL && Head != NULL)
{
Next = Head->Flink;
while (Next != Head)
{
pTrans = CONTAINING_RECORD(Next, TRANS_RECORD, Entry);
if (pTrans->bStarted)
{
if ( (level == 0 || level == 1)
&& IsEqualGUID(pTrans->pGuid, pGuid))
{
return pTrans;
}
else if (level > 0)
{
return FindTransByList(& pTrans->SubTransListHead,
pGuid,
level - 1);
}
}
Next = Next->Flink;
}
}
// Found the correct list; now find
// the matching transaction
//
if (level == 0 && Head != NULL)
{
Next = Head->Flink;
while (Next != Head)
{
pTrans = CONTAINING_RECORD(Next, TRANS_RECORD, Entry);
if (IsEqualGUID( pTrans->pGuid, pGuid))
{
return pTrans;
}
Next = Next->Flink;
}
// If not Found, go ahead and add it.
//
pTrans = malloc(sizeof(TRANS_RECORD));
if (pTrans == NULL)
{
return NULL;
}
InitTransRecord(pTrans);
pTrans->pGuid = pGuid;
InsertHeadList( Head, &pTrans->Entry );
}
return pTrans;
}
PMOF_DATA
FindMofData(
PMOF_INFO pMofInfo,
PWCHAR strSortKey
)
{
PLIST_ENTRY Next;
PLIST_ENTRY Head;
PMOF_DATA pMofData = NULL;
if (pMofInfo == NULL) {
return NULL;
}
Head = &pMofInfo->DataListHead;
if (Head != NULL)
{
Next = Head->Flink;
while (Next != Head)
{
pMofData = CONTAINING_RECORD(Next, MOF_DATA, Entry);
if (strSortKey == NULL && pMofData->strSortKey == NULL)
{
return pMofData;
}
else if ( strSortKey != NULL
&& pMofData->strSortKey != NULL
&& !wcscmp(pMofData->strSortKey, strSortKey))
{
return pMofData;
}
Next = Next->Flink;
}
// If not Found, go ahead and add it.
//
pMofData = (PMOF_DATA)malloc(sizeof(MOF_DATA));
if (pMofData == NULL)
{
return NULL;
}
InitMofData(pMofData);
if (strSortKey != NULL)
{
pMofData->strSortKey =
(PWCHAR) malloc((lstrlenW(strSortKey) + 1) * sizeof(WCHAR));
if (pMofData->strSortKey != NULL) {
wcscpy(pMofData->strSortKey, strSortKey);
}
}
InsertHeadList(Head, &pMofData->Entry);
}
return pMofData;
}
BOOLEAN
DeleteTrans(
PTRANS_RECORD Trans
)
{
if (Trans == NULL)
return FALSE;
RemoveEntryList( &Trans->Entry );
free( Trans );
return TRUE;
}
BOOLEAN
DeleteTransList(
PLIST_ENTRY Head,
ULONG level
)
{
PLIST_ENTRY Next;
PTRANS_RECORD pTrans;
if( Head == NULL || level > MAX_TRANS_LEVEL )
return FALSE;
Next = Head->Flink;
while(Next != Head){
pTrans = CONTAINING_RECORD( Next, TRANS_RECORD, Entry );
Next = Next->Flink;
DeleteTransList( &pTrans->SubTransListHead, level+1);
DeleteTrans( pTrans );
}
return TRUE;
}
PPROCESS_RECORD
FindProcessById(
ULONG Id,
BOOLEAN CheckAlive
)
{
PLIST_ENTRY Next, Head;
PPROCESS_RECORD Process=NULL;
EnterTracelibCritSection();
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
Process = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
if (Process->PID == Id) {
LeaveTracelibCritSection();
if ((Process->DeadFlag) && (CheckAlive))
return NULL;
else
return Process;
}
Next = Next->Flink;
}
LeaveTracelibCritSection();
return NULL;
}
PTHREAD_RECORD
FindGlobalThreadById(
ULONG ThreadId,
PEVENT_TRACE pEvent
)
{
PLIST_ENTRY Next,
Head;
PTHREAD_RECORD Thread;
PEVENT_TRACE_HEADER pHeader = (PEVENT_TRACE_HEADER) & pEvent->Header;
int i = (int)ThreadId;
i = i % THREAD_HASH_TABLESIZE;
Head = &CurrentSystem.ThreadHashList[i];
Next = Head->Flink;
while (Next != Head)
{
Thread = CONTAINING_RECORD(Next, THREAD_RECORD, Entry);
Next = Next->Flink;
if (Thread->TID == ThreadId)
{
if (ThreadId == 0)
{
ULONG ProcessorId = pEvent->ClientContext & 0x000000FF;
if (ProcessorId != Thread->ProcessorID)
{
continue;
}
}
if (!Thread->DeadFlag)
{
return Thread;
}
else if ( Thread->TimeEnd
== (ULONGLONG) pHeader->TimeStamp.QuadPart)
{
return Thread;
}
else
{
// The alive thead must be at the head of the list
// otherwise bail
//
return NULL;
}
}
}
return NULL;
}
PWORKLOAD_RECORD
FindWorkloadById(
ULONG Id
)
{
PLIST_ENTRY Next, Head;
PWORKLOAD_RECORD Workload = NULL;
Head = &CurrentSystem.WorkloadListHead;
Next = Head->Flink;
while (Next != Head) {
Workload = CONTAINING_RECORD( Next, WORKLOAD_RECORD, Entry );
if (Workload->ClassNumber == Id) {
return Workload;
}
Next = Next->Flink;
}
return NULL;
}
BOOLEAN
AddDisk(
ULONG DiskNumber,
PTDISK_RECORD *ReturnedDisk
)
{
PTDISK_RECORD Disk;
Disk = malloc(sizeof(TDISK_RECORD));
if (Disk == NULL) {
return FALSE;
}
InitDiskRecord(Disk, DiskNumber);
Disk->DiskNumber = DiskNumber;
InsertHeadList( &CurrentSystem.GlobalDiskListHead, &Disk->Entry );
*ReturnedDisk = Disk;
return TRUE;
}
BOOLEAN
DeleteDisk(
PTDISK_RECORD Disk
)
{
PLIST_ENTRY Head, Next;
PPROCESS_RECORD Process;
PFILE_RECORD File;
if (Disk == NULL)
return FALSE;
RemoveEntryList( &Disk->Entry );
if (Disk->DiskName != NULL)
free(Disk->DiskName);
Head = &Disk->ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
Process = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
Next = Next->Flink;
DeleteProcess( Process );
}
Head = &Disk->FileListHead;
Next = Head->Flink;
while (Next != Head) {
File = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
Next = Next->Flink;
DeleteFileRecord( File );
}
free( Disk );
return TRUE;
}
PTDISK_RECORD
FindLocalDiskById(
PLIST_ENTRY Head,
ULONG Id
)
{
PLIST_ENTRY Next;
PTDISK_RECORD Disk = NULL;
if (Head == NULL)
return NULL;
Next = Head->Flink;
while (Next != Head) {
Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
if (Disk->DiskNumber == Id) {
return Disk;
}
Next = Next->Flink;
}
// If not Found, go ahead and add it.
//
Disk = malloc(sizeof(TDISK_RECORD));
if (Disk == NULL) {
return FALSE;
}
InitDiskRecord(Disk, Id);
Disk->DiskNumber = Id;
InsertHeadList( Head, &Disk->Entry );
return Disk;
}
PTDISK_RECORD
FindProcessDiskById(
PPROCESS_RECORD pProcess,
ULONG Id
)
{
PLIST_ENTRY Next, Head;
PTDISK_RECORD Disk = NULL;
if (pProcess == NULL)
return NULL;
Head = &pProcess->DiskListHead;
Next = Head->Flink;
while (Next != Head) {
Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
if (Disk->DiskNumber == Id) {
return Disk;
}
Next = Next->Flink;
}
// If not Found, go ahead and add it.
//
Disk = malloc(sizeof(TDISK_RECORD));
if (Disk == NULL) {
return FALSE;
}
InitDiskRecord(Disk, Id);
Disk->DiskNumber = Id;
InsertHeadList( &pProcess->DiskListHead, &Disk->Entry );
return Disk;
}
PPROCESS_RECORD
FindDiskProcessById(
PTDISK_RECORD pDisk,
ULONG Id
)
{
PLIST_ENTRY Next, Head;
PPROCESS_RECORD Process = NULL;
PPROCESS_RECORD gProcess = NULL;
if (pDisk == NULL)
return NULL;
Head = &pDisk->ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
Process = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
if (Process->PID == Id) {
return Process;
}
Next = Next->Flink;
}
// If not Found, go ahead and add it.
//
Process = malloc(sizeof(PROCESS_RECORD));
if (Process == NULL) {
return FALSE;
}
InitProcessRecord(Process);
Process->PID = Id;
// Find the global Process Record and copy the UserName and Image.
//
gProcess = FindProcessById(Id, FALSE);
if (gProcess != NULL) {
if ( ! IsEmpty( gProcess->UserName ) ) {
ASSIGN_STRING( Process->UserName, gProcess->UserName );
if( NULL == Process->UserName ) {
free(Process);
return NULL;
}
}
if (! IsEmpty( gProcess->ImageName ) ) {
ASSIGN_STRING( Process->ImageName, gProcess->ImageName );
if (Process->UserName == NULL) {
free(Process);
return NULL;
}
}
}
InsertHeadList( &pDisk->ProcessListHead, &Process->Entry );
return Process;
}
PTDISK_RECORD
FindGlobalDiskById(
ULONG Id
)
{
PLIST_ENTRY Next, Head;
PTDISK_RECORD Disk = NULL;
Head = &CurrentSystem.GlobalDiskListHead;
Next = Head->Flink;
while (Next != Head) {
Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
if (Disk->DiskNumber == Id) {
return Disk;
}
Next = Next->Flink;
}
return NULL;
}
VOID
DeleteMofVersion(
PMOF_VERSION pMofVersion,
FILE* file
)
{
PLIST_ENTRY Next, Head;
PITEM_DESC pMofItem;
//
// Traverse through the MOF_VERSION list and
// delete each one
//
if (pMofVersion == NULL)
return;
if( NULL != file ){
fwprintf( file, L" %s (Type:%d Level:%d Version:%d)\n",
pMofVersion->strType ? pMofVersion->strType : L"Default",
pMofVersion->TypeIndex,
pMofVersion->Level,
pMofVersion->Version
);
}
Head = &pMofVersion->ItemHeader;
Next = Head->Flink;
while (Head != Next) {
pMofItem = CONTAINING_RECORD(Next, ITEM_DESC, Entry);
Next = Next->Flink;
RemoveEntryList( &pMofItem->Entry );
if (pMofItem->strDescription != NULL){
if( NULL != file ){
fwprintf( file, L" %s\n",
pMofItem->strDescription
);
}
free (pMofItem->strDescription);
}
free (pMofItem);
}
}
VOID
DeleteMofInfo(
PMOF_INFO pMofInfo,
FILE* f
)
{
PLIST_ENTRY Next, Head;
PMOF_VERSION pMofVersion;
//
// Traverse through the MOF_VERSION list and
// delete each one
//
if (pMofInfo == NULL){
return;
}
if( NULL != f ){
WCHAR buffer[MAXSTR];
fwprintf( f, L"%s\n",
pMofInfo->strDescription ? pMofInfo->strDescription : CpdiGuidToString( buffer, &pMofInfo->Guid ) );
}
Head = &pMofInfo->VersionHeader;
Next = Head->Flink;
while (Head != Next) {
pMofVersion = CONTAINING_RECORD(Next, MOF_VERSION, Entry);
Next = Next->Flink;
RemoveEntryList( &pMofVersion->Entry );
DeleteMofVersion( pMofVersion, f );
}
//
// Delete any strings allocated for this structure
//
if (pMofInfo->strDescription){
free(pMofInfo->strDescription);
}
//
// Finally delete the object
//
free(pMofInfo);
}
VOID
Cleanup()
{
PTDISK_RECORD Disk;
PTHREAD_RECORD Thread;
PPROCESS_RECORD Process;
PFILE_RECORD FileRec;
PWORKLOAD_RECORD pWorkload;
PMODULE_RECORD pModule;
PMOF_INFO pMofInfo;
PJOB_RECORD pJob;
PLIST_ENTRY Next, Head;
PLIST_ENTRY EventListHead;
FILE* f = NULL;
// Clean up the Global Disk List for now.
//
EventListHead = &CurrentSystem.EventListHead;
Head = EventListHead;
Next = Head->Flink;
if( (TraceContext->Flags & TRACE_INTERPRET) && NULL != TraceContext->CompFileName ){
f = _wfopen( TraceContext->CompFileName, L"w" );
}
while (Head != Next) {
pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
Next = Next->Flink;
RemoveEntryList( &pMofInfo->Entry );
DeleteMofInfo(pMofInfo, f);
}
if( NULL != f ){
fclose( f );
f = NULL;
}
Head = &CurrentSystem.GlobalDiskListHead;
Next = Head->Flink;
while (Next != Head) {
Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
Next = Next->Flink;
DeleteDisk( Disk );
}
// Clean up the Global Thread List for now.
//
Head = &CurrentSystem.GlobalThreadListHead;
Next = Head->Flink;
while (Next != Head) {
Thread = CONTAINING_RECORD( Next, THREAD_RECORD, Entry );
Next = Next->Flink;
DeleteThread( Thread );
}
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
Process = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
Next = Next->Flink;
DeleteProcess( Process );
}
Head = &CurrentSystem.GlobalModuleListHead;
Next = Head->Flink;
while (Next != Head)
{
pModule = CONTAINING_RECORD(Next, MODULE_RECORD, Entry);
Next = Next->Flink;
RemoveEntryList(& pModule->Entry);
if(pModule->strModuleName)
{
free(pModule->strModuleName);
}
free(pModule);
}
Head = &CurrentSystem.HotFileListHead;
Next = Head->Flink;
while (Next != Head) {
FileRec = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
Next = Next->Flink;
DeleteFileRecord( FileRec );
}
// Cleanup workload structures
//
Head = &CurrentSystem.WorkloadListHead;
Next = Head->Flink;
while (Next != Head) {
pWorkload = CONTAINING_RECORD( Next, WORKLOAD_RECORD, Entry );
Next = Next->Flink;
DeleteWorkloadRecord( pWorkload );
}
//
// Cleanup the Job List structures
//
Head = &CurrentSystem.JobListHead;
Next = Head->Flink;
while (Next != Head) {
pJob = CONTAINING_RECORD( Next, JOB_RECORD, Entry );
Next = Next->Flink;
DeleteJobRecord (pJob, FALSE);
}
}
BOOLEAN
AddFile(
WCHAR* fileName,
PFILE_RECORD *ReturnedFile
)
{
PFILE_RECORD fileRec;
if (fileName == NULL)
return FALSE;
fileRec = malloc(sizeof(FILE_RECORD));
if (fileRec == NULL) {
return FALSE;
}
InitFileRecord( fileRec );
fileRec->FileName = malloc( (lstrlenW(fileName)+ 1) * sizeof(WCHAR));
if (fileRec->FileName != NULL) {
wcscpy(fileRec->FileName, fileName);
}
EnterTracelibCritSection();
InsertHeadList( &CurrentSystem.HotFileListHead, &fileRec->Entry );
LeaveTracelibCritSection();
*ReturnedFile = fileRec;
return TRUE;
}
BOOLEAN
DeleteFileRecord(
PFILE_RECORD fileRec
)
{
PLIST_ENTRY Next, Head;
PPROTO_PROCESS_RECORD pProto;
if (fileRec == NULL)
return FALSE;
EnterTracelibCritSection();
RemoveEntryList( &fileRec->Entry );
LeaveTracelibCritSection();
if (fileRec->FileName != NULL)
free(fileRec->FileName);
Head = &fileRec->ProtoProcessListHead;
Next = Head->Flink;
while (Head != Next) {
pProto = CONTAINING_RECORD( Next, PROTO_PROCESS_RECORD, Entry);
Next = Next->Flink;
RemoveEntryList( &pProto->Entry );
free(pProto);
}
free( fileRec );
return TRUE;
}
PFILE_RECORD
FindFileRecordByName(
WCHAR* fileName
)
{
PLIST_ENTRY Next, Head;
PFILE_RECORD fileRec = NULL;
if (fileName == NULL)
return NULL;
EnterTracelibCritSection();
Head = &CurrentSystem.HotFileListHead;
Next = Head->Flink;
while (Next != Head) {
fileRec = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
if (!wcscmp(fileName, fileRec->FileName)) {
LeaveTracelibCritSection();
return fileRec;
}
Next = Next->Flink;
}
LeaveTracelibCritSection();
return NULL;
}
PFILE_RECORD
FindFileInProcess(
PPROCESS_RECORD pProcess,
WCHAR* fileName
)
{
PLIST_ENTRY Next, Head;
PFILE_RECORD fileRec = NULL;
if (pProcess == NULL || fileName == NULL)
return NULL;
EnterTracelibCritSection();
Head = &pProcess->FileListHead;
Next = Head->Flink;
while (Next != Head) {
fileRec = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
if (!wcscmp(fileName, fileRec->FileName)) {
//ReleaseMutex(CurrentSystem.HotFileListMutex);
LeaveTracelibCritSection();
return fileRec;
}
Next = Next->Flink;
}
LeaveTracelibCritSection();
return NULL;
}
VOID
AssignClass(
PPROCESS_RECORD pProcess,
PTHREAD_RECORD pThread
)
{
UNREFERENCED_PARAMETER(pProcess);
pThread->ClassNumber = 1; // For the Time being make it single class.
}
VOID
Classify()
{
// Assign Class to each Thread or Process.
//
PLIST_ENTRY Head, Next;
PTHREAD_RECORD pThread;
Head = &CurrentSystem.GlobalThreadListHead;
Next = Head->Flink;
while (Next != Head) {
pThread = CONTAINING_RECORD( Next, THREAD_RECORD, Entry );
AssignClass(NULL, pThread);
Aggregate(pThread);
Next = Next->Flink;
}
}
// Given the number of classes this routine
// creates and initializes the workload object
//
VOID
InitClass()
{
PWORKLOAD_RECORD pWorkload;
ULONG nclass;
ULONG i;
// Create the Class records here.
//
nclass = 1;
CurrentSystem.NumberOfWorkloads = 1;
for (i = 1; i <= nclass; i++) {
pWorkload = malloc(sizeof(WORKLOAD_RECORD));
if (pWorkload == NULL) {
return;
}
InitWorkloadRecord( pWorkload );
pWorkload->ClassNumber = i;
InsertHeadList( &CurrentSystem.WorkloadListHead, &pWorkload->Entry );
}
}
PTDISK_RECORD
FindDiskInList(
IN PLIST_ENTRY Head,
IN ULONG Id
)
{
PLIST_ENTRY Next;
PTDISK_RECORD pDisk = NULL;
if (Head != NULL) {
Next = Head->Flink;
while (Next != Head) {
pDisk = CONTAINING_RECORD ( Next, TDISK_RECORD, Entry );
if (pDisk->DiskNumber == Id) {
return pDisk;
}
Next = Next->Flink;
}
pDisk = malloc(sizeof(TDISK_RECORD));
if (pDisk == NULL) {
return NULL;
}
InitDiskRecord( pDisk, Id );
InsertHeadList( Head, &pDisk->Entry );
}
return pDisk;
}
VOID
Aggregate(
IN PTHREAD_RECORD pThread
)
{
PWORKLOAD_RECORD pWorkload;
PTDISK_RECORD pDisk, pClassDisk;
PLIST_ENTRY Next, Head;
// Aggregate the metrics over each class.
//
if ((pWorkload = FindWorkloadById(pThread->ClassNumber)) != NULL) {
pWorkload->UserCPU += (pThread->UCPUEnd - pThread->UCPUStart)
* CurrentSystem.TimerResolution;
pWorkload->KernelCPU += (pThread->KCPUEnd - pThread->KCPUStart)
* CurrentSystem.TimerResolution;
//
// Walk through the Thread Disk records and aggregate them
// to the class
Head = &pThread->DiskListHead;
Next = Head->Flink;
while (Next != Head) {
pDisk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
Next = Next->Flink;
pClassDisk = FindDiskInList(&pWorkload->DiskListHead,
pDisk->DiskNumber) ;
if (pClassDisk != NULL) {
pClassDisk->ReadCount += pDisk->ReadCount;
pClassDisk->WriteCount += pDisk->WriteCount;
pClassDisk->ReadSize += (pDisk->ReadCount * pDisk->ReadSize);
pClassDisk->WriteSize += (pDisk->WriteCount * pDisk->WriteSize);
pWorkload->ReadCount += pDisk->ReadCount;
}
}
}
}
ULONGLONG
CalculateProcessLifeTime(
PPROCESS_RECORD pProcess
)
{
BOOLEAN fFirst = TRUE;
ULONGLONG TimeStart = 0;
ULONGLONG TimeEnd = 0;
PLIST_ENTRY pHead = &pProcess->ThreadListHead;
PLIST_ENTRY pNext = pHead->Flink;
PTHREAD_RECORD pThread;
while (pNext != pHead)
{
pThread = CONTAINING_RECORD(pNext, THREAD_RECORD, Entry);
pNext = pNext->Flink;
if (fFirst)
{
TimeStart = pThread->TimeStart;
TimeEnd = pThread->TimeEnd;
fFirst = FALSE;
}
else if (pThread->TimeStart < TimeStart)
{
TimeStart = pThread->TimeStart;
}
else if (pThread->TimeEnd > TimeEnd)
{
TimeEnd = pThread->TimeEnd;
}
}
return (TimeEnd - TimeStart);
}
ULONG
CalculateProcessKCPU(
PPROCESS_RECORD pProcess
)
{
ULONG KCPUTotal = 0;
ULONG KCPUMissing = 0;
PLIST_ENTRY pHead = &pProcess->ThreadListHead;
PLIST_ENTRY pNext = pHead->Flink;
PTHREAD_RECORD pThread;
while (pNext != pHead)
{
pThread = CONTAINING_RECORD(pNext, THREAD_RECORD, Entry);
pNext = pNext->Flink;
if (pThread->KCPUEnd > pThread->KCPUStart)
{
if ((pProcess->PID != 0) ||
((pProcess->PID == 0) && (pThread->TID == 0)) ){
KCPUTotal += pThread->KCPUEnd - pThread->KCPUStart;
}
else {
KCPUMissing += pThread->KCPUEnd - pThread->KCPUStart;
}
}
}
return (ULONG) (KCPUTotal * CurrentSystem.TimerResolution);
}
ULONG
CalculateProcessUCPU(
PPROCESS_RECORD pProcess
)
{
ULONG UCPUTotal = 0;
ULONG UCPUMissing = 0;
PLIST_ENTRY pHead = &pProcess->ThreadListHead;
PLIST_ENTRY pNext = pHead->Flink;
PTHREAD_RECORD pThread;
while (pNext != pHead)
{
pThread = CONTAINING_RECORD(pNext, THREAD_RECORD, Entry);
pNext = pNext->Flink;
if (pThread->UCPUEnd > pThread->UCPUStart)
{
if ((pProcess->PID != 0) ||
((pProcess->PID == 0) && (pThread->TID == 0)) ) {
UCPUTotal += pThread->UCPUEnd - pThread->UCPUStart;
}
else {
UCPUMissing += pThread->UCPUEnd - pThread->UCPUStart;
}
}
}
return (ULONG) (UCPUTotal * CurrentSystem.TimerResolution);
}
PJOB_RECORD FindJobRecord(
ULONG JobId
)
{
PLIST_ENTRY Head, Next;
PJOB_RECORD pJob;
EnterTracelibCritSection();
Head = &CurrentSystem.JobListHead;
Next = Head->Flink;
while (Next != Head) {
pJob = CONTAINING_RECORD ( Next, JOB_RECORD, Entry );
if (pJob->JobId == JobId) {
LeaveTracelibCritSection();
return pJob;
}
Next = Next->Flink;
}
LeaveTracelibCritSection();
return NULL;
}
//
// A New Job with a JobId has been found. This routine will create a
// new job record to track it through various threads in the system
//
PJOB_RECORD
AddJobRecord(
ULONG JobId
)
{
PJOB_RECORD pJob;
pJob = malloc(sizeof(JOB_RECORD));
if (pJob == NULL) {
SetLastError( ERROR_OUTOFMEMORY);
return NULL;
}
RtlZeroMemory(pJob, sizeof(JOB_RECORD));
pJob->JobId = JobId;
EnterTracelibCritSection();
InsertHeadList( &CurrentSystem.JobListHead, &pJob->Entry );
LeaveTracelibCritSection();
return pJob;
}
//
// Deletes a Job record with the JobId. Before deleting the contents
// of the job record is dumped to a temp file for later reporting.
//
ULONG
DeleteJobRecord(
PJOB_RECORD pJob,
ULONG bSave
)
{
if (pJob == NULL)
return ERROR_INVALID_PARAMETER;
//
// Print the Contents of pJob to file.
//
// If the -spooler option isn't given to the reducer this fprintf causes the
// program to crash. Maybe TRACE_SPOOLER should alway be set.
if (CurrentSystem.TempFile != NULL) {
fprintf(CurrentSystem.TempFile, "%d, %d, %d, %d, %I64u, %I64u, %I64u, %I64u, %d, %d, %d, %d, %d, %hd, %d, %hd, %hd, %hd, %hd, %hd, %hd, %d\n",
pJob->JobId, pJob->KCPUTime, pJob->UCPUTime, pJob->ReadIO, pJob->StartTime, pJob->EndTime,
(pJob->ResponseTime - pJob->PauseTime), pJob->PrintJobTime, pJob->WriteIO,
pJob->DataType, pJob->JobSize, pJob->Pages, pJob->PagesPerSide,
pJob->FilesOpened, pJob->GdiJobSize, pJob->Color, pJob->XRes, pJob->YRes,
pJob->Quality, pJob->Copies, pJob->TTOption,
pJob->NumberOfThreads);
}
EnterTracelibCritSection();
RemoveEntryList( &pJob->Entry );
LeaveTracelibCritSection();
free (pJob);
return ERROR_SUCCESS;
}