diff --git a/reactos/ntoskrnl/ex/init.c b/reactos/ntoskrnl/ex/init.c index 76449f777cb..66e8938ed03 100644 --- a/reactos/ntoskrnl/ex/init.c +++ b/reactos/ntoskrnl/ex/init.c @@ -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; diff --git a/reactos/ntoskrnl/ex/sysinfo.c b/reactos/ntoskrnl/ex/sysinfo.c index 3165f1ec7b5..770cae38ee5 100644 --- a/reactos/ntoskrnl/ex/sysinfo.c +++ b/reactos/ntoskrnl/ex/sysinfo.c @@ -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; diff --git a/reactos/ntoskrnl/include/internal/i386/ke.h b/reactos/ntoskrnl/include/internal/i386/ke.h index ed6c4897b32..0612a21e5a4 100644 --- a/reactos/ntoskrnl/include/internal/i386/ke.h +++ b/reactos/ntoskrnl/include/internal/i386/ke.h @@ -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 ; " diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h index 7c52b79451b..2a68a836d7c 100644 --- a/reactos/ntoskrnl/include/internal/ps.h +++ b/reactos/ntoskrnl/include/internal/ps.h @@ -437,8 +437,6 @@ struct _EPROCESS */ MADDRESS_SPACE AddressSpace; LIST_ENTRY ProcessListEntry; - PVOID TebBlock; - PVOID TebLastAllocated; }; #define PROCESS_STATE_TERMINATED (1) diff --git a/reactos/ntoskrnl/ke/i386/kernel.c b/reactos/ntoskrnl/ke/i386/kernel.c index 1d07b534158..f92a4fa2bfd 100644 --- a/reactos/ntoskrnl/ke/i386/kernel.c +++ b/reactos/ntoskrnl/ke/i386/kernel.c @@ -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) { diff --git a/reactos/ntoskrnl/ke/kthread.c b/reactos/ntoskrnl/ke/kthread.c index 5a950e90977..913d62b53e9 100644 --- a/reactos/ntoskrnl/ke/kthread.c +++ b/reactos/ntoskrnl/ke/kthread.c @@ -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) diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/main.c index ac9528b6ab4..000cd14960c 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/main.c @@ -109,7 +109,7 @@ KiSystemStartup(BOOLEAN BootProcessor) } else { /* Do application processor initialization */ - PsApplicationProcessorInit(); + KeApplicationProcessorInitDispatcher(); /* Lower IRQL and go to Idle Thread */ KeLowerIrql(PASSIVE_LEVEL); diff --git a/reactos/ntoskrnl/mm/process.c b/reactos/ntoskrnl/mm/process.c index 0e8c19247fd..f5ddc7a9abb 100644 --- a/reactos/ntoskrnl/mm/process.c +++ b/reactos/ntoskrnl/mm/process.c @@ -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 diff --git a/reactos/ntoskrnl/ps/kill.c b/reactos/ntoskrnl/ps/kill.c index 37b1c405b21..0c3392c18ba 100644 --- a/reactos/ntoskrnl/ps/kill.c +++ b/reactos/ntoskrnl/ps/kill.c @@ -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; } diff --git a/reactos/ntoskrnl/ps/notify.c b/reactos/ntoskrnl/ps/notify.c index 2bccc23ab75..2622610be0a 100644 --- a/reactos/ntoskrnl/ps/notify.c +++ b/reactos/ntoskrnl/ps/notify.c @@ -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) + { + 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 */ diff --git a/reactos/ntoskrnl/ps/psmgr.c b/reactos/ntoskrnl/ps/psmgr.c index 7adcef1f0b2..e7853a25e9a 100644 --- a/reactos/ntoskrnl/ps/psmgr.c +++ b/reactos/ntoskrnl/ps/psmgr.c @@ -15,15 +15,26 @@ #include 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) diff --git a/reactos/ntoskrnl/ps/thread.c b/reactos/ntoskrnl/ps/thread.c index b2a69f9be3d..828e3d1fc21 100644 --- a/reactos/ntoskrnl/ps/thread.c +++ b/reactos/ntoskrnl/ps/thread.c @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ps/thread.c @@ -9,14 +8,6 @@ * Phillip Susi */ -/* - * NOTE: - * - * All of the routines that manipulate the thread queue synchronize on - * a single spinlock - * - */ - /* INCLUDES ****************************************************************/ #include @@ -30,402 +21,30 @@ extern PEPROCESS PsIdleProcess; POBJECT_TYPE EXPORTED PsThreadType = NULL; -extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS]; -extern ULONG IdleProcessorMask; -extern LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY]; - - -BOOLEAN DoneInitYet = FALSE; -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}; +PTEB +STDCALL +MmCreateTeb(PEPROCESS Process, + PCLIENT_ID ClientId, + PINITIAL_TEB InitialTeb); /* FUNCTIONS ***************************************************************/ -#ifdef KeGetCurrentThread -#undef KeGetCurrentThread -#endif -/* - * @implemented - */ -PKTHREAD -STDCALL -KeGetCurrentThread(VOID) +VOID STDCALL +LdrInitApcRundownRoutine ( PKAPC Apc ) { -#ifdef CONFIG_SMP - ULONG Flags; - PKTHREAD Thread; - Ke386SaveFlags(Flags); - Ke386DisableInterrupts(); - Thread = KeGetCurrentPrcb()->CurrentThread; - Ke386RestoreFlags(Flags); - return Thread; -#else - return(KeGetCurrentPrcb()->CurrentThread); -#endif + ExFreePool(Apc); } -/* - * @implemented - */ -HANDLE STDCALL PsGetCurrentThreadId(VOID) + +VOID STDCALL +LdrInitApcKernelRoutine ( + PKAPC Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArgument2) { - return(PsGetCurrentThread()->Cid.UniqueThread); -} - -/* - * @implemented - */ -ULONG -STDCALL -PsGetThreadFreezeCount( - PETHREAD Thread - ) -{ - return Thread->Tcb.FreezeCount; -} - -/* - * @implemented - */ -BOOLEAN -STDCALL -PsGetThreadHardErrorsAreDisabled( - PETHREAD Thread - ) -{ - return Thread->HardErrorsAreDisabled; -} - -/* - * @implemented - */ -HANDLE -STDCALL -PsGetThreadId( - PETHREAD Thread - ) -{ - return Thread->Cid.UniqueThread; -} - -/* - * @implemented - */ -PEPROCESS -STDCALL -PsGetThreadProcess( - PETHREAD Thread - ) -{ - return Thread->ThreadsProcess; -} - -/* - * @implemented - */ -HANDLE -STDCALL -PsGetThreadProcessId( - PETHREAD Thread - ) -{ - return Thread->Cid.UniqueProcess; -} - -/* - * @implemented - */ -HANDLE -STDCALL -PsGetThreadSessionId( - PETHREAD Thread - ) -{ - return (HANDLE)Thread->ThreadsProcess->SessionId; -} - -/* - * @implemented - */ -PTEB -STDCALL -PsGetThreadTeb( - PETHREAD Thread - ) -{ - return Thread->Tcb.Teb; -} - -/* - * @implemented - */ -PVOID -STDCALL -PsGetThreadWin32Thread( - PETHREAD Thread - ) -{ - return Thread->Tcb.Win32Thread; -} - -/* - * @implemented - */ -KPROCESSOR_MODE -STDCALL -PsGetCurrentThreadPreviousMode ( - VOID - ) -{ - return (KPROCESSOR_MODE)PsGetCurrentThread()->Tcb.PreviousMode; -} - -/* - * @implemented - */ -PVOID -STDCALL -PsGetCurrentThreadStackBase ( - VOID - ) -{ - return PsGetCurrentThread()->Tcb.StackBase; -} - -/* - * @implemented - */ -PVOID -STDCALL -PsGetCurrentThreadStackLimit ( - VOID - ) -{ - return (PVOID)PsGetCurrentThread()->Tcb.StackLimit; -} - -/* - * @implemented - */ -BOOLEAN STDCALL -PsIsThreadTerminating(IN PETHREAD Thread) -{ - return (Thread->HasTerminated ? TRUE : FALSE); -} - -/* - * @implemented - */ -BOOLEAN -STDCALL -PsIsSystemThread(PETHREAD Thread) -{ - return (Thread->SystemThread ? TRUE: FALSE); -} - -/* - * @implemented - */ -BOOLEAN -STDCALL -PsIsThreadImpersonating( - PETHREAD Thread - ) -{ - return Thread->ActiveImpersonationInfo; -} - -VOID PsDumpThreads(BOOLEAN IncludeSystem) -{ - PLIST_ENTRY AThread, AProcess; - PEPROCESS Process; - PETHREAD Thread; - ULONG nThreads = 0; - - AProcess = PsActiveProcessHead.Flink; - while(AProcess != &PsActiveProcessHead) - { - Process = CONTAINING_RECORD(AProcess, EPROCESS, ProcessListEntry); - /* FIXME - skip suspended, ... processes? */ - if((Process != PsInitialSystemProcess) || - (Process == PsInitialSystemProcess && IncludeSystem)) - { - AThread = Process->ThreadListHead.Flink; - while(AThread != &Process->ThreadListHead) - { - Thread = CONTAINING_RECORD(AThread, ETHREAD, ThreadListEntry); - - nThreads++; - DbgPrint("Thread->Tcb.State %d Affinity %08x Priority %d PID.TID %d.%d Name %.8s Stack: \n", - Thread->Tcb.State, - Thread->Tcb.Affinity, - Thread->Tcb.Priority, - Thread->ThreadsProcess->UniqueProcessId, - Thread->Cid.UniqueThread, - Thread->ThreadsProcess->ImageFileName); - if(Thread->Tcb.State == THREAD_STATE_READY || - Thread->Tcb.State == THREAD_STATE_SUSPENDED || - Thread->Tcb.State == THREAD_STATE_BLOCKED) - { - ULONG i = 0; - PULONG Esp = (PULONG)Thread->Tcb.KernelStack; - PULONG Ebp = (PULONG)Esp[4]; - DbgPrint("Ebp 0x%.8X\n", Ebp); - while(Ebp != 0 && Ebp >= (PULONG)Thread->Tcb.StackLimit) - { - DbgPrint("%.8X %.8X%s", Ebp[0], Ebp[1], (i % 8) == 7 ? "\n" : " "); - Ebp = (PULONG)Ebp[0]; - i++; - } - if((i % 8) != 0) - { - DbgPrint("\n"); - } - } - AThread = AThread->Flink; - } - } - AProcess = AProcess->Flink; - } -} - -VOID -PsFreezeAllThreads(PEPROCESS Process) - /* - * Used by the debugging code to freeze all the process's threads - * while the debugger is examining their state. - */ -{ - KIRQL oldIrql; - PLIST_ENTRY current_entry; - PETHREAD current; - - oldIrql = KeAcquireDispatcherDatabaseLock(); - current_entry = Process->ThreadListHead.Flink; - while (current_entry != &Process->ThreadListHead) - { - current = CONTAINING_RECORD(current_entry, ETHREAD, - ThreadListEntry); - - /* - * We have to be careful here, we can't just set the freeze the - * thread inside kernel mode since it may be holding a lock. - */ - - current_entry = current_entry->Flink; - } - - KeReleaseDispatcherDatabaseLock(oldIrql); -} - -ULONG -PsEnumThreadsByProcess(PEPROCESS Process) -{ - KIRQL oldIrql; - PLIST_ENTRY current_entry; - ULONG Count = 0; - - oldIrql = KeAcquireDispatcherDatabaseLock(); - - current_entry = Process->ThreadListHead.Flink; - while (current_entry != &Process->ThreadListHead) - { - Count++; - current_entry = current_entry->Flink; - } - - KeReleaseDispatcherDatabaseLock(oldIrql); - return Count; -} - -/* - * @unimplemented - */ -NTSTATUS -STDCALL -PsRemoveCreateThreadNotifyRoutine ( - IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine - ) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -/* - * @unimplemented - */ -ULONG -STDCALL -PsSetLegoNotifyRoutine( - PVOID LegoNotifyRoutine - ) -{ - UNIMPLEMENTED; - return 0; -} - -/* - * @implemented - */ -VOID -STDCALL -PsSetThreadHardErrorsAreDisabled( - PETHREAD Thread, - BOOLEAN HardErrorsAreDisabled - ) -{ - Thread->HardErrorsAreDisabled = HardErrorsAreDisabled; -} - -/* - * @implemented - */ -VOID -STDCALL -PsSetThreadWin32Thread( - PETHREAD Thread, - PVOID Win32Thread - ) -{ - Thread->Tcb.Win32Thread = Win32Thread; -} - -VOID -PsApplicationProcessorInit(VOID) -{ - KIRQL oldIrql; - oldIrql = KeAcquireDispatcherDatabaseLock(); - IdleProcessorMask |= (1 << KeGetCurrentProcessorNumber()); - KeReleaseDispatcherDatabaseLock(oldIrql); -} - -VOID INIT_FUNCTION -PsPrepareForApplicationProcessorInit(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); + ExFreePool(Apc); } VOID @@ -517,176 +136,325 @@ PsInitializeThread ( return STATUS_SUCCESS; } - -static NTSTATUS -PsCreateTeb ( - HANDLE ProcessHandle, - PTEB *TebPtr, - PETHREAD Thread, - PINITIAL_TEB InitialTeb ) +VOID PsDumpThreads(BOOLEAN IncludeSystem) { - PEPROCESS Process; + PLIST_ENTRY AThread, AProcess; + PEPROCESS Process; + PETHREAD Thread; + ULONG nThreads = 0; + + AProcess = PsActiveProcessHead.Flink; + while(AProcess != &PsActiveProcessHead) + { + Process = CONTAINING_RECORD(AProcess, EPROCESS, ProcessListEntry); + /* FIXME - skip suspended, ... processes? */ + if((Process != PsInitialSystemProcess) || + (Process == PsInitialSystemProcess && IncludeSystem)) + { + AThread = Process->ThreadListHead.Flink; + while(AThread != &Process->ThreadListHead) + { + Thread = CONTAINING_RECORD(AThread, ETHREAD, ThreadListEntry); + + nThreads++; + DbgPrint("Thread->Tcb.State %d Affinity %08x Priority %d PID.TID %d.%d Name %.8s Stack: \n", + Thread->Tcb.State, + Thread->Tcb.Affinity, + Thread->Tcb.Priority, + Thread->ThreadsProcess->UniqueProcessId, + Thread->Cid.UniqueThread, + Thread->ThreadsProcess->ImageFileName); + if(Thread->Tcb.State == THREAD_STATE_READY || + Thread->Tcb.State == THREAD_STATE_SUSPENDED || + Thread->Tcb.State == THREAD_STATE_BLOCKED) + { + ULONG i = 0; + PULONG Esp = (PULONG)Thread->Tcb.KernelStack; + PULONG Ebp = (PULONG)Esp[4]; + DbgPrint("Ebp 0x%.8X\n", Ebp); + while(Ebp != 0 && Ebp >= (PULONG)Thread->Tcb.StackLimit) + { + DbgPrint("%.8X %.8X%s", Ebp[0], Ebp[1], (i % 8) == 7 ? "\n" : " "); + Ebp = (PULONG)Ebp[0]; + i++; + } + if((i % 8) != 0) + { + DbgPrint("\n"); + } + } + AThread = AThread->Flink; + } + } + AProcess = AProcess->Flink; + } +} + +/* + * @implemented + */ +HANDLE +STDCALL +PsGetCurrentThreadId(VOID) +{ + return(PsGetCurrentThread()->Cid.UniqueThread); +} + +/* + * @implemented + */ +ULONG +STDCALL +PsGetThreadFreezeCount(PETHREAD Thread) +{ + return Thread->Tcb.FreezeCount; +} + +/* + * @implemented + */ +BOOLEAN +STDCALL +PsGetThreadHardErrorsAreDisabled(PETHREAD Thread) +{ + return Thread->HardErrorsAreDisabled; +} + +/* + * @implemented + */ +HANDLE +STDCALL +PsGetThreadId(PETHREAD Thread) +{ + return Thread->Cid.UniqueThread; +} + +/* + * @implemented + */ +PEPROCESS +STDCALL +PsGetThreadProcess(PETHREAD Thread) +{ + return Thread->ThreadsProcess; +} + +/* + * @implemented + */ +HANDLE +STDCALL +PsGetThreadProcessId(PETHREAD Thread) +{ + return Thread->Cid.UniqueProcess; +} + +/* + * @implemented + */ +HANDLE +STDCALL +PsGetThreadSessionId(PETHREAD Thread) +{ + return (HANDLE)Thread->ThreadsProcess->SessionId; +} + +/* + * @implemented + */ +PTEB +STDCALL +PsGetThreadTeb(PETHREAD Thread) +{ + return Thread->Tcb.Teb; +} + +/* + * @implemented + */ +PVOID +STDCALL +PsGetThreadWin32Thread(PETHREAD Thread) +{ + return Thread->Tcb.Win32Thread; +} + +/* + * @implemented + */ +KPROCESSOR_MODE +STDCALL +PsGetCurrentThreadPreviousMode(VOID) +{ + return (KPROCESSOR_MODE)PsGetCurrentThread()->Tcb.PreviousMode; +} + +/* + * @implemented + */ +PVOID +STDCALL +PsGetCurrentThreadStackBase(VOID) +{ + return PsGetCurrentThread()->Tcb.StackBase; +} + +/* + * @implemented + */ +PVOID +STDCALL +PsGetCurrentThreadStackLimit(VOID) +{ + return (PVOID)PsGetCurrentThread()->Tcb.StackLimit; +} + +/* + * @implemented + */ +BOOLEAN +STDCALL +PsIsThreadTerminating(IN PETHREAD Thread) +{ + return (Thread->HasTerminated ? TRUE : FALSE); +} + +/* + * @implemented + */ +BOOLEAN +STDCALL +PsIsSystemThread(PETHREAD Thread) +{ + return (Thread->SystemThread ? TRUE: FALSE); +} + +/* + * @implemented + */ +BOOLEAN +STDCALL +PsIsThreadImpersonating(PETHREAD Thread) +{ + return Thread->ActiveImpersonationInfo; +} + +/* + * @implemented + */ +VOID +STDCALL +PsSetThreadHardErrorsAreDisabled(PETHREAD Thread, + BOOLEAN HardErrorsAreDisabled) +{ + Thread->HardErrorsAreDisabled = HardErrorsAreDisabled; +} + +/* + * @implemented + */ +VOID +STDCALL +PsSetThreadWin32Thread(PETHREAD Thread, + PVOID Win32Thread) +{ + Thread->Tcb.Win32Thread = Win32Thread; +} + +/* + * @implemented + */ +NTSTATUS STDCALL +PsCreateSystemThread ( + PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID ClientId, + PKSTART_ROUTINE StartRoutine, + PVOID StartContext ) +/* + * FUNCTION: Creates a thread which executes in kernel mode + * ARGUMENTS: + * ThreadHandle (OUT) = Caller supplied storage for the returned thread + * handle + * DesiredAccess = Requested access to the thread + * ObjectAttributes = Object attributes (optional) + * ProcessHandle = Handle of process thread will run in + * NULL to use system process + * ClientId (OUT) = Caller supplied storage for the returned client id + * of the thread (optional) + * StartRoutine = Entry point for the thread + * StartContext = Argument supplied to the thread when it begins + * execution + * RETURNS: Success or failure status + */ +{ + PETHREAD Thread; NTSTATUS Status; - ULONG ByteCount; - ULONG RegionSize; - ULONG TebSize; - PVOID TebBase; - TEB Teb; + KIRQL oldIrql; PAGED_CODE(); - TebSize = PAGE_SIZE; - - if (NULL == Thread->ThreadsProcess) - { - /* We'll be allocating a 64k block here and only use 4k of it, but this - path should almost never be taken. Actually, I never saw it was taken, - so maybe we should just ASSERT(NULL != Thread->ThreadsProcess) and - move on */ - TebBase = NULL; - Status = ZwAllocateVirtualMemory(ProcessHandle, - &TebBase, - 0, - &TebSize, - MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, - PAGE_READWRITE); - if (! NT_SUCCESS(Status)) - { - DPRINT1("Failed to allocate virtual memory for TEB\n"); - return Status; - } - } - else - { - Process = Thread->ThreadsProcess; - PsLockProcess(Process, FALSE); - if (NULL == Process->TebBlock || - Process->TebBlock == Process->TebLastAllocated) - { - Process->TebBlock = NULL; - RegionSize = MM_VIRTMEM_GRANULARITY; - Status = ZwAllocateVirtualMemory(ProcessHandle, - &Process->TebBlock, - 0, - &RegionSize, - MEM_RESERVE | MEM_TOP_DOWN, - PAGE_READWRITE); - if (! NT_SUCCESS(Status)) - { - PsUnlockProcess(Process); - DPRINT1("Failed to reserve virtual memory for TEB\n"); - return Status; - } - Process->TebLastAllocated = (PVOID) ((char *) Process->TebBlock + RegionSize); - } - TebBase = (PVOID) ((char *) Process->TebLastAllocated - PAGE_SIZE); - Status = ZwAllocateVirtualMemory(ProcessHandle, - &TebBase, - 0, - &TebSize, - MEM_COMMIT, - PAGE_READWRITE); - if (! NT_SUCCESS(Status)) - { - DPRINT1("Failed to commit virtual memory for TEB\n"); - return Status; - } - Process->TebLastAllocated = TebBase; - PsUnlockProcess(Process); - } - - DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize); - ASSERT(NULL != TebBase && PAGE_SIZE <= TebSize); - - RtlZeroMemory(&Teb, sizeof(TEB)); - /* set all pointers to and from the TEB */ - Teb.Tib.Self = TebBase; - if (Thread->ThreadsProcess) - { - Teb.Peb = Thread->ThreadsProcess->Peb; /* No PEB yet!! */ - } - DPRINT("Teb.Peb %x\n", Teb.Peb); - - /* 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; - } - } - - /* more initialization */ - Teb.Cid.UniqueThread = Thread->Cid.UniqueThread; - Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess; - Teb.CurrentLocale = PsDefaultThreadLocaleId; - - /* Terminate the exception handler list */ - Teb.Tib.ExceptionList = (PVOID)-1; - - DPRINT("sizeof(TEB) %x\n", sizeof(TEB)); - - /* write TEB data into teb page */ - Status = NtWriteVirtualMemory(ProcessHandle, - TebBase, - &Teb, - sizeof(TEB), - &ByteCount); + DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n", + ThreadHandle,ProcessHandle); + Status = PsInitializeThread( + NULL, + &Thread, + ObjectAttributes, + KernelMode, + FALSE); if (!NT_SUCCESS(Status)) { - /* free TEB */ - DPRINT1 ("Writing TEB failed!\n"); + return(Status); + } - RegionSize = 0; - NtFreeVirtualMemory(ProcessHandle, - TebBase, - &RegionSize, - MEM_RELEASE); + /* Set the thread as a system thread */ + Thread->SystemThread = TRUE; + Status = PsCreateCidHandle(Thread, + PsThreadType, + &Thread->Cid.UniqueThread); + if(!NT_SUCCESS(Status)) + { + ObDereferenceObject(Thread); return Status; } - if (TebPtr != NULL) + Thread->StartAddress = StartRoutine; + Status = KiArchInitThread ( + &Thread->Tcb, StartRoutine, StartContext); + if (!NT_SUCCESS(Status)) { - *TebPtr = (PTEB)TebBase; + ObDereferenceObject(Thread); + return(Status); } - DPRINT("TEB allocated at %p\n", TebBase); + if (ClientId != NULL) + { + *ClientId=Thread->Cid; + } + + oldIrql = KeAcquireDispatcherDatabaseLock (); + KiUnblockThread(&Thread->Tcb, NULL, 0); + KeReleaseDispatcherDatabaseLock(oldIrql); + + Status = ObInsertObject( + (PVOID)Thread, + NULL, + DesiredAccess, + 0, + NULL, + ThreadHandle); + + /* don't dereference the thread, the initial reference serves as the keep-alive + reference which will be removed by the thread reaper */ return Status; } - -VOID STDCALL -LdrInitApcRundownRoutine ( PKAPC Apc ) -{ - ExFreePool(Apc); -} - - -VOID STDCALL -LdrInitApcKernelRoutine ( - PKAPC Apc, - PKNORMAL_ROUTINE* NormalRoutine, - PVOID* NormalContext, - PVOID* SystemArgument1, - PVOID* SystemArgument2) -{ - ExFreePool(Apc); -} - - NTSTATUS STDCALL NtCreateThread ( OUT PHANDLE ThreadHandle, @@ -703,7 +471,6 @@ NtCreateThread ( INITIAL_TEB SafeInitialTeb; PEPROCESS Process; PETHREAD Thread; - PTEB TebBase; PKAPC LdrInitApc; KIRQL oldIrql; KPROCESSOR_MODE PreviousMode; @@ -814,17 +581,7 @@ NtCreateThread ( return(Status); } - Status = PsCreateTeb(ProcessHandle, - &TebBase, - Thread, - InitialTeb); - if (!NT_SUCCESS(Status)) - { - PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType); - ObDereferenceObject(Thread); - return(Status); - } - Thread->Tcb.Teb = TebBase; + Thread->Tcb.Teb = MmCreateTeb(Process, &Thread->Cid, InitialTeb); Thread->StartAddress = NULL; @@ -901,153 +658,6 @@ NtCreateThread ( return Status; } - -/* - * @implemented - */ -NTSTATUS STDCALL -PsCreateSystemThread ( - PHANDLE ThreadHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - HANDLE ProcessHandle, - PCLIENT_ID ClientId, - PKSTART_ROUTINE StartRoutine, - PVOID StartContext ) -/* - * FUNCTION: Creates a thread which executes in kernel mode - * ARGUMENTS: - * ThreadHandle (OUT) = Caller supplied storage for the returned thread - * handle - * DesiredAccess = Requested access to the thread - * ObjectAttributes = Object attributes (optional) - * ProcessHandle = Handle of process thread will run in - * NULL to use system process - * ClientId (OUT) = Caller supplied storage for the returned client id - * of the thread (optional) - * StartRoutine = Entry point for the thread - * StartContext = Argument supplied to the thread when it begins - * execution - * RETURNS: Success or failure status - */ -{ - PETHREAD Thread; - NTSTATUS Status; - KIRQL oldIrql; - - PAGED_CODE(); - - DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n", - ThreadHandle,ProcessHandle); - - Status = PsInitializeThread( - NULL, - &Thread, - ObjectAttributes, - KernelMode, - FALSE); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - /* Set the thread as a system thread */ - Thread->SystemThread = TRUE; - - Status = PsCreateCidHandle(Thread, - PsThreadType, - &Thread->Cid.UniqueThread); - if(!NT_SUCCESS(Status)) - { - ObDereferenceObject(Thread); - return Status; - } - - Thread->StartAddress = StartRoutine; - Status = KiArchInitThread ( - &Thread->Tcb, StartRoutine, StartContext); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(Thread); - return(Status); - } - - if (ClientId != NULL) - { - *ClientId=Thread->Cid; - } - - oldIrql = KeAcquireDispatcherDatabaseLock (); - KiUnblockThread(&Thread->Tcb, NULL, 0); - KeReleaseDispatcherDatabaseLock(oldIrql); - - Status = ObInsertObject( - (PVOID)Thread, - NULL, - DesiredAccess, - 0, - NULL, - ThreadHandle); - - /* don't dereference the thread, the initial reference serves as the keep-alive - reference which will be removed by the thread reaper */ - - return Status; -} - -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); -} - /********************************************************************** * NtOpenThread/4 * @@ -1154,7 +764,6 @@ NtYieldExecution(VOID) return(STATUS_SUCCESS); } - /* * NOT EXPORTED */ @@ -1165,30 +774,14 @@ NtTestAlert(VOID) return KeTestAlertThread(ExGetPreviousMode()) ? STATUS_ALERTED : STATUS_SUCCESS; } -VOID -KeSetPreviousMode (ULONG Mode) -{ - PsGetCurrentThread()->Tcb.PreviousMode = (UCHAR)Mode; -} - - /* * @implemented */ -KPROCESSOR_MODE STDCALL -KeGetPreviousMode (VOID) -{ - return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode; -} - - -/* - * @implemented - */ -KPROCESSOR_MODE STDCALL +KPROCESSOR_MODE +STDCALL ExGetPreviousMode (VOID) { - return (KPROCESSOR_MODE)PsGetCurrentThread()->Tcb.PreviousMode; + return (KPROCESSOR_MODE)PsGetCurrentThread()->Tcb.PreviousMode; } /* EOF */