mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 23:45:42 +00:00
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 svn path=/trunk/; revision=13974
This commit is contained in:
parent
a8f6850b9f
commit
b2a42182ef
10 changed files with 643 additions and 499 deletions
|
@ -58,7 +58,7 @@ static ULONG gNumberOfControllers = 0;
|
||||||
|
|
||||||
/* Queue thread management */
|
/* Queue thread management */
|
||||||
static KEVENT QueueThreadTerminate;
|
static KEVENT QueueThreadTerminate;
|
||||||
static PVOID ThreadObject;
|
static PVOID QueueThreadObject;
|
||||||
|
|
||||||
|
|
||||||
static VOID NTAPI MotorStopDpcFunc(PKDPC UnusedDpc,
|
static VOID NTAPI MotorStopDpcFunc(PKDPC UnusedDpc,
|
||||||
|
@ -378,8 +378,8 @@ static VOID NTAPI Unload(PDRIVER_OBJECT DriverObject)
|
||||||
KdPrint(("floppy: unloading\n"));
|
KdPrint(("floppy: unloading\n"));
|
||||||
|
|
||||||
KeSetEvent(&QueueThreadTerminate, 0, FALSE);
|
KeSetEvent(&QueueThreadTerminate, 0, FALSE);
|
||||||
KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, 0);
|
KeWaitForSingleObject(QueueThreadObject, Executive, KernelMode, FALSE, 0);
|
||||||
ObDereferenceObject(ThreadObject);
|
ObDereferenceObject(QueueThreadObject);
|
||||||
|
|
||||||
for(i = 0; i < gNumberOfControllers; i++)
|
for(i = 0; i < gNumberOfControllers; i++)
|
||||||
{
|
{
|
||||||
|
@ -1152,7 +1152,7 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject,
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
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"));
|
KdPrint(("floppy: Unable to reference returned thread handle; failing init\n"));
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
|
|
@ -36,23 +36,34 @@ typedef VOID STDCALL_FUNC
|
||||||
|
|
||||||
struct _DISPATCHER_HEADER;
|
struct _DISPATCHER_HEADER;
|
||||||
|
|
||||||
typedef enum _KERNEL_OBJECTS {
|
typedef enum _KOBJECTS {
|
||||||
KNotificationEvent = 0,
|
EventNotificationObject = 0,
|
||||||
KSynchronizationEvent = 1,
|
EventSynchronizationObject = 1,
|
||||||
KMutant = 2,
|
MutantObject = 2,
|
||||||
KProcess = 3,
|
ProcessObject = 3,
|
||||||
KQueue = 4,
|
QueueObject = 4,
|
||||||
KSemaphore = 5,
|
SemaphoreObject = 5,
|
||||||
KThread = 6,
|
ThreadObject = 6,
|
||||||
KNotificationTimer = 8,
|
GateObject = 7,
|
||||||
KSynchronizationTimer = 9,
|
TimerNotificationObject = 8,
|
||||||
KApc = 18,
|
TimerSynchronizationObject = 9,
|
||||||
KDpc = 19,
|
Spare2Object = 10,
|
||||||
KDeviceQueue = 20,
|
Spare3Object = 11,
|
||||||
KEventPair = 21,
|
Spare4Object = 12,
|
||||||
KInterrupt = 22,
|
Spare5Object = 13,
|
||||||
KProfile = 23
|
Spare6Object = 14,
|
||||||
} KERNEL_OBJECTS;
|
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>
|
#include <pshpack1.h>
|
||||||
|
|
||||||
|
|
|
@ -113,8 +113,7 @@ OBJECTS_KE = \
|
||||||
ke/sem.o \
|
ke/sem.o \
|
||||||
ke/spinlock.o \
|
ke/spinlock.o \
|
||||||
ke/timer.o \
|
ke/timer.o \
|
||||||
ke/wait.o \
|
ke/wait.o
|
||||||
ke/alert.o
|
|
||||||
|
|
||||||
# Memory Manager (Mm)
|
# Memory Manager (Mm)
|
||||||
OBJECTS_MM = \
|
OBJECTS_MM = \
|
||||||
|
|
|
@ -498,7 +498,7 @@ VOID STDCALL PsExitSpecialApc(PKAPC Apc,
|
||||||
#define PROCESS_PRIO_RT 18
|
#define PROCESS_PRIO_RT 18
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID STDCALL
|
||||||
KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First);
|
KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First);
|
||||||
NTSTATUS KeReleaseThread(PKTHREAD Thread);
|
NTSTATUS KeReleaseThread(PKTHREAD Thread);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ KeInitializeApc(
|
||||||
|
|
||||||
/* Set up the basic APC Structure Data */
|
/* Set up the basic APC Structure Data */
|
||||||
RtlZeroMemory(Apc, sizeof(KAPC));
|
RtlZeroMemory(Apc, sizeof(KAPC));
|
||||||
Apc->Type = KApc;
|
Apc->Type = ApcObject;
|
||||||
Apc->Size = sizeof(KAPC);
|
Apc->Size = sizeof(KAPC);
|
||||||
|
|
||||||
/* Set the Environment */
|
/* Set the Environment */
|
||||||
|
|
|
@ -88,7 +88,7 @@ KeInitializeDpc (PKDPC Dpc,
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
|
DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
|
||||||
Dpc->Type = KDpc;
|
Dpc->Type = DpcObject;
|
||||||
Dpc->Number= 0;
|
Dpc->Number= 0;
|
||||||
Dpc->Importance= MediumImportance;
|
Dpc->Importance= MediumImportance;
|
||||||
Dpc->DeferredRoutine = DeferredRoutine;
|
Dpc->DeferredRoutine = DeferredRoutine;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
/* $Id$
|
/*
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ke/kthread.c
|
* FILE: ntoskrnl/ke/kthread.c
|
||||||
* PURPOSE: Microkernel thread support
|
* 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 *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
@ -16,19 +16,93 @@
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
VOID
|
ULONG
|
||||||
KiServiceCheck (VOID)
|
STDCALL
|
||||||
|
KeAlertResumeThread(IN PKTHREAD Thread)
|
||||||
{
|
{
|
||||||
PETHREAD Thread;
|
ULONG PreviousCount;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
Thread = PsGetCurrentThread();
|
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||||
|
|
||||||
if (Thread->Tcb.ServiceTable != KeServiceDescriptorTableShadow)
|
/* Lock the Dispatcher Database and the APC Queue */
|
||||||
{
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
PsInitWin32Thread (Thread);
|
KiAcquireSpinLock(&Thread->ApcQueueLock);
|
||||||
|
|
||||||
Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow;
|
/* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 @@ KiServiceCheck (VOID)
|
||||||
*/
|
*/
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
KeCapturePersistentThreadState(
|
KeCapturePersistentThreadState(IN PVOID CurrentThread,
|
||||||
IN PVOID CurrentThread,
|
IN ULONG Setting1,
|
||||||
IN ULONG Setting1,
|
IN ULONG Setting2,
|
||||||
IN ULONG Setting2,
|
IN ULONG Setting3,
|
||||||
IN ULONG Setting3,
|
IN ULONG Setting4,
|
||||||
IN ULONG Setting4,
|
IN ULONG Setting5,
|
||||||
IN ULONG Setting5,
|
IN PVOID ThreadState)
|
||||||
IN PVOID ThreadState
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FUNCTION: Initialize the microkernel state of the thread
|
||||||
|
*/
|
||||||
VOID
|
VOID
|
||||||
KeFreeStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
STDCALL
|
||||||
PFN_TYPE Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
|
KeInitializeThread(PKPROCESS Process,
|
||||||
|
PKTHREAD Thread,
|
||||||
|
BOOLEAN First)
|
||||||
{
|
{
|
||||||
ASSERT(SwapEntry == 0);
|
PVOID KernelStack;
|
||||||
if (Page != 0)
|
NTSTATUS Status;
|
||||||
{
|
extern unsigned int init_stack_top;
|
||||||
MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
|
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 @@ KeFreeStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||||
*/
|
*/
|
||||||
KPRIORITY
|
KPRIORITY
|
||||||
STDCALL
|
STDCALL
|
||||||
KeQueryPriorityThread (
|
KeQueryPriorityThread (IN PKTHREAD Thread)
|
||||||
IN PKTHREAD Thread
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return Thread->Priority;
|
return Thread->Priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -77,16 +352,26 @@ KeQueryPriorityThread (
|
||||||
*/
|
*/
|
||||||
ULONG
|
ULONG
|
||||||
STDCALL
|
STDCALL
|
||||||
KeQueryRuntimeThread(
|
KeQueryRuntimeThread(IN PKTHREAD Thread,
|
||||||
IN PKTHREAD Thread,
|
OUT PULONG UserTime)
|
||||||
OUT PULONG UserTime
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/* Return the User Time */
|
/* Return the User Time */
|
||||||
*UserTime = Thread->UserTime;
|
*UserTime = Thread->UserTime;
|
||||||
|
|
||||||
/* Return the Kernel Time */
|
/* Return the Kernel Time */
|
||||||
return Thread->KernelTime;
|
return Thread->KernelTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
NTSTATUS
|
||||||
|
@ -123,195 +408,26 @@ KeReleaseThread(PKTHREAD Thread)
|
||||||
*/
|
*/
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
STDCALL
|
STDCALL
|
||||||
KeSetKernelStackSwapEnable(
|
KeSetKernelStackSwapEnable(IN BOOLEAN Enable)
|
||||||
IN BOOLEAN Enable
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
PKTHREAD Thread;
|
PKTHREAD Thread = KeGetCurrentThread();
|
||||||
BOOLEAN PreviousState;
|
BOOLEAN PreviousState;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
Thread = KeGetCurrentThread();
|
/* Lock the Dispatcher Database */
|
||||||
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
|
|
||||||
/* Save Old State */
|
/* Save Old State */
|
||||||
PreviousState = Thread->EnableStackSwap;
|
PreviousState = Thread->EnableStackSwap;
|
||||||
|
|
||||||
/* Set New State */
|
/* Set New State */
|
||||||
Thread->EnableStackSwap = Enable;
|
Thread->EnableStackSwap = Enable;
|
||||||
|
|
||||||
/* Return Old State */
|
/* No, Release Lock */
|
||||||
return PreviousState;
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
/* Return Old State */
|
||||||
KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
|
return PreviousState;
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -321,33 +437,33 @@ VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
KeRevertToUserAffinityThread(VOID)
|
KeRevertToUserAffinityThread(VOID)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SMP
|
PKTHREAD CurrentThread = KeGetCurrentThread();
|
||||||
PKTHREAD CurrentThread;
|
KIRQL OldIrql;
|
||||||
KIRQL oldIrql;
|
|
||||||
|
|
||||||
oldIrql = KeAcquireDispatcherDatabaseLock();
|
ASSERT(CurrentThread->SystemAffinityActive != FALSE);
|
||||||
|
|
||||||
CurrentThread = KeGetCurrentThread();
|
/* Lock the Dispatcher Database */
|
||||||
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
|
|
||||||
ASSERT(CurrentThread->SystemAffinityActive != FALSE);
|
/* Return to User Affinity */
|
||||||
|
CurrentThread->Affinity = CurrentThread->UserAffinity;
|
||||||
|
|
||||||
/* Return to User Affinity */
|
/* Disable System Affinity */
|
||||||
CurrentThread->Affinity = CurrentThread->UserAffinity;
|
CurrentThread->SystemAffinityActive = FALSE;
|
||||||
|
|
||||||
/* Disable System Affinity */
|
/* Check if we need to Dispatch a New thread */
|
||||||
CurrentThread->SystemAffinityActive = FALSE;
|
if (CurrentThread->Affinity & (1 << KeGetCurrentProcessorNumber())) {
|
||||||
|
|
||||||
if (CurrentThread->Affinity & (1 << KeGetCurrentProcessorNumber()))
|
/* No, just release */
|
||||||
{
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
KeReleaseDispatcherDatabaseLock(oldIrql);
|
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
/* We need to dispatch a new thread */
|
||||||
CurrentThread->WaitIrql = oldIrql;
|
CurrentThread->WaitIrql = OldIrql;
|
||||||
PsDispatchThreadNoLock(THREAD_STATE_READY);
|
PsDispatchThreadNoLock(THREAD_STATE_READY);
|
||||||
KeLowerIrql(oldIrql);
|
KeLowerIrql(OldIrql);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -355,20 +471,26 @@ KeRevertToUserAffinityThread(VOID)
|
||||||
*/
|
*/
|
||||||
CCHAR
|
CCHAR
|
||||||
STDCALL
|
STDCALL
|
||||||
KeSetIdealProcessorThread (
|
KeSetIdealProcessorThread(IN PKTHREAD Thread,
|
||||||
IN PKTHREAD Thread,
|
IN CCHAR Processor)
|
||||||
IN CCHAR Processor)
|
|
||||||
{
|
{
|
||||||
CCHAR PreviousIdealProcessor;
|
CCHAR PreviousIdealProcessor;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
/* Save Old Ideal Processor */
|
/* Lock the Dispatcher Database */
|
||||||
PreviousIdealProcessor = Thread->IdealProcessor;
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
|
|
||||||
/* Set New Ideal Processor */
|
/* Save Old Ideal Processor */
|
||||||
Thread->IdealProcessor = Processor;
|
PreviousIdealProcessor = Thread->IdealProcessor;
|
||||||
|
|
||||||
/* Return Old Ideal Processor */
|
/* Set New Ideal Processor */
|
||||||
return PreviousIdealProcessor;
|
Thread->IdealProcessor = Processor;
|
||||||
|
|
||||||
|
/* Release Lock */
|
||||||
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
|
|
||||||
|
/* Return Old Ideal Processor */
|
||||||
|
return PreviousIdealProcessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -378,86 +500,237 @@ VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
KeSetSystemAffinityThread(IN KAFFINITY Affinity)
|
KeSetSystemAffinityThread(IN KAFFINITY Affinity)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SMP
|
PKTHREAD CurrentThread = KeGetCurrentThread();
|
||||||
PKTHREAD CurrentThread;
|
KIRQL OldIrql;
|
||||||
KIRQL oldIrql;
|
|
||||||
|
|
||||||
oldIrql = KeAcquireDispatcherDatabaseLock();
|
ASSERT(Affinity & ((1 << KeNumberProcessors) - 1));
|
||||||
|
|
||||||
CurrentThread = KeGetCurrentThread();
|
/* Lock the Dispatcher Database */
|
||||||
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
|
|
||||||
ASSERT(Affinity & ((1 << KeNumberProcessors) - 1));
|
/* Set the System Affinity Specified */
|
||||||
|
CurrentThread->Affinity = Affinity;
|
||||||
|
|
||||||
/* Set the System Affinity Specified */
|
/* Enable System Affinity */
|
||||||
CurrentThread->Affinity = Affinity;
|
CurrentThread->SystemAffinityActive = TRUE;
|
||||||
|
|
||||||
/* Enable System Affinity */
|
/* Check if we need to Dispatch a New thread */
|
||||||
CurrentThread->SystemAffinityActive = TRUE;
|
if (Affinity & (1 << KeGetCurrentProcessorNumber())) {
|
||||||
|
|
||||||
if (Affinity & (1 << KeGetCurrentProcessorNumber()))
|
/* No, just release */
|
||||||
{
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
KeReleaseDispatcherDatabaseLock(oldIrql);
|
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
/* We need to dispatch a new thread */
|
||||||
CurrentThread->WaitIrql = oldIrql;
|
CurrentThread->WaitIrql = OldIrql;
|
||||||
PsDispatchThreadNoLock(THREAD_STATE_READY);
|
PsDispatchThreadNoLock(THREAD_STATE_READY);
|
||||||
KeLowerIrql(oldIrql);
|
KeLowerIrql(OldIrql);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
/* The Increment Argument seems to be ignored by NT and always 0 when called */
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
KeTerminateThread(IN KPRIORITY Increment)
|
KeTerminateThread(IN KPRIORITY Increment)
|
||||||
{
|
{
|
||||||
/* The Increment Argument seems to be ignored by NT and always 0 when called */
|
/* Call our own internal routine */
|
||||||
|
PsTerminateCurrentThread(0);
|
||||||
/* Call our own internal routine */
|
|
||||||
PsTerminateCurrentThread(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
STDCALL
|
||||||
|
KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
PKTHREAD Thread = KeGetCurrentThread();
|
||||||
|
BOOLEAN OldState;
|
||||||
|
|
||||||
|
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||||
|
|
||||||
|
/* Lock the Dispatcher Database and the APC Queue */
|
||||||
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
|
KiAcquireSpinLock(&Thread->ApcQueueLock);
|
||||||
|
|
||||||
|
/* Save the old State */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release Locks and return the Old State */
|
||||||
|
KiReleaseSpinLock(&Thread->ApcQueueLock);
|
||||||
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
|
return OldState;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
KiServiceCheck (VOID)
|
||||||
|
{
|
||||||
|
PKTHREAD Thread = KeGetCurrentThread();
|
||||||
|
|
||||||
|
/* Check if we need to inialize Win32 for this Thread */
|
||||||
|
if (Thread->ServiceTable != KeServiceDescriptorTableShadow) {
|
||||||
|
|
||||||
|
/* We do. Initialize it and save the new table */
|
||||||
|
PsInitWin32Thread((PETHREAD)Thread);
|
||||||
|
Thread->ServiceTable = KeServiceDescriptorTableShadow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* NOT EXPORTED
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
NtAlertResumeThread(IN HANDLE ThreadHandle,
|
||||||
|
OUT PULONG SuspendCount)
|
||||||
|
{
|
||||||
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
|
PETHREAD Thread;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG PreviousState;
|
||||||
|
|
||||||
|
/* Check if parameters are valid */
|
||||||
|
if(PreviousMode != KernelMode) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
|
ProbeForWrite(SuspendCount,
|
||||||
|
sizeof(HANDLE),
|
||||||
|
sizeof(ULONG));
|
||||||
|
|
||||||
|
} _SEH_HANDLE {
|
||||||
|
|
||||||
|
Status = _SEH_GetExceptionCode();
|
||||||
|
|
||||||
|
} _SEH_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reference the Object */
|
||||||
|
Status = ObReferenceObjectByHandle(ThreadHandle,
|
||||||
|
THREAD_SUSPEND_RESUME,
|
||||||
|
PsThreadType,
|
||||||
|
PreviousMode,
|
||||||
|
(PVOID*)&Thread,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Check for Success */
|
||||||
|
if (NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Call the Kernel Function */
|
||||||
|
PreviousState = KeAlertResumeThread(&Thread->Tcb);
|
||||||
|
|
||||||
|
/* Dereference Object */
|
||||||
|
ObDereferenceObject(Thread);
|
||||||
|
|
||||||
|
if (SuspendCount) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
|
*SuspendCount = PreviousState;
|
||||||
|
|
||||||
|
} _SEH_HANDLE {
|
||||||
|
|
||||||
|
Status = _SEH_GetExceptionCode();
|
||||||
|
|
||||||
|
} _SEH_END;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*
|
||||||
|
* EXPORTED
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
NtAlertThread (IN HANDLE ThreadHandle)
|
||||||
|
{
|
||||||
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
|
PETHREAD Thread;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* Reference the Object */
|
||||||
|
Status = ObReferenceObjectByHandle(ThreadHandle,
|
||||||
|
THREAD_SUSPEND_RESUME,
|
||||||
|
PsThreadType,
|
||||||
|
PreviousMode,
|
||||||
|
(PVOID*)&Thread,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Check for Success */
|
||||||
|
if (NT_SUCCESS(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);
|
||||||
|
|
||||||
|
/* Dereference Object */
|
||||||
|
ObDereferenceObject(Thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
NtDelayExecution(IN BOOLEAN Alertable,
|
NtDelayExecution(IN BOOLEAN Alertable,
|
||||||
IN PLARGE_INTEGER DelayInterval)
|
IN PLARGE_INTEGER DelayInterval)
|
||||||
{
|
{
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
LARGE_INTEGER SafeInterval;
|
LARGE_INTEGER SafeInterval;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check if parameters are valid */
|
||||||
|
if(PreviousMode != KernelMode) {
|
||||||
|
|
||||||
if(PreviousMode != KernelMode)
|
_SEH_TRY {
|
||||||
{
|
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
|
||||||
|
|
||||||
_SEH_TRY
|
ProbeForRead(DelayInterval,
|
||||||
{
|
sizeof(LARGE_INTEGER),
|
||||||
ProbeForRead(DelayInterval,
|
sizeof(ULONG));
|
||||||
sizeof(LARGE_INTEGER),
|
|
||||||
sizeof(ULONG));
|
|
||||||
/* make a copy on the kernel stack and let DelayInterval point to it so
|
|
||||||
we don't need to wrap KeDelayExecutionThread in SEH! */
|
|
||||||
SafeInterval = *DelayInterval;
|
|
||||||
DelayInterval = &SafeInterval;
|
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
/* make a copy on the kernel stack and let DelayInterval point to it so
|
||||||
{
|
we don't need to wrap KeDelayExecutionThread in SEH! */
|
||||||
return Status;
|
SafeInterval = *DelayInterval;
|
||||||
}
|
|
||||||
|
} _SEH_HANDLE {
|
||||||
|
|
||||||
|
Status = _SEH_GetExceptionCode();
|
||||||
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
return KeDelayExecutionThread(PreviousMode,
|
/* Call the Kernel Function */
|
||||||
Alertable,
|
Status = KeDelayExecutionThread(PreviousMode,
|
||||||
DelayInterval);
|
Alertable,
|
||||||
|
&SafeInterval);
|
||||||
|
|
||||||
|
/* Return Status */
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ KiSideEffectsBeforeWake(DISPATCHER_HEADER * hdr,
|
||||||
case InternalProcessType:
|
case InternalProcessType:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InternalThreadType:
|
case ThreadObject:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InternalNotificationEvent:
|
case InternalNotificationEvent:
|
||||||
|
@ -386,7 +386,7 @@ BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment)
|
||||||
case InternalProcessType:
|
case InternalProcessType:
|
||||||
return(KeDispatcherObjectWakeAll(hdr, increment));
|
return(KeDispatcherObjectWakeAll(hdr, increment));
|
||||||
|
|
||||||
case InternalThreadType:
|
case ThreadObject:
|
||||||
return(KeDispatcherObjectWakeAll(hdr, increment));
|
return(KeDispatcherObjectWakeAll(hdr, increment));
|
||||||
|
|
||||||
case InternalMutexType:
|
case InternalMutexType:
|
||||||
|
|
|
@ -1055,6 +1055,17 @@ NtYieldExecution(VOID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOT EXPORTED
|
||||||
|
*/
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtTestAlert(VOID)
|
||||||
|
{
|
||||||
|
/* Check and Alert Thread if needed */
|
||||||
|
return KeTestAlertThread(ExGetPreviousMode()) ? STATUS_ALERTED : STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue