Alex Ionescu ionucu@videotron.ca - Removed ke/alert.c and moved its functions where they belong. - Commented and organized KeInitializeThread. - Began switch to true KOBJECT enumeration used in NT. - Implemented KeAlertResumeThread and NtAlertResumeThread. - Harmonized Formatting in ke/kthread.c Modified: trunk/reactos/drivers/storage/floppy/floppy.c Modified: trunk/reactos/include/ddk/ketypes.h Modified: trunk/reactos/ntoskrnl/Makefile Modified: trunk/reactos/ntoskrnl/include/internal/ps.h Deleted: trunk/reactos/ntoskrnl/ke/alert.c Modified: trunk/reactos/ntoskrnl/ke/apc.c Modified: trunk/reactos/ntoskrnl/ke/dpc.c Modified: trunk/reactos/ntoskrnl/ke/kthread.c Modified: trunk/reactos/ntoskrnl/ke/wait.c Modified: trunk/reactos/ntoskrnl/ps/thread.c _____
Modified: trunk/reactos/drivers/storage/floppy/floppy.c --- trunk/reactos/drivers/storage/floppy/floppy.c 2005-03-12 19:22:30 UTC (rev 13973) +++ trunk/reactos/drivers/storage/floppy/floppy.c 2005-03-12 19:23:04 UTC (rev 13974) @@ -58,7 +58,7 @@
/* Queue thread management */ static KEVENT QueueThreadTerminate; -static PVOID ThreadObject; +static PVOID QueueThreadObject;
static VOID NTAPI MotorStopDpcFunc(PKDPC UnusedDpc, @@ -378,8 +378,8 @@ KdPrint(("floppy: unloading\n"));
KeSetEvent(&QueueThreadTerminate, 0, FALSE); - KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, 0); - ObDereferenceObject(ThreadObject); + KeWaitForSingleObject(QueueThreadObject, Executive, KernelMode, FALSE, 0); + ObDereferenceObject(QueueThreadObject);
for(i = 0; i < gNumberOfControllers; i++) { @@ -1152,7 +1152,7 @@ return STATUS_INSUFFICIENT_RESOURCES; }
- if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode, &ThreadObject, NULL) != STATUS_SUCCESS) + if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode, &QueueThreadObject, NULL) != STATUS_SUCCESS) { KdPrint(("floppy: Unable to reference returned thread handle; failing init\n")); return STATUS_UNSUCCESSFUL; _____
Modified: trunk/reactos/include/ddk/ketypes.h --- trunk/reactos/include/ddk/ketypes.h 2005-03-12 19:22:30 UTC (rev 13973) +++ trunk/reactos/include/ddk/ketypes.h 2005-03-12 19:23:04 UTC (rev 13974) @@ -36,23 +36,34 @@
struct _DISPATCHER_HEADER;
-typedef enum _KERNEL_OBJECTS { - KNotificationEvent = 0, - KSynchronizationEvent = 1, - KMutant = 2, - KProcess = 3, - KQueue = 4, - KSemaphore = 5, - KThread = 6, - KNotificationTimer = 8, - KSynchronizationTimer = 9, - KApc = 18, - KDpc = 19, - KDeviceQueue = 20, - KEventPair = 21, - KInterrupt = 22, - KProfile = 23 -} KERNEL_OBJECTS; +typedef enum _KOBJECTS { + EventNotificationObject = 0, + EventSynchronizationObject = 1, + MutantObject = 2, + ProcessObject = 3, + QueueObject = 4, + SemaphoreObject = 5, + ThreadObject = 6, + GateObject = 7, + TimerNotificationObject = 8, + TimerSynchronizationObject = 9, + Spare2Object = 10, + Spare3Object = 11, + Spare4Object = 12, + Spare5Object = 13, + Spare6Object = 14, + Spare7Object = 15, + Spare8Object = 16, + Spare9Object = 17, + ApcObject = 18, + DpcObject = 19, + DeviceQueueObject = 20, + EventPairObject = 21, + InterruptObject = 22, + ProfileObject = 23, + ThreadedDpcObject = 24, + MaximumKernelObject = 25 +} KOBJECTS;
#include <pshpack1.h>
_____
Modified: trunk/reactos/ntoskrnl/Makefile --- trunk/reactos/ntoskrnl/Makefile 2005-03-12 19:22:30 UTC (rev 13973) +++ trunk/reactos/ntoskrnl/Makefile 2005-03-12 19:23:04 UTC (rev 13974) @@ -113,8 +113,7 @@
ke/sem.o \ ke/spinlock.o \ ke/timer.o \ - ke/wait.o \ - ke/alert.o + ke/wait.o
# Memory Manager (Mm) OBJECTS_MM = \ _____
Modified: trunk/reactos/ntoskrnl/include/internal/ps.h --- trunk/reactos/ntoskrnl/include/internal/ps.h 2005-03-12 19:22:30 UTC (rev 13973) +++ trunk/reactos/ntoskrnl/include/internal/ps.h 2005-03-12 19:23:04 UTC (rev 13974) @@ -498,7 +498,7 @@
#define PROCESS_PRIO_RT 18
-VOID +VOID STDCALL KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First); NTSTATUS KeReleaseThread(PKTHREAD Thread);
_____
Deleted: trunk/reactos/ntoskrnl/ke/alert.c --- trunk/reactos/ntoskrnl/ke/alert.c 2005-03-12 19:22:30 UTC (rev 13973) +++ trunk/reactos/ntoskrnl/ke/alert.c 2005-03-12 19:23:04 UTC (rev 13974) @@ -1,150 +0,0 @@
-/* $Id:$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/alert.c - * PURPOSE: Alerts - * - * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - */ - -/* INCLUDES *****************************************************************/ - -#include <ntoskrnl.h> -#define NDEBUG -#include <internal/debug.h> - -/* GLOBALS *******************************************************************/ - - -/* FUNCTIONS *****************************************************************/ - - -BOOLEAN -STDCALL -KeTestAlertThread(IN KPROCESSOR_MODE AlertMode) -/* - * FUNCTION: Tests whether there are any pending APCs for the current thread - * and if so the APCs will be delivered on exit from kernel mode - */ -{ - KIRQL OldIrql; - PKTHREAD Thread = KeGetCurrentThread(); - BOOLEAN OldState; - - ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); - - OldIrql = KeAcquireDispatcherDatabaseLock(); - KiAcquireSpinLock(&Thread->ApcQueueLock); - - OldState = Thread->Alerted[AlertMode]; - - /* If the Thread is Alerted, Clear it */ - if (OldState) { - Thread->Alerted[AlertMode] = FALSE; - } else if ((AlertMode == UserMode) && (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode]))) { - /* If the mode is User and the Queue isn't empty, set Pending */ - Thread->ApcState.UserApcPending = TRUE; - } - - KiReleaseSpinLock(&Thread->ApcQueueLock); - KeReleaseDispatcherDatabaseLock(OldIrql); - return OldState; -} - - -VOID -KeAlertThread(PKTHREAD Thread, KPROCESSOR_MODE AlertMode) -{ - KIRQL oldIrql; - - - oldIrql = KeAcquireDispatcherDatabaseLock(); - - - /* Return if thread is already alerted. */ - if (Thread->Alerted[AlertMode] == FALSE) - { - if (Thread->State == THREAD_STATE_BLOCKED && - (AlertMode == KernelMode || Thread->WaitMode == AlertMode) && - Thread->Alertable) - { - KiAbortWaitThread(Thread, STATUS_ALERTED); - } - else - { - Thread->Alerted[AlertMode] = TRUE; - } - } - - KeReleaseDispatcherDatabaseLock(oldIrql); - -} - - -/* - * - * NOT EXPORTED - */ -NTSTATUS STDCALL -NtAlertResumeThread(IN HANDLE ThreadHandle, - OUT PULONG SuspendCount) -{ - UNIMPLEMENTED; - return(STATUS_NOT_IMPLEMENTED); - -} - -/* - * @implemented - * - * EXPORTED - */ -NTSTATUS STDCALL -NtAlertThread (IN HANDLE ThreadHandle) -{ - KPROCESSOR_MODE PreviousMode; - PETHREAD Thread; - NTSTATUS Status; - - PreviousMode = ExGetPreviousMode(); - - Status = ObReferenceObjectByHandle(ThreadHandle, - THREAD_SUSPEND_RESUME, - PsThreadType, - PreviousMode, - (PVOID*)&Thread, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - /* do an alert depending on the processor mode. If some kmode code wants to - enforce a umode alert it should call KeAlertThread() directly. If kmode - code wants to do a kmode alert it's sufficient to call it with Zw or just - use KeAlertThread() directly */ - - KeAlertThread(&Thread->Tcb, PreviousMode); - - ObDereferenceObject(Thread); - return(STATUS_SUCCESS); -} - - -/* - * NOT EXPORTED - */ -NTSTATUS -STDCALL -NtTestAlert(VOID) -{ - KPROCESSOR_MODE PreviousMode; - - PreviousMode = ExGetPreviousMode(); - - /* Check and Alert Thread if needed */ - - return KeTestAlertThread(PreviousMode) ? STATUS_ALERTED : STATUS_SUCCESS; -} - _____
Modified: trunk/reactos/ntoskrnl/ke/apc.c --- trunk/reactos/ntoskrnl/ke/apc.c 2005-03-12 19:22:30 UTC (rev 13973) +++ trunk/reactos/ntoskrnl/ke/apc.c 2005-03-12 19:23:04 UTC (rev 13974) @@ -58,7 +58,7 @@
/* Set up the basic APC Structure Data */ RtlZeroMemory(Apc, sizeof(KAPC)); - Apc->Type = KApc; + Apc->Type = ApcObject; Apc->Size = sizeof(KAPC); /* Set the Environment */ _____
Modified: trunk/reactos/ntoskrnl/ke/dpc.c --- trunk/reactos/ntoskrnl/ke/dpc.c 2005-03-12 19:22:30 UTC (rev 13973) +++ trunk/reactos/ntoskrnl/ke/dpc.c 2005-03-12 19:23:04 UTC (rev 13974) @@ -88,7 +88,7 @@
*/ { DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine); - Dpc->Type = KDpc; + Dpc->Type = DpcObject; Dpc->Number= 0; Dpc->Importance= MediumImportance; Dpc->DeferredRoutine = DeferredRoutine; _____
Modified: trunk/reactos/ntoskrnl/ke/kthread.c --- trunk/reactos/ntoskrnl/ke/kthread.c 2005-03-12 19:22:30 UTC (rev 13973) +++ trunk/reactos/ntoskrnl/ke/kthread.c 2005-03-12 19:23:04 UTC (rev 13974) @@ -1,11 +1,11 @@
-/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/kthread.c * PURPOSE: Microkernel thread support * - * PROGRAMMERS: David Welch (welch@cwcom.net) + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Commented, reorganized some stuff, fixed/implemented some functions. + * David Welch (welch@cwcom.net) */
/* INCLUDES *****************************************************************/ @@ -16,19 +16,93 @@
/* FUNCTIONS *****************************************************************/
-VOID -KiServiceCheck (VOID) +ULONG +STDCALL +KeAlertResumeThread(IN PKTHREAD Thread) { - PETHREAD Thread; + ULONG PreviousCount; + KIRQL OldIrql;
- Thread = PsGetCurrentThread(); + ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); + + /* Lock the Dispatcher Database and the APC Queue */ + OldIrql = KeAcquireDispatcherDatabaseLock(); + KiAcquireSpinLock(&Thread->ApcQueueLock);
- if (Thread->Tcb.ServiceTable != KeServiceDescriptorTableShadow) - { - PsInitWin32Thread (Thread); + /* Return if Thread is already alerted. */ + if (Thread->Alerted[KernelMode] == FALSE) { + + /* If it's Blocked, unblock if it we should */ + if (Thread->State == THREAD_STATE_BLOCKED && Thread->Alertable) { + + DPRINT("Aborting Wait\n"); + KiAbortWaitThread(Thread, STATUS_ALERTED); + + } else { + + /* If not, simply Alert it */ + Thread->Alerted[KernelMode] = TRUE; + } + } + + /* Save the old Suspend Count */ + PreviousCount = Thread->SuspendCount; + + /* If the thread is suspended, decrease one of the suspend counts */ + if (PreviousCount) { + + /* Decrease count. If we are now zero, unwait it completely */ + if (--Thread->SuspendCount) { + + /* Signal and satisfy */ + Thread->SuspendSemaphore.Header.SignalState++; + KiDispatcherObjectWake(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT); + } + }
- Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow; + /* Release Locks and return the Old State */ + KiReleaseSpinLock(&Thread->ApcQueueLock); + KeReleaseDispatcherDatabaseLock(OldIrql); + return PreviousCount; +} + +BOOLEAN +STDCALL +KeAlertThread(PKTHREAD Thread, + KPROCESSOR_MODE AlertMode) +{ + KIRQL OldIrql; + BOOLEAN PreviousState; + + /* Acquire the Dispatcher Database Lock */ + OldIrql = KeAcquireDispatcherDatabaseLock(); + + /* Save the Previous State */ + PreviousState = Thread->Alerted[AlertMode]; + + /* Return if Thread is already alerted. */ + if (PreviousState == FALSE) { + + /* If it's Blocked, unblock if it we should */ + if (Thread->State == THREAD_STATE_BLOCKED && + (AlertMode == KernelMode || Thread->WaitMode == AlertMode) && + Thread->Alertable) { + + DPRINT("Aborting Wait\n"); + KiAbortWaitThread(Thread, STATUS_ALERTED); + + } else { + + /* If not, simply Alert it */ + Thread->Alerted[AlertMode] = TRUE; + } } + + /* Release the Dispatcher Lock */ + KeReleaseDispatcherDatabaseLock(OldIrql); + + /* Return the old state */ + return PreviousState; }
/* @@ -36,28 +110,231 @@ */ VOID STDCALL -KeCapturePersistentThreadState( - IN PVOID CurrentThread, - IN ULONG Setting1, - IN ULONG Setting2, - IN ULONG Setting3, - IN ULONG Setting4, - IN ULONG Setting5, - IN PVOID ThreadState -) +KeCapturePersistentThreadState(IN PVOID CurrentThread, + IN ULONG Setting1, + IN ULONG Setting2, + IN ULONG Setting3, + IN ULONG Setting4, + IN ULONG Setting5, + IN PVOID ThreadState) { - UNIMPLEMENTED; + UNIMPLEMENTED; }
+/* + * FUNCTION: Initialize the microkernel state of the thread + */ VOID -KeFreeStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, - PFN_TYPE Page, SWAPENTRY SwapEntry, BOOLEAN Dirty) +STDCALL +KeInitializeThread(PKPROCESS Process, + PKTHREAD Thread, + BOOLEAN First) { - ASSERT(SwapEntry == 0); - if (Page != 0) - { - MmReleasePageMemoryConsumer(MC_NPPOOL, Page); + PVOID KernelStack; + NTSTATUS Status; + extern unsigned int init_stack_top; + extern unsigned int init_stack; + PMEMORY_AREA StackArea; + ULONG i; + PHYSICAL_ADDRESS BoundaryAddressMultiple; + + /* Initialize the Boundary Address */ + BoundaryAddressMultiple.QuadPart = 0; + + /* Initalize the Dispatcher Header */ + KeInitializeDispatcherHeader(&Thread->DispatcherHeader, + ThreadObject, + sizeof(KTHREAD), + FALSE); + InitializeListHead(&Thread->MutantListHead); + + /* If this is isn't the first thread, allocate the Kernel Stack */ + if (!First) { + + PFN_TYPE Page[MM_STACK_SIZE / PAGE_SIZE]; + KernelStack = NULL; + + MmLockAddressSpace(MmGetKernelAddressSpace()); + Status = MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_KERNEL_STACK, + &KernelStack, + MM_STACK_SIZE, + 0, + &StackArea, + FALSE, + FALSE, + BoundaryAddressMultiple); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + + /* Check for Success */ + if (!NT_SUCCESS(Status)) { + + DPRINT1("Failed to create thread stack\n"); + KEBUGCHECK(0); + } + + /* Mark the Stack */ + for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++) { + + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]); + + /* Check for success */ + if (!NT_SUCCESS(Status)) { + + KEBUGCHECK(0); + } + } + + /* Create a Virtual Mapping for it */ + Status = MmCreateVirtualMapping(NULL, + KernelStack, + PAGE_READWRITE, + Page, + MM_STACK_SIZE / PAGE_SIZE); + + /* Check for success */ + if (!NT_SUCCESS(Status)) { + + KEBUGCHECK(0); + } + + /* Set the Kernel Stack */ + Thread->InitialStack = (PCHAR)KernelStack + MM_STACK_SIZE; + Thread->StackBase = (PCHAR)KernelStack + MM_STACK_SIZE; + Thread->StackLimit = (ULONG_PTR)KernelStack; + Thread->KernelStack = (PCHAR)KernelStack + MM_STACK_SIZE; + + } else { + + /* Use the Initial Stack */ + Thread->InitialStack = (PCHAR)init_stack_top; + Thread->StackBase = (PCHAR)init_stack_top; + Thread->StackLimit = (ULONG_PTR)init_stack; + Thread->KernelStack = (PCHAR)init_stack_top; } + + /* + * Establish the pde's for the new stack and the thread structure within the + * address space of the new process. They are accessed while taskswitching or + * while handling page faults. At this point it isn't possible to call the + * page fault handler for the missing pde's. + */ + MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread->StackLimit, MM_STACK_SIZE); + MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD)); + + /* Set the Thread to initalized */ + Thread->State = THREAD_STATE_INITIALIZED; + + /* The Native API function will initialize the TEB field later */ + Thread->Teb = NULL; + + /* Initialize stuff to zero */ + Thread->TlsArray = NULL; + Thread->DebugActive = 0; + Thread->Alerted[0] = 0; + Thread->Alerted[1] = 0; + Thread->Iopl = 0; + + /* Set up FPU/NPX Stuff */ + Thread->NpxState = NPX_STATE_INVALID; + Thread->NpxIrql = 0; + + /* Setup APC Fields */ + InitializeListHead(&Thread->ApcState.ApcListHead[0]); + InitializeListHead(&Thread->ApcState.ApcListHead[1]); + Thread->ApcState.Process = Process; + Thread->ApcState.KernelApcInProgress = 0; + Thread->ApcState.KernelApcPending = 0; + Thread->ApcState.UserApcPending = 0; + Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState; + Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState; + Thread->ApcStateIndex = OriginalApcEnvironment; + Thread->ApcQueueable = TRUE; + RtlZeroMemory(&Thread->SavedApcState, sizeof(KAPC_STATE)); + KeInitializeSpinLock(&Thread->ApcQueueLock); + + /* Setup Wait Fields */ + Thread->WaitStatus = STATUS_SUCCESS; + Thread->WaitIrql = PASSIVE_LEVEL; + Thread->WaitMode = 0; + Thread->WaitNext = FALSE; + Thread->WaitListEntry.Flink = NULL; + Thread->WaitListEntry.Blink = NULL; + Thread->WaitTime = 0; + Thread->WaitBlockList = NULL; + RtlZeroMemory(Thread->WaitBlock, sizeof(KWAIT_BLOCK) * 4); + RtlZeroMemory(&Thread->Timer, sizeof(KTIMER)); + KeInitializeTimer(&Thread->Timer); + + /* Setup scheduler Fields */ + Thread->BasePriority = Process->BasePriority; + Thread->DecrementCount = 0; + Thread->PriorityDecrement = 0; + Thread->Quantum = Process->ThreadQuantum; + Thread->Saturation = 0; + Thread->Priority = Process->BasePriority; + Thread->UserAffinity = Process->Affinity; + Thread->SystemAffinityActive = 0; + Thread->Affinity = Process->Affinity; + Thread->Preempted = 0; + Thread->ProcessReadyQueue = 0; + Thread->KernelStackResident = 1; + Thread->NextProcessor = 0; + Thread->ContextSwitches = 0; + + /* Setup Queue Fields */ + Thread->Queue = NULL; + Thread->QueueListEntry.Flink = NULL; + Thread->QueueListEntry.Blink = NULL; + + /* Setup Misc Fields */ + Thread->LegoData = 0; + Thread->PowerState = 0; + Thread->ServiceTable = KeServiceDescriptorTable; + Thread->CallbackStack = NULL; + Thread->Win32Thread = NULL; + Thread->TrapFrame = NULL; + Thread->EnableStackSwap = 0; + Thread->LargeStack = 0; + Thread->ResourceIndex = 0; + Thread->PreviousMode = KernelMode; + Thread->KernelTime = 0; + Thread->UserTime = 0; + Thread->AutoAlignment = Process->AutoAlignment; + + /* FIXME OPTIMIZATION OF DOOM. DO NOT ENABLE FIXME */ +#if 0 + Thread->WaitBlock[3].Object = (PVOID)&Thread->Timer; + Thread->WaitBlock[3].Thread = Thread; + Thread->WaitBlock[3].WaitKey = STATUS_TIMEOUT; + Thread->WaitBlock[3].WaitType = WaitAny; + Thread->WaitBlock[3].NextWaitBlock = NULL; + InsertTailList(&Thread->Timer.Header.WaitListHead, + &Thread->WaitBlock[3].WaitListEntry); +#endif + + /* Initialize the Suspend APC */ + KeInitializeApc(&Thread->SuspendApc, + Thread, + OriginalApcEnvironment, + PiSuspendThreadKernelRoutine, + PiSuspendThreadRundownRoutine, + PiSuspendThreadNormalRoutine, + KernelMode, + NULL); + + /* Initialize the Suspend Semaphore */ + KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128); + + /* Insert the Thread into the Process's Thread List */ + InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry); + + /* Set up the Suspend Counts */ + Thread->FreezeCount = 0; + Thread->SuspendCount = 0; + + /* Do x86 specific part */ }
/* @@ -65,11 +342,9 @@ */ KPRIORITY STDCALL -KeQueryPriorityThread ( - IN PKTHREAD Thread - ) +KeQueryPriorityThread (IN PKTHREAD Thread) { - return Thread->Priority; + return Thread->Priority; }
/* @@ -77,19 +352,29 @@ */ ULONG STDCALL -KeQueryRuntimeThread( - IN PKTHREAD Thread, - OUT PULONG UserTime - ) +KeQueryRuntimeThread(IN PKTHREAD Thread, + OUT PULONG UserTime) { - /* Return the User Time */ - *UserTime = Thread->UserTime; - - /* Return the Kernel Time */ - return Thread->KernelTime; + /* Return the User Time */ + *UserTime = Thread->UserTime; + + /* Return the Kernel Time */ + return Thread->KernelTime; }
-NTSTATUS +VOID +KeFreeStackPage(PVOID Context, + MEMORY_AREA* MemoryArea, + PVOID Address, + PFN_TYPE Page, + SWAPENTRY SwapEntry, + BOOLEAN Dirty) +{ + ASSERT(SwapEntry == 0); + if (Page) MmReleasePageMemoryConsumer(MC_NPPOOL, Page); +} + +NTSTATUS KeReleaseThread(PKTHREAD Thread) /* * FUNCTION: Releases the resource allocated for a thread by @@ -123,195 +408,26 @@ */ BOOLEAN STDCALL -KeSetKernelStackSwapEnable( - IN BOOLEAN Enable - ) +KeSetKernelStackSwapEnable(IN BOOLEAN Enable) { - PKTHREAD Thread; - BOOLEAN PreviousState; - - Thread = KeGetCurrentThread(); - - /* Save Old State */ - PreviousState = Thread->EnableStackSwap; - - /* Set New State */ - Thread->EnableStackSwap = Enable; + PKTHREAD Thread = KeGetCurrentThread(); + BOOLEAN PreviousState; + KIRQL OldIrql; + + /* Lock the Dispatcher Database */ + OldIrql = KeAcquireDispatcherDatabaseLock();
- /* Return Old State */ - return PreviousState; -} + /* Save Old State */ + PreviousState = Thread->EnableStackSwap;
-VOID -KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First) -/* - * FUNCTION: Initialize the microkernel state of the thread - */ -{ - PVOID KernelStack; - NTSTATUS Status; - extern unsigned int init_stack_top; - extern unsigned int init_stack; - PMEMORY_AREA StackArea; - ULONG i; - PHYSICAL_ADDRESS BoundaryAddressMultiple; - - BoundaryAddressMultiple.QuadPart = 0; - - KeInitializeDispatcherHeader(&Thread->DispatcherHeader, - InternalThreadType, - sizeof(ETHREAD), - FALSE); - InitializeListHead(&Thread->MutantListHead); - if (!First) - { - PFN_TYPE Page[MM_STACK_SIZE / PAGE_SIZE]; - KernelStack = NULL; - - MmLockAddressSpace(MmGetKernelAddressSpace()); - Status = MmCreateMemoryArea(NULL, - MmGetKernelAddressSpace(), - MEMORY_AREA_KERNEL_STACK, - &KernelStack, - MM_STACK_SIZE, - 0, - &StackArea, - FALSE, - FALSE, - BoundaryAddressMultiple); - MmUnlockAddressSpace(MmGetKernelAddressSpace()); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to create thread stack\n"); - KEBUGCHECK(0); - } - for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++) - { - Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]); - if (!NT_SUCCESS(Status)) - { - KEBUGCHECK(0); - } - } - Status = MmCreateVirtualMapping(NULL, - KernelStack, - PAGE_READWRITE, - Page, - MM_STACK_SIZE / PAGE_SIZE); - if (!NT_SUCCESS(Status)) - { - KEBUGCHECK(0); - } - Thread->InitialStack = (PCHAR)KernelStack + MM_STACK_SIZE; - Thread->StackBase = (PCHAR)KernelStack + MM_STACK_SIZE; - Thread->StackLimit = (ULONG_PTR)KernelStack; - Thread->KernelStack = (PCHAR)KernelStack + MM_STACK_SIZE; - } - else - { - Thread->InitialStack = (PCHAR)init_stack_top; - Thread->StackBase = (PCHAR)init_stack_top; - Thread->StackLimit = (ULONG_PTR)init_stack; - Thread->KernelStack = (PCHAR)init_stack_top; - } + /* Set New State */ + Thread->EnableStackSwap = Enable;
- /* - * Establish the pde's for the new stack and the thread structure within the - * address space of the new process. They are accessed while taskswitching or - * while handling page faults. At this point it isn't possible to call the - * page fault handler for the missing pde's. - */ - - MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread->StackLimit, MM_STACK_SIZE); - MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD)); - - /* - * The Native API function will initialize the TEB field later - */ - Thread->Teb = NULL; - Thread->TlsArray = NULL; - Thread->DebugActive = 0; - Thread->State = THREAD_STATE_INITIALIZED; - Thread->Alerted[0] = 0; - Thread->Alerted[1] = 0; - Thread->Iopl = 0; - Thread->NpxState = NPX_STATE_INVALID; - - Thread->Saturation = 0; - Thread->Priority = Process->BasePriority; - InitializeListHead(&Thread->ApcState.ApcListHead[0]); - InitializeListHead(&Thread->ApcState.ApcListHead[1]); - Thread->ApcState.Process = Process; - Thread->ApcState.KernelApcInProgress = 0; - Thread->ApcState.KernelApcPending = 0; - Thread->ApcState.UserApcPending = 0; - Thread->ContextSwitches = 0; - Thread->WaitStatus = STATUS_SUCCESS; - Thread->WaitIrql = PASSIVE_LEVEL; - Thread->WaitMode = 0; - Thread->WaitNext = FALSE; - Thread->WaitBlockList = NULL; - Thread->WaitListEntry.Flink = NULL; - Thread->WaitListEntry.Blink = NULL; - Thread->WaitTime = 0; - Thread->BasePriority = Process->BasePriority; - Thread->DecrementCount = 0; - Thread->PriorityDecrement = 0; - Thread->Quantum = Process->ThreadQuantum; - RtlZeroMemory(Thread->WaitBlock, sizeof(KWAIT_BLOCK)*4); - Thread->LegoData = 0; - Thread->UserAffinity = Process->Affinity; - Thread->SystemAffinityActive = 0; - Thread->PowerState = 0; - Thread->NpxIrql = 0; - Thread->ServiceTable = KeServiceDescriptorTable; - Thread->Queue = NULL; - KeInitializeSpinLock(&Thread->ApcQueueLock); - RtlZeroMemory(&Thread->Timer, sizeof(KTIMER)); - KeInitializeTimer(&Thread->Timer); - Thread->QueueListEntry.Flink = NULL; - Thread->QueueListEntry.Blink = NULL; - Thread->Affinity = Process->Affinity; - Thread->Preempted = 0; - Thread->ProcessReadyQueue = 0; - Thread->KernelStackResident = 1; - Thread->NextProcessor = 0; - Thread->CallbackStack = NULL; - Thread->Win32Thread = NULL; - Thread->TrapFrame = NULL; - Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState; - Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState; - Thread->EnableStackSwap = 0; - Thread->LargeStack = 0; - Thread->ResourceIndex = 0; - Thread->PreviousMode = KernelMode; - Thread->KernelTime = 0; - Thread->UserTime = 0; - RtlZeroMemory(&Thread->SavedApcState, sizeof(KAPC_STATE)); - - Thread->ApcStateIndex = OriginalApcEnvironment; - Thread->ApcQueueable = TRUE; - Thread->AutoAlignment = Process->AutoAlignment; - - KeInitializeApc(&Thread->SuspendApc, - Thread, - OriginalApcEnvironment, - PiSuspendThreadKernelRoutine, - PiSuspendThreadRundownRoutine, - PiSuspendThreadNormalRoutine, - KernelMode, - NULL); - KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128); - - InsertTailList(&Process->ThreadListHead, - &Thread->ThreadListEntry); - Thread->FreezeCount = 0; - Thread->SuspendCount = 0; - - /* - * Do x86 specific part - */ + /* No, Release Lock */ + KeReleaseDispatcherDatabaseLock(OldIrql); + + /* Return Old State */ + return PreviousState; }
/* @@ -321,33 +437,33 @@ STDCALL KeRevertToUserAffinityThread(VOID) { -#ifdef CONFIG_SMP - PKTHREAD CurrentThread; - KIRQL oldIrql; + PKTHREAD CurrentThread = KeGetCurrentThread(); + KIRQL OldIrql;
- oldIrql = KeAcquireDispatcherDatabaseLock(); + ASSERT(CurrentThread->SystemAffinityActive != FALSE); + + /* Lock the Dispatcher Database */ + OldIrql = KeAcquireDispatcherDatabaseLock();
- CurrentThread = KeGetCurrentThread(); + /* Return to User Affinity */ + CurrentThread->Affinity = CurrentThread->UserAffinity;
- ASSERT(CurrentThread->SystemAffinityActive != FALSE); - - /* Return to User Affinity */ - CurrentThread->Affinity = CurrentThread->UserAffinity; - - /* Disable System Affinity */ - CurrentThread->SystemAffinityActive = FALSE; - - if (CurrentThread->Affinity & (1 << KeGetCurrentProcessorNumber())) - { - KeReleaseDispatcherDatabaseLock(oldIrql); - } - else - { - CurrentThread->WaitIrql = oldIrql; - PsDispatchThreadNoLock(THREAD_STATE_READY); - KeLowerIrql(oldIrql); - } -#endif + /* Disable System Affinity */ + CurrentThread->SystemAffinityActive = FALSE; + + /* Check if we need to Dispatch a New thread */ + if (CurrentThread->Affinity & (1 << KeGetCurrentProcessorNumber())) { + + /* No, just release */ + KeReleaseDispatcherDatabaseLock(OldIrql); + + } else { + + /* We need to dispatch a new thread */ + CurrentThread->WaitIrql = OldIrql; + PsDispatchThreadNoLock(THREAD_STATE_READY); + KeLowerIrql(OldIrql); + } }
/* @@ -355,20 +471,26 @@ */ CCHAR STDCALL -KeSetIdealProcessorThread ( - IN PKTHREAD Thread, - IN CCHAR Processor) +KeSetIdealProcessorThread(IN PKTHREAD Thread, + IN CCHAR Processor) { [truncated at 1000 lines; 369 more skipped]