Thread Creation and Context Switching re-write, plus Idle/First Thread
minimization attempt. Full changelog on ML, too large to post here
Modified: trunk/reactos/ntoskrnl/Makefile.i386
Modified: trunk/reactos/ntoskrnl/include/internal/arch/ps.h
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ps.h
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h
Modified: trunk/reactos/ntoskrnl/include/internal/ps.h
Modified: trunk/reactos/ntoskrnl/kd/gdbstub.c
Modified: trunk/reactos/ntoskrnl/kd/kdebug.c
Modified: trunk/reactos/ntoskrnl/ke/i386/bios.c
Deleted: trunk/reactos/ntoskrnl/ke/i386/bthread.S
Added: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c
Modified: trunk/reactos/ntoskrnl/ke/i386/gdt.c
Modified: trunk/reactos/ntoskrnl/ke/i386/idt.c
Modified: trunk/reactos/ntoskrnl/ke/i386/kernel.c
Modified: trunk/reactos/ntoskrnl/ke/i386/ldt.c
Modified: trunk/reactos/ntoskrnl/ke/i386/thread.c
Deleted: trunk/reactos/ntoskrnl/ke/i386/tskswitch.S
Modified: trunk/reactos/ntoskrnl/ke/i386/v86m.c
Modified: trunk/reactos/ntoskrnl/ke/kthread.c
Modified: trunk/reactos/ntoskrnl/ke/main.c
Modified: trunk/reactos/ntoskrnl/ps/debug.c
Modified: trunk/reactos/ntoskrnl/ps/idle.c
Modified: trunk/reactos/ntoskrnl/ps/kill.c
Modified: trunk/reactos/ntoskrnl/ps/psmgr.c
Modified: trunk/reactos/ntoskrnl/ps/thread.c
_____
Modified: trunk/reactos/ntoskrnl/Makefile.i386
--- trunk/reactos/ntoskrnl/Makefile.i386 2005-04-22 12:46:27 UTC
(rev 14741)
+++ trunk/reactos/ntoskrnl/Makefile.i386 2005-04-22 12:52:25 UTC
(rev 14742)
@@ -17,9 +17,8 @@
ke/i386/thread.o \
ke/i386/usercall.o \
ke/i386/trap.o \
- ke/i386/bthread.o \
ke/i386/syscall.o \
- ke/i386/tskswitch.o \
+ ke/i386/ctxswitch.o \
ke/i386/v86m.o \
ke/i386/v86m_sup.o \
ke/i386/vdm.o \
_____
Modified: trunk/reactos/ntoskrnl/include/internal/arch/ps.h
--- trunk/reactos/ntoskrnl/include/internal/arch/ps.h 2005-04-22
12:46:27 UTC (rev 14741)
+++ trunk/reactos/ntoskrnl/include/internal/arch/ps.h 2005-04-22
12:52:25 UTC (rev 14742)
@@ -21,8 +21,7 @@
#ifdef i386
#include <internal/i386/ps.h>
-#define KiArchContextSwitch Ki386ContextSwitch
-#define KiArchInitThread Ke386InitThread
+#define KiArchContextSwitch KiSwapContext
#define KiArchInitThreadWithContext Ke386InitThreadWithContext
#else
#error "Unknown processor"
_____
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h
--- trunk/reactos/ntoskrnl/include/internal/i386/ke.h 2005-04-22
12:46:27 UTC (rev 14741)
+++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h 2005-04-22
12:52:25 UTC (rev 14742)
@@ -203,6 +203,28 @@
VOID
KeCreateApplicationProcessorIdleThread(ULONG Id);
+typedef
+VOID
+STDCALL
+(*PKSYSTEM_ROUTINE)(PKSTART_ROUTINE StartRoutine,
+ PVOID StartContext);
+
+VOID
+STDCALL
+Ke386InitThreadWithContext(PKTHREAD Thread,
+ PKSYSTEM_ROUTINE SystemRoutine,
+ PKSTART_ROUTINE StartRoutine,
+ PVOID StartContext,
+ PCONTEXT Context);
+
+VOID
+STDCALL
+KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
+ PKSTART_ROUTINE StartRoutine,
+ PVOID StartContext,
+ BOOLEAN UserThread,
+ KTRAP_FRAME TrapFrame);
+
#ifdef CONFIG_SMP
#define LOCK "lock ; "
#else
_____
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ps.h
--- trunk/reactos/ntoskrnl/include/internal/i386/ps.h 2005-04-22
12:46:27 UTC (rev 14741)
+++ trunk/reactos/ntoskrnl/include/internal/i386/ps.h 2005-04-22
12:52:25 UTC (rev 14742)
@@ -27,8 +27,12 @@
#define KTHREAD_TEB 0x20
#define KTHREAD_KERNEL_STACK 0x28
#define KTHREAD_NPX_STATE 0x31
+#define KTHREAD_STATE 0x2D
+#define KTHREAD_APCSTATE_PROCESS 0x34 + 0x10
#define KTHREAD_PENDING_USER_APC 0x34 + 0x16
-#define KTHREAD_APCSTATE_PROCESS 0x44
+#define KTHREAD_PENDING_KERNEL_APC 0x34 + 0x15
+#define KTHREAD_CONTEXT_SWITCHES 0x4C
+#define KTHREAD_WAIT_IRQL 0x54
#define KTHREAD_SERVICE_TABLE 0xDC
#define KTHREAD_PREVIOUS_MODE 0x137
#define KTHREAD_TRAP_FRAME 0x128
@@ -44,7 +48,9 @@
#define KPCR_EXCEPTION_LIST 0x0
#define KPCR_INITIAL_STACK 0x4
+#define KPCR_STACK_LIMIT 0x8
#define KPCR_SELF 0x1C
+#define KPCR_GDT 0x3C
#define KPCR_TSS 0x40
#define KPCR_CURRENT_THREAD 0x124
#define KPCR_NPX_THREAD 0x2A4
@@ -298,17 +304,6 @@
#endif /* __USE_W32API */
-VOID
-Ki386ContextSwitch(struct _KTHREAD* NewThread,
- struct _KTHREAD* OldThread);
-NTSTATUS
-Ke386InitThread(struct _KTHREAD* Thread, PKSTART_ROUTINE fn,
- PVOID StartContext);
-NTSTATUS
-Ke386InitThreadWithContext(struct _KTHREAD* Thread, PCONTEXT Context);
-NTSTATUS
-Ki386ValidateUserContext(PCONTEXT Context);
-
#endif /* __ASM__ */
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_PS_H */
_____
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
--- trunk/reactos/ntoskrnl/include/internal/ke.h 2005-04-22
12:46:27 UTC (rev 14741)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h 2005-04-22
12:52:25 UTC (rev 14742)
@@ -114,6 +114,10 @@
NTSTATUS
STDCALL
KeSuspendThread(PKTHREAD Thread);
+
+NTSTATUS
+FASTCALL
+KiSwapContext(PKTHREAD NewThread);
/* gmutex.c
********************************************************************/
@@ -238,9 +242,16 @@
VOID inline FASTCALL KeReleaseDispatcherDatabaseLock(KIRQL Irql);
VOID inline FASTCALL KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID);
-VOID
+VOID
STDCALL
-KeInitializeThread(struct _KPROCESS* Process, PKTHREAD Thread, BOOLEAN
First);
+KeInitializeThread(struct _KPROCESS* Process,
+ PKTHREAD Thread,
+ PKSYSTEM_ROUTINE SystemRoutine,
+ PKSTART_ROUTINE StartRoutine,
+ PVOID StartContext,
+ PCONTEXT Context,
+ PVOID Teb,
+ PVOID KernelStack);
VOID
STDCALL
_____
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h
--- trunk/reactos/ntoskrnl/include/internal/mm.h 2005-04-22
12:46:27 UTC (rev 14741)
+++ trunk/reactos/ntoskrnl/include/internal/mm.h 2005-04-22
12:52:25 UTC (rev 14742)
@@ -508,6 +508,17 @@
STDCALL
MmCreatePeb(PEPROCESS Process);
+PTEB
+STDCALL
+MmCreateTeb(PEPROCESS Process,
+ PCLIENT_ID ClientId,
+ PINITIAL_TEB InitialTeb);
+
+VOID
+STDCALL
+MmDeleteTeb(PEPROCESS Process,
+ PTEB Teb);
+
/* i386/pfault.c
*************************************************************/
NTSTATUS MmPageFault(ULONG Cs,
_____
Modified: trunk/reactos/ntoskrnl/include/internal/ps.h
--- trunk/reactos/ntoskrnl/include/internal/ps.h 2005-04-22
12:46:27 UTC (rev 14741)
+++ trunk/reactos/ntoskrnl/include/internal/ps.h 2005-04-22
12:52:25 UTC (rev 14742)
@@ -497,7 +497,18 @@
PEPROCESS Parent OPTIONAL);
-
+VOID
+STDCALL
+PspSystemThreadStartup(PKSTART_ROUTINE StartRoutine,
+ PVOID StartContext);
+
+NTSTATUS
+PsInitializeIdleOrFirstThread (
+ PEPROCESS Process,
+ PETHREAD* ThreadPtr,
+ PKSTART_ROUTINE StartRoutine,
+ KPROCESSOR_MODE AccessMode,
+ BOOLEAN First);
/*
* Internal thread priorities, added by Phillip Susi
* TODO: rebalence these to make use of all priorities... the ones
above 16
_____
Modified: trunk/reactos/ntoskrnl/kd/gdbstub.c
--- trunk/reactos/ntoskrnl/kd/gdbstub.c 2005-04-22 12:46:27 UTC (rev
14741)
+++ trunk/reactos/ntoskrnl/kd/gdbstub.c 2005-04-22 12:52:25 UTC (rev
14742)
@@ -131,6 +131,20 @@
#define EIP_REGNO 8
+typedef
+VOID
+STDCALL_FUNC
+(*PKSYSTEM_ROUTINE)(PKSTART_ROUTINE StartRoutine,
+ PVOID StartContext);
+
+VOID
+STDCALL
+KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
+ PKSTART_ROUTINE StartRoutine,
+ PVOID StartContext,
+ BOOLEAN UserThread,
+ KTRAP_FRAME TrapFrame);
+
static CPU_REGISTER GspRegisters[NUMREGS] =
{
{ 4, FIELD_OFFSET (KTRAP_FRAME_X86, Eax), FIELD_OFFSET (CONTEXT,
Eax), TRUE },
@@ -582,7 +596,7 @@
* This thread has not been sheduled yet so assume it
* is still in PsBeginThreadWithContextInternal().
*/
- Value = (ULONG) PsBeginThreadWithContextInternal;
+ Value = (ULONG)KiThreadStartup;
}
else
{
_____
Modified: trunk/reactos/ntoskrnl/kd/kdebug.c
--- trunk/reactos/ntoskrnl/kd/kdebug.c 2005-04-22 12:46:27 UTC (rev
14741)
+++ trunk/reactos/ntoskrnl/kd/kdebug.c 2005-04-22 12:52:25 UTC (rev
14742)
@@ -426,7 +426,7 @@
VOID STDCALL
KdSystemDebugControl(ULONG Code)
{
- extern VOID PsDumpThreads(BOOLEAN IncludeSystem);
+ extern VOID STDCALL PspDumpThreads(BOOLEAN IncludeSystem);
/* A - Dump the entire contents of the non-paged pool. */
if (Code == 0)
@@ -462,12 +462,12 @@
/* F */
else if (Code == 5)
{
- PsDumpThreads(TRUE);
+ PspDumpThreads(TRUE);
}
/* G */
else if (Code == 6)
{
- PsDumpThreads(FALSE);
+ PspDumpThreads(FALSE);
}
/* H */
else if (Code == 7)
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/bios.c
--- trunk/reactos/ntoskrnl/ke/i386/bios.c 2005-04-22 12:46:27 UTC
(rev 14741)
+++ trunk/reactos/ntoskrnl/ke/i386/bios.c 2005-04-22 12:52:25 UTC
(rev 14742)
@@ -1,4 +1,4 @@
-/* $Id:$
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
_____
Deleted: trunk/reactos/ntoskrnl/ke/i386/bthread.S
--- trunk/reactos/ntoskrnl/ke/i386/bthread.S 2005-04-22 12:46:27 UTC
(rev 14741)
+++ trunk/reactos/ntoskrnl/ke/i386/bthread.S 2005-04-22 12:52:25 UTC
(rev 14742)
@@ -1,146 +0,0 @@
-/*
- * ReactOS kernel
- * Copyright (C) 2000 David Welch <welch(a)cwcom.net>
- *
- * This program is free software; you can redistribute it and/or
modify
- * it under the terms of the GNU General Public License as published
by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id$
- *
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/ke/i386/bthread.S
- * PURPOSE: Trap handlers
- * PROGRAMMER: David Welch (david.welch(a)seh.ox.ac.uk)
- */
-
-/* INCLUDES
******************************************************************/
-
-#include <ddk/status.h>
-#include <internal/i386/segment.h>
-#include <internal/ps.h>
-#include <ddk/defines.h>
-
-/* Values for contextflags */
-#define CONTEXT_i386 0x10000
-#ifndef CONTEXT_CONTROL
-#define CONTEXT_CONTROL (CONTEXT_i386 | 1)
-#endif
-#ifndef CONTEXT_INTEGER
-#define CONTEXT_INTEGER (CONTEXT_i386 | 2)
-#endif
-#ifndef CONTEXT_SEGMENTS
-#define CONTEXT_SEGMENTS (CONTEXT_i386 | 4)
-#endif
-#ifndef CONTEXT_FLOATING_POINT
-#define CONTEXT_FLOATING_POINT (CONTEXT_i386 | 8)
-#endif
-#ifndef CONTEXT_DEBUG_REGISTERS
-#define CONTEXT_DEBUG_REGISTERS (CONTEXT_i386 | 0x10)
-#endif
-#ifndef CONTEXT_FULL
-#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER |
CONTEXT_SEGMENTS)
-#endif
-
-/* FUNCTIONS
*****************************************************************/
-
-/*
- *
- */
-
-.globl _PsBeginThreadWithContextInternal
-.globl _PsBeginThread
-
-_PsBeginThread:
- /*
- * This isn't really a function, we are called as the return
address
- * of the context switch function
- */
-
- /*
- * Do the necessary prolog after a context switch
- */
- call _PiBeforeBeginThread
-
- /*
- * Call the actual start of the thread
- */
- movl 4(%esp), %ebx /* Start routine */
- movl 8(%esp), %eax /* Start context */
- pushl %eax
- call *%ebx /* Call the start routine
*/
- addl $4, %esp
-
- /*
- * Terminate the thread
- */
- pushl %eax
- call _PsTerminateSystemThread@4
- addl $4, %esp
-
- /*
- * If that fails then bug check
- */
- pushl $0
- call _KeBugCheck@4
- addl $4, %esp
-
- /*
- * And if that fails then loop
- */
-.1:
- jmp .1
-
-
-_PsBeginThreadWithContextInternal:
- /*
- * This isn't really a function, we are called as the return
- * address of a context switch
- */
-
- /*
- * Do the necessary prolog before the context switch
- */
- call _PiBeforeBeginThread
-
- /*
- * Load the context flags.
- */
- popl %ebx
-
- /*
- * Load the debugging registers
- */
- testl $(CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386), %ebx
- jz .L1
- popl %eax /* Dr0 */
- movl %eax, %dr0
- popl %eax /* Dr1 */
- movl %eax, %dr1
- popl %eax /* Dr2 */
- movl %eax, %dr2
- popl %eax /* Dr3 */
- movl %eax, %dr3
- popl %eax /* Dr6 */
- movl %eax, %dr6
- popl %eax /* Dr7 */
- movl %eax, %dr7
- jmp .L3
-.L1:
- addl $24, %esp
-.L3:
-
- /* Load the rest of the thread's user mode context. */
- movl $0, %eax
- jmp _KiServiceExit
_____
Added: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
--- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S 2005-04-22 12:46:27 UTC
(rev 14741)
+++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S 2005-04-22 12:52:25 UTC
(rev 14742)
@@ -0,0 +1,290 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/ke/i386/ctxswitch.S
+ * PURPOSE: Thread Context Switching
+ *
+ * PROGRAMMERS: Alex Ionescu (alex(a)relsoft.net)
+ */
+
+/* INCLUDES
******************************************************************/
+
+#include <roscfg.h>
+#include <internal/i386/segment.h>
+#include <internal/i386/ke.h>
+#include <internal/i386/fpu.h>
+#include <internal/ps.h>
+#include <ntos/tss.h>
+#include <internal/ntoskrnl.h>
+.intel_syntax noprefix
+
+#define Running 2
+#define SIZEOF_TRAP_FRAME 0x8c
+#define APC_LEVEL 1
+
+/* GLOBALS
****************************************************************/
+
+/* FUNCTIONS
****************************************************************/
+
+/*++
+ * KiThreadStartup
+ *
+ * The KiThreadStartup routine is the beginning of any thread.
+ *
+ * Params:
+ * SystemRoutine - Pointer to the System Startup Routine. Either
+ * PspUserThreadStartup or PspSystemThreadStartup
+ *
+ * StartRoutine - For Kernel Threads only, specifies the starting
execution
+ * point of the new thread.
+ *
+ * StartContext - For Kernel Threads only, specifies a pointer to
variable
+ * context data to be sent to the StartRoutine
above.
+ *
+ * UserThread - Indicates whether or not this is a user thread.
This tells
+ * us if the thread has a context or not.
+ *
+ * TrapFrame - Pointer to the KTHREAD to which the caller wishes to
+ * switch from.
+ *
+ * Returns:
+ * Should never return for a system thread. Returns through the
System Call
+ * Exit Dispatcher for a user thread.
+ *
+ * Remarks:
+ * If a return from a system thread is detected, a bug check will
occur.
+ *
+ *--*/
+.globl _KiThreadStartup@156
+_KiThreadStartup@156:
+
+ /*
+ * Clear all the non-volatile registers, so the thread won't be
tempted to
+ * expect any static data (like some badly coded usermode/win9x
apps do)
+ */
+ xor ebx, ebx
+ xor esi, edi
+ xor edi, edi
+ xor ebp, ebp
+
+ /* It's now safe to go to APC */
+ mov ecx, APC_LEVEL
+ call @KfLowerIrql@4
+
+ /*
+ * Call the System Routine which is right on our stack now.
+ * After we pop the pointer, the Start Routine/Context will be on
the
+ * stack, as parameters to the System Routine
+ */
+ pop eax
+ call eax
+
+ /* The thread returned... was it a user-thread? */
+ pop ecx
+ or ecx, ecx
+ jz BadThread
+
+ /* Yes it was, set our trapframe for the System Call Exit
Dispatcher */
+ mov ebp, esp
+
+ /* Exit back to user-mode */
+ jmp _KiServiceExit
+
+BadThread:
+
+ /* A system thread returned...this is very bad! */
+ int 3
+
+/*++
+ * KiSwapContextInternal
+ *
+ * The KiSwapContextInternal routine switches context to another
thread.
+ *
+ * Params:
+ * ESI - Pointer to the KTHREAD to which the caller wishes to
+ * switch to.
+ * EDI - Pointer to the KTHREAD to which the caller wishes to
+ * switch from.
+ *
+ * Returns:
+ * None.
+ *
+ * Remarks:
+ * Absolutely all registers except ESP can be trampled here for
maximum code flexibility.
+ *
+ *--*/
+.globl @KiSwapContextInternal@0
+@KiSwapContextInternal@0:
+
+ /* Get the PCR. It's faster to use ebx+offset then fs:offset */
+ mov ebx, [fs:0x1C]
+
+ /* Set the Thread to running */
+ mov byte ptr [esi+KTHREAD_STATE], Running
+
+ /* Save the Exception list */
+ push [ebx+KPCR_EXCEPTION_LIST]
+
+ /* Switching, disable interrupts now */
+ cli
+
+#ifdef CONFIG_SMP
+ /* Save FPU state if the thread has used it. */
+ mov [ebx+KPCR_NPX_THREAD], 0
+ test byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_DIRTY
+ jz 3f
+ mov eax, [edi+KTHREAD_INITIAL_STACK]
+ cmp _FxsrSupport, 0
+ je 1f
+ fxsave [eax-SIZEOF_FX_SAVE_AREA]
+ jmp 2f
+1:
+ fnsave [eax-SIZEOF_FX_SAVE_AREA]
+2:
+ mov byte ptr [edi+KTHREAD_INITIAL_STACK], NPX_STATE_VALID
+3:
+#endif /* CONFIG_SMP */
+
+ /* Save the stack pointer in this processors TSS */
+ mov ebp, [ebx+KPCR_TSS]
+ push ss:[ebp+KTSS_ESP0]
+
+ /* Switch stacks */
+ mov [edi+KTHREAD_KERNEL_STACK], esp
+ mov esp, [esi+KTHREAD_KERNEL_STACK]
+
+ /* Stack is OK, safe to enable interrupts now */
+ sti
+
+ /* Check if address space switch is needed */
+ mov eax, [edi+KTHREAD_APCSTATE_PROCESS]
+ cmp eax, [esi+KTHREAD_APCSTATE_PROCESS]
+
+ /* If they match, then use the fast-path and skip all this */
+ jz SameProcess
+
+ /* Get the new Process. */
+ mov edi, [esi+KTHREAD_APCSTATE_PROCESS]
+
+ /* Check if we need an LDT */
+ xor eax, eax
+ cmp [edi+KPROCESS_LDT_DESCRIPTOR0], eax
+ jz NoLdt
+
+ /* Write the LDT Selector */
+ mov ebp, [ebx+KPCR_GDT]
+ mov eax, [edi+KPROCESS_LDT_DESCRIPTOR0]
+ mov [ebp+LDT_SELECTOR], eax
+ mov eax, [edi+KPROCESS_LDT_DESCRIPTOR1]
+ mov [ebp+LDT_SELECTOR+4], eax
+
+ /* Save LDT Selector */
+ mov eax, LDT_SELECTOR
+
+NoLdt:
+
+ /* Load LDT */
+ lldt ax
+
+ /* Get the IOPM */
+ mov ecx, [edi+KPROCESS_IOPM_OFFSET]
+
+ /* Set current IOPM offset in the TSS */
+ mov [ebp+KTSS_IOMAPBASE], cx
+
+ /* Change the address space */
+ mov eax, [edi+KPROCESS_DIRECTORY_TABLE_BASE]
+ mov cr3, eax
+
+SameProcess:
+
+ /* Set the TEB */
+ mov eax, [esi+KTHREAD_TEB]
+ mov ecx, [ebx+KPCR_GDT]
+ mov [ecx+0x3A], ax
+ shr eax, 16
+ mov [ecx+0x3C], al
+ mov [ecx+0x3F], ah
+
+ /* Increase context switches */
+ inc dword ptr [esi+KTHREAD_CONTEXT_SWITCHES]
+
+ /* Set TS in cr0 to catch FPU code and load the FPU state when
needed */
+#ifndef CONFIG_SMP
+ cmp [ebx+KPCR_NPX_THREAD], esi
+ je 4f
+#endif /* !CONFIG_SMP */
+ mov eax, cr0
+ or eax, X86_CR0_TS
+ mov cr0, eax
+4:
+
+ /* Restore the stack pointer in this processors TSS */
+ pop ss:[ebp+KTSS_ESP0]
+
+ /* Restore exception list */
+ pop [ebx+KPCR_EXCEPTION_LIST]
+
+ call @KeReleaseDispatcherDatabaseLockFromDpcLevel@0
+
+ /* Return */
+ ret
+
+/*++
+ * KiSwapContext
+ *
+ * The KiSwapContext routine switches context to another thread.
+ *
+ * Params:
+ * TargetThread - Pointer to the KTHREAD to which the caller wishes
to
+ * switch to.
+ *
+ * Returns:
+ * The WaitStatus of the Target Thread. NOT YET SUPPORTED.
+ *
+ * Remarks:
+ * This is a wrapper around KiSwapContextInternal which will save
all the
+ * non-volatile registers so that the Internal function can use all
of
+ * them. It will also save the old current thread and set the new
one.
+ *
+ * The calling thread does not return after KiSwapContextInternal
until
+ * another thread switches to IT.
+ *
+ *--*/
+.globl @KiSwapContext@4
+@KiSwapContext@4:
+
+ /* Note, we CANNOT touch ebp */
+
+ /* Save 4 registers */
+ sub esp, 4 * 4
+
+ /* Save all the non-volatile ones */
+ mov [esp+12], ebx
+ mov [esp+8], esi
+ mov [esp+4], edi
+ mov [esp+0], ebp
+
+ /* Get the Current Thread */
+ mov edi, fs:[KPCR_CURRENT_THREAD]
+
+ /* Get the New Thread */
+ mov esi, ecx
+
+ /* Save it as Current thread */
+ mov fs:[KPCR_CURRENT_THREAD], esi
+
+ /* Do the swap with the registers correctly setup */
+ call @KiSwapContextInternal@0
+
+ /* Return the registers */
+ mov ebp, [esp+0]
+ mov esi, [esp+4]
+ mov edi, [esp+8]
+ mov ebx, [esp+12]
+
+ /* Clean stack */
+ add esp, 4 * 4
+
+ ret
+
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c
--- trunk/reactos/ntoskrnl/ke/i386/exp.c 2005-04-22 12:46:27 UTC
(rev 14741)
+++ trunk/reactos/ntoskrnl/ke/i386/exp.c 2005-04-22 12:52:25 UTC
(rev 14742)
@@ -502,6 +502,7 @@
*/
if (Tf->Eflags & (1 << 17))
{
+ DPRINT("Tf->Eflags, %x, Tf->Eip %x, ExceptionNr: %d\n",
Tf->Eflags, Tf->Eip, ExceptionNr);
return(KeV86Exception(ExceptionNr, Tf, cr2));
}
@@ -511,7 +512,7 @@
if (PsGetCurrentThread() != NULL &&
Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
{
- DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
+ DPRINT1("Stack underflow (tf->esp %x Limit %x)\n",
Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
ExceptionNr = 12;
}
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/gdt.c
--- trunk/reactos/ntoskrnl/ke/i386/gdt.c 2005-04-22 12:46:27 UTC
(rev 14741)
+++ trunk/reactos/ntoskrnl/ke/i386/gdt.c 2005-04-22 12:52:25 UTC
(rev 14742)
@@ -1,4 +1,4 @@
-/* $Id:$
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/idt.c
--- trunk/reactos/ntoskrnl/ke/i386/idt.c 2005-04-22 12:46:27 UTC
(rev 14741)
+++ trunk/reactos/ntoskrnl/ke/i386/idt.c 2005-04-22 12:52:25 UTC
(rev 14742)
@@ -1,4 +1,4 @@
-/* $Id:$
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/kernel.c
--- trunk/reactos/ntoskrnl/ke/i386/kernel.c 2005-04-22 12:46:27 UTC
(rev 14741)
+++ trunk/reactos/ntoskrnl/ke/i386/kernel.c 2005-04-22 12:52:25 UTC
(rev 14742)
@@ -133,7 +133,7 @@
IdleProcessorMask |= (1 << KeGetCurrentProcessorNumber());
KeReleaseDispatcherDatabaseLock(oldIrql);
}
-
+
VOID
INIT_FUNCTION
KeCreateApplicationProcessorIdleThread(ULONG Id)
@@ -141,11 +141,11 @@
PETHREAD IdleThread;
PKPRCB Prcb = ((PKPCR)((ULONG_PTR)KPCR_BASE + Id * PAGE_SIZE))->Prcb;
- PsInitializeThread(PsIdleProcess,
+ PsInitializeIdleOrFirstThread(PsIdleProcess,
&IdleThread,
NULL,
- KernelMode,
- FALSE);
+ KernelMode,
+ FALSE);
IdleThread->Tcb.State = Running;
IdleThread->Tcb.FreezeCount = 0;
IdleThread->Tcb.Affinity = 1 << Id;
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/ldt.c
--- trunk/reactos/ntoskrnl/ke/i386/ldt.c 2005-04-22 12:46:27 UTC
(rev 14741)
+++ trunk/reactos/ntoskrnl/ke/i386/ldt.c 2005-04-22 12:52:25 UTC
(rev 14742)
@@ -1,4 +1,4 @@
-/* $Id:$
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/thread.c
--- trunk/reactos/ntoskrnl/ke/i386/thread.c 2005-04-22 12:46:27 UTC
(rev 14741)
+++ trunk/reactos/ntoskrnl/ke/i386/thread.c 2005-04-22 12:52:25 UTC
(rev 14742)
@@ -1,11 +1,10 @@
-/* $Id:$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/i386/thread.c
- * PURPOSE: Architecture multitasking functions
+ * PURPOSE: i386 Thread Context Creation
*
- * PROGRAMMERS: David Welch (welch(a)cwcom.net)
+ * PROGRAMMERS: Alex Ionescu (alex(a)relsoft.net)
*/
/* INCLUDES
****************************************************************/
@@ -13,172 +12,177 @@
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
+
+typedef struct _KSHARED_CTXSWITCH_FRAME {
+ ULONG Esp0;
+ PVOID ExceptionList;
+ PVOID RetEip;
+} KSHARED_CTXSWITCH_FRAME, *PKSHARED_CTXSWITCH_FRAME;
-/* FUNCTIONS
*****************************************************************/
+typedef struct _KSTART_FRAME {
+ PKSYSTEM_ROUTINE SystemRoutine;
+ PKSTART_ROUTINE StartRoutine;
+ PVOID StartContext;
+ BOOLEAN UserThread;
+} KSTART_FRAME, *PKSTART_FRAME;
-NTSTATUS
-Ki386ValidateUserContext(PCONTEXT Context)
/*
- * FUNCTION: Validates a processor context
- * ARGUMENTS:
- * Context = Context to validate
- * RETURNS: Status
- * NOTE: This only validates the context as not violating system
security, it
- * doesn't guararantee the thread won't crash at some point
- * NOTE2: This relies on there only being two selectors which can
access
- * system space
+ * This is the Initial Thread Stack Frame on i386.
+ *
+ * It is composed of :
+ *
+ * - A shared Thread Switching frame so that we can use
+ * the context-switching code when initializing the thread.
+ *
+ * - The Stack Frame for KiThreadStartup, which are the parameters
+ * that it will receive (System/Start Routines & Context)
+ *
+ * - A Trap Frame with the Initial Context *IF AND ONLY IF THE
THREAD IS USER*
+ *
+ * - The FPU Save Area, theoretically part of the Trap Frame's
"ExtendedRegisters"
+ *
+ * This Initial Thread Stack Frame starts at Thread->InitialStack and
it spans
+ * a total size of 0x2B8 bytes.
*/
-{
- if (Context->Eip >= KERNEL_BASE)
- {
- return(STATUS_UNSUCCESSFUL);
- }
- if (Context->SegCs == KERNEL_CS)
- {
- return(STATUS_UNSUCCESSFUL);
- }
- if (Context->SegDs == KERNEL_DS)
- {
- return(STATUS_UNSUCCESSFUL);
- }
- if (Context->SegEs == KERNEL_DS)
- {
- return(STATUS_UNSUCCESSFUL);
- }
- if (Context->SegFs == KERNEL_DS)
- {
- return(STATUS_UNSUCCESSFUL);
- }
- if (Context->SegGs == KERNEL_DS)
- {
- return(STATUS_UNSUCCESSFUL);
- }
- if ((Context->EFlags & X86_EFLAGS_IOPL) != 0 ||
- (Context->EFlags & X86_EFLAGS_NT) ||
- (Context->EFlags & X86_EFLAGS_VM) ||
- (!(Context->EFlags & X86_EFLAGS_IF)))
- {
- return(STATUS_UNSUCCESSFUL);
- }
- return(STATUS_SUCCESS);
-}
+typedef struct _KUINIT_FRAME {
+ KSHARED_CTXSWITCH_FRAME CtxSwitchFrame; /* -0x2B8 */
+ KSTART_FRAME StartFrame; /* -0x2AC */
+ KTRAP_FRAME TrapFrame; /* -0x29C */
+ FX_SAVE_AREA FxSaveArea; /* -0x210 */
+} KUINIT_FRAME, *PKUINIT_FRAME;
-NTSTATUS
-Ke386InitThreadWithContext(PKTHREAD Thread, PCONTEXT Context)
-{
- PULONG KernelStack;
- ULONG InitSize;
- PKTRAP_FRAME TrapFrame;
- PFX_SAVE_AREA FxSaveArea;
+typedef struct _KKINIT_FRAME {
+ KSHARED_CTXSWITCH_FRAME CtxSwitchFrame; /* -0x22C */
+ KSTART_FRAME StartFrame; /* -0x220 */
+ FX_SAVE_AREA FxSaveArea; /* -0x210 */
+} KKINIT_FRAME, *PKKINIT_FRAME;
- /*
- * Setup a stack frame for exit from the task switching routine
- */
-
- InitSize = 6 * sizeof(DWORD) + sizeof(DWORD) + 6 * sizeof(DWORD) +
- + sizeof(KTRAP_FRAME) + sizeof (FX_SAVE_AREA);
- KernelStack = (PULONG)((char*)Thread->KernelStack - InitSize);
+/* FUNCTIONS
*****************************************************************/
- /* Set up the initial frame for the return from the dispatcher. */
- KernelStack[0] = (ULONG)Thread->InitialStack - sizeof(FX_SAVE_AREA);
/* TSS->Esp0 */
- KernelStack[1] = 0; /* EDI */
- KernelStack[2] = 0; /* ESI */
- KernelStack[3] = 0; /* EBX */
- KernelStack[4] = 0; /* EBP */
- KernelStack[5] = (ULONG)&PsBeginThreadWithContextInternal; /* EIP
*/
+VOID
+STDCALL
+Ke386InitThreadWithContext(PKTHREAD Thread,
+ PKSYSTEM_ROUTINE SystemRoutine,
+ PKSTART_ROUTINE StartRoutine,
+ PVOID StartContext,
+ PCONTEXT Context)
+{
+ PFX_SAVE_AREA FxSaveArea;
+ PKSTART_FRAME StartFrame;
+ PKSHARED_CTXSWITCH_FRAME CtxSwitchFrame;
+ PKTRAP_FRAME TrapFrame = NULL;
+
+ /* Check if this is a With-Context Thread */
+ DPRINT("Ke386InitThreadContext\n");
+ if (Context) {
+
+ /* Set up the Initial Frame */
+ PKUINIT_FRAME InitFrame;
+ InitFrame = (PKUINIT_FRAME)((ULONG_PTR)Thread->InitialStack -
sizeof(KUINIT_FRAME));
+ DPRINT("Setting up a user-mode thread with the Frame at: %x\n",
InitFrame);
+
+ /* Setup the Fx Area */
+ FxSaveArea = &InitFrame->FxSaveArea;
+ DPRINT("Fx Save Area: %x\n", FxSaveArea);
+
+ /* Setup the Initial Fx State */
+ if (KiContextToFxSaveArea(FxSaveArea, Context)) {
- /* Save the context flags. */
- KernelStack[6] = Context->ContextFlags;
-
- /* Set up the initial values of the debugging registers. */
- KernelStack[7] = Context->Dr0;
- KernelStack[8] = Context->Dr1;
- KernelStack[9] = Context->Dr2;
- KernelStack[10] = Context->Dr3;
- KernelStack[11] = Context->Dr6;
- KernelStack[12] = Context->Dr7;
-
- /* Set up a trap frame from the context. */
- TrapFrame = (PKTRAP_FRAME)(&KernelStack[13]);
- TrapFrame->DebugEbp = (PVOID)Context->Ebp;
- TrapFrame->DebugEip = (PVOID)Context->Eip;
- TrapFrame->DebugArgMark = 0;
- TrapFrame->DebugPointer = 0;
- TrapFrame->TempCs = 0;
- TrapFrame->TempEip = 0;
- TrapFrame->Gs = (USHORT)Context->SegGs;
- TrapFrame->Es = (USHORT)Context->SegEs;
- TrapFrame->Ds = (USHORT)Context->SegDs;
- TrapFrame->Edx = Context->Edx;
- TrapFrame->Ecx = Context->Ecx;
- TrapFrame->Eax = Context->Eax;
- TrapFrame->PreviousMode = UserMode;
- TrapFrame->ExceptionList = (PVOID)0xFFFFFFFF;
- TrapFrame->Fs = TEB_SELECTOR;
- TrapFrame->Edi = Context->Edi;
- TrapFrame->Esi = Context->Esi;
- TrapFrame->Ebx = Context->Ebx;
- TrapFrame->Ebp = Context->Ebp;
- TrapFrame->ErrorCode = 0;
- TrapFrame->Cs = Context->SegCs;
- TrapFrame->Eip = Context->Eip;
- TrapFrame->Eflags = Context->EFlags | X86_EFLAGS_IF;
- TrapFrame->Eflags &= ~(X86_EFLAGS_VM | X86_EFLAGS_NT |
X86_EFLAGS_IOPL);
- TrapFrame->Esp = Context->Esp;
- TrapFrame->Ss = (USHORT)Context->SegSs;
- /* FIXME: Should check for a v86 mode context here. */
-
- /* Set up the initial floating point state. */
- /* FIXME: Do we have to zero the FxSaveArea or is it already? */
- FxSaveArea = (PFX_SAVE_AREA)((ULONG_PTR)KernelStack + InitSize -
sizeof(FX_SAVE_AREA));
- if (KiContextToFxSaveArea(FxSaveArea, Context))
- {
- Thread->NpxState = NPX_STATE_VALID;
+ Thread->NpxState = NPX_STATE_VALID;
+
+ } else {
[truncated at 1000 lines; 2134 more skipped]