|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
ready.c
Abstract:
WinDbg Extension Api
Author:
Ramon J San Andres (ramonsa) 8-Nov-1993
Environment:
User Mode.
Revision History: Jamie Hankins (a-jamhan) 20-Oct-1997 Added CheckControlC to loop.
--*/
#include "precomp.h"
#pragma hdrstop
HRESULT DumpReadyList( ULONG dwProcessor, ULONG Flags ) /*++
Routine Description:
Arguments:
args -
Return Value:
None
--*/
{
ULONG64 DispatcherReadyListHead; ULONG HighestProcessor; LONG i; ULONG Index; ULONG ListEntrySize; ULONG MaximumProcessors; ULONG64 MemoryAddress; ULONG64 ProcessorBlock[64]; ULONG PtrSize = DBG_PTR_SIZE; ULONG ReadyListHeadOffset; ULONG result; BOOLEAN ThreadDumped = FALSE; ULONG WaitListOpffset;
//
// Get number of processors.
//
MaximumProcessors = GetByteValue("nt!KeNumberProcessors");
//
// Get address of processor block array and read entire array.
//
MemoryAddress = GetExpression("nt!KiProcessorBlock"); if (MemoryAddress == 0) { dprintf("Unable to read processor block array\n"); return E_INVALIDARG; }
HighestProcessor = 0; for (Index = 0; Index < MaximumProcessors; Index += 1) { if (!ReadPointer(MemoryAddress + Index * PtrSize, &ProcessorBlock[Index])) { dprintf("Unable to read processor block array\n"); return E_INVALIDARG; }
if (ProcessorBlock[Index] != 0) { HighestProcessor = Index; } }
//
// Get ready list head offset.
//
if (GetFieldOffset("nt!_KPRCB", "DispatcherReadyListHead", &ReadyListHeadOffset)) { dprintf("Unable to read KPRCB.DispatcherReadyListHead offset.\n"); return E_INVALIDARG; }
//
// Scan the ready list for each processor.
//
for (Index = 0; Index <= HighestProcessor; Index += 1) { DispatcherReadyListHead = ProcessorBlock[Index]; if ( DispatcherReadyListHead ) { DispatcherReadyListHead += ReadyListHeadOffset;
ListEntrySize = GetTypeSize("nt!_LIST_ENTRY"); if (ListEntrySize == 0) { ListEntrySize = DBG_PTR_SIZE * 2; } GetFieldOffset("nt!_ETHREAD", "Tcb.WaitListEntry", &WaitListOpffset); for (i = MAXIMUM_PRIORITY-1; i >= 0 ; i -= 1 ) { ULONG64 Flink, Blink; if ( GetFieldValue( DispatcherReadyListHead + i*ListEntrySize, "nt!_LIST_ENTRY", "Flink", Flink) ) { dprintf( "Could not read contents of DispatcherReadyListHead at %08p [%ld]\n", (DispatcherReadyListHead + i * ListEntrySize), i); return E_INVALIDARG; } if (Flink != DispatcherReadyListHead+i*ListEntrySize) { ULONG64 ThreadEntry, ThreadFlink; dprintf("Ready Threads at priority %ld on processor %d\n", i, Index); for (ThreadEntry = Flink ; ThreadEntry != DispatcherReadyListHead+i*ListEntrySize ; ThreadEntry = ThreadFlink ) { ULONG64 ThreadBaseAddress = (ThreadEntry - WaitListOpffset); if ( GetFieldValue( ThreadBaseAddress, "nt!_ETHREAD", "Tcb.WaitListEntry.Flink", ThreadFlink) ) { dprintf("Could not read contents of thread %p\n", ThreadBaseAddress); } if(CheckControlC()) { return E_INVALIDARG; } DumpThread(dwProcessor," ", ThreadBaseAddress, Flags); ThreadDumped = TRUE; } } else { GetFieldValue( DispatcherReadyListHead + i*ListEntrySize, "nt!_LIST_ENTRY", "Blink", Blink); if (Flink != Blink) { dprintf("Ready linked list may to be corrupt...\n"); } } } if (!ThreadDumped) { dprintf("No threads in READY state\n"); }
} else { dprintf("Could not determine address of DispatcherReadyListHead\n"); return E_INVALIDARG; } }
return S_OK; }
HRESULT DumpReadyList_3598( ULONG dwProcessor, ULONG Flags )
/*++
Routine Description:
Arguments:
args -
Return Value:
None
--*/
{ ULONG64 KiDispatcherReadyListHead; ULONG ListEntrySize, WaitListOpffset; ULONG result; LONG i; BOOLEAN ThreadDumped = FALSE;
KiDispatcherReadyListHead = GetExpression( "nt!KiDispatcherReadyListHead" ); if ( KiDispatcherReadyListHead ) {
ListEntrySize = GetTypeSize("nt!_LIST_ENTRY"); if (ListEntrySize == 0) { ListEntrySize = DBG_PTR_SIZE * 2; } GetFieldOffset("nt!_ETHREAD", "Tcb.WaitListEntry", &WaitListOpffset);
for (i = MAXIMUM_PRIORITY-1; i >= 0 ; i -= 1 ) { ULONG64 Flink, Blink;
if ( GetFieldValue( KiDispatcherReadyListHead + i*ListEntrySize, "nt!_LIST_ENTRY", "Flink", Flink) ) { dprintf( "Could not read contents of KiDispatcherReadyListHead at %08p [%ld]\n", (KiDispatcherReadyListHead + i * ListEntrySize), i ); return E_INVALIDARG; }
if (Flink != KiDispatcherReadyListHead+i*ListEntrySize) { ULONG64 ThreadEntry, ThreadFlink;
dprintf("Ready Threads at priority %ld\n", i);
for (ThreadEntry = Flink ; ThreadEntry != KiDispatcherReadyListHead+i*ListEntrySize ; ThreadEntry = ThreadFlink ) { ULONG64 ThreadBaseAddress = (ThreadEntry - WaitListOpffset);
if ( GetFieldValue( ThreadBaseAddress, "nt!_ETHREAD", "Tcb.WaitListEntry.Flink", ThreadFlink) ) { dprintf("Could not read contents of thread %p\n", ThreadBaseAddress); }
if(CheckControlC()) { return E_INVALIDARG; }
DumpThread(dwProcessor," ", ThreadBaseAddress, Flags); ThreadDumped = TRUE;
} } else { GetFieldValue( KiDispatcherReadyListHead + i*ListEntrySize, "nt!_LIST_ENTRY", "Blink", Blink); if (Flink != Blink) { dprintf("Ready linked list may to be corrupt...\n"); } } }
if (!ThreadDumped) { dprintf("No threads in READY state\n"); } } else { dprintf("Could not determine address of KiDispatcherReadyListHead\n"); return E_INVALIDARG; } return S_OK; }
DECLARE_API( ready )
/*++
Routine Description:
Arguments:
args -
Return Value:
None
--*/
{
DWORD Flags; ULONG dwProcessor=0;
INIT_API(); GetCurrentProcessor(Client, &dwProcessor, NULL);
Flags = (ULONG)GetExpression(args); if (BuildNo <= 3598) { DumpReadyList_3598(dwProcessor, Flags); } else { DumpReadyList(dwProcessor, Flags); }
EXIT_API(); return S_OK; }
|