Implement PsSetLegoNotifyRoutine and PsRemoveCreateThreadNotifyroutine. Clean up ps/thread.c, move things to their own subsystem, do proper TEB Allocation with MmCreateTeb, remove TEB EPROCESS hack fields. Rename PsFrezeAllThreads to KeFreezeAllThreads and implement a working version.

svn path=/trunk/; revision=14663
This commit is contained in:
Alex Ionescu 2005-04-18 04:46:06 +00:00
parent f4d2ac0b1e
commit 6829bd8c8b
12 changed files with 729 additions and 803 deletions

View file

@ -461,7 +461,7 @@ ExpInitializeExecutive(VOID)
/* Set up the Kernel and Process Manager for this CPU */
KePrepareForApplicationProcessorInit(KeNumberProcessors);
PsPrepareForApplicationProcessorInit(KeNumberProcessors);
KeCreateApplicationProcessorIdleThread(KeNumberProcessors);
/* Allocate a stack for use when booting the processor */
ProcessorStack = Ki386InitialStackArray[((int)KeNumberProcessors)] + MM_STACK_SIZE;

View file

@ -587,8 +587,13 @@ QSI_DEF(SystemProcessInformation)
SpiCur = (PSYSTEM_PROCESSES)pCur;
nThreads = PsEnumThreadsByProcess(pr);
current_entry = pr->ThreadListHead.Flink;
while (current_entry != &pr->ThreadListHead)
{
nThreads++;
current_entry = current_entry->Flink;
}
// size of the structure for every process
curSize = sizeof(SYSTEM_PROCESSES)-sizeof(SYSTEM_THREADS)+sizeof(SYSTEM_THREADS)*nThreads;
ovlSize += curSize+inLen;
@ -667,7 +672,7 @@ QSI_DEF(SystemProcessInformation)
}
pr = PsGetNextProcess(pr);
nThreads = 0;
if ((pr == syspr) || (pr == NULL))
{
SpiCur->NextEntryDelta = 0;

View file

@ -198,6 +198,10 @@ ULONG KeAllocateGdtSelector(ULONG Desc[2]);
VOID KeFreeGdtSelector(ULONG Entry);
VOID
NtEarlyInitVdm(VOID);
VOID
KeApplicationProcessorInitDispatcher(VOID);
VOID
KeCreateApplicationProcessorIdleThread(ULONG Id);
#ifdef CONFIG_SMP
#define LOCK "lock ; "

View file

@ -437,8 +437,6 @@ struct _EPROCESS
*/
MADDRESS_SPACE AddressSpace;
LIST_ENTRY ProcessListEntry;
PVOID TebBlock;
PVOID TebLastAllocated;
};
#define PROCESS_STATE_TERMINATED (1)

View file

@ -26,6 +26,8 @@ BOOLEAN Ke386NoExecute = FALSE;
BOOLEAN Ke386Pae = FALSE;
BOOLEAN Ke386GlobalPagesEnabled = FALSE;
ULONG KiFastSystemCallDisable = 1;
extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
extern ULONG IdleProcessorMask;
/* FUNCTIONS *****************************************************************/
@ -123,6 +125,42 @@ Ki386GetCpuId(VOID)
}
}
VOID
KeApplicationProcessorInitDispatcher(VOID)
{
KIRQL oldIrql;
oldIrql = KeAcquireDispatcherDatabaseLock();
IdleProcessorMask |= (1 << KeGetCurrentProcessorNumber());
KeReleaseDispatcherDatabaseLock(oldIrql);
}
VOID
INIT_FUNCTION
KeCreateApplicationProcessorIdleThread(ULONG Id)
{
PETHREAD IdleThread;
PKPRCB Prcb = ((PKPCR)((ULONG_PTR)KPCR_BASE + Id * PAGE_SIZE))->Prcb;
PsInitializeThread(PsIdleProcess,
&IdleThread,
NULL,
KernelMode,
FALSE);
IdleThread->Tcb.State = THREAD_STATE_RUNNING;
IdleThread->Tcb.FreezeCount = 0;
IdleThread->Tcb.Affinity = 1 << Id;
IdleThread->Tcb.UserAffinity = 1 << Id;
IdleThread->Tcb.Priority = LOW_PRIORITY;
IdleThread->Tcb.BasePriority = LOW_PRIORITY;
Prcb->IdleThread = &IdleThread->Tcb;
Prcb->CurrentThread = &IdleThread->Tcb;
Ki386InitialStackArray[Id] = (PVOID)IdleThread->Tcb.StackLimit;
DPRINT("IdleThread for Processor %d has PID %d\n",
Id, IdleThread->Cid.UniqueThread);
}
VOID INIT_FUNCTION
KePrepareForApplicationProcessorInit(ULONG Id)
{

View file

@ -342,6 +342,46 @@ KiSuspendThreadNormalRoutine(PVOID NormalContext,
DPRINT("Done Waiting\n");
}
#ifdef KeGetCurrentThread
#undef KeGetCurrentThread
#endif
/*
* @implemented
*/
PKTHREAD
STDCALL
KeGetCurrentThread(VOID)
{
#ifdef CONFIG_SMP
ULONG Flags;
PKTHREAD Thread;
Ke386SaveFlags(Flags);
Ke386DisableInterrupts();
Thread = KeGetCurrentPrcb()->CurrentThread;
Ke386RestoreFlags(Flags);
return Thread;
#else
return(KeGetCurrentPrcb()->CurrentThread);
#endif
}
VOID
STDCALL
KeSetPreviousMode(ULONG Mode)
{
PsGetCurrentThread()->Tcb.PreviousMode = (UCHAR)Mode;
}
/*
* @implemented
*/
KPROCESSOR_MODE
STDCALL
KeGetPreviousMode(VOID)
{
return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode;
}
VOID
STDCALL
KeRundownThread(VOID)
@ -422,7 +462,51 @@ BOOLEAN
STDCALL
KiInsertQueueApc(PKAPC Apc,
KPRIORITY PriorityBoost);
/*
* Used by the debugging code to freeze all the process's threads
* while the debugger is examining their state.
*/
VOID
STDCALL
KeFreezeAllThreads(PKPROCESS Process)
{
KIRQL OldIrql;
PLIST_ENTRY CurrentEntry;
PKTHREAD Current;
PKTHREAD CurrentThread = KeGetCurrentThread();
/* Acquire Lock */
OldIrql = KeAcquireDispatcherDatabaseLock();
/* Loop the Process's Threads */
CurrentEntry = Process->ThreadListHead.Flink;
while (CurrentEntry != &Process->ThreadListHead)
{
/* Get the Thread */
Current = CONTAINING_RECORD(CurrentEntry, KTHREAD, ThreadListEntry);
/* Make sure it's not ours */
if (Current == CurrentThread) continue;
/* Make sure it wasn't already frozen, and that it's not suspended */
if (!(++Current->FreezeCount) && !(Current->SuspendCount))
{
/* Insert the APC */
if (!KiInsertQueueApc(&Current->SuspendApc, IO_NO_INCREMENT))
{
/* Unsignal the Semaphore, the APC already got inserted */
Current->SuspendSemaphore.Header.SignalState--;
}
}
CurrentEntry = CurrentEntry->Flink;
}
/* Release the lock */
KeReleaseDispatcherDatabaseLock(OldIrql);
}
NTSTATUS
STDCALL
KeSuspendThread(PKTHREAD Thread)

View file

@ -109,7 +109,7 @@ KiSystemStartup(BOOLEAN BootProcessor)
} else {
/* Do application processor initialization */
PsApplicationProcessorInit();
KeApplicationProcessorInitDispatcher();
/* Lower IRQL and go to Idle Thread */
KeLowerIrql(PASSIVE_LEVEL);

View file

@ -16,6 +16,7 @@
extern ULONG NtMajorVersion;
extern ULONG NtMinorVersion;
extern ULONG NtOSCSDVersion;
/* FUNCTIONS *****************************************************************/
PVOID
@ -28,25 +29,33 @@ MiCreatePebOrTeb(PEPROCESS Process,
PMEMORY_AREA MemoryArea;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
BoundaryAddressMultiple.QuadPart = 0;
PVOID AllocatedBase = BaseAddress;
/* Acquire the Lock */
MmLockAddressSpace(ProcessAddressSpace);
/* Create a Peb or Teb */
Status = MmCreateMemoryArea(Process,
ProcessAddressSpace,
MEMORY_AREA_PEB_OR_TEB,
&BaseAddress,
PAGE_SIZE,
PAGE_READWRITE,
&MemoryArea,
FALSE,
FALSE,
BoundaryAddressMultiple);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to allocate PEB or TEB\n");
}
/*
* Create a Peb or Teb.
* Loop until it works, decreasing by PAGE_SIZE each time. The logic here
* is that a PEB allocation should never fail since the address is free,
* while TEB allocation can fail, and we should simply try the address
* below. Is there a nicer way of doing this automagically? (ie: findning)
* a gap region? -- Alex
*/
do {
DPRINT("Trying to allocate: %x\n", AllocatedBase);
Status = MmCreateMemoryArea(Process,
ProcessAddressSpace,
MEMORY_AREA_PEB_OR_TEB,
&AllocatedBase,
PAGE_SIZE,
PAGE_READWRITE,
&MemoryArea,
TRUE,
FALSE,
BoundaryAddressMultiple);
AllocatedBase = AllocatedBase - PAGE_SIZE;
} while (Status != STATUS_SUCCESS);
/* Initialize the Region */
MmInitialiseRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead,
@ -60,7 +69,7 @@ MiCreatePebOrTeb(PEPROCESS Process,
/* Unlock Address Space */
DPRINT("Returning\n");
MmUnlockAddressSpace(ProcessAddressSpace);
return BaseAddress;
return AllocatedBase + PAGE_SIZE;
}
VOID
@ -77,7 +86,7 @@ MiFreeStackPage(PVOID Context,
VOID
STDCALL
MmDeleteKernelStack(PVOID Stack,
MmDeleteKernelStack(PVOID Stack,
BOOLEAN GuiStack)
{
/* Lock the Address Space */
@ -93,6 +102,54 @@ MmDeleteKernelStack(PVOID Stack,
MmUnlockAddressSpace(MmGetKernelAddressSpace());
}
VOID
MiFreePebPage(PVOID Context,
MEMORY_AREA* MemoryArea,
PVOID Address,
PFN_TYPE Page,
SWAPENTRY SwapEntry,
BOOLEAN Dirty)
{
PEPROCESS Process = (PEPROCESS)Context;
if (Page != 0)
{
SWAPENTRY SavedSwapEntry;
SavedSwapEntry = MmGetSavedSwapEntryPage(Page);
if (SavedSwapEntry != 0)
{
MmFreeSwapPage(SavedSwapEntry);
MmSetSavedSwapEntryPage(Page, 0);
}
MmDeleteRmap(Page, Process, Address);
MmReleasePageMemoryConsumer(MC_USER, Page);
}
else if (SwapEntry != 0)
{
MmFreeSwapPage(SwapEntry);
}
}
VOID
STDCALL
MmDeleteTeb(PEPROCESS Process,
PTEB Teb)
{
PMADDRESS_SPACE ProcessAddressSpace = &Process->AddressSpace;
/* Lock the Address Space */
MmLockAddressSpace(ProcessAddressSpace);
/* Delete the Stack */
MmFreeMemoryAreaByPtr(ProcessAddressSpace,
Teb,
MiFreePebPage,
Process);
/* Unlock the Address Space */
MmUnlockAddressSpace(ProcessAddressSpace);
}
PVOID
STDCALL
MmCreateKernelStack(BOOLEAN GuiStack)
@ -218,11 +275,64 @@ MmCreatePeb(PEPROCESS Process)
return STATUS_SUCCESS;
}
VOID
PTEB
STDCALL
MmCreateTeb(VOID)
MmCreateTeb(PEPROCESS Process,
PCLIENT_ID ClientId,
PINITIAL_TEB InitialTeb)
{
PTEB Teb;
BOOLEAN Attached = FALSE;
/* Attach to the process */
DPRINT("MmCreateTeb\n");
if (Process != PsGetCurrentProcess())
{
/* Attach to Target */
KeAttachProcess(&Process->Pcb);
Attached = TRUE;
}
/* Allocate the TEB */
Teb = MiCreatePebOrTeb(Process, (PVOID)TEB_BASE);
/* Initialize the PEB */
RtlZeroMemory(Teb, sizeof(TEB));
/* Set TIB Data */
Teb->Tib.ExceptionList = (PVOID)0xFFFFFFFF;
Teb->Tib.Version = 1;
Teb->Tib.Self = (PNT_TIB)Teb;
/* Set TEB Data */
Teb->Cid = *ClientId;
Teb->RealClientId = *ClientId;
Teb->Peb = Process->Peb;
Teb->CurrentLocale = PsDefaultThreadLocaleId;
/* Store stack information from InitialTeb */
if(InitialTeb != NULL)
{
/* fixed-size stack */
if(InitialTeb->StackBase && InitialTeb->StackLimit)
{
Teb->Tib.StackBase = InitialTeb->StackBase;
Teb->Tib.StackLimit = InitialTeb->StackLimit;
Teb->DeallocationStack = InitialTeb->StackLimit;
}
/* expandable stack */
else
{
Teb->Tib.StackBase = InitialTeb->StackCommit;
Teb->Tib.StackLimit = InitialTeb->StackCommitMax;
Teb->DeallocationStack = InitialTeb->StackReserved;
}
}
/* Return TEB Address */
DPRINT("Allocated: %x\n", Teb);
if (Attached) KeDetachProcess();
return Teb;
}
NTSTATUS

View file

@ -24,6 +24,11 @@ BOOLEAN PspReaping = FALSE;
extern LIST_ENTRY PsActiveProcessHead;
extern FAST_MUTEX PspActiveProcessMutex;
VOID
STDCALL
MmDeleteTeb(PEPROCESS Process,
PTEB Teb);
/* FUNCTIONS *****************************************************************/
STDCALL
@ -204,9 +209,8 @@ PspExitThread(NTSTATUS ExitStatus)
PETHREAD CurrentThread;
BOOLEAN Last;
PEPROCESS CurrentProcess;
SIZE_T Length = PAGE_SIZE;
PVOID TebBlock;
PTERMINATION_PORT TerminationPort;
PTEB Teb;
DPRINT("PspExitThread(ExitStatus %x), Current: 0x%x\n", ExitStatus, PsGetCurrentThread());
@ -285,26 +289,10 @@ PspExitThread(NTSTATUS ExitStatus)
//CmNotifyRunDown(CurrentThread);
/* Free the TEB */
if(CurrentThread->Tcb.Teb) {
DPRINT("Decommit teb at %p\n", CurrentThread->Tcb.Teb);
TebBlock = MM_ROUND_DOWN(CurrentThread->Tcb.Teb, MM_VIRTMEM_GRANULARITY);
ZwFreeVirtualMemory(NtCurrentProcess(),
(PVOID *)&CurrentThread->Tcb.Teb,
&Length,
MEM_DECOMMIT);
DPRINT("teb %p, TebBlock %p\n", CurrentThread->Tcb.Teb, TebBlock);
if (TebBlock != CurrentProcess->TebBlock ||
CurrentProcess->TebBlock == CurrentProcess->TebLastAllocated) {
MmLockAddressSpace(&CurrentProcess->AddressSpace);
MmReleaseMemoryAreaIfDecommitted(CurrentProcess, &CurrentProcess->AddressSpace, TebBlock);
MmUnlockAddressSpace(&CurrentProcess->AddressSpace);
}
if((Teb = CurrentThread->Tcb.Teb)) {
DPRINT1("Decommit teb at %p\n", Teb);
MmDeleteTeb(CurrentProcess, Teb);
CurrentThread->Tcb.Teb = NULL;
}

View file

@ -18,9 +18,9 @@
#define MAX_THREAD_NOTIFY_ROUTINE_COUNT 8
#define TAG_KAPC TAG('k','p','a','p') /* kpap - kernel ps apc */
static ULONG PiThreadNotifyRoutineCount = 0;
static ULONG PspThreadNotifyRoutineCount = 0;
static PCREATE_THREAD_NOTIFY_ROUTINE
PiThreadNotifyRoutine[MAX_THREAD_NOTIFY_ROUTINE_COUNT];
PspThreadNotifyRoutine[MAX_THREAD_NOTIFY_ROUTINE_COUNT];
static PCREATE_PROCESS_NOTIFY_ROUTINE
PspProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
@ -28,6 +28,8 @@ PspProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
static PLOAD_IMAGE_NOTIFY_ROUTINE
PspLoadImageNotifyRoutine[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT];
static PVOID PspLegoNotifyRoutine;
/* FUNCTIONS ***************************************************************/
/*
@ -74,6 +76,20 @@ PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
return STATUS_INVALID_PARAMETER;
}
/*
* @implemented
*/
ULONG
STDCALL
PsSetLegoNotifyRoutine(PVOID LegoNotifyRoutine)
{
/* Set the System-Wide Lego Routine */
PspLegoNotifyRoutine = LegoNotifyRoutine;
/* Return the location to the Lego Data */
return FIELD_OFFSET(KTHREAD, LegoData);
}
/*
* @implemented
*/
@ -124,17 +140,60 @@ PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine)
return STATUS_INVALID_PARAMETER;
}
VOID STDCALL
PspRunCreateThreadNotifyRoutines (
PETHREAD CurrentThread,
BOOLEAN Create )
/*
* @implemented
*/
NTSTATUS
STDCALL
PsRemoveCreateThreadNotifyRoutine(IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine)
{
ULONG i;
/* Loop the routines */
for(i=0;i<MAX_THREAD_NOTIFY_ROUTINE_COUNT;i++)
{
/* Check for a match */
if ((PVOID)PspThreadNotifyRoutine[i] == (PVOID)NotifyRoutine)
{
/* Remove and return */
PspThreadNotifyRoutine[i] = NULL;
return(STATUS_SUCCESS);
}
}
/* Nothing found */
return STATUS_INVALID_PARAMETER;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
PsSetCreateThreadNotifyRoutine(IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine)
{
if (PspThreadNotifyRoutineCount >= MAX_THREAD_NOTIFY_ROUTINE_COUNT)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
PspThreadNotifyRoutine[PspThreadNotifyRoutineCount] = NotifyRoutine;
PspThreadNotifyRoutineCount++;
return(STATUS_SUCCESS);
}
VOID
STDCALL
PspRunCreateThreadNotifyRoutines(PETHREAD CurrentThread,
BOOLEAN Create)
{
ULONG i;
CLIENT_ID Cid = CurrentThread->Cid;
for (i = 0; i < PiThreadNotifyRoutineCount; i++)
for (i = 0; i < PspThreadNotifyRoutineCount; i++)
{
PiThreadNotifyRoutine[i](Cid.UniqueProcess, Cid.UniqueThread, Create);
PspThreadNotifyRoutine[i](Cid.UniqueProcess, Cid.UniqueThread, Create);
}
}
@ -173,22 +232,4 @@ PspRunLoadImageNotifyRoutines(PUNICODE_STRING FullImageName,
}
}
/*
* @implemented
*/
NTSTATUS STDCALL
PsSetCreateThreadNotifyRoutine (
IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine )
{
if (PiThreadNotifyRoutineCount >= MAX_THREAD_NOTIFY_ROUTINE_COUNT)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
PiThreadNotifyRoutine[PiThreadNotifyRoutineCount] = NotifyRoutine;
PiThreadNotifyRoutineCount++;
return(STATUS_SUCCESS);
}
/* EOF */

View file

@ -15,15 +15,26 @@
#include <internal/debug.h>
extern LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
extern LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY];
static GENERIC_MAPPING PiProcessMapping = {
STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
STANDARD_RIGHTS_WRITE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE |
PROCESS_TERMINATE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION | PROCESS_SET_PORT,
PROCESS_TERMINATE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION |
PROCESS_SET_PORT,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
PROCESS_ALL_ACCESS};
static GENERIC_MAPPING PiThreadMapping = {
STANDARD_RIGHTS_READ | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION,
STANDARD_RIGHTS_WRITE | THREAD_TERMINATE | THREAD_SUSPEND_RESUME |
THREAD_ALERT | THREAD_SET_INFORMATION | THREAD_SET_CONTEXT,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
THREAD_ALL_ACCESS};
BOOLEAN DoneInitYet = FALSE;
VOID
INIT_FUNCTION
PsInitClientIDManagment(VOID);
@ -48,6 +59,60 @@ PiInitProcessManager(VOID)
PsInitialiseW32Call();
}
VOID
INIT_FUNCTION
PsInitThreadManagment(VOID)
/*
* FUNCTION: Initialize thread managment
*/
{
PETHREAD FirstThread;
ULONG i;
for (i=0; i < MAXIMUM_PRIORITY; i++)
{
InitializeListHead(&PriorityListHead[i]);
}
PsThreadType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
PsThreadType->Tag = TAG('T', 'H', 'R', 'T');
PsThreadType->TotalObjects = 0;
PsThreadType->TotalHandles = 0;
PsThreadType->PeakObjects = 0;
PsThreadType->PeakHandles = 0;
PsThreadType->PagedPoolCharge = 0;
PsThreadType->NonpagedPoolCharge = sizeof(ETHREAD);
PsThreadType->Mapping = &PiThreadMapping;
PsThreadType->Dump = NULL;
PsThreadType->Open = NULL;
PsThreadType->Close = NULL;
PsThreadType->Delete = PspDeleteThread;
PsThreadType->Parse = NULL;
PsThreadType->Security = NULL;
PsThreadType->QueryName = NULL;
PsThreadType->OkayToClose = NULL;
PsThreadType->Create = NULL;
PsThreadType->DuplicationNotify = NULL;
RtlInitUnicodeString(&PsThreadType->TypeName, L"Thread");
ObpCreateTypeObject(PsThreadType);
PsInitializeThread(NULL, &FirstThread, NULL, KernelMode, TRUE);
FirstThread->Tcb.State = THREAD_STATE_RUNNING;
FirstThread->Tcb.FreezeCount = 0;
FirstThread->Tcb.UserAffinity = (1 << 0); /* Set the affinity of the first thread to the boot processor */
FirstThread->Tcb.Affinity = (1 << 0);
KeGetCurrentPrcb()->CurrentThread = (PVOID)FirstThread;
DPRINT("FirstThread %x\n",FirstThread);
DoneInitYet = TRUE;
ExInitializeWorkItem(&PspReaperWorkItem, PspReapRoutine, NULL);
}
VOID
INIT_FUNCTION
PsInitProcessManagment(VOID)

File diff suppressed because it is too large Load diff