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@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@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@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@cwcom.net)
+ * PROGRAMMERS:     Alex Ionescu (alex@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]