ULONG IdleProcessorMask = 0;
extern LIST_ENTRY PspReaperListHead;
+ULONG KiMask32Array[MAXIMUM_PRIORITY] =
+{
+ 0x1, 0x2, 0x4, 0x8, 0x10, 0x20,
+ 0x40, 0x80, 0x100, 0x200, 0x4000, 0x800,
+ 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000,
+ 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000,
+ 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000,
+ 0x40000000, 0x80000000
+};
+
/* FUNCTIONS *****************************************************************/
+UCHAR
+NTAPI
+KeFindNextRightSetAffinity(IN UCHAR Number,
+ IN ULONG Set)
+{
+ ULONG Bit, Result;
+ ASSERT(Set != 0);
+
+ /* Calculate the mask */
+ Bit = (AFFINITY_MASK(Number) - 1) & Set;
+
+ /* If it's 0, use the one we got */
+ if (!Bit) Bit = Set;
+
+ /* Now find the right set and return it */
+ BitScanReverse(&Result, Bit);
+ return (UCHAR)Result;
+}
+
STATIC
VOID
KiRequestReschedule(CCHAR Processor)
UNIMPLEMENTED;
}
-/*
- * FUNCTION: Initialize the microkernel state of the thread
- */
-VOID
-STDCALL
-KeInitializeThread(PKPROCESS Process,
- PKTHREAD Thread,
- PKSYSTEM_ROUTINE SystemRoutine,
- PKSTART_ROUTINE StartRoutine,
- PVOID StartContext,
- PCONTEXT Context,
- PVOID Teb,
- PVOID KernelStack)
+NTSTATUS
+NTAPI
+KeInitThread(IN OUT PKTHREAD Thread,
+ IN PVOID KernelStack,
+ IN PKSYSTEM_ROUTINE SystemRoutine,
+ IN PKSTART_ROUTINE StartRoutine,
+ IN PVOID StartContext,
+ IN PCONTEXT Context,
+ IN PVOID Teb,
+ IN PKPROCESS Process)
{
+ BOOLEAN AllocatedStack = FALSE;
ULONG i;
PKWAIT_BLOCK TimerWaitBlock;
PKTIMER Timer;
+ NTSTATUS Status;
/* Initalize the Dispatcher Header */
- DPRINT("Initializing Dispatcher Header for New Thread: %x in Process: %x\n", Thread, Process);
KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
ThreadObject,
sizeof(KTHREAD) / sizeof(LONG),
FALSE);
- DPRINT("Thread Header Created. SystemRoutine: %x, StartRoutine: %x with Context: %x\n",
- SystemRoutine, StartRoutine, StartContext);
- DPRINT("UserMode Information. Context: %x, Teb: %x\n", Context, Teb);
-
/* Initialize the Mutant List */
InitializeListHead(&Thread->MutantListHead);
Thread->WaitBlock[i].Thread = Thread;
}
+ /* Set swap settings */
+ Thread->EnableStackSwap = FALSE;//TRUE;
+ Thread->IdealProcessor = 1;
+ Thread->SwapBusy = FALSE;
+ Thread->AdjustReason = 0;
+
+ /* Initialize the lock */
+ KeInitializeSpinLock(&Thread->ThreadLock);
+
/* Setup the Service Descriptor Table for Native Calls */
Thread->ServiceTable = KeServiceDescriptorTable;
NULL);
/* Initialize the Suspend Semaphore */
- KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128);
+ KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 2);
/* Setup the timer */
Timer = &Thread->Timer;
/* Set the TEB */
Thread->Teb = Teb;
+ /* Check if we have a kernel stack */
+ if (!KernelStack)
+ {
+ /* We don't, allocate one */
+ KernelStack = (PVOID)((ULONG_PTR)MmCreateKernelStack(FALSE) +
+ KERNEL_STACK_SIZE);
+ if (!KernelStack) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Remember for later */
+ AllocatedStack = TRUE;
+ }
+
/* Set the Thread Stacks */
Thread->InitialStack = (PCHAR)KernelStack;
Thread->StackBase = (PCHAR)KernelStack;
Thread->StackLimit = (ULONG_PTR)KernelStack - KERNEL_STACK_SIZE;
Thread->KernelStackResident = TRUE;
- /*
- * 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, KERNEL_STACK_SIZE);
+ /* ROS Mm HACK */
+ MmUpdatePageDir((PEPROCESS)Process,
+ (PVOID)Thread->StackLimit,
+ KERNEL_STACK_SIZE);
MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
- /* Initalize the Thread Context */
- DPRINT("Initializing the Context for the thread: %x\n", Thread);
- KiArchInitThreadWithContext(Thread,
- SystemRoutine,
- StartRoutine,
- StartContext,
- Context);
+ /* Enter SEH to avoid crashes due to user mode */
+ Status = STATUS_SUCCESS;
+ _SEH_TRY
+ {
+ /* Initalize the Thread Context */
+ KiArchInitThreadWithContext(Thread,
+ SystemRoutine,
+ StartRoutine,
+ StartContext,
+ Context);
+ }
+ _SEH_HANDLE
+ {
+ /* Set failure status */
+ Status = STATUS_UNSUCCESSFUL;
- /* Setup scheduler Fields based on Parent */
- DPRINT("Thread context created, setting Scheduler Data\n");
- Thread->BasePriority = Process->BasePriority;
+ /* Check if a stack was allocated */
+ if (AllocatedStack)
+ {
+ /* Delete the stack */
+ MmDeleteKernelStack(Thread->StackBase, FALSE);
+ Thread->InitialStack = NULL;
+ }
+ }
+ _SEH_END;
+
+ /* Set the Thread to initalized */
+ Thread->State = Initialized;
+ return Status;
+}
+
+VOID
+NTAPI
+KeStartThread(IN OUT PKTHREAD Thread)
+{
+ KIRQL OldIrql;
+ PKPROCESS Process = Thread->ApcState.Process;
+ PKNODE Node;
+ PKPRCB NodePrcb;
+ ULONG Set, Mask;
+ UCHAR IdealProcessor;
+
+ /* Setup static fields from parent */
+ Thread->Iopl = Process->Iopl;
Thread->Quantum = Process->QuantumReset;
Thread->QuantumReset = Process->QuantumReset;
- Thread->Affinity = Process->Affinity;
+ Thread->SystemAffinityActive = FALSE;
+
+ /* Lock the process */
+ KeAcquireSpinLock(&Process->ProcessLock, &OldIrql);
+
+ /* Setup volatile data */
Thread->Priority = Process->BasePriority;
+ Thread->BasePriority = Process->BasePriority;
+ Thread->Affinity = Process->Affinity;
Thread->UserAffinity = Process->Affinity;
- Thread->DisableBoost = Process->DisableBoost;
- Thread->AutoAlignment = Process->AutoAlignment;
- Thread->Iopl = Process->Iopl;
- /* Set the Thread to initalized */
- Thread->State = Initialized;
+ /* Get the KNODE and its PRCB */
+ Node = KeNodeBlock[Process->IdealNode];
+ NodePrcb = (PKPRCB)(KPCR_BASE + (Process->ThreadSeed * PAGE_SIZE));
- /*
- * Insert the Thread into the Process's Thread List
- * Note, this is the KTHREAD Thread List. It is removed in
- * ke/kthread.c!KeTerminateThread.
- */
+ /* Calculate affinity mask */
+ Set = ~NodePrcb->MultiThreadProcessorSet;
+ Mask = (ULONG)(Node->ProcessorMask & Process->Affinity);
+ Set &= Mask;
+ if (Set) Mask = Set;
+
+ /* Get the new thread seed */
+ IdealProcessor = KeFindNextRightSetAffinity(Process->ThreadSeed, Mask);
+ Process->ThreadSeed = IdealProcessor;
+
+ /* Sanity check */
+ ASSERT((Thread->UserAffinity & AFFINITY_MASK(IdealProcessor)));
+
+ /* Set the Ideal Processor */
+ Thread->IdealProcessor = IdealProcessor;
+ Thread->UserIdealProcessor = IdealProcessor;
+
+ /* Lock the Dispatcher Database */
+ KeAcquireDispatcherDatabaseLockAtDpcLevel();
+
+ /* Insert the thread into the process list */
InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);
- DPRINT("Thread initalized\n");
+
+ /* Increase the stack count */
+ ASSERT(Process->StackCount != MAXULONG_PTR);
+ Process->StackCount++;
+
+ /* Release locks and return */
+ KeReleaseDispatcherDatabaseLockFromDpcLevel();
+ KeReleaseSpinLock(&Process->ProcessLock, OldIrql);
}
+VOID
+NTAPI
+KeInitializeThread(IN PKPROCESS Process,
+ IN OUT PKTHREAD Thread,
+ IN PKSYSTEM_ROUTINE SystemRoutine,
+ IN PKSTART_ROUTINE StartRoutine,
+ IN PVOID StartContext,
+ IN PCONTEXT Context,
+ IN PVOID Teb,
+ IN PVOID KernelStack)
+{
+ /* Initailize and start the thread on success */
+ if (NT_SUCCESS(KeInitThread(Thread,
+ KernelStack,
+ SystemRoutine,
+ StartRoutine,
+ StartContext,
+ Context,
+ Teb,
+ Process)))
+ {
+ /* Start it */
+ KeStartThread(Thread);
+ }
+}
/*
* @implemented
VOID
NTAPI
-KeInitializeProcess(PKPROCESS Process,
- KPRIORITY Priority,
- KAFFINITY Affinity,
- LARGE_INTEGER DirectoryTableBase)
+KeInitializeProcess(IN OUT PKPROCESS Process,
+ IN KPRIORITY Priority,
+ IN KAFFINITY Affinity,
+ IN LARGE_INTEGER DirectoryTableBase)
{
- DPRINT("KeInitializeProcess. Process: %x, DirectoryTableBase: %x\n",
- Process, DirectoryTableBase);
+ ULONG i = 0;
+ UCHAR IdealNode = 0;
+ PKNODE Node;
/* Initialize the Dispatcher Header */
KeInitializeDispatcherHeader(&Process->Header,
sizeof(KPROCESS),
FALSE);
- /* Initialize Scheduler Data, Disable Alignment Faults and Set the PDE */
+ /* Initialize Scheduler Data, Alignment Faults and Set the PDE */
Process->Affinity = Affinity;
- Process->BasePriority = Priority;
+ Process->BasePriority = (CHAR)Priority;
Process->QuantumReset = 6;
Process->DirectoryTableBase = DirectoryTableBase;
Process->AutoAlignment = TRUE;
Process->IopmOffset = 0xFFFF;
- Process->State = ProcessInMemory;
- /* Initialize the Thread List */
+ /* Initialize the lists */
InitializeListHead(&Process->ThreadListHead);
- KeInitializeSpinLock(&Process->ProcessLock);
- DPRINT("The Process has now been initalized with the Kernel\n");
+ InitializeListHead(&Process->ProfileListHead);
+ InitializeListHead(&Process->ReadyListHead);
+
+ /* Initialize the current State */
+ Process->State = ProcessInMemory;
+
+ /* Check how many Nodes there are on the system */
+ if (KeNumberNodes > 1)
+ {
+ /* Set the new seed */
+ KeProcessNodeSeed = (KeProcessNodeSeed + 1) / KeNumberNodes;
+ IdealNode = KeProcessNodeSeed;
+
+ /* Loop every node */
+ do
+ {
+ /* Check if the affinity matches */
+ if (KeNodeBlock[IdealNode]->ProcessorMask != Affinity) break;
+
+ /* No match, try next Ideal Node and increase node loop index */
+ IdealNode++;
+ i++;
+
+ /* Check if the Ideal Node is beyond the total number of nodes */
+ if (IdealNode >= KeNumberNodes)
+ {
+ /* Normalize the Ideal Node */
+ IdealNode -= KeNumberNodes;
+ }
+ } while (i < KeNumberNodes);
+ }
+
+ /* Set the ideal node and get the ideal node block */
+ Process->IdealNode = IdealNode;
+ Node = KeNodeBlock[IdealNode];
+ ASSERT(Node->ProcessorMask & Affinity);
+
+ /* Find the matching affinity set to calculate the thread seed */
+ Affinity &= Node->ProcessorMask;
+ Process->ThreadSeed = KeFindNextRightSetAffinity(Node->Seed,
+ (ULONG)Affinity);
+ Node->Seed = Process->ThreadSeed;
}
ULONG
* - MAJOR: Use Guarded Mutex instead of Fast Mutex for Active Process Locks.
* - Generate process cookie for user-more thread.
* - Add security calls where necessary.
- * - KeInit/StartThread for better isolation of code
*/
/* INCLUDES ****************************************************************/
{
/* Remember that we're dead */
DeadThread = TRUE;
-}
+ }
else
{
/* Get the Locale ID and save Preferred Proc */
HANDLE hThread;
PEPROCESS Process;
PETHREAD Thread;
- PTEB TebBase;
+ PTEB TebBase = NULL;
KIRQL OldIrql;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
HANDLE_TABLE_ENTRY CidEntry;
- ULONG_PTR KernelStack;
PAGED_CODE();
/* If we were called from PsCreateSystemThread, then we're kernel mode */
/* Acquire rundown protection */
ExAcquireRundownProtection(&Process->RundownProtect);
- /* Allocate Stack for non-GUI Thread */
- KernelStack = (ULONG_PTR)MmCreateKernelStack(FALSE) + KERNEL_STACK_SIZE;
-
/* Now let the kernel initialize the context */
if (ThreadContext)
{
Thread->Win32StartAddress = (PVOID)ThreadContext->Eax;
/* Let the kernel intialize the Thread */
- KeInitializeThread(&Process->Pcb,
- &Thread->Tcb,
- PspUserThreadStartup,
- NULL,
- NULL,
- ThreadContext,
- TebBase,
- (PVOID)KernelStack);
+ Status = KeInitThread(&Thread->Tcb,
+ NULL,
+ PspUserThreadStartup,
+ NULL,
+ Thread->StartAddress,
+ ThreadContext,
+ TebBase,
+ &Process->Pcb);
}
else
{
InterlockedOr((PLONG)&Thread->CrossThreadFlags, CT_SYSTEM_THREAD_BIT);
/* Let the kernel intialize the Thread */
- KeInitializeThread(&Process->Pcb,
- &Thread->Tcb,
- PspSystemThreadStartup,
- StartRoutine,
- StartContext,
- NULL,
- NULL,
- (PVOID)KernelStack);
+ Status = KeInitThread(&Thread->Tcb,
+ NULL,
+ PspSystemThreadStartup,
+ StartRoutine,
+ StartContext,
+ NULL,
+ NULL,
+ &Process->Pcb);
}
+ /* Check if we failed */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Delete the TEB if we had done */
+ if (TebBase) MmDeleteTeb(Process, TebBase);
+
+ /* Release rundown and dereference */
+ ExReleaseRundownProtection(&Process->RundownProtect);
+ ObDereferenceObject(Thread);
+ return Status;
+ }
+
+ /* FIXME: Acquire exclusive pushlock */
+
/*
* Insert the Thread into the Process's Thread List
* Note, this is the ETHREAD Thread List. It is removed in
InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);
Process->ActiveThreads++;
+ /* Start the thread */
+ KeStartThread(&Thread->Tcb);
+
+ /* FIXME: Wake pushlock */
+
/* Release rundown */
ExReleaseRundownProtection(&Process->RundownProtect);
PspRunCreateThreadNotifyRoutines(Thread, TRUE);
/* Suspend the Thread if we have to */
- if (CreateSuspended)
- {
- KeSuspendThread(&Thread->Tcb);
- }
+ if (CreateSuspended) KeSuspendThread(&Thread->Tcb);
/* Check if we were already terminated */
if (Thread->Terminated)