Fixes for APC handling

Fixes for exceptions
Remove KeAddTimeoutThread
Beginnings of debug handling
Fixes for contiguous memory allocation
Cancel the thread timer before termination

svn path=/trunk/; revision=1709
This commit is contained in:
David Welch 2001-03-18 19:35:14 +00:00
parent 01846dd237
commit d60628a01b
27 changed files with 951 additions and 715 deletions

View file

@ -1,5 +1,5 @@
file ntoskrnl/ntoskrnl.nostrip.exe
#add-symbol-file lib/ntdll/ntdll.dll 0x77f61000
#add-symbol-file apps/apc/apc.exe 0x401000
#add-symbol-file apps/exp/exp.exe 0x401000
#add-symbol-file subsys/csrss/csrss.exe 0x401000
break exp.c:154
break exp.c:254

View file

@ -1,3 +1,8 @@
2001-03-17 David Welch <welch@cwcom.net>
* ntoskrnl/ke/catch.c (KiDispatchException): Implementation of
exception handling, user-mode only.
2001-03-16 David Welch <welch@cwcom.net>
* include/ddk/zw.h: Corrected declarations of NtCreateProfile,

View file

@ -56,7 +56,7 @@ NET_DEVICE_DRIVERS = ne2000
SYS_APPS = shell winlogon services
APPS = args hello test cat bench apc shm lpc thread event file gditest \
pteb consume dump_shared_data vmtest regtest
pteb consume dump_shared_data vmtest regtest exp
# objdir

View file

@ -1,5 +1,5 @@
/* $Id: zw.h,v 1.42 2001/03/16 18:11:20 dwelch Exp $
/* $Id: zw.h,v 1.43 2001/03/18 19:35:11 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -3620,7 +3620,7 @@ STDCALL
NtRaiseException(
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context,
IN BOOL IsDebugger OPTIONAL
IN BOOLEAN SearchFrames
);
NTSTATUS
@ -3628,7 +3628,7 @@ STDCALL
ZwRaiseException(
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context,
IN BOOL IsDebugger OPTIONAL
IN BOOLEAN SearchFrames
);
/*

View file

@ -1,6 +1,8 @@
#ifndef __INCLUDE_NAPI_DBG_H
#define __INCLUDE_NAPI_DBG_H
#include <napi/lpc.h>
#define DBG_EVENT_EXCEPTION (1)
#define DBG_EVENT_CREATE_THREAD (2)
#define DBG_EVENT_CREATE_PROCESS (3)
@ -19,7 +21,7 @@ typedef struct _LPC_DBG_MESSAGE
struct
{
EXCEPTION_RECORD ExceptionRecord;
ULONG FirstChange;
ULONG FirstChance;
} Exception;
struct
{

View file

@ -42,4 +42,5 @@ cp apps/vmtest/vmtest.exe $1/reactos/bin
cp apps/uitest/uitest.exe $1/reactos/bin/
cp apps/gditest/gditest.exe $1/reactos/bin/
cp apps/ptest/ptest.exe $1/reactos/bin/
cp apps/timer/timer.exe $1/reactos/bin/
cp apps/timer/timer.exe $1/reactos/bin/
cp apps/exp/exp.exe $1/reactos/bin

View file

@ -1,4 +1,4 @@
/* $Id: exception.c,v 1.4 2001/03/17 11:11:11 dwelch Exp $
/* $Id: exception.c,v 1.5 2001/03/18 19:35:12 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -24,7 +24,7 @@ ULONG
RtlDispatchException(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context)
{
return(0);
}
VOID STDCALL

View file

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.24 2001/03/16 23:04:59 dwelch Exp $
# $Id: Makefile,v 1.25 2001/03/18 19:35:12 dwelch Exp $
#
# ReactOS Operating System
#
@ -238,7 +238,8 @@ OBJECTS_CM = \
OBJECTS_DBG = \
dbg/dbgctrl.o \
dbg/errinfo.o \
dbg/print.o
dbg/print.o \
dbg/user.o
# Loader
OBJECTS_LDR = \

View file

@ -1,11 +1,17 @@
#ifndef __INCLUDE_INTERNAL_DBG_H
#define __INCLUDE_INTERNAL_DBG_H
#include <napi/lpc.h>
#include <napi/dbg.h>
#include <internal/port.h>
NTSTATUS STDCALL
LpcSendDebugMessagePort(PEPORT Port,
PLPC_DBG_MESSAGE Message);
PLPC_DBG_MESSAGE Message,
PLPC_DBG_MESSAGE Reply);
VOID
DbgkCreateThread(PVOID StartAddress);
ULONG
DbgkForwardException(EXCEPTION_RECORD Er, ULONG FirstChance);
#endif /* __INCLUDE_INTERNAL_DBG_H */

View file

@ -91,8 +91,6 @@ VOID KeExpireTimers( PKDPC Apc,
PVOID Arg1,
PVOID Arg2,
PVOID Arg3 );
NTSTATUS KeAddThreadTimeout(struct _KTHREAD* Thread,
PLARGE_INTEGER Interval);
VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header, ULONG Type,
ULONG Size, ULONG SignalState);
@ -129,5 +127,12 @@ VOID
NtEarlyInitVdm(VOID);
VOID
KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Eip);
VOID
KiDispatchException(PEXCEPTION_RECORD Er,
PCONTEXT Context,
PKTRAP_FRAME Tf,
KPROCESSOR_MODE PreviousMode,
BOOLEAN SearchFrames);
VOID KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
PCONTEXT Context);
#endif

View file

@ -95,7 +95,7 @@ KiDeliverNormalApc(VOID)
Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry);
if (Apc->NormalRoutine != NULL)
{
(void)RemoveTailList(&Thread->Tcb.ApcState.ApcListHead[0]);
(VOID)RemoveTailList(&Thread->Tcb.ApcState.ApcListHead[0]);
Thread->Tcb.ApcState.KernelApcInProgress++;
Thread->Tcb.ApcState.KernelApcPending--;
@ -243,35 +243,39 @@ VOID STDCALL KiDeliverApc(ULONG Unknown1,
*/
{
PETHREAD Thread = PsGetCurrentThread();
PLIST_ENTRY current;
PLIST_ENTRY current_entry;
PKAPC Apc;
KIRQL oldlvl;
DPRINT("KiDeliverApc()\n");
KeAcquireSpinLock(&PiApcLock, &oldlvl);
while(!IsListEmpty(&(Thread->Tcb.ApcState.ApcListHead[0])))
{
current = Thread->Tcb.ApcState.ApcListHead[0].Blink;
Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry);
if (Apc->NormalRoutine == NULL)
{
(void)RemoveTailList(&Thread->Tcb.ApcState.ApcListHead[0]);
Thread->Tcb.ApcState.KernelApcInProgress++;
Thread->Tcb.ApcState.KernelApcPending--;
KeReleaseSpinLock(&PiApcLock, oldlvl);
Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry);
Apc->KernelRoutine(Apc,
&Apc->NormalRoutine,
&Apc->NormalContext,
&Apc->SystemArgument1,
&Apc->SystemArgument2);
KeAcquireSpinLock(&PiApcLock, &oldlvl);
Thread->Tcb.ApcState.KernelApcInProgress--;
}
}
current_entry = Thread->Tcb.ApcState.ApcListHead[0].Flink;
while(current_entry != &Thread->Tcb.ApcState.ApcListHead[0])
{
Apc = CONTAINING_RECORD(current_entry, KAPC, ApcListEntry);
if (Apc->NormalRoutine == NULL)
{
current_entry = current_entry->Flink;
RemoveEntryList(&Apc->ApcListEntry);
Thread->Tcb.ApcState.KernelApcInProgress++;
Thread->Tcb.ApcState.KernelApcPending--;
KeReleaseSpinLock(&PiApcLock, oldlvl);
Apc->KernelRoutine(Apc,
&Apc->NormalRoutine,
&Apc->NormalContext,
&Apc->SystemArgument1,
&Apc->SystemArgument2);
KeAcquireSpinLock(&PiApcLock, &oldlvl);
Thread->Tcb.ApcState.KernelApcInProgress--;
}
else
{
current_entry = current_entry->Flink;
}
}
KeReleaseSpinLock(&PiApcLock, oldlvl);
}
@ -320,13 +324,28 @@ KeInsertQueueApc (PKAPC Apc,
TargetThread->ApcState.UserApcPending++;
}
Apc->Inserted = TRUE;
/*
* If this is a kernel-mode APC and it is waiting at PASSIVE_LEVEL and
* not inside a critical section then wake it up. Otherwise it will
* execute the APC as soon as it returns to PASSIVE_LEVEL.
* FIXME: Check for sending an APC to the current thread.
* FIXME: If the thread is running on another processor then send an
* IPI.
* FIXME: Check if the thread is terminating.
*/
if (Apc->ApcMode == KernelMode && TargetThread->KernelApcDisable >= 1 &&
TargetThread->WaitIrql < APC_LEVEL && Apc->NormalRoutine == NULL)
{
KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb),
STATUS_KERNEL_APC);
}
/*
* If this is a 'funny' user-mode APC then mark the thread as
* alerted so it will execute the APC on exit from kernel mode. If it
* is waiting alertably then wake it up so it can return to user mode.
*/
if (Apc->ApcMode == KernelMode && Apc->NormalRoutine != NULL)
{
TargetThread->Alerted[1] = 1;
@ -341,12 +360,9 @@ KeInsertQueueApc (PKAPC Apc,
}
/*
* For user mode APCs if the thread is already waiting then we wait it
* up and increment UserApcPending so it will deliver the APC on exit
* from kernel mode. If the thread isn't waiting then before it
* enters an alertable, user mode wait then it will check for
* user mode APCs and if there are any pending then return immediately
* and they will be delivered on exit from kernel mode
* If the thread is waiting alertably then wake it up and it will
* return to to user-mode executing the APC in the process. Otherwise the
* thread will execute the APC next time it enters an alertable wait.
*/
if (Apc->ApcMode == UserMode && TargetThread->Alertable == TRUE &&
TargetThread->WaitMode == UserMode)
@ -429,6 +445,7 @@ KeInitializeApc (PKAPC Apc,
"KernelRoutine %x, RundownRoutine %x, NormalRoutine %x, Mode %d, "
"Context %x)\n",Apc,Thread,StateIndex,KernelRoutine,RundownRoutine,
NormalRoutine,Mode,Context);
memset(Apc, 0, sizeof(KAPC));
Apc->Thread = Thread;
Apc->ApcListEntry.Flink = NULL;

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: catch.c,v 1.12 2001/03/17 11:11:11 dwelch Exp $
/* $Id: catch.c,v 1.13 2001/03/18 19:35:12 dwelch Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/catch.c
@ -29,6 +29,7 @@
#include <ddk/ntddk.h>
#include <internal/ke.h>
#include <internal/ldr.h>
#include <internal/ps.h>
#include <internal/debug.h>
@ -36,26 +37,31 @@
VOID
KiDispatchException(PEXCEPTION_RECORD Er,
ULONG Reserved,
PCONTEXT Context,
PKTRAP_FRAME Tf,
KPROCESSOR_MODE PreviousMode,
BOOLEAN SearchFrames)
{
CONTEXT Context;
CONTEXT TContext;
Context.ContextFlags = CONTEXT_FULL;
if (PreviousMode == UserMode)
{
Context.ContextFlags = Context.ContextFlags | CONTEXT_DEBUGGER;
}
/* PCR->KeExceptionDispatchCount++; */
// KeContextFromKframes(Tf, Reserved, &Context);
if (Context != NULL)
{
TContext.ContextFlags = CONTEXT_FULL;
if (PreviousMode == UserMode)
{
TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
}
KeTrapFrameToContext(Tf, &TContext);
Context = &TContext;
}
if (Er->ExceptionCode == STATUS_BREAKPOINT)
{
Context.Eip--;
Context->Eip--;
}
if (PreviousMode == UserMode)
@ -86,7 +92,7 @@ KiDispatchException(PEXCEPTION_RECORD Er,
/* Pointer to CONTEXT structure */
Stack[2] = (ULONG)&Stack[CDest];
memcpy(&Stack[3], Er, sizeof(EXCEPTION_RECORD));
memcpy(&Stack[CDest], &Context, sizeof(CONTEXT));
memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
return;
@ -94,13 +100,18 @@ KiDispatchException(PEXCEPTION_RECORD Er,
/* FIXME: Forward the exception to the debugger */
/* FIXME: Forward the exception to the debugger */
/* FIXME: Forward the exception to the process exception port */
/* Terminate the offending thread */
ZwTerminateThread(NtCurrentThread(), Er->ExceptionCode);
/* If that fails then bugcheck */
KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
}
else
{
KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
}
}
VOID STDCALL
@ -116,7 +127,7 @@ ExRaiseDatatypeMisalignment (VOID)
}
VOID STDCALL
ExRaiseStatus (IN NTSTATUS Status)
ExRaiseStatus (IN NTSTATUS Status)
{
DbgPrint("ExRaiseStatus(%x)\n",Status);
for(;;);
@ -125,11 +136,16 @@ ExRaiseStatus (IN NTSTATUS Status)
NTSTATUS STDCALL
NtRaiseException (IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context,
IN BOOL IsDebugger OPTIONAL)
NtRaiseException (IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context,
IN BOOLEAN SearchFrames)
{
UNIMPLEMENTED;
KiDispatchException(ExceptionRecord,
Context,
PsGetCurrentThread()->Tcb.TrapFrame,
ExGetPreviousMode(),
SearchFrames);
return(STATUS_SUCCESS);
}

View file

@ -48,24 +48,24 @@
extern void interrupt_handler2e(void);
extern void interrupt_handler2d(void);
extern void exception_handler0(void);
extern void exception_handler1(void);
extern void exception_handler2(void);
extern void exception_handler3(void);
extern void exception_handler4(void);
extern void exception_handler5(void);
extern void exception_handler6(void);
extern void exception_handler7(void);
extern void exception_handler8(void);
extern void exception_handler9(void);
extern void exception_handler10(void);
extern void exception_handler11(void);
extern void exception_handler12(void);
extern void exception_handler13(void);
extern void exception_handler14(void);
extern void exception_handler15(void);
extern void exception_handler16(void);
extern void exception_handler_unknown(void);
extern VOID KiTrap0(VOID);
extern VOID KiTrap1(VOID);
extern VOID KiTrap2(VOID);
extern VOID KiTrap3(VOID);
extern VOID KiTrap4(VOID);
extern VOID KiTrap5(VOID);
extern VOID KiTrap6(VOID);
extern VOID KiTrap7(VOID);
extern VOID KiTrap8(VOID);
extern VOID KiTrap9(VOID);
extern VOID KiTrap10(VOID);
extern VOID KiTrap11(VOID);
extern VOID KiTrap12(VOID);
extern VOID KiTrap13(VOID);
extern VOID KiTrap14(VOID);
extern VOID KiTrap15(VOID);
extern VOID KiTrap16(VOID);
extern VOID KiTrapUnknown(VOID);
extern ULONG init_stack;
extern ULONG init_stack_top;
@ -105,7 +105,59 @@ print_address(PVOID address)
}
ULONG
exception_handler(struct trap_frame* tf)
KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
{
EXCEPTION_RECORD Er;
if (ExceptionNr == 0)
{
Er.ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO;
}
else if (ExceptionNr == 1)
{
Er.ExceptionCode = STATUS_SINGLE_STEP;
}
else if (ExceptionNr == 3)
{
Er.ExceptionCode = STATUS_BREAKPOINT;
}
else if (ExceptionNr == 4)
{
Er.ExceptionCode = STATUS_INTEGER_OVERFLOW;
}
else if (ExceptionNr == 5)
{
Er.ExceptionCode = STATUS_ARRAY_BOUNDS_EXCEEDED;
}
else if (ExceptionNr == 6)
{
Er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
}
else
{
Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
}
Er.ExceptionFlags = 0;
Er.ExceptionRecord = NULL;
Er.ExceptionAddress = (PVOID)Tf->Eip;
if (ExceptionNr == 14)
{
Er.NumberParameters = 2;
Er.ExceptionInformation[0] = Tf->ErrorCode & 0x1;
Er.ExceptionInformation[1] = (ULONG)Cr2;
}
else
{
Er.NumberParameters = 0;
}
KiDispatchException(&Er, 0, Tf, UserMode, TRUE);
return(0);
}
ULONG
KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
/*
* FUNCTION: Called by the lowlevel execption handlers to print an amusing
* message and halt the computer
@ -118,6 +170,7 @@ exception_handler(struct trap_frame* tf)
// unsigned int j, sym;
PULONG stack;
NTSTATUS Status;
ULONG Esp0;
static char *TypeStrings[] =
{
"Divide Error",
@ -139,65 +192,70 @@ exception_handler(struct trap_frame* tf)
"Alignment Check",
"Machine Check"
};
/* Use the address of the trap frame as approximation to the ring0 esp */
Esp0 = (ULONG)Tf;
__asm__("movl %%cr2,%0\n\t"
: "=d" (cr2));
/* Get CR2 */
__asm__("movl %%cr2,%0\n\t" : "=d" (cr2));
/*
* If this was a V86 mode exception then handle it specially
*/
#if 0
if (tf->eflags & (1 << 17))
{
return(KeV86Exception(tf, cr2));
}
#endif
/*
* Check for stack underflow
*/
if (PsGetCurrentThread() != NULL &&
tf->esp < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
{
DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
tf->esp, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
tf->type = 12;
Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
ExceptionNr = 12;
}
if (tf->type == 14)
if (ExceptionNr == 14)
{
__asm__("sti\n\t");
Status = MmPageFault(tf->cs&0xffff,
&tf->eip,
&tf->eax,
Status = MmPageFault(Tf->Cs&0xffff,
&Tf->Eip,
&Tf->Eax,
cr2,
tf->error_code);
Tf->ErrorCode);
if (NT_SUCCESS(Status))
{
return(0);
}
}
/*
* FIXME: Something better
*/
if (tf->type==1)
if ((Tf->Cs & 0xFFFF) == USER_CS)
{
DbgPrint("Trap at CS:EIP %x:%x\n",tf->cs&0xffff,tf->eip);
return(0);
return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
}
/*
* Print out the CPU registers
*/
if (tf->type < 19)
if (ExceptionNr < 19)
{
DbgPrint("%s Exception: %d(%x)\n",TypeStrings[tf->type],tf->type,
tf->error_code&0xffff);
DbgPrint("%s Exception: %d(%x)\n",TypeStrings[ExceptionNr],
ExceptionNr, Tf->ErrorCode&0xffff);
}
else
{
DbgPrint("Exception: %d(%x)\n",tf->type,tf->error_code&0xffff);
DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff);
}
DbgPrint("CS:EIP %x:%x ",tf->cs&0xffff,tf->eip);
print_address((PVOID)tf->eip);
DbgPrint("CS:EIP %x:%x ", Tf->Cs&0xffff, Tf->Eip);
print_address((PVOID)Tf->Eip);
DbgPrint("\n");
__asm__("movl %%cr3,%0\n\t"
: "=d" (cr3));
DbgPrint("cr2 %x cr3 %x ",cr2,cr3);
// for(;;);
__asm__("movl %%cr3,%0\n\t" : "=d" (cr3));
DbgPrint("cr2 %x cr3 %x ", cr2, cr3);
DbgPrint("Proc: %x ",PsGetCurrentProcess());
if (PsGetCurrentProcess() != NULL)
{
@ -211,14 +269,14 @@ exception_handler(struct trap_frame* tf)
PsGetCurrentThread()->Cid.UniqueThread);
}
DbgPrint("\n");
DbgPrint("DS %x ES %x FS %x GS %x\n", tf->ds&0xffff, tf->es&0xffff,
tf->fs&0xffff, tf->gs&0xfff);
DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", tf->eax, tf->ebx, tf->ecx);
DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", tf->edx, tf->ebp, tf->esi);
DbgPrint("EDI: %.8x EFLAGS: %.8x ", tf->edi, tf->eflags);
if ((tf->cs&0xffff) == KERNEL_CS)
DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->Ds&0xffff, Tf->Es&0xffff,
Tf->Fs&0xffff, Tf->Gs&0xfff);
DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx);
DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", Tf->Edx, Tf->Ebp, Tf->Esi);
DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->Eflags);
if ((Tf->Cs&0xffff) == KERNEL_CS)
{
DbgPrint("kESP %.8x ", tf->esp);
DbgPrint("kESP %.8x ", Esp0);
if (PsGetCurrentThread() != NULL)
{
DbgPrint("kernel stack base %x\n",
@ -228,12 +286,12 @@ exception_handler(struct trap_frame* tf)
}
else
{
DbgPrint("kernel ESP %.8x\n", tf->esp);
DbgPrint("User ESP %.8x\n", Tf->Esp);
}
if ((tf->cs & 0xffff) == KERNEL_CS)
if ((Tf->Cs & 0xffff) == KERNEL_CS)
{
DbgPrint("ESP %x\n", tf->esp);
stack = (PULONG) (tf->esp + 24);
DbgPrint("ESP %x\n", Esp0);
stack = (PULONG) (Esp0 + 24);
stack = (PULONG)(((ULONG)stack) & (~0x3));
DbgPrint("stack<%p>: ", stack);
@ -261,8 +319,8 @@ exception_handler(struct trap_frame* tf)
else
{
#if 1
DbgPrint("SS:ESP %x:%x\n", tf->ss0, tf->esp0);
stack=(PULONG)(tf->esp0);
DbgPrint("SS:ESP %x:%x\n", Tf->Ss, Tf->Esp);
stack=(PULONG)(Tf->Esp);
DbgPrint("Stack:\n");
for (i=0; i<64; i++)
@ -277,11 +335,11 @@ exception_handler(struct trap_frame* tf)
}
}
if (MmIsPagePresent(NULL, (PVOID)tf->eip))
if (MmIsPagePresent(NULL, (PVOID)Tf->Eip))
{
unsigned char instrs[512];
memcpy(instrs, (PVOID)tf->eip, 512);
memcpy(instrs, (PVOID)Tf->Eip, 512);
DbgPrint("Instrs: ");
@ -294,13 +352,12 @@ exception_handler(struct trap_frame* tf)
}
DbgPrint("\n");
if ((tf->cs&0xffff) == USER_CS &&
tf->eip < KERNEL_BASE)
if ((Tf->Cs&0xffff) == USER_CS &&
Tf->Eip < KERNEL_BASE)
{
DbgPrint("Killing current task\n");
// for(;;);
KeLowerIrql(PASSIVE_LEVEL);
if ((tf->cs&0xffff) == USER_CS)
if ((Tf->Cs&0xffff) == USER_CS)
{
ZwTerminateProcess(NtCurrentProcess(),
STATUS_NONCONTINUABLE_EXCEPTION);
@ -366,27 +423,27 @@ void KeInitExceptions(void)
DPRINT("KeInitExceptions()\n",0);
set_interrupt_gate(0,(int)exception_handler0);
set_interrupt_gate(1,(int)exception_handler1);
set_interrupt_gate(2,(int)exception_handler2);
set_interrupt_gate(3,(int)exception_handler3);
set_interrupt_gate(4,(int)exception_handler4);
set_interrupt_gate(5,(int)exception_handler5);
set_interrupt_gate(6,(int)exception_handler6);
set_interrupt_gate(7,(int)exception_handler7);
set_interrupt_gate(8,(int)exception_handler8);
set_interrupt_gate(9,(int)exception_handler9);
set_interrupt_gate(10,(int)exception_handler10);
set_interrupt_gate(11,(int)exception_handler11);
set_interrupt_gate(12,(int)exception_handler12);
set_interrupt_gate(13,(int)exception_handler13);
set_interrupt_gate(14,(int)exception_handler14);
set_interrupt_gate(15,(int)exception_handler15);
set_interrupt_gate(16,(int)exception_handler16);
set_interrupt_gate(0, (ULONG)KiTrap0);
set_interrupt_gate(1, (ULONG)KiTrap1);
set_interrupt_gate(2, (ULONG)KiTrap2);
set_interrupt_gate(3, (ULONG)KiTrap3);
set_interrupt_gate(4, (ULONG)KiTrap4);
set_interrupt_gate(5, (ULONG)KiTrap5);
set_interrupt_gate(6, (ULONG)KiTrap6);
set_interrupt_gate(7, (ULONG)KiTrap7);
set_interrupt_gate(8, (ULONG)KiTrap8);
set_interrupt_gate(9, (ULONG)KiTrap9);
set_interrupt_gate(10, (ULONG)KiTrap10);
set_interrupt_gate(11, (ULONG)KiTrap11);
set_interrupt_gate(12, (ULONG)KiTrap12);
set_interrupt_gate(13, (ULONG)KiTrap13);
set_interrupt_gate(14, (ULONG)KiTrap14);
set_interrupt_gate(15, (ULONG)KiTrap15);
set_interrupt_gate(16, (ULONG)KiTrap16);
for (i=17;i<256;i++)
{
set_interrupt_gate(i,(int)exception_handler_unknown);
set_interrupt_gate(i,(int)KiTrapUnknown);
}
set_system_call_gate(0x2d,(int)interrupt_handler2d);

View file

@ -706,6 +706,10 @@ lowmem_pagetable:
.long 0x3f0007,0x3f1007,0x3f2007,0x3f3007,0x3f4007,0x3f5007,0x3f6007,0x3f7007
.long 0x3f8007,0x3f9007,0x3fa007,0x3fb007,0x3fc007,0x3fd007,0x3fe007,0x3ff007
_init_stack:
.fill 3*4096,1,0
_init_stack_top:
_gdt_descr:
.word (10*8)-1
.long _KiGdt
@ -713,8 +717,4 @@ _gdt_descr:
_idt_descr:
.word (256*8)-1
.long _KiIdt
_init_stack:
.fill 4096,1,0
_init_stack_top:

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: syscall.S,v 1.1 2000/12/10 23:42:00 dwelch Exp $
/* $Id: syscall.S,v 1.2 2001/03/18 19:35:13 dwelch Exp $
*
* FILE: ntoskrnl/hal/x86/syscall.s
* PURPOSE: 2E trap handler
@ -96,7 +96,10 @@ L3:
movl %ebx, %es
movl %ebx, %gs
/* Save the old trap frame pointer (over the EDX register??) */
/*
* Save the old trap frame pointer over where we would save the EDX
* register.
*/
movl KTHREAD_TRAP_FRAME(%esi), %ebx
movl %ebx, 0x3C(%esp)

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: trap.s,v 1.6 2000/12/23 02:37:40 dwelch Exp $
/* $Id: trap.s,v 1.7 2001/03/18 19:35:13 dwelch Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/i386/trap.s
@ -36,336 +36,283 @@
/*
* Epilog for exception handlers
*/
_exception_handler_epilog:
_KiTrapEpilog:
cmpl $1, %eax /* Check for v86 recovery */
jne _exception_handler_ret
jne _KiTrapRet
jmp _KiV86Complete
_exception_handler_ret:
addl $4, %esp /* Ignore pointer to trap frame */
popa /* Restore general purpose registers */
addl $4, %esp /* Ignore trap code */
popl %ds /* Restore segment registers */
popl %es
popl %fs
_KiTrapRet:
/* Get a pointer to the current thread */
movl %fs:0x124, %esi
/* Restore the old trap frame pointer */
movl 0x3c(%esp), %ebx
movl %ebx, KTHREAD_TRAP_FRAME(%esi)
/* Skip debug information and unsaved registers */
addl $0x30, %esp
popl %gs
addl $4, %esp /* Ignore error code */
iret /* Return from interrupt */
.globl _exception_handler0
_exception_handler0:
pushl $0
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $0
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
popl %es
popl %ds
popl %edx
popl %ecx
popl %eax
.globl _exception_handler1
_exception_handler1:
pushl $0
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $1
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
/* Restore the old previous mode */
popl %ebx
movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi)
/* Restore the old exception handler list */
popl %ebx
movl %ebx, %fs:KPCR_EXCEPTION_LIST
popl %fs
popl %edi
popl %esi
popl %ebx
popl %ebp
addl $0x4, %esp /* Ignore error code */
iret
.globl _exception_handler2
_exception_handler2:
pushl $0
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $2
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
.globl _exception_handler3
_exception_handler3:
pushl $0
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $3
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
.globl _exception_handler4
_exception_handler4:
pushl $0
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $4
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
.globl _exception_handler5
_exception_handler5:
pushl $0
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $5
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
.globl _exception_handler6
_exception_handler6:
pushl $0
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $6
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
.globl _exception_handler7
_exception_handler7:
pushl $0
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $7
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
.globl _exception_handler8
_exception_handler8:
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $8
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
.globl _exception_handler9
_exception_handler9:
pushl $0
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $9
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
.globl _exception_handler10
_exception_handler10:
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $10
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
.globl _exception_handler11
_exception_handler11:
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $11
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
.globl _exception_handler12
_exception_handler12:
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $12
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
.globl _exception_handler13
_exception_handler13:
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $13
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
.globl _exception_handler14
_exception_handler14:
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $14
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
.globl _exception_handler15
_exception_handler15:
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $15
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
.globl _exception_handler16
_exception_handler16:
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl $16
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
.globl _exception_handler_unknown
_exception_handler_unknown:
pushl $0
pushl %gs
.globl _KiTrapProlog
_KiTrapProlog:
pushl %edi
pushl %fs
pushl %es
pushl %ds
pushl $0xff
pusha
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
pushl %esp
call _exception_handler
jmp _exception_handler_epilog
/* Load the PCR selector into fs */
movl $PCR_SELECTOR, %ebx
movl %ebx, %fs
/* Save the old exception list */
movl %fs:KPCR_EXCEPTION_LIST, %ebx
pushl %ebx
/* Put the exception handler chain terminator */
movl $0xffffffff, %fs:KPCR_EXCEPTION_LIST
/* Get a pointer to the current thread */
movl %fs:KPCR_CURRENT_THREAD, %edi
/* The current thread may be NULL early in the boot process */
cmpl $0, %edi
je .L4
/* Save the old previous mode */
movl $0, %ebx
movb %ss:KTHREAD_PREVIOUS_MODE(%edi), %bl
pushl %ebx
/* Set the new previous mode based on the saved CS selector */
movl 0x24(%esp), %ebx
cmpl $KERNEL_CS, %ebx
jne .L1
movb $KernelMode, %ss:KTHREAD_PREVIOUS_MODE(%edi)
jmp .L3
.L1:
movb $UserMode, %ss:KTHREAD_PREVIOUS_MODE(%edi)
.L3:
/* Save other registers */
pushl %eax
pushl %ecx
pushl %edx
pushl %ds
pushl %es
pushl %gs
pushl $0 /* DR7 */
pushl $0 /* DR6 */
pushl $0 /* DR3 */
pushl $0 /* DR2 */
pushl $0 /* DR1 */
pushl $0 /* DR0 */
pushl $0 /* XXX: TempESP */
pushl $0 /* XXX: TempCS */
pushl $0 /* XXX: DebugPointer */
pushl $0 /* XXX: DebugArgMark */
pushl $0 /* XXX: DebugEIP */
pushl $0 /* XXX: DebugEBP */
/* Load the segment registers */
movl $KERNEL_DS, %ebx
movl %ebx, %ds
movl %ebx, %es
movl %ebx, %gs
/* Set ES to kernel segment */
movw $KERNEL_DS,%bx
movw %bx,%es
/* Call the C exception handler */
movl %esp, %ebx
pushl %esi
pushl %ebx
call _KiTrapHandler
addl $4, %esp
addl $4, %esp
/* Return to the caller */
jmp _KiTrapEpilog
/* Handle the no-thread case out of line */
.L4:
pushl $0
jmp .L3
.globl _KiTrap0
_KiTrap0:
/* No error code */
pushl $0
pushl %ebp
pushl %ebx
pushl %esi
movl $0, %esi
jmp _KiTrapProlog
.globl _KiTrap1
_KiTrap1:
/* No error code */
pushl $0
pushl %ebp
pushl %ebx
pushl %esi
movl $1, %esi
jmp _KiTrapProlog
.globl _KiTrap2
_KiTrap2:
pushl $0
pushl %ebp
pushl %ebx
pushl %esi
movl $2, %esi
jmp _KiTrapProlog
.globl _KiTrap3
_KiTrap3:
pushl $0
pushl %ebp
pushl %ebx
pushl %esi
movl $3, %esi
jmp _KiTrapProlog
.globl _KiTrap4
_KiTrap4:
pushl $0
pushl %ebp
pushl %ebx
pushl %esi
movl $4, %esi
jmp _KiTrapProlog
.globl _KiTrap5
_KiTrap5:
pushl $0
pushl %ebp
pushl %ebx
pushl %esi
movl $5, %esi
jmp _KiTrapProlog
.globl _KiTrap6
_KiTrap6:
pushl $0
pushl %ebp
pushl %ebx
pushl %esi
movl $6, %esi
jmp _KiTrapProlog
.globl _KiTrap7
_KiTrap7:
pushl $0
pushl %ebp
pushl %ebx
pushl %esi
movl $7, %esi
jmp _KiTrapProlog
.globl _KiTrap8
_KiTrap8:
pushl %ebp
pushl %ebx
pushl %esi
movl $8, %esi
jmp _KiTrapProlog
.globl _KiTrap9
_KiTrap9:
pushl $0
pushl %ebp
pushl %ebx
pushl %esi
movl $9, %esi
jmp _KiTrapProlog
.globl _KiTrap10
_KiTrap10:
pushl %ebp
pushl %ebx
pushl %esi
movl $10, %esi
jmp _KiTrapProlog
.globl _KiTrap11
_KiTrap11:
pushl %ebp
pushl %ebx
pushl %esi
movl $11, %esi
jmp _KiTrapProlog
.globl _KiTrap12
_KiTrap12:
pushl %ebp
pushl %ebx
pushl %esi
movl $12, %esi
jmp _KiTrapProlog
.globl _KiTrap13
_KiTrap13:
pushl %ebp
pushl %ebx
pushl %esi
movl $13, %esi
jmp _KiTrapProlog
.globl _KiTrap14
_KiTrap14:
pushl %ebp
pushl %ebx
pushl %esi
movl $14, %esi
jmp _KiTrapProlog
.globl _KiTrap15
_KiTrap15:
pushl %ebp
pushl %ebx
pushl %esi
movl $15, %esi
jmp _KiTrapProlog
.globl _KiTrap16
_KiTrap16:
pushl %ebp
pushl %ebx
pushl %esi
movl $16, %esi
jmp _KiTrapProlog
.globl _KiTrapUnknown
_KiTrapUnknown:
pushl $0
pushl %ebp
pushl %ebx
pushl %esi
movl $255, %esi
jmp _KiTrapProlog
/* EOF */

View file

@ -124,6 +124,7 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
* FIXME: Think how this might work
*/
Thread->NpxState = 0;
Thread->Saturation = 0;
Thread->Priority = 0;
InitializeListHead(&Thread->ApcState.ApcListHead[0]);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: main.c,v 1.80 2001/03/16 18:11:23 dwelch Exp $
/* $Id: main.c,v 1.81 2001/03/18 19:35:12 dwelch Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/main.c
@ -588,7 +588,29 @@ _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
LdrProcessDriver((PVOID)start, name);
}
}
DbgPrint("About to try MmAllocateContiguousAlignedMemory\n");
do
{
extern PVOID STDCALL
MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes,
IN PHYSICAL_ADDRESS HighestAcceptableAddress,
IN ULONG Alignment);
PVOID v;
PHYSICAL_ADDRESS p;
p.QuadPart = 16*1024*1024;
v = MmAllocateContiguousAlignedMemory(12*1024, p,
64*1024);
if (v != NULL)
{
DbgPrint("Worked\n");
}
else
{
DbgPrint("Failed\n");
}
}
while (0);
/* Create the SystemRoot symbolic link */
DbgPrint("CommandLine: %s\n", (PUCHAR)KeLoaderBlock.CommandLine);

View file

@ -1,4 +1,4 @@
/* $Id: timer.c,v 1.42 2001/03/16 16:05:33 dwelch Exp $
/* $Id: timer.c,v 1.43 2001/03/18 19:35:13 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -113,22 +113,6 @@ NTSTATUS STDCALL NtQueryPerformanceCounter (IN PLARGE_INTEGER Counter,
}
NTSTATUS KeAddThreadTimeout(PKTHREAD Thread, PLARGE_INTEGER Interval)
{
assert(Thread != NULL);
assert(Interval != NULL);
DPRINT("KeAddThreadTimeout(Thread %x, Interval %x)\n",Thread,Interval);
KeInitializeTimer(&Thread->Timer);
KeSetTimer(&Thread->Timer, *Interval, &Thread->TimerDpc);
DPRINT("Thread->Timer.entry.Flink %x\n",
Thread->Timer.TimerListEntry.Flink);
return STATUS_SUCCESS;
}
NTSTATUS STDCALL NtDelayExecution(IN ULONG Alertable,
IN TIME* Interval)
@ -161,9 +145,11 @@ KeDelayExecutionThread (KPROCESSOR_MODE WaitMode,
* RETURNS: Status
*/
{
PKTHREAD CurrentThread = KeGetCurrentThread();
KeAddThreadTimeout(CurrentThread, Interval);
return (KeWaitForSingleObject(&CurrentThread->Timer,
PKTHREAD Thread = KeGetCurrentThread();
KeInitializeTimer(&Thread->Timer);
KeSetTimer(&Thread->Timer, *Interval, NULL);
return (KeWaitForSingleObject(&Thread->Timer,
Executive,
UserMode,
Alertable,
@ -286,7 +272,7 @@ KeCancelTimer (PKTIMER Timer)
DPRINT("KeCancelTimer(Timer %x)\n",Timer);
KeRaiseIrql( HIGH_LEVEL, &oldlvl );
KeRaiseIrql(HIGH_LEVEL, &oldlvl);
KeAcquireSpinLockAtDpcLevel( &TimerListLock );
if (Timer->TimerListEntry.Flink == NULL)
@ -367,7 +353,8 @@ KeQueryTickCount (PLARGE_INTEGER TickCount)
TickCount->QuadPart = KiTimerTicks;
}
static void HandleExpiredTimer(PKTIMER current)
STATIC VOID
HandleExpiredTimer(PKTIMER current)
{
DPRINT("HandleExpiredTime(current %x)\n",current);
if (current->Dpc != NULL)
@ -449,10 +436,6 @@ KiUpdateSystemTime (KIRQL oldIrql, ULONG Eip)
KiTimerTicks++;
system_time = system_time + CLOCK_INCREMENT;
/*
* Display the tick count in the top left of the screen as a debugging
* aid
*/
vidmem[0] = ' ';
if (oldIrql < DISPATCH_LEVEL)
{

View file

@ -199,65 +199,68 @@ VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus)
static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr)
{
PKWAIT_BLOCK current;
PLIST_ENTRY current_entry;
PKWAIT_BLOCK PrevBlock;
NTSTATUS Status;
PKWAIT_BLOCK current;
PLIST_ENTRY current_entry;
PKWAIT_BLOCK PrevBlock;
NTSTATUS Status;
DPRINT("KeDispatcherObjectWakeAll(hdr %x)\n",hdr);
if (IsListEmpty(&hdr->WaitListHead))
{
return(FALSE);
}
while (!IsListEmpty(&(hdr->WaitListHead)))
{
current_entry = RemoveHeadList(&hdr->WaitListHead);
current = CONTAINING_RECORD(current_entry,
KWAIT_BLOCK,
WaitListEntry);
DPRINT("Waking %x\n",current->Thread);
if (current->WaitType == WaitAny)
{
DPRINT("WaitAny: Remove all wait blocks.\n");
for( PrevBlock = current->Thread->WaitBlockList; PrevBlock; PrevBlock = PrevBlock->NextWaitBlock )
if( PrevBlock != current )
RemoveEntryList( &(PrevBlock->WaitListEntry) );
current->Thread->WaitBlockList = 0;
}
else
{
DPRINT("WaitAll: Remove the current wait block only.\n");
PrevBlock = current->Thread->WaitBlockList;
if (PrevBlock == current)
{
DPRINT( "WaitAll: Current block is list head.\n" );
current->Thread->WaitBlockList = current->NextWaitBlock;
}
else
{
DPRINT( "WaitAll: Current block is not list head.\n" );
while ( PrevBlock && PrevBlock->NextWaitBlock != current)
{
PrevBlock = PrevBlock->NextWaitBlock;
}
if (PrevBlock)
{
PrevBlock->NextWaitBlock = current->NextWaitBlock;
}
}
}
KiSideEffectsBeforeWake(hdr, current->Thread);
Status = current->WaitKey;
if (current->Thread->WaitBlockList == NULL)
{
PsUnblockThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
&Status);
}
}
return(TRUE);
DPRINT("KeDispatcherObjectWakeAll(hdr %x)\n",hdr);
if (IsListEmpty(&hdr->WaitListHead))
{
return(FALSE);
}
while (!IsListEmpty(&hdr->WaitListHead))
{
current_entry = RemoveHeadList(&hdr->WaitListHead);
current = CONTAINING_RECORD(current_entry,
KWAIT_BLOCK,
WaitListEntry);
DPRINT("Waking %x\n",current->Thread);
if (current->WaitType == WaitAny)
{
DPRINT("WaitAny: Remove all wait blocks.\n");
for(PrevBlock = current->Thread->WaitBlockList; PrevBlock;
PrevBlock = PrevBlock->NextWaitBlock)
{
if (PrevBlock != current)
RemoveEntryList(&PrevBlock->WaitListEntry);
}
current->Thread->WaitBlockList = 0;
}
else
{
DPRINT("WaitAll: Remove the current wait block only.\n");
PrevBlock = current->Thread->WaitBlockList;
if (PrevBlock == current)
{
DPRINT( "WaitAll: Current block is list head.\n" );
current->Thread->WaitBlockList = current->NextWaitBlock;
}
else
{
DPRINT( "WaitAll: Current block is not list head.\n" );
while (PrevBlock && PrevBlock->NextWaitBlock != current)
{
PrevBlock = PrevBlock->NextWaitBlock;
}
if (PrevBlock)
{
PrevBlock->NextWaitBlock = current->NextWaitBlock;
}
}
}
KiSideEffectsBeforeWake(hdr, current->Thread);
Status = current->WaitKey;
if (current->Thread->WaitBlockList == NULL)
{
PsUnblockThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
&Status);
}
}
return(TRUE);
}
static BOOLEAN KeDispatcherObjectWakeOne(DISPATCHER_HEADER* hdr)
@ -342,31 +345,30 @@ BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr)
case InternalSynchronizationEvent:
return(KeDispatcherObjectWakeOne(hdr));
case InternalSynchronizationTimer:
return(KeDispatcherObjectWakeOne(hdr));
case InternalSemaphoreType:
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
if(hdr->SignalState>0)
{
do
{
{
do
{
DPRINT("Waking one semaphore waiter\n");
Ret = KeDispatcherObjectWakeOne(hdr);
} while(hdr->SignalState > 0 && Ret) ;
return(Ret);
}
} while(hdr->SignalState > 0 && Ret) ;
return(Ret);
}
else return FALSE;
case InternalProcessType:
case InternalProcessType:
return(KeDispatcherObjectWakeAll(hdr));
case InternalThreadType:
return(KeDispatcherObjectWakeAll(hdr));
case InternalThreadType:
return(KeDispatcherObjectWakeAll(hdr));
case InternalMutexType:
return(KeDispatcherObjectWakeOne(hdr));
case InternalMutexType:
return(KeDispatcherObjectWakeOne(hdr));
}
DbgPrint("Dispatcher object %x has unknown type %d\n", hdr, hdr->Type);
KeBugCheck(0);
@ -398,29 +400,36 @@ NTSTATUS STDCALL KeWaitForSingleObject (PVOID Object,
NTSTATUS Status;
KIRQL WaitIrql;
DPRINT("Entering KeWaitForSingleObject(Object %x) "
"PsGetCurrentThread() %x\n",Object,PsGetCurrentThread());
CurrentThread = KeGetCurrentThread();
WaitIrql = KeGetCurrentIrql();
/*
* Set up the timeout
* FIXME: Check for zero timeout
*/
if (Timeout != NULL)
{
KeAddThreadTimeout(CurrentThread, Timeout);
KeInitializeTimer(&CurrentThread->Timer);
KeSetTimer(&CurrentThread->Timer, *Timeout, NULL);
}
do
{
KeAcquireDispatcherDatabaseLock(FALSE);
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
/*
* If we are going to wait alertably and a user apc is pending
* then return
*/
if (Alertable && KiTestAlert())
{
KeReleaseDispatcherDatabaseLock(FALSE);
return(STATUS_USER_APC);
}
/*
* If the object is signalled
*/
if (KiIsObjectSignalled(hdr, CurrentThread))
{
KeReleaseDispatcherDatabaseLock(FALSE);
@ -429,8 +438,25 @@ NTSTATUS STDCALL KeWaitForSingleObject (PVOID Object,
KeCancelTimer(&KeGetCurrentThread()->Timer);
}
return(STATUS_WAIT_0);
}
}
/*
* Check if we have already timed out
*/
if (Timeout != NULL &&
KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread))
{
KeReleaseDispatcherDatabaseLock(FALSE);
if (Timeout != NULL)
{
KeCancelTimer(&KeGetCurrentThread()->Timer);
}
return(STATUS_TIMEOUT);
}
/*
* Set up for a wait
*/
CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL;
/* Append wait block to the KTHREAD wait block list */
CurrentThread->WaitBlockList = &CurrentThread->WaitBlock[0];
@ -438,9 +464,24 @@ NTSTATUS STDCALL KeWaitForSingleObject (PVOID Object,
CurrentThread->WaitBlock[0].Thread = CurrentThread;
CurrentThread->WaitBlock[0].WaitKey = 0;
CurrentThread->WaitBlock[0].WaitType = WaitAny;
CurrentThread->WaitBlock[0].NextWaitBlock = NULL;
InsertTailList(&hdr->WaitListHead,
&CurrentThread->WaitBlock[0].WaitListEntry);
if (Timeout != NULL)
{
CurrentThread->WaitBlock[0].NextWaitBlock =
&CurrentThread->WaitBlock[1];
CurrentThread->WaitBlock[1].Object = (PVOID)&CurrentThread->Timer;
CurrentThread->WaitBlock[1].Thread = CurrentThread;
CurrentThread->WaitBlock[1].WaitKey = 1;
CurrentThread->WaitBlock[1].WaitType = WaitAny;
CurrentThread->WaitBlock[1].NextWaitBlock = NULL;
InsertTailList(&CurrentThread->Timer.Header.WaitListHead,
&CurrentThread->WaitBlock[1].WaitListEntry);
}
else
{
CurrentThread->WaitBlock[0].NextWaitBlock = NULL;
}
PsBlockThread(&Status, (UCHAR)Alertable, WaitMode, TRUE, WaitIrql);
} while (Status == STATUS_KERNEL_APC);
@ -448,21 +489,25 @@ NTSTATUS STDCALL KeWaitForSingleObject (PVOID Object,
{
KeCancelTimer(&KeGetCurrentThread()->Timer);
}
if (Status == (STATUS_WAIT_0 + 1))
{
Status = STATUS_TIMEOUT;
}
DPRINT("Returning from KeWaitForSingleObject()\n");
return(Status);
}
NTSTATUS STDCALL
KeWaitForMultipleObjects (ULONG Count,
PVOID Object[],
WAIT_TYPE WaitType,
KWAIT_REASON WaitReason,
KPROCESSOR_MODE WaitMode,
BOOLEAN Alertable,
PLARGE_INTEGER Timeout,
PKWAIT_BLOCK WaitBlockArray)
KeWaitForMultipleObjects (ULONG Count,
PVOID Object[],
WAIT_TYPE WaitType,
KWAIT_REASON WaitReason,
KPROCESSOR_MODE WaitMode,
BOOLEAN Alertable,
PLARGE_INTEGER Timeout,
PKWAIT_BLOCK WaitBlockArray)
{
DISPATCHER_HEADER* hdr;
PKWAIT_BLOCK blk;
@ -479,87 +524,150 @@ KeWaitForMultipleObjects (ULONG Count,
CurrentThread = KeGetCurrentThread();
WaitIrql = KeGetCurrentIrql();
/*
* Work out where we are going to put the wait blocks
*/
if (WaitBlockArray == NULL)
{
if (Count > 4)
if (Count > THREAD_WAIT_OBJECTS)
{
DbgPrint("(%s:%d) Too many objects!\n",
__FILE__,__LINE__);
return STATUS_UNSUCCESSFUL;
return(STATUS_UNSUCCESSFUL);
}
blk = &CurrentThread->WaitBlock[0];
}
else
{
if (Count > 64)
if (Count > EX_MAXIMUM_WAIT_OBJECTS)
{
DbgPrint("(%s:%d) Too many objects!\n",
__FILE__,__LINE__);
return STATUS_UNSUCCESSFUL;
return(STATUS_UNSUCCESSFUL);
}
blk = WaitBlockArray;
}
/*
* Set up the timeout if required
*/
if (Timeout != NULL)
{
KeAddThreadTimeout(CurrentThread,Timeout);
KeInitializeTimer(&CurrentThread->Timer);
KeSetTimer(&CurrentThread->Timer, *Timeout, NULL);
}
do {
KeAcquireDispatcherDatabaseLock(FALSE);
for (i = 0; i < Count; i++)
{
hdr = (DISPATCHER_HEADER *)Object[i];
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
if (KiIsObjectSignalled(hdr, CurrentThread))
{
CountSignaled++;
if (WaitType == WaitAny)
{
KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("One object is already signaled!\n");
do
{
KeAcquireDispatcherDatabaseLock(FALSE);
/*
* If we are going to wait alertably and a user apc is pending
* then return
*/
if (Alertable && KiTestAlert())
{
KeReleaseDispatcherDatabaseLock(FALSE);
return(STATUS_USER_APC);
}
/*
* Check if the wait is already satisfied
*/
for (i = 0; i < Count; i++)
{
hdr = (DISPATCHER_HEADER *)Object[i];
if (KiIsObjectSignalled(hdr, CurrentThread))
{
CountSignaled++;
if (WaitType == WaitAny)
{
KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("One object is already signaled!\n");
return(STATUS_WAIT_0 + i);
}
}
}
}
}
}
if ((WaitType == WaitAll) && (CountSignaled == Count))
{
KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("All objects are already signaled!\n");
return(STATUS_WAIT_0);
}
if ((WaitType == WaitAll) && (CountSignaled == Count))
{
KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("All objects are already signaled!\n");
return(STATUS_WAIT_0);
}
/* Append wait block to the KTHREAD wait block list */
CurrentThread->WaitBlockList = blk;
for (i = 0; i < Count; i++)
{
hdr = (DISPATCHER_HEADER *)Object[i];
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
blk->Object = Object[i];
blk->Thread = CurrentThread;
blk->WaitKey = i;
blk->WaitType = WaitType;
if (i == Count - 1)
blk->NextWaitBlock = NULL;
else
blk->NextWaitBlock = blk + 1;
InsertTailList(&(hdr->WaitListHead),&(blk->WaitListEntry));
blk = blk->NextWaitBlock;
}
PsBlockThread(&Status, Alertable, WaitMode, TRUE, WaitIrql);
} while( Status == STATUS_KERNEL_APC );
/*
* Check if we have already timed out
*/
if (Timeout != NULL &&
KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread))
{
KeReleaseDispatcherDatabaseLock(FALSE);
if (Timeout != NULL)
{
KeCancelTimer(&KeGetCurrentThread()->Timer);
}
return(STATUS_TIMEOUT);
}
/* Append wait block to the KTHREAD wait block list */
CurrentThread->WaitBlockList = blk;
/*
* Set up the wait
*/
for (i = 0; i < Count; i++)
{
hdr = (DISPATCHER_HEADER *)Object[i];
blk->Object = Object[i];
blk->Thread = CurrentThread;
blk->WaitKey = i;
blk->WaitType = WaitType;
if (i == (Count - 1))
{
if (Timeout != NULL)
{
blk->NextWaitBlock = &CurrentThread->WaitBlock[3];
}
else
{
blk->NextWaitBlock = NULL;
}
}
else
{
blk->NextWaitBlock = blk + 1;
}
InsertTailList(&hdr->WaitListHead, &blk->WaitListEntry);
blk = blk->NextWaitBlock;
}
if (Timeout != NULL)
{
CurrentThread->WaitBlock[3].Object = (PVOID)&CurrentThread->Timer;
CurrentThread->WaitBlock[3].Thread = CurrentThread;
CurrentThread->WaitBlock[3].WaitKey = Count;
CurrentThread->WaitBlock[3].WaitType = WaitAny;
CurrentThread->WaitBlock[3].NextWaitBlock = NULL;
InsertTailList(&CurrentThread->Timer.Header.WaitListHead,
&CurrentThread->WaitBlock[3].WaitListEntry);
}
PsBlockThread(&Status, Alertable, WaitMode, TRUE, WaitIrql);
} while(Status == STATUS_KERNEL_APC);
if (Timeout != NULL)
KeCancelTimer(&KeGetCurrentThread()->Timer);
{
KeCancelTimer(&KeGetCurrentThread()->Timer);
}
if (Status == (STATUS_WAIT_63 + 1))
{
Status = STATUS_TIMEOUT;
}
DPRINT("Returning from KeWaitForMultipleObjects()\n");
return(Status);
}

View file

@ -1,4 +1,4 @@
/* $Id: send.c,v 1.3 2000/10/22 16:36:51 ekohl Exp $
/* $Id: send.c,v 1.4 2001/03/18 19:35:13 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -32,16 +32,16 @@
* REVISIONS
*
*/
NTSTATUS STDCALL LpcSendTerminationPort (IN PEPORT Port,
IN TIME CreationTime)
NTSTATUS STDCALL
LpcSendTerminationPort (IN PEPORT Port,
IN TIME CreationTime)
{
NTSTATUS Status;
LPC_TERMINATION_MESSAGE Msg;
NTSTATUS Status;
LPC_TERMINATION_MESSAGE Msg;
Msg.CreationTime = CreationTime;
Status = LpcRequestPort (Port,
&Msg.Header);
return(Status);
Msg.CreationTime = CreationTime;
Status = LpcRequestPort (Port, &Msg.Header);
return(Status);
}
@ -57,13 +57,45 @@ NTSTATUS STDCALL LpcSendTerminationPort (IN PEPORT Port,
* REVISIONS
*
*/
NTSTATUS STDCALL LpcSendDebugMessagePort (IN PEPORT Port,
IN PLPC_DBG_MESSAGE Message)
NTSTATUS STDCALL
LpcSendDebugMessagePort (IN PEPORT Port,
IN PLPC_DBG_MESSAGE Message,
OUT PLPC_DBG_MESSAGE Reply)
{
NTSTATUS Status;
KIRQL oldIrql;
PQUEUEDMESSAGE ReplyMessage;
Status = LpcRequestPort(Port, &Message->Header);
return(Status);
Status = EiReplyOrRequestPort(Port,
&Message->Header,
LPC_REQUEST,
Port);
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(Port);
return(Status);
}
KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE);
/*
* Wait for a reply
*/
KeWaitForSingleObject(&Port->Event,
UserRequest,
UserMode,
FALSE,
NULL);
/*
* Dequeue the reply
*/
KeAcquireSpinLock(&Port->Lock, &oldIrql);
ReplyMessage = EiDequeueMessagePort(Port);
KeReleaseSpinLock(&Port->Lock, oldIrql);
memcpy(Reply, &ReplyMessage->Message, ReplyMessage->Message.MessageSize);
ExFreePool(ReplyMessage);
return(STATUS_SUCCESS);
}
@ -149,9 +181,10 @@ NTSTATUS STDCALL NtRequestPort (IN HANDLE PortHandle,
* REVISIONS
*
*/
NTSTATUS STDCALL NtRequestWaitReplyPort (IN HANDLE PortHandle,
PLPC_MESSAGE LpcRequest,
PLPC_MESSAGE LpcReply)
NTSTATUS STDCALL
NtRequestWaitReplyPort (IN HANDLE PortHandle,
PLPC_MESSAGE LpcRequest,
PLPC_MESSAGE LpcReply)
{
NTSTATUS Status;
PEPORT Port;
@ -177,14 +210,13 @@ NTSTATUS STDCALL NtRequestWaitReplyPort (IN HANDLE PortHandle,
LpcRequest,
LPC_REQUEST,
Port);
KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE);
if (!NT_SUCCESS(Status))
{
DbgPrint("Enqueue failed\n");
ObDereferenceObject(Port);
return(Status);
}
KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE);
/*
* Wait for a reply

View file

@ -83,13 +83,13 @@ MmGetContinuousPages(ULONG NumberOfBytes,
break;
}
}
else if (start != -1)
else
{
start = -1;
/*
* Fast forward to the base of the next aligned region
*/
i = i + (Alignment / PAGESIZE);
i = ROUND_UP((i + 1), (Alignment / PAGESIZE));
}
}
if (start == -1 || length != NrPages)
@ -176,11 +176,19 @@ PVOID MmInitializePageList(PVOID FirstPhysKernelAddress,
}
}
}
/*
* Page zero is reserved
*/
MmPageArray[0].Flags = MM_PHYSICAL_PAGE_BIOS;
MmPageArray[0].ReferenceCount = 0;
InsertTailList(&BiosPageListHead,
&MmPageArray[0].ListEntry);
i = 1;
if ((ULONG)FirstPhysKernelAddress < 0xa0000)
{
MmStats.NrFreePages += ((ULONG)FirstPhysKernelAddress/PAGESIZE);
MmStats.NrFreePages += (((ULONG)FirstPhysKernelAddress/PAGESIZE) - 1);
for (; i<((ULONG)FirstPhysKernelAddress/PAGESIZE); i++)
{
MmPageArray[i].Flags = MM_PHYSICAL_PAGE_FREE;
@ -216,7 +224,7 @@ PVOID MmInitializePageList(PVOID FirstPhysKernelAddress,
}
else
{
MmStats.NrFreePages += (0xa0000 / PAGESIZE);
MmStats.NrFreePages += ((0xa0000 / PAGESIZE) - 1);
for (; i<(0xa0000 / PAGESIZE); i++)
{
MmPageArray[i].Flags = MM_PHYSICAL_PAGE_FREE;

View file

@ -1,4 +1,4 @@
/* $Id: create.c,v 1.31 2001/03/16 18:11:24 dwelch Exp $
/* $Id: create.c,v 1.32 2001/03/18 19:35:13 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -26,6 +26,7 @@
#include <internal/ps.h>
#include <internal/ob.h>
#include <internal/id.h>
#include <internal/dbg.h>
#define NDEBUG
#include <internal/debug.h>
@ -577,27 +578,11 @@ NtCreateThread (PHANDLE ThreadHandle,
/*
* Maybe send a message to the process's debugger
*/
#if 0
if (ParentProcess->DebugPort != NULL)
{
LPC_DBG_MESSAGE Message;
PEPROCESS Process;
Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
sizeof(LPC_MESSAGE_HEADER);
Message.EventCode = DBG_EVENT_CREATE_THREAD;
Message.Data.CreateThread.StartAddress =
;
Message.Data.CreateProcess.Base = ImageBase;
Message.Data.CreateProcess.EntryPoint = NULL; //
Status = LpcSendDebugMessagePort(ParentProcess->DebugPort,
&Message);
}
#endif
DbgkCreateThread((PVOID)ThreadContext->Eip);
/*
* Start the thread running
*/
if (!CreateSuspended)
{
DPRINT("Not creating suspended\n");

View file

@ -133,6 +133,7 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus)
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
CurrentThread->ExitStatus = ExitStatus;
KeCancelTimer(&KeGetCurrentThread()->Timer);
KeAcquireDispatcherDatabaseLock(FALSE);
CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE;
KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader);

View file

@ -1,4 +1,4 @@
/* $Id: process.c,v 1.58 2001/03/07 16:48:45 dwelch Exp $
/* $Id: process.c,v 1.59 2001/03/18 19:35:14 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -532,6 +532,7 @@ NtCreateProcess (OUT PHANDLE ProcessHandle,
/*
* Maybe send a message to the creator process's debugger
*/
#if 0
if (ParentProcess->DebugPort != NULL)
{
LPC_DBG_MESSAGE Message;
@ -554,6 +555,7 @@ NtCreateProcess (OUT PHANDLE ProcessHandle,
Status = LpcSendDebugMessagePort(ParentProcess->DebugPort,
&Message);
}
#endif
ObDereferenceObject(Process);
ObDereferenceObject(ParentProcess);

View file

@ -1,6 +1,23 @@
/* $Id: suspend.c,v 1.4 2001/03/16 18:11:24 dwelch Exp $
/*
* ReactOS kernel
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
*
* 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: suspend.c,v 1.5 2001/03/18 19:35:14 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ps/suspend.c
* PURPOSE: Thread managment

View file

@ -1,4 +1,4 @@
/* $Id: thread.c,v 1.71 2001/03/16 18:11:24 dwelch Exp $
/* $Id: thread.c,v 1.72 2001/03/18 19:35:14 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -73,14 +73,6 @@ HANDLE STDCALL PsGetCurrentThreadId(VOID)
VOID PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread)
{
// DPRINT("PsInsertIntoThreadList(Priority %x, Thread %x)\n",Priority,
// Thread);
// DPRINT("Offset %x\n", THREAD_PRIORITY_MAX + Priority);
if (PiThreadListLock.Lock == 0)
{
KeBugCheck(0);
}
if (Priority >= MAXIMUM_PRIORITY || Priority < 0)
{
DPRINT1("Invalid thread priority\n");
@ -128,11 +120,6 @@ static PETHREAD PsScanThreadList (KPRIORITY Priority)
PLIST_ENTRY current_entry;
PETHREAD current;
// DPRINT("PsScanThreadList(Priority %d)\n",Priority);
if (PiThreadListLock.Lock == 0)
{
KeBugCheck(0);
}
current_entry = RemoveHeadList(&PriorityListHead[Priority]);
if (current_entry != &PriorityListHead[Priority])
{
@ -251,6 +238,36 @@ PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode,
KeLowerIrql(WaitIrql);
}
VOID
PsFreezeAllThreads(PEPROCESS Process)
/*
* Used by the debugging code to freeze all the process's threads
* while the debugger is examining their state.
*/
{
KIRQL oldIrql;
PLIST_ENTRY current_entry;
PETHREAD current;
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
current_entry = Process->ThreadListHead.Flink;
while (current_entry != &Process->ThreadListHead)
{
current = CONTAINING_RECORD(current_entry, ETHREAD,
Tcb.ProcessThreadListEntry);
/*
* We have to be careful here, we can't just set the freeze the
* thread inside kernel mode since it may be holding a lock.
*/
current_entry = current_entry->Flink;
}
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
}
VOID
PsInitThreadManagment(VOID)
/*