Reworked APC and waiting code, seems more stable now

KeWaitForMultipleObjects is broken, shouldn't be difficult to fix
Corrected bug in ntdll ldr which prevented VC applications being loaded
Added thread testing application
Tried to make thread termination reentrant
Improved stack frame dump

svn path=/trunk/; revision=868
This commit is contained in:
David Welch 1999-12-13 22:04:41 +00:00
parent 90e6a2244e
commit ac7a3aa542
29 changed files with 858 additions and 760 deletions

View file

@ -41,7 +41,7 @@ FS_DRIVERS = vfat
# FS_DRIVERS = minix ext2 template # FS_DRIVERS = minix ext2 template
KERNEL_SERVICES = $(DEVICE_DRIVERS) $(FS_DRIVERS) KERNEL_SERVICES = $(DEVICE_DRIVERS) $(FS_DRIVERS)
APPS = args hello shell test cat bench apc shm lpc APPS = args hello shell test cat bench apc shm lpc thread
# APPS = cmd # APPS = cmd
all: buildno $(COMPONENTS) $(DLLS) $(SUBSYS) $(LOADERS) $(KERNEL_SERVICES) $(APPS) all: buildno $(COMPONENTS) $(DLLS) $(SUBSYS) $(LOADERS) $(KERNEL_SERVICES) $(APPS)

View file

@ -0,0 +1,41 @@
#
#
#
PROGS = thread
all: $(PROGS:%=%.exe)
.phony: all
clean: $(PROGS:%=%_clean)
$(PROGS:%=%_clean): %_clean:
- $(RM) $*.o
- $(RM) $*.exe
- $(RM) $*.sym
.phony: clean
floppy: # $(PROGS:%=$(FLOPPY_DIR)/apps/%.exe)
$(PROGS:%=$(FLOPPY_DIR)/apps/%.exe): $(FLOPPY_DIR)/apps/%.exe: %.exe
ifeq ($(DOSCLI),yes)
$(CP) $*.exe $(FLOPPY_DIR)\apps\$*.exe
else
$(CP) $*.exe $(FLOPPY_DIR)/apps/$*.exe
endif
dist: $(PROGS:%=../../$(DIST_DIR)/apps/%.exe)
$(PROGS:%=../../$(DIST_DIR)/apps/%.exe): ../../$(DIST_DIR)/apps/%.exe: %.exe
ifeq ($(DOSCLI),yes)
$(CP) $*.exe ..\..\$(DIST_DIR)\apps\$*.exe
else
$(CP) $*.exe ../../$(DIST_DIR)/apps/$*.exe
endif
thread.exe: thread.c
$(CC) $(CFLAGS) thread.c -lkernel32 -o thread.exe
$(NM) --numeric-sort thread.exe > thread.sym
include ../../rules.mak

View file

@ -0,0 +1,45 @@
#include <stdio.h>
#include <windows.h>
#define NR_THREADS (10)
ULONG nr;
DWORD WINAPI thread_main1(LPVOID param)
{
ULONG s;
printf("Thread %d running\n", (DWORD)param);
s = nr = ((nr * 1103515245) + 12345) & 0x7fffffff;
s = s % 10;
printf("s %d\n", s);
Sleep(s);
return 0;
}
int main (int argc, char* argv[])
{
HANDLE hThread;
DWORD i=0;
DWORD id;
ULONG nr;
nr = atoi(argv[1]);
printf("Seed %d\n", nr);
printf("Creating %d threads...\n",NR_THREADS*2);
for (i=0;i<NR_THREADS;i++)
{
CreateThread(NULL,
0,
thread_main1,
(LPVOID)i,
0,
&id);
}
printf("All threads created...\n");
for(;;);
return 0;
}

View file

@ -226,7 +226,7 @@ typedef struct _KTHREAD
KAPC SuspendApc; KAPC SuspendApc;
KSEMAPHORE SuspendSemaphore; KSEMAPHORE SuspendSemaphore;
LIST_ENTRY ThreadListEntry; LIST_ENTRY ThreadListEntry;
UCHAR FreezeCount; CHAR FreezeCount;
ULONG SuspendCount; ULONG SuspendCount;
UCHAR IdealProcessor; UCHAR IdealProcessor;
UCHAR DisableBoost; UCHAR DisableBoost;

View file

@ -28,10 +28,12 @@ NTSTATUS KeAddThreadTimeout(PKTHREAD Thread, PLARGE_INTEGER Interval);
VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header, ULONG Type, VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header, ULONG Type,
ULONG Size, ULONG SignalState); ULONG Size, ULONG SignalState);
VOID KeDumpStackFrames(ULONG DummyArg, ULONG NrFrames); VOID KeDumpStackFrames(PVOID Stack, ULONG NrFrames);
ULONG KeAllocateGdtSelector(ULONG Desc[2]); ULONG KeAllocateGdtSelector(ULONG Desc[2]);
VOID KeFreeGdtSelector(ULONG Entry); VOID KeFreeGdtSelector(ULONG Entry);
BOOLEAN KiTestAlert(PKTHREAD Thread, PCONTEXT UserContext); BOOLEAN KiTestAlert(PKTHREAD Thread, PCONTEXT UserContext);
VOID KeCallApcsThread(VOID);
VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus);
/* INITIALIZATION FUNCTIONS *************************************************/ /* INITIALIZATION FUNCTIONS *************************************************/

View file

@ -17,6 +17,7 @@ VOID PsInitThreadManagment(VOID);
VOID PsInitProcessManagment(VOID); VOID PsInitProcessManagment(VOID);
VOID PsInitIdleThread(VOID); VOID PsInitIdleThread(VOID);
VOID PsDispatchThread(ULONG NewThreadStatus); VOID PsDispatchThread(ULONG NewThreadStatus);
VOID PsDispatchThreadNoLock(ULONG NewThreadStatus);
VOID PiTerminateProcessThreads(PEPROCESS Process, NTSTATUS ExitStatus); VOID PiTerminateProcessThreads(PEPROCESS Process, NTSTATUS ExitStatus);
VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus); VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus);
VOID PsReleaseThread(PETHREAD Thread); VOID PsReleaseThread(PETHREAD Thread);
@ -24,14 +25,26 @@ VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext);
VOID PsBeginThreadWithContextInternal(VOID); VOID PsBeginThreadWithContextInternal(VOID);
VOID PiKillMostProcesses(VOID); VOID PiKillMostProcesses(VOID);
NTSTATUS STDCALL PiTerminateProcess(PEPROCESS Process, NTSTATUS ExitStatus); NTSTATUS STDCALL PiTerminateProcess(PEPROCESS Process, NTSTATUS ExitStatus);
ULONG PsUnfreezeThread(PETHREAD Thread, PNTSTATUS WaitStatus);
ULONG PsFreezeThread(PETHREAD Thread, PNTSTATUS WaitStatus,
UCHAR Alertable, ULONG WaitMode);
VOID PiInitApcManagement(VOID);
VOID PiDeleteThread(PVOID ObjectBody);
VOID PiCloseThread(PVOID ObjectBody, ULONG HandleCount);
NTSTATUS PsInitializeThread(HANDLE ProcessHandle,
PETHREAD* ThreadPtr,
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes);
#define THREAD_STATE_INVALID (0) #define THREAD_STATE_INVALID (0)
#define THREAD_STATE_RUNNABLE (1) #define THREAD_STATE_RUNNABLE (1)
#define THREAD_STATE_RUNNING (2) #define THREAD_STATE_RUNNING (2)
#define THREAD_STATE_SUSPENDED (3) #define THREAD_STATE_SUSPENDED (3)
#define THREAD_STATE_TERMINATED_1 (4) #define THREAD_STATE_FROZEN (4)
#define THREAD_STATE_TERMINATED_2 (5) #define THREAD_STATE_TERMINATED_1 (5)
#define THREAD_STATE_MAX (6) #define THREAD_STATE_TERMINATED_2 (6)
#define THREAD_STATE_MAX (7)
// Internal thread priorities, added by Phillip Susi // Internal thread priorities, added by Phillip Susi

View file

@ -24,3 +24,4 @@ cp apps/shm/shmsrv.exe $1/reactos/bin
cp apps/shm/shmclt.exe $1/reactos/bin cp apps/shm/shmclt.exe $1/reactos/bin
cp apps/lpc/lpcsrv.exe $1/reactos/bin cp apps/lpc/lpcsrv.exe $1/reactos/bin
cp apps/lpc/lpcclt.exe $1/reactos/bin cp apps/lpc/lpcclt.exe $1/reactos/bin
cp apps/thread/thread.exe $1/reactos/bin

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.33 1999/08/29 13:44:53 dwelch Exp $ # $Id: makefile,v 1.34 1999/12/13 22:04:33 dwelch Exp $
# #
# ReactOS Operating System # ReactOS Operating System
# #
@ -197,7 +197,7 @@ $(TARGET).dll: $(DLLMAIN) $(OBJECTS) $(TARGET).def
-o $(TARGET).dll \ -o $(TARGET).dll \
$(TARGET).o \ $(TARGET).o \
../kernel32/kernel32.a \ ../kernel32/kernel32.a \
-Wl,--image-base,0x20000000 \ -Wl,--image-base,0x77630000 \
-Wl,--file-alignment,0x1000 \ -Wl,--file-alignment,0x1000 \
-Wl,--section-alignment,0x1000 \ -Wl,--section-alignment,0x1000 \
-Wl,temp.exp -Wl,temp.exp

View file

@ -1,4 +1,4 @@
/* $Id: proc.c,v 1.24 1999/12/06 00:23:40 ekohl Exp $ /* $Id: proc.c,v 1.25 1999/12/13 22:04:34 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -290,36 +290,27 @@ WaitForInputIdle (
} }
VOID VOID STDCALL Sleep (DWORD dwMilliseconds)
STDCALL
Sleep (
DWORD dwMilliseconds
)
{ {
SleepEx (dwMilliseconds, FALSE); SleepEx (dwMilliseconds, FALSE);
return; return;
} }
DWORD STDCALL SleepEx(DWORD dwMilliseconds,
DWORD BOOL bAlertable)
STDCALL
SleepEx (
DWORD dwMilliseconds,
BOOL bAlertable
)
{ {
TIME Interval; TIME Interval;
NTSTATUS errCode; NTSTATUS errCode;
Interval.QuadPart = dwMilliseconds * 1000; Interval.QuadPart = dwMilliseconds * 1000;
errCode = NtDelayExecution(bAlertable,&Interval); errCode = NtDelayExecution(bAlertable,&Interval);
if ( !NT_SUCCESS(errCode) ) if (!NT_SUCCESS(errCode))
{ {
SetLastError(RtlNtStatusToDosError(errCode)); SetLastError(RtlNtStatusToDosError(errCode));
return -1; return -1;
} }
return 0; return 0;
} }

View file

@ -17,7 +17,7 @@
#include <string.h> #include <string.h>
#include <internal/i386/segment.h> #include <internal/i386/segment.h>
//#define NDEBUG #define NDEBUG
#include <kernel32/kernel32.h> #include <kernel32/kernel32.h>

View file

@ -1,4 +1,4 @@
/* $Id: utils.c,v 1.19 1999/12/11 21:14:47 dwelch Exp $ /* $Id: utils.c,v 1.20 1999/12/13 22:04:34 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -698,7 +698,7 @@ static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders,
PDLL Module; PDLL Module;
NTSTATUS Status; NTSTATUS Status;
DPRINT1("LdrFixupImports(NTHeaders %x, ImageBase %x)\n", NTHeaders, DPRINT("LdrFixupImports(NTHeaders %x, ImageBase %x)\n", NTHeaders,
ImageBase); ImageBase);
/* /*
@ -708,7 +708,7 @@ static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders,
ImageBase + NTHeaders->OptionalHeader ImageBase + NTHeaders->OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
.VirtualAddress); .VirtualAddress);
DPRINT1("ImportModuleDirectory %x\n", ImportModuleDirectory); DPRINT("ImportModuleDirectory %x\n", ImportModuleDirectory);
while (ImportModuleDirectory->dwRVAModuleName) while (ImportModuleDirectory->dwRVAModuleName)
{ {
@ -717,7 +717,7 @@ static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders,
DWORD pName; DWORD pName;
PWORD pHint; PWORD pHint;
DPRINT1("ImportModule->Directory->dwRVAModuleName %s\n", DPRINT("ImportModule->Directory->dwRVAModuleName %s\n",
(PCHAR)(ImageBase + ImportModuleDirectory->dwRVAModuleName)); (PCHAR)(ImageBase + ImportModuleDirectory->dwRVAModuleName));
Status = LdrLoadDll(&Module, Status = LdrLoadDll(&Module,

View file

@ -47,8 +47,6 @@ static unsigned int HiSetCurrentPICMask(unsigned int mask)
return mask; return mask;
} }
extern VOID KeApcProlog2();
static VOID HiSwitchIrql(KIRQL oldIrql) static VOID HiSwitchIrql(KIRQL oldIrql)
/* /*
* FUNCTION: Switches to the current irql * FUNCTION: Switches to the current irql
@ -85,28 +83,37 @@ static VOID HiSwitchIrql(KIRQL oldIrql)
__asm__("sti\n\t"); __asm__("sti\n\t");
return; return;
} }
HiSetCurrentPICMask(0);
if(CurrentIrql == APC_LEVEL) HiSetCurrentPICMask(0);
{ if (CurrentIrql == APC_LEVEL)
if (DpcQueueSize > 0 ) {
{ if (DpcQueueSize > 0 )
KeSetCurrentIrql(DISPATCH_LEVEL); {
__asm__("sti\n\t"); KeSetCurrentIrql(DISPATCH_LEVEL);
KeDrainDpcQueue(); __asm__("sti\n\t");
__asm__("cli\n\t"); KeDrainDpcQueue();
KeSetCurrentIrql(PASSIVE_LEVEL); __asm__("cli\n\t");
} KeSetCurrentIrql(PASSIVE_LEVEL);
__asm__("sti\n\t"); }
return; __asm__("sti\n\t");
} return;
if( CurrentIrql == PASSIVE_LEVEL && CurrentThread && CurrentThread->ApcState.KernelApcPending ) }
{
KeSetCurrentIrql( APC_LEVEL ); if (CurrentIrql == PASSIVE_LEVEL &&
KeApcProlog2(); CurrentThread != NULL &&
KeSetCurrentIrql( PASSIVE_LEVEL ); CurrentThread->ApcState.KernelApcPending)
} {
KeSetCurrentIrql(APC_LEVEL);
__asm__("sti\n\t"); __asm__("sti\n\t");
KeCallApcsThread();
__asm__("cli\n\t");
KeSetCurrentIrql(PASSIVE_LEVEL);
__asm__("sti\n\t");
}
else
{
__asm__("sti\n\t");
}
} }
VOID KeSetCurrentIrql(KIRQL newlvl) VOID KeSetCurrentIrql(KIRQL newlvl)

View file

@ -67,13 +67,9 @@ VOID KeAcquireSpinLockAtDpcLevel(PKSPIN_LOCK SpinLock)
* SpinLock = Spinlock to acquire * SpinLock = Spinlock to acquire
*/ */
{ {
if (SpinLock->Lock == 1)
{
DbgPrint("May be acquiring locked spinlock\n");
}
while (InterlockedExchange(&SpinLock->Lock, 1) == 1) while (InterlockedExchange(&SpinLock->Lock, 1) == 1)
{ {
DbgPrint("Spinning on spinlock\n"); DbgPrint("Spinning on spinlock %x\n", SpinLock);
KeBugCheck(0); KeBugCheck(0);
} }
} }

View file

@ -253,7 +253,7 @@ VOID IopCompleteRequest(struct _KAPC* Apc,
"(*SystemArgument1) %x\n", Apc, SystemArgument1, "(*SystemArgument1) %x\n", Apc, SystemArgument1,
*SystemArgument1); *SystemArgument1);
IoSecondStageCompletion((PIRP)(*SystemArgument1), IoSecondStageCompletion((PIRP)(*SystemArgument1),
SystemArgument2); (KPRIORITY)(*SystemArgument2));
} }
VOID IoCompleteRequest(PIRP Irp, CCHAR PriorityBoost) VOID IoCompleteRequest(PIRP Irp, CCHAR PriorityBoost)
@ -270,8 +270,8 @@ VOID IoCompleteRequest(PIRP Irp, CCHAR PriorityBoost)
NTSTATUS Status; NTSTATUS Status;
PKTHREAD Thread; PKTHREAD Thread;
DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d)\n", DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
Irp,PriorityBoost); Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
for (i=0;i<Irp->StackCount;i++) for (i=0;i<Irp->StackCount;i++)
{ {
@ -307,14 +307,16 @@ VOID IoCompleteRequest(PIRP Irp, CCHAR PriorityBoost)
(PVOID) (PVOID)
Irp->Overlay.AsynchronousParameters.UserApcContext); Irp->Overlay.AsynchronousParameters.UserApcContext);
KeInsertQueueApc(&Irp->Tail.Apc, KeInsertQueueApc(&Irp->Tail.Apc,
Irp, (PVOID)Irp,
PriorityBoost, (PVOID)(ULONG)PriorityBoost,
KernelMode); KernelMode);
DPRINT("Finished dispatching APC\n");
} }
else else
{ {
DPRINT("Calling completion routine directly\n"); DPRINT("Calling completion routine directly\n");
IoSecondStageCompletion(Irp,PriorityBoost); IoSecondStageCompletion(Irp,PriorityBoost);
DPRINT("Finished completition routine\n");
} }
} }

View file

@ -16,19 +16,32 @@
#include <internal/string.h> #include <internal/string.h>
#include <internal/i386/segment.h> #include <internal/i386/segment.h>
#include <internal/ps.h> #include <internal/ps.h>
#include <internal/ke.h>
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
extern VOID KeApcProlog(VOID); /* GLOBALS *******************************************************************/
static KSPIN_LOCK PiApcLock; static KSPIN_LOCK PiApcLock;
/* PROTOTYPES ****************************************************************/
VOID KeApcProlog3(PKAPC Apc);
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
VOID KeCallKernelRoutineApc(PKAPC Apc)
/*
* FUNCTION: Call the kernel routine for an APC
*/
{
DPRINT("KeCallKernelRoutineApc(Apc %x)\n",Apc);
Apc->KernelRoutine(Apc,
&Apc->NormalRoutine,
&Apc->NormalContext,
&Apc->SystemArgument1,
&Apc->SystemArgument2);
DPRINT("Finished KeCallKernelRoutineApc()\n");
}
BOOLEAN KiTestAlert(PKTHREAD Thread, BOOLEAN KiTestAlert(PKTHREAD Thread,
PCONTEXT UserContext) PCONTEXT UserContext)
/* /*
@ -77,81 +90,41 @@ BOOLEAN KiTestAlert(PKTHREAD Thread,
* Now call for the kernel routine for the APC, which will free * Now call for the kernel routine for the APC, which will free
* the APC data structure * the APC data structure
*/ */
KeApcProlog3(Apc); KeCallKernelRoutineApc(Apc);
} }
UserContext->Esp = (ULONG)Esp; UserContext->Esp = (ULONG)Esp;
InitializeListHead(&Thread->ApcState.ApcListHead[1]); InitializeListHead(&Thread->ApcState.ApcListHead[1]);
return(TRUE); return(TRUE);
} }
VOID KeApcProlog2() VOID KeCallApcsThread(VOID)
{ {
PETHREAD Thread = PsGetCurrentThread(); PETHREAD Thread = PsGetCurrentThread();
PLIST_ENTRY current; PLIST_ENTRY current;
PKAPC Apc; PKAPC Apc;
KIRQL oldlvl; KIRQL oldlvl;
DPRINT( "KeApcProlog2()\n" ); DPRINT("KeCallApcsThread()\n");
KeLowerIrql( APC_LEVEL ); KeAcquireSpinLock(&PiApcLock, &oldlvl);
KeAcquireSpinLock( &PiApcLock, &oldlvl ); while(!IsListEmpty(&(Thread->Tcb.ApcState.ApcListHead[0])))
while( !IsListEmpty( &(Thread->Tcb.ApcState.ApcListHead[0]) ) )
{ {
DPRINT( "Delivering APC\n" ); DPRINT("Delivering APC\n");
current = RemoveTailList( &(Thread->Tcb.ApcState.ApcListHead[0]) ); current = RemoveTailList(&(Thread->Tcb.ApcState.ApcListHead[0]));
KeReleaseSpinLock( &PiApcLock, oldlvl ); Thread->Tcb.ApcState.KernelApcInProgress++;
Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry); Thread->Tcb.ApcState.KernelApcPending--;
KeApcProlog3(Apc); KeReleaseSpinLock(&PiApcLock, oldlvl);
KeAcquireSpinLock( &PiApcLock, &oldlvl );
Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry);
KeCallKernelRoutineApc(Apc);
KeAcquireSpinLock(&PiApcLock, &oldlvl);
DPRINT("Called kernel routine for APC\n");
// PsFreezeThread(Thread, NULL, FALSE, KernelMode);
DPRINT("Done frozen thread\n");
Thread->Tcb.ApcState.KernelApcInProgress--;
} }
KeReleaseSpinLock( &PiApcLock, oldlvl ); KeReleaseSpinLock(&PiApcLock, oldlvl);
Thread->Tcb.WaitStatus = STATUS_ALERTED; // Thread->Tcb.WaitStatus = STATUS_KERNEL_APC;
KeLowerIrql( PASSIVE_LEVEL );
}
VOID KeApcProlog3(PKAPC Apc)
/*
* FUNCTION: This is called from the prolog proper (in assembly) to deliver
* a kernel APC
*/
{
PKTHREAD Thread = KeGetCurrentThread();
DPRINT("KeApcProlog3(Apc %x)\n",Apc);
InterlockedIncrement( &(Thread->ApcState.KernelApcInProgress) );
InterlockedDecrement( &(Thread->ApcState.KernelApcPending) );
Apc->KernelRoutine(Apc,
&Apc->NormalRoutine,
&Apc->NormalContext,
&Apc->SystemArgument1,
&Apc->SystemArgument2);
InterlockedDecrement( &(Thread->ApcState.KernelApcInProgress) );
}
VOID KeDeliverKernelApc( PKTHREAD TargetThread )
/*
* FUNCTION: Simulates an interrupt on the target thread which will transfer
* control to a kernel mode routine
* Must be called while holding the PiApcLock
*/
{
PULONG Stack;
DPRINT( "KeDeliverKernelApc( TargetThread %x)\n", TargetThread );
if (TargetThread == KeGetCurrentThread())
{
KeApcProlog2();
return;
}
TargetThread->Context.esp = TargetThread->Context.esp - 12;
Stack = (PULONG)TargetThread->Context.esp;
Stack[0] = TargetThread->Context.eip;
Stack[1] = TargetThread->Context.cs;
Stack[2] = TargetThread->Context.eflags;
TargetThread->Context.eip = (ULONG)KeApcProlog;
PsResumeThread(CONTAINING_RECORD(TargetThread,ETHREAD,Tcb),
NULL);
} }
VOID KeInsertQueueApc(PKAPC Apc, VOID KeInsertQueueApc(PKAPC Apc,
@ -173,7 +146,7 @@ VOID KeInsertQueueApc(PKAPC Apc,
"SystemArgument2 %x, Mode %d)\n",Apc,SystemArgument1, "SystemArgument2 %x, Mode %d)\n",Apc,SystemArgument1,
SystemArgument2,Mode); SystemArgument2,Mode);
KeAcquireSpinLock( &PiApcLock, &oldlvl ); KeAcquireSpinLock(&PiApcLock, &oldlvl);
Apc->SystemArgument1 = SystemArgument1; Apc->SystemArgument1 = SystemArgument1;
Apc->SystemArgument2 = SystemArgument2; Apc->SystemArgument2 = SystemArgument2;
@ -200,25 +173,12 @@ VOID KeInsertQueueApc(PKAPC Apc,
} }
Apc->Inserted = TRUE; Apc->Inserted = TRUE;
DPRINT("TargetThread->KernelApcDisable %d\n", if (Apc->ApcMode == KernelMode && TargetThread->KernelApcDisable >= 1 &&
TargetThread->KernelApcDisable); TargetThread->WaitIrql < APC_LEVEL)
DPRINT("Apc->KernelRoutine %x\n", Apc->KernelRoutine);
DPRINT( "TargetThread->Altertable = %x, TargetThread->WaitIrql = %d\n", TargetThread->Alertable, TargetThread->WaitIrql );
if (Apc->ApcMode == KernelMode && TargetThread->KernelApcDisable >= 1 )
if( TargetThread != PsGetCurrentThread() )
{
PsSuspendThread( CONTAINING_RECORD( TargetThread, ETHREAD, Tcb ), NULL, TRUE, KernelMode );
KeReleaseSpinLock( &PiApcLock, oldlvl );
if( TargetThread->WaitIrql < APC_LEVEL )
KeDeliverKernelApc( TargetThread );
}
else {
if( TargetThread->WaitIrql < APC_LEVEL )
KeDeliverKernelApc( TargetThread );
}
else
{ {
DPRINT("Queuing APC for later delivery\n"); KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb),
STATUS_KERNEL_APC);
KeReleaseSpinLock(&PiApcLock, oldlvl);
} }
if (Apc->ApcMode == UserMode && TargetThread->Alertable == TRUE && if (Apc->ApcMode == UserMode && TargetThread->Alertable == TRUE &&
TargetThread->WaitMode == UserMode) TargetThread->WaitMode == UserMode)
@ -228,8 +188,9 @@ VOID KeInsertQueueApc(PKAPC Apc,
DPRINT("Resuming thread for user APC\n"); DPRINT("Resuming thread for user APC\n");
Status = STATUS_USER_APC; Status = STATUS_USER_APC;
PsResumeThread((PETHREAD)TargetThread, KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb),
&Status); STATUS_USER_APC);
KeReleaseSpinLock(&PiApcLock, oldlvl);
} }
} }
@ -332,8 +293,8 @@ NTSTATUS STDCALL NtTestAlert(VOID)
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
VOID PiInitApcManagement() VOID PiInitApcManagement(VOID)
{ {
KeInitializeSpinLock( &PiApcLock ); KeInitializeSpinLock(&PiApcLock);
} }

View file

@ -19,6 +19,7 @@
/* GLOBALS ******************************************************************/ /* GLOBALS ******************************************************************/
static LIST_ENTRY BugcheckCallbackListHead = {NULL,NULL}; static LIST_ENTRY BugcheckCallbackListHead = {NULL,NULL};
static ULONG InBugCheck;
VOID PsDumpThreads(VOID); VOID PsDumpThreads(VOID);
@ -32,6 +33,7 @@ BOOLEAN KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
VOID KeInitializeBugCheck(VOID) VOID KeInitializeBugCheck(VOID)
{ {
InitializeListHead(&BugcheckCallbackListHead); InitializeListHead(&BugcheckCallbackListHead);
InBugCheck = 0;
} }
VOID KeInitializeCallbackRecord(PKBUGCHECK_CALLBACK_RECORD CallbackRecord) VOID KeInitializeCallbackRecord(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
@ -72,7 +74,7 @@ VOID KeBugCheckEx(ULONG BugCheckCode,
BugCheckParameter1,BugCheckParameter2,BugCheckParameter3, BugCheckParameter1,BugCheckParameter2,BugCheckParameter3,
BugCheckParameter4); BugCheckParameter4);
PsDumpThreads(); PsDumpThreads();
KeDumpStackFrames(0,64); KeDumpStackFrames(&((&BugCheckCode)[-1]),64);
for(;;) for(;;)
__asm__("hlt\n\t"); //PJS: use HLT instruction, rather than busy wait __asm__("hlt\n\t"); //PJS: use HLT instruction, rather than busy wait
@ -87,6 +89,19 @@ VOID KeBugCheck(ULONG BugCheckCode)
* RETURNS: Doesn't * RETURNS: Doesn't
*/ */
{ {
KeBugCheckEx(BugCheckCode,0,0,0,0); __asm__("cli\n\t");
DbgPrint("Bug detected (code %x)\n", BugCheckCode);
if (InBugCheck == 1)
{
DbgPrint("Recursive bug check halting now\n");
for(;;);
}
InBugCheck = 1;
PsDumpThreads();
KeDumpStackFrames(&((&BugCheckCode)[-1]), 80);
for(;;)
{
__asm__("hlt\n\t");
}
} }

View file

@ -242,7 +242,7 @@ asmlinkage void exception_handler(unsigned int edi,
} }
DbgPrint("CS:EIP %x:%x\n",cs&0xffff,eip); DbgPrint("CS:EIP %x:%x\n",cs&0xffff,eip);
DbgPrint("CS:EIP %x:", cs&0xffff); DbgPrint("CS:EIP %x:", cs&0xffff);
print_address(eip); print_address((PVOID)eip);
DbgPrint("\n"); DbgPrint("\n");
__asm__("movl %%cr2,%0\n\t" __asm__("movl %%cr2,%0\n\t"
: "=d" (cr2)); : "=d" (cr2));
@ -302,7 +302,7 @@ asmlinkage void exception_handler(unsigned int edi,
stack[i] <= ((ULONG)&init_stack_top))) stack[i] <= ((ULONG)&init_stack_top)))
{ {
// DbgPrint(" %.8x", stack[i]); // DbgPrint(" %.8x", stack[i]);
print_address(stack[i]); print_address((PVOID)stack[i]);
DbgPrint(" "); DbgPrint(" ");
} }
} }
@ -328,6 +328,7 @@ asmlinkage void exception_handler(unsigned int edi,
DbgPrint("\n"); DbgPrint("\n");
DbgPrint("Killing current task\n"); DbgPrint("Killing current task\n");
// for(;;);
KeLowerIrql(PASSIVE_LEVEL); KeLowerIrql(PASSIVE_LEVEL);
if ((cs&0xffff) == USER_CS) if ((cs&0xffff) == USER_CS)
{ {
@ -338,12 +339,13 @@ asmlinkage void exception_handler(unsigned int edi,
for(;;); for(;;);
} }
VOID KeDumpStackFrames(ULONG DummyArg, ULONG NrFrames) VOID KeDumpStackFrames(PVOID _Stack, ULONG NrFrames)
{ {
PULONG Stack = &((&DummyArg)[-1]); PULONG Stack = (PULONG)_Stack;
ULONG i; ULONG i;
Stack = (PVOID)(((ULONG)Stack) & (~0x3)); Stack = (PVOID)(((ULONG)Stack) & (~0x3));
DbgPrint("Stack: %x\n", Stack);
DbgPrint("Frames:\n"); DbgPrint("Frames:\n");
for (i=0; i<NrFrames; i++) for (i=0; i<NrFrames; i++)
@ -352,7 +354,7 @@ VOID KeDumpStackFrames(ULONG DummyArg, ULONG NrFrames)
if (Stack[i] > KERNEL_BASE) if (Stack[i] > KERNEL_BASE)
{ {
// DbgPrint("%.8x ",Stack[i]); // DbgPrint("%.8x ",Stack[i]);
print_address(Stack[i]); print_address((PVOID)Stack[i]);
DbgPrint(" "); DbgPrint(" ");
} }
if (Stack[i] == 0xceafbeef) if (Stack[i] == 0xceafbeef)

View file

@ -1,4 +1,4 @@
/* $Id: main.c,v 1.31 1999/11/24 11:51:50 dwelch Exp $ /* $Id: main.c,v 1.32 1999/12/13 22:04:36 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -26,7 +26,7 @@
#include <internal/mmhal.h> #include <internal/mmhal.h>
#include <internal/i386/segment.h> #include <internal/i386/segment.h>
#define NDEBUG //#define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
@ -128,70 +128,6 @@ unsigned int old_idt[256][2];
//extern unsigned int idt[]; //extern unsigned int idt[];
unsigned int old_idt_valid = 1; unsigned int old_idt_valid = 1;
ERESOURCE TestResource;
NTSTATUS thread_main(PVOID param)
{
ULONG Id;
Id = (ULONG)param;
DbgPrint("THREAD(%d) Resource %x\n",Id,&TestResource);
DbgPrint("THREAD(%d) Acquiring resource for shared access\n", Id);
ExAcquireResourceExclusiveLite(&TestResource, TRUE);
DbgPrint("THREAD(%d) Acquired resource for shared access\n", Id);
return(STATUS_SUCCESS);
}
VOID resource_test(VOID)
{
HANDLE thread1_handle;
CLIENT_ID thread1_cid;
HANDLE thread2_handle;
CLIENT_ID thread2_cid;
ULONG i;
ExInitializeResourceLite(&TestResource);
DbgPrint("Resource %x\n", &TestResource);
ExAcquireResourceExclusiveLite(&TestResource, TRUE);
DbgPrint("Acquired resource for exclusive access\n");
PsCreateSystemThread(&thread1_handle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&thread1_cid,
thread_main,
(PVOID)1);
PsCreateSystemThread(&thread2_handle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&thread2_cid,
thread_main,
(PVOID)2);
DbgPrint("KeGetCurrentIrql() %d\n", KeGetCurrentIrql());
for (i=0; i<10000000; i++)
{
__asm__("nop\n\t");
}
ExReleaseResourceLite(&TestResource);
DbgPrint("Released resource\n");
for(;;);
}
asmlinkage void _main(boot_param* _bp) asmlinkage void _main(boot_param* _bp)
/* /*
* FUNCTION: Called by the boot loader to start the kernel * FUNCTION: Called by the boot loader to start the kernel
@ -271,7 +207,7 @@ asmlinkage void _main(boot_param* _bp)
/* /*
* Initalize services loaded at boot time * Initalize services loaded at boot time
*/ */
DPRINT("%d files loaded\n",bp.nr_files); DPRINT1("%d files loaded\n",bp.nr_files);
/* Pass 1: load registry chunks passed in */ /* Pass 1: load registry chunks passed in */
start = KERNEL_BASE + PAGE_ROUND_UP(bp.module_length[0]); start = KERNEL_BASE + PAGE_ROUND_UP(bp.module_length[0]);
@ -279,7 +215,7 @@ asmlinkage void _main(boot_param* _bp)
{ {
if (!strcmp ((PCHAR) start, "REGEDIT4")) if (!strcmp ((PCHAR) start, "REGEDIT4"))
{ {
DPRINT("process registry chunk at %08lx\n", start); DPRINT1("process registry chunk at %08lx\n", start);
CmImportHive((PCHAR) start); CmImportHive((PCHAR) start);
} }
start = start + bp.module_length[i]; start = start + bp.module_length[i];
@ -292,7 +228,7 @@ asmlinkage void _main(boot_param* _bp)
{ {
if (strcmp ((PCHAR) start, "REGEDIT4")) if (strcmp ((PCHAR) start, "REGEDIT4"))
{ {
DPRINT("process module at %08lx\n", start); DPRINT1("process module at %08lx\n", start);
LdrProcessDriver((PVOID)start); LdrProcessDriver((PVOID)start);
} }
start = start + bp.module_length[i]; start = start + bp.module_length[i];
@ -301,13 +237,15 @@ asmlinkage void _main(boot_param* _bp)
/* /*
* Load Auto configured drivers * Load Auto configured drivers
*/ */
CHECKPOINT;
LdrLoadAutoConfigDrivers(); LdrLoadAutoConfigDrivers();
/* /*
* Launch initial process * Launch initial process
*/ */
LdrLoadInitialProcess(); CHECKPOINT;
LdrLoadInitialProcess();
/* /*
* Enter idle loop * Enter idle loop
*/ */

View file

@ -1,4 +1,4 @@
/* $Id: timer.c,v 1.23 1999/12/11 17:25:26 phreak Exp $ /* $Id: timer.c,v 1.24 1999/12/13 22:04:36 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -132,8 +132,11 @@ NTSTATUS KeAddThreadTimeout(PKTHREAD Thread, PLARGE_INTEGER Interval)
NTSTATUS STDCALL NtDelayExecution(IN BOOLEAN Alertable, NTSTATUS STDCALL NtDelayExecution(IN BOOLEAN Alertable,
IN TIME* Interval) IN TIME* Interval)
{ {
UNIMPLEMENTED; NTSTATUS Status;
return(STATUS_UNSUCCESSFUL);
Status = KeDelayExecutionThread(UserMode, Alertable,
(PLARGE_INTEGER)Internal);
return(Status);
} }
@ -396,7 +399,7 @@ VOID KeExpireTimers(VOID)
// DPRINT("current_entry->Flink %x\n",current_entry->Flink); // DPRINT("current_entry->Flink %x\n",current_entry->Flink);
// DPRINT("current_entry->Flink->Flink %x\n",current_entry->Flink->Flink); // DPRINT("current_entry->Flink->Flink %x\n",current_entry->Flink->Flink);
KeRaiseIrql( HIGH_LEVEL, &oldlvl ); KeRaiseIrql(HIGH_LEVEL, &oldlvl);
KeAcquireSpinLockAtDpcLevel(&TimerListLock); KeAcquireSpinLockAtDpcLevel(&TimerListLock);
while (current_entry!=(&TimerListHead)) while (current_entry!=(&TimerListHead))
@ -411,7 +414,7 @@ VOID KeExpireTimers(VOID)
} }
} }
KeReleaseSpinLock( &TimerListLock, oldlvl ); KeReleaseSpinLock(&TimerListLock, oldlvl);
// DPRINT("Finished KeExpireTimers()\n"); // DPRINT("Finished KeExpireTimers()\n");
} }
@ -429,7 +432,7 @@ VOID KiTimerInterrupt(VOID)
extern unsigned int EiFreeNonPagedPool; extern unsigned int EiFreeNonPagedPool;
extern unsigned int EiUsedNonPagedPool; extern unsigned int EiUsedNonPagedPool;
extern ULONG PiNrThreads; extern ULONG PiNrThreads;
extern ULONG MiNrFreePages; // extern ULONG MiNrFreePages;
if (TimerInitDone == FALSE) if (TimerInitDone == FALSE)
{ {
@ -462,7 +465,8 @@ VOID KiTimerInterrupt(VOID)
// sprintf(str,"%.8u %.8u",(unsigned int)EiNrUsedBlocks, // sprintf(str,"%.8u %.8u",(unsigned int)EiNrUsedBlocks,
// (unsigned int)EiFreeNonPagedPool); // (unsigned int)EiFreeNonPagedPool);
// sprintf(str,"%.8u %.8u",EiFreeNonPagedPool,EiUsedNonPagedPool); // sprintf(str,"%.8u %.8u",EiFreeNonPagedPool,EiUsedNonPagedPool);
sprintf(str,"%.8u %.8u",(unsigned int)PiNrRunnableThreads,(unsigned int)PiNrThreads); sprintf(str,"%.8u %.8u",(unsigned int)PiNrRunnableThreads,
(unsigned int)PiNrThreads);
// sprintf(str,"%.8u %.8u", (unsigned int)PiNrRunnableThreads, // sprintf(str,"%.8u %.8u", (unsigned int)PiNrRunnableThreads,
// (unsigned int)MiNrFreePages); // (unsigned int)MiNrFreePages);
for (i=0;i<17;i++) for (i=0;i<17;i++)

View file

@ -18,6 +18,7 @@
#include <ddk/ntddk.h> #include <ddk/ntddk.h>
#include <internal/ke.h> #include <internal/ke.h>
#include <internal/ps.h>
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
@ -120,6 +121,32 @@ static BOOLEAN KiIsObjectSignalled(DISPATCHER_HEADER* hdr)
return(TRUE); return(TRUE);
} }
VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus)
{
PKWAIT_BLOCK WaitBlock;
BOOLEAN WasWaiting = FALSE;
KeAcquireDispatcherDatabaseLock(FALSE);
WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList;
if (WaitBlock != NULL)
{
WasWaiting = TRUE;
}
while (WaitBlock != NULL)
{
RemoveEntryList(&WaitBlock->WaitListEntry);
WaitBlock = WaitBlock->NextWaitBlock;
}
Thread->Tcb.WaitBlockList = NULL;
if (WasWaiting)
{
PsUnfreezeThread(Thread, &WaitStatus);
}
KeReleaseDispatcherDatabaseLock(FALSE);
}
static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr) static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr)
{ {
@ -136,21 +163,21 @@ static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr)
while (!IsListEmpty(&(hdr->WaitListHead))) while (!IsListEmpty(&(hdr->WaitListHead)))
{ {
NTSTATUS Status = STATUS_WAIT_0; NTSTATUS Status = STATUS_WAIT_0;
current_entry = RemoveHeadList(&hdr->WaitListHead); current_entry = RemoveHeadList(&hdr->WaitListHead);
current = CONTAINING_RECORD(current_entry,KWAIT_BLOCK, current = CONTAINING_RECORD(current_entry,KWAIT_BLOCK,
WaitListEntry); WaitListEntry);
DPRINT("Waking %x\n",current->Thread); DPRINT("Waking %x\n",current->Thread);
if (current->WaitType == WaitAny) if (current->WaitType == WaitAny)
{ {
DPRINT("WaitAny: Remove all wait blocks.\n"); DPRINT("WaitAny: Remove all wait blocks.\n");
//count the number of the wait block that is waking us, and set that as the wake status //count the number of the wait block that is waking us, and set that as the wake status
for( PrevBlock = current->Thread->WaitBlockList; PrevBlock; ++Status, PrevBlock = PrevBlock->NextWaitBlock ) for( PrevBlock = current->Thread->WaitBlockList; PrevBlock; ++Status, PrevBlock = PrevBlock->NextWaitBlock )
if( PrevBlock == current ) if( PrevBlock == current )
break; break;
if( PrevBlock == 0 ) if( PrevBlock == 0 )
DbgPrint( "WaitOne: Wait Block not in list! Wait result will be corrupt\n" ); DbgPrint( "WaitOne: Wait Block not in list! Wait result will be corrupt\n" );
current->Thread->WaitBlockList = NULL; current->Thread->WaitBlockList = NULL;
} }
else else
@ -188,8 +215,8 @@ static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr)
KiSideEffectsBeforeWake(hdr); KiSideEffectsBeforeWake(hdr);
PsResumeThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb), PsUnfreezeThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
&Status); &Status);
}; };
return(TRUE); return(TRUE);
} }
@ -261,8 +288,8 @@ static BOOLEAN KeDispatcherObjectWakeOne(DISPATCHER_HEADER* hdr)
KiSideEffectsBeforeWake(hdr); KiSideEffectsBeforeWake(hdr);
PsResumeThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb), PsUnfreezeThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
&Status); &Status);
return(TRUE); return(TRUE);
} }
@ -356,43 +383,53 @@ NTSTATUS KeWaitForSingleObject(PVOID Object,
return(STATUS_USER_APC); return(STATUS_USER_APC);
} }
KeAcquireDispatcherDatabaseLock(FALSE);
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
if (KiIsObjectSignalled(hdr))
{
KeReleaseDispatcherDatabaseLock(FALSE);
return(STATUS_WAIT_0);
}
if (Timeout != NULL) if (Timeout != NULL)
{ {
KeAddThreadTimeout(CurrentThread,Timeout); KeAddThreadTimeout(CurrentThread,Timeout);
} }
/* Append wait block to the KTHREAD wait block list */ do
CurrentThread->WaitBlockList = &blk; {
KeAcquireDispatcherDatabaseLock(FALSE);
blk.Object = Object;
blk.Thread = CurrentThread; DPRINT("hdr->SignalState %d\n", hdr->SignalState);
blk.WaitKey = 0;
blk.WaitType = WaitAny; if (KiIsObjectSignalled(hdr))
blk.NextWaitBlock = NULL; {
DPRINT("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x blk.WaitListEntry = %x\n", KeReleaseDispatcherDatabaseLock(FALSE);
hdr->WaitListHead.Flink,hdr->WaitListHead.Blink, blk.WaitListEntry ); if (Timeout != NULL)
InsertTailList(&(hdr->WaitListHead),&(blk.WaitListEntry)); {
KeReleaseDispatcherDatabaseLock(FALSE); KeCancelTimer(&KeGetCurrentThread()->Timer);
DPRINT("Waiting at %s:%d with irql %d\n", __FILE__, __LINE__, }
KeGetCurrentIrql()); return(STATUS_WAIT_0);
PsSuspendThread(PsGetCurrentThread(), }
&Status,
(UCHAR)Alertable, /* Append wait block to the KTHREAD wait block list */
WaitMode); CurrentThread->WaitBlockList = &blk;
blk.Object = Object;
blk.Thread = CurrentThread;
blk.WaitKey = 0;
blk.WaitType = WaitAny;
blk.NextWaitBlock = NULL;
DPRINT("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x blk.WaitListEntry = %x\n",
hdr->WaitListHead.Flink,hdr->WaitListHead.Blink, blk.WaitListEntry );
InsertTailList(&hdr->WaitListHead, &blk.WaitListEntry);
KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("Waiting for %x with irql %d\n", Object, KeGetCurrentIrql());
PsFreezeThread(PsGetCurrentThread(),
&Status,
(UCHAR)Alertable,
WaitMode);
DPRINT("Woke from wait\n");
} while (Status == STATUS_KERNEL_APC);
if (Timeout != NULL) if (Timeout != NULL)
{
KeCancelTimer(&KeGetCurrentThread()->Timer); KeCancelTimer(&KeGetCurrentThread()->Timer);
}
DPRINT("Returning from KeWaitForSingleObject()\n"); DPRINT("Returning from KeWaitForSingleObject()\n");
return Status; return Status;
} }
@ -505,7 +542,7 @@ NTSTATUS KeWaitForMultipleObjects(ULONG Count,
DPRINT("Waiting at %s:%d with irql %d\n", __FILE__, __LINE__, DPRINT("Waiting at %s:%d with irql %d\n", __FILE__, __LINE__,
KeGetCurrentIrql()); KeGetCurrentIrql());
PsSuspendThread(PsGetCurrentThread(), PsFreezeThread(PsGetCurrentThread(),
&Status, &Status,
Alertable, Alertable,
WaitMode); WaitMode);

View file

@ -1,4 +1,4 @@
/* $Id: loader.c,v 1.39 1999/12/04 04:59:38 bpalmer Exp $ /* $Id: loader.c,v 1.40 1999/12/13 22:04:37 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -467,7 +467,7 @@ LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING pModuleName)
unsigned int DriverSize, Idx, Idx2; unsigned int DriverSize, Idx, Idx2;
ULONG RelocDelta, NumRelocs; ULONG RelocDelta, NumRelocs;
DWORD CurrentSize, TotalRelocs; DWORD CurrentSize, TotalRelocs;
PVOID DriverBase, CurrentBase; PVOID DriverBase;
PULONG PEMagic; PULONG PEMagic;
PIMAGE_DOS_HEADER PEDosHeader; PIMAGE_DOS_HEADER PEDosHeader;
PIMAGE_FILE_HEADER PEFileHeader; PIMAGE_FILE_HEADER PEFileHeader;

View file

@ -1,4 +1,4 @@
# $Id: makefile_rex,v 1.39 1999/12/10 17:04:35 dwelch Exp $ # $Id: makefile_rex,v 1.40 1999/12/13 22:04:35 dwelch Exp $
# #
# ReactOS Operating System # ReactOS Operating System
# #
@ -26,7 +26,7 @@ RTL_OBJECTS = rtl/vsprintf.o rtl/lookas.o rtl/unicode.o rtl/time.o \
KE_OBJECTS = ke/main.o ke/timer.o ke/error.o ke/catch.o \ KE_OBJECTS = ke/main.o ke/timer.o ke/error.o ke/catch.o \
ke/dpc.o ke/wait.o ke/kqueue.o ke/dispatch.o \ ke/dpc.o ke/wait.o ke/kqueue.o ke/dispatch.o \
ke/sem.o ke/critical.o ke/event.o ke/apc.o ke/bug.o \ ke/sem.o ke/critical.o ke/event.o ke/apc.o ke/bug.o \
ke/mutex.o ke/kernel.o ke/ldt.o ke/apchelp.o \ ke/mutex.o ke/kernel.o ke/ldt.o \
ke/process.o ke/gdt.o ke/idt.o ke/udelay.o ke/process.o ke/gdt.o ke/idt.o ke/udelay.o
KE_I386_OBJECTS = ke/i386/thread.o ke/i386/usercall.o ke/i386/exp.o KE_I386_OBJECTS = ke/i386/thread.o ke/i386/usercall.o ke/i386/exp.o
@ -48,7 +48,7 @@ IO_OBJECTS = io/iomgr.o io/create.o io/irp.o io/device.o io/rw.o \
OB_OBJECTS = ob/object.o ob/handle.o ob/namespc.o ob/ntobj.o ob/dirobj.o OB_OBJECTS = ob/object.o ob/handle.o ob/namespc.o ob/ntobj.o ob/dirobj.o
PS_OBJECTS = ps/psmgr.o ps/thread.o ps/process.o ps/idle.o ps/kill.o \ PS_OBJECTS = ps/psmgr.o ps/thread.o ps/process.o ps/idle.o ps/kill.o \
ps/tinfo.o ps/tinfo.o ps/create.o
EX_OBJECTS = ex/work.o ex/fmutex.o ex/resource.o ex/time.o ex/interlck.o \ EX_OBJECTS = ex/work.o ex/fmutex.o ex/resource.o ex/time.o ex/interlck.o \
ex/callback.o ex/napi.o ex/power.o ex/sysinfo.o ex/locale.o \ ex/callback.o ex/napi.o ex/power.o ex/sysinfo.o ex/locale.o \
@ -226,6 +226,6 @@ ke/main.o: ke/main.c ../include/reactos/buildno.h
#WITH_DEBUGGING = yes #WITH_DEBUGGING = yes
WIN32_LEAN_AND_MEAN = yes WIN32_LEAN_AND_MEAN = yes
#WARNINGS_ARE_ERRORS = yes WARNINGS_ARE_ERRORS = yes
include ../rules.mak include ../rules.mak

View file

@ -71,4 +71,4 @@ _MmSafeCopyToUser:
ret ret
_MemSafeCopyToUserEnd: _MmSafeCopyToUserEnd:

View file

@ -240,7 +240,7 @@ NTSTATUS STDCALL NtCreatePagingFile(IN PUNICODE_STRING PageFileName,
break; break;
} }
} }
MiFreeSwapPages = MiFreeSwapPages + ActualSize; MiFreeSwapPages = MiFreeSwapPages + MinimumSize;
KeReleaseSpinLock(&PagingFileListLock, oldIrql); KeReleaseSpinLock(&PagingFileListLock, oldIrql);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);

View file

@ -57,7 +57,7 @@ NTSTATUS MmReleaseMmInfo(PEPROCESS Process)
PLIST_ENTRY CurrentEntry; PLIST_ENTRY CurrentEntry;
PMEMORY_AREA Current; PMEMORY_AREA Current;
DbgPrint("MmReleaseMmInfo(Process %x)\n",Process); DPRINT("MmReleaseMmInfo(Process %x)\n",Process);
while (!IsListEmpty(&Process->Pcb.MemoryAreaList)) while (!IsListEmpty(&Process->Pcb.MemoryAreaList))
{ {

View file

@ -1,4 +1,4 @@
/* $Id: port.c,v 1.13 1999/12/10 17:04:36 dwelch Exp $ /* $Id: port.c,v 1.14 1999/12/13 22:04:39 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -351,7 +351,7 @@ NTSTATUS STDCALL NtAcceptConnectPort (PHANDLE ServerPortHandle,
{ {
NTSTATUS Status; NTSTATUS Status;
PEPORT NamedPort; PEPORT NamedPort;
PEPORT OurPort; PEPORT OurPort = NULL;
PQUEUEDMESSAGE ConnectionRequest; PQUEUEDMESSAGE ConnectionRequest;
KIRQL oldIrql; KIRQL oldIrql;

View file

@ -0,0 +1,392 @@
/* $Id: create.c,v 1.1 1999/12/13 22:04:41 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ps/thread.c
* PURPOSE: Thread managment
* PROGRAMMER: David Welch (welch@mcmail.com)
* REVISION HISTORY:
* 23/06/98: Created
* 12/10/99: Phillip Susi: Thread priorities, and APC work
*/
/*
* NOTE:
*
* All of the routines that manipulate the thread queue synchronize on
* a single spinlock
*
*/
/* INCLUDES ****************************************************************/
#include <ddk/ntddk.h>
#include <internal/ke.h>
#include <internal/ob.h>
#include <string.h>
#include <internal/string.h>
#include <internal/hal.h>
#include <internal/ps.h>
#include <internal/ob.h>
#define NDEBUG
#include <internal/debug.h>
/* GLOBAL *******************************************************************/
static ULONG PiNextThreadUniqueId = 0;
extern KSPIN_LOCK PiThreadListLock;
extern ULONG PiNrThreads;
extern LIST_ENTRY PiThreadListHead;
/* FUNCTIONS ***************************************************************/
static VOID PiTimeoutThread( struct _KDPC *dpc, PVOID Context, PVOID arg1, PVOID arg2 )
{
// wake up the thread, and tell it it timed out
NTSTATUS Status = STATUS_TIMEOUT;
PsUnfreezeThread( (ETHREAD *)Context, &Status );
}
VOID PiBeforeBeginThread(VOID)
{
DPRINT("PiBeforeBeginThread()\n");
//KeReleaseSpinLock(&PiThreadListLock, PASSIVE_LEVEL);
KeLowerIrql(PASSIVE_LEVEL);
DPRINT("KeGetCurrentIrql() %d\n", KeGetCurrentIrql());
}
VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext)
{
NTSTATUS Ret;
// KeReleaseSpinLock(&PiThreadListLock,PASSIVE_LEVEL);
KeLowerIrql(PASSIVE_LEVEL);
Ret = StartRoutine(StartContext);
PsTerminateSystemThread(Ret);
KeBugCheck(0);
}
VOID PiDeleteThread(PVOID ObjectBody)
{
KIRQL oldIrql;
DPRINT("PiDeleteThread(ObjectBody %x)\n",ObjectBody);
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
ObDereferenceObject(((PETHREAD)ObjectBody)->ThreadsProcess);
((PETHREAD)ObjectBody)->ThreadsProcess = NULL;
PiNrThreads--;
RemoveEntryList(&((PETHREAD)ObjectBody)->Tcb.ThreadListEntry);
HalReleaseTask((PETHREAD)ObjectBody);
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
}
VOID PiCloseThread(PVOID ObjectBody, ULONG HandleCount)
{
DPRINT("PiCloseThread(ObjectBody %x)\n", ObjectBody);
DPRINT("ObGetReferenceCount(ObjectBody) %d "
"ObGetHandleCount(ObjectBody) %d\n",
ObGetReferenceCount(ObjectBody),
ObGetHandleCount(ObjectBody));
}
NTSTATUS PsInitializeThread(HANDLE ProcessHandle,
PETHREAD * ThreadPtr,
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ThreadAttributes)
{
PETHREAD Thread;
NTSTATUS Status;
KIRQL oldIrql;
PEPROCESS Process;
/*
* Reference process
*/
if (ProcessHandle != NULL)
{
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_CREATE_THREAD,
PsProcessType,
UserMode,
(PVOID*)&Process,
NULL);
if (Status != STATUS_SUCCESS)
{
DPRINT("Failed at %s:%d\n",__FILE__,__LINE__);
return(Status);
}
}
else
{
Process = SystemProcess;
ObReferenceObjectByPointer(Process,
PROCESS_CREATE_THREAD,
PsProcessType,
UserMode);
}
/*
* Create and initialize thread
*/
Thread = ObCreateObject(ThreadHandle,
DesiredAccess,
ThreadAttributes,
PsThreadType);
DPRINT("Thread = %x\n",Thread);
PiNrThreads++;
Thread->Tcb.State = THREAD_STATE_SUSPENDED;
Thread->Tcb.SuspendCount = 0;
Thread->Tcb.FreezeCount = 1;
InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[0]);
InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[1]);
Thread->Tcb.KernelApcDisable = 1;
Thread->Tcb.WaitIrql = PASSIVE_LEVEL;
Thread->ThreadsProcess = Process;
KeInitializeDpc( &Thread->Tcb.TimerDpc, PiTimeoutThread, Thread );
KeInitializeDispatcherHeader(&Thread->Tcb.DispatcherHeader,
InternalThreadType,
sizeof(ETHREAD),
FALSE);
InitializeListHead(&Thread->IrpList);
Thread->Cid.UniqueThread = (HANDLE)InterlockedIncrement(
&PiNextThreadUniqueId);
Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread);
*ThreadPtr = Thread;
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
InsertTailList(&PiThreadListHead, &Thread->Tcb.ThreadListEntry);
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
Thread->Tcb.BasePriority = Thread->ThreadsProcess->Pcb.BasePriority;
Thread->Tcb.Priority = Thread->Tcb.BasePriority;
return(STATUS_SUCCESS);
}
static NTSTATUS PsCreateTeb (HANDLE ProcessHandle,
PNT_TEB *TebPtr,
PETHREAD Thread,
PINITIAL_TEB InitialTeb)
{
MEMORY_BASIC_INFORMATION Info;
NTSTATUS Status;
ULONG ByteCount;
ULONG RegionSize;
ULONG TebSize;
PVOID TebBase;
NT_TEB Teb;
TebBase = (PVOID)0x7FFDE000;
TebSize = PAGESIZE;
while (TRUE)
{
/* The TEB must reside in user space */
Status = NtAllocateVirtualMemory(ProcessHandle,
&TebBase,
0,
&TebSize,
MEM_COMMIT,
PAGE_READWRITE);
if (NT_SUCCESS(Status))
{
DPRINT ("TEB allocated at %x\n", TebBase);
break;
}
else
{
DPRINT ("TEB allocation failed! Status %x\n",Status);
}
TebBase = Info.BaseAddress - TebSize;
}
DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize);
/* set all pointers to and from the TEB */
Teb.Tib.Self = TebBase;
if (Thread->ThreadsProcess)
{
Teb.Peb = Thread->ThreadsProcess->Peb; /* No PEB yet!! */
}
/* store stack information from InitialTeb */
if (InitialTeb != NULL)
{
Teb.Tib.StackBase = InitialTeb->StackBase;
Teb.Tib.StackLimit = InitialTeb->StackLimit;
/*
* I don't know if this is really stored in a WNT-TEB,
* but it's needed to free the thread stack. (Eric Kohl)
*/
Teb.StackCommit = InitialTeb->StackCommit;
Teb.StackCommitMax = InitialTeb->StackCommitMax;
Teb.StackReserved = InitialTeb->StackReserved;
}
/* more initialization */
Teb.Cid.UniqueThread = Thread->Cid.UniqueThread;
Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess;
/* write TEB data into teb page */
Status = NtWriteVirtualMemory(ProcessHandle,
TebBase,
&Teb,
sizeof(NT_TEB),
&ByteCount);
if (!NT_SUCCESS(Status))
{
/* free TEB */
DPRINT ("Writing TEB failed!\n");
RegionSize = 0;
NtFreeVirtualMemory(ProcessHandle,
TebBase,
&RegionSize,
MEM_RELEASE);
return Status;
}
/* FIXME: fs:[0] = TEB */
if (TebPtr != NULL)
{
// *TebPtr = (PNT_TEB)TebBase;
}
DPRINT ("TEB allocated at %p\n", TebBase);
return Status;
}
NTSTATUS STDCALL NtCreateThread (PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
HANDLE ProcessHandle,
PCLIENT_ID Client,
PCONTEXT ThreadContext,
PINITIAL_TEB InitialTeb,
BOOLEAN CreateSuspended)
{
PETHREAD Thread;
PNT_TEB TebBase;
NTSTATUS Status;
DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n",
ThreadHandle,ThreadContext);
Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle,
DesiredAccess,ObjectAttributes);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Status = HalInitTaskWithContext(Thread,ThreadContext);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Status = PsCreateTeb (ProcessHandle,
&TebBase,
Thread,
InitialTeb);
if (!NT_SUCCESS(Status))
{
return(Status);
}
/* Attention: TebBase is in user memory space */
// Thread->Tcb.Teb = TebBase;
Thread->StartAddress=NULL;
if (Client!=NULL)
{
*Client=Thread->Cid;
}
if (!CreateSuspended)
{
DPRINT("Not creating suspended\n");
PsUnfreezeThread(Thread, NULL);
}
DPRINT("Thread %x\n", Thread);
DPRINT("ObGetReferenceCount(Thread) %d ObGetHandleCount(Thread) %x\n",
ObGetReferenceCount(Thread), ObGetHandleCount(Thread));
DPRINT("Finished PsCreateThread()\n");
return(STATUS_SUCCESS);
}
NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
HANDLE ProcessHandle,
PCLIENT_ID ClientId,
PKSTART_ROUTINE StartRoutine,
PVOID StartContext)
/*
* FUNCTION: Creates a thread which executes in kernel mode
* ARGUMENTS:
* ThreadHandle (OUT) = Caller supplied storage for the returned thread
* handle
* DesiredAccess = Requested access to the thread
* ObjectAttributes = Object attributes (optional)
* ProcessHandle = Handle of process thread will run in
* NULL to use system process
* ClientId (OUT) = Caller supplied storage for the returned client id
* of the thread (optional)
* StartRoutine = Entry point for the thread
* StartContext = Argument supplied to the thread when it begins
* execution
* RETURNS: Success or failure status
*/
{
PETHREAD Thread;
NTSTATUS Status;
DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n",
ThreadHandle,ProcessHandle);
Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle,
DesiredAccess,ObjectAttributes);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Thread->StartAddress=StartRoutine;
Status = HalInitTask(Thread,StartRoutine,StartContext);
if (!NT_SUCCESS(Status))
{
return(Status);
}
if (ClientId!=NULL)
{
*ClientId=Thread->Cid;
}
PsUnfreezeThread(Thread, NULL);
return(STATUS_SUCCESS);
}

View file

@ -16,7 +16,7 @@
#include <internal/mm.h> #include <internal/mm.h>
#include <internal/ob.h> #include <internal/ob.h>
//#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
/* GLOBALS *******************************************************************/ /* GLOBALS *******************************************************************/
@ -32,17 +32,17 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus)
* FUNCTION: Terminates the current thread * FUNCTION: Terminates the current thread
*/ */
{ {
KIRQL oldlvl; KIRQL oldIrql;
PETHREAD CurrentThread; PETHREAD CurrentThread;
PiNrRunnableThreads--; PiNrRunnableThreads--;
CurrentThread = PsGetCurrentThread(); CurrentThread = PsGetCurrentThread();
CurrentThread->ExitStatus = ExitStatus;
DPRINT("terminating %x\n",CurrentThread); DPRINT("terminating %x\n",CurrentThread);
KeRaiseIrql(DISPATCH_LEVEL,&oldlvl); KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
CurrentThread->ExitStatus = ExitStatus;
DPRINT("ObGetReferenceCount(CurrentThread) %d\n", DPRINT("ObGetReferenceCount(CurrentThread) %d\n",
ObGetReferenceCount(CurrentThread)); ObGetReferenceCount(CurrentThread));
@ -52,7 +52,7 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus)
CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE; CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE;
KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader); KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader);
PsDispatchThread(THREAD_STATE_TERMINATED_1); PsDispatchThreadNoLock(THREAD_STATE_TERMINATED_1);
KeBugCheck(0); KeBugCheck(0);
} }
@ -69,6 +69,7 @@ VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus)
PiNrRunnableThreads--; PiNrRunnableThreads--;
RemoveEntryList(&Thread->Tcb.QueueListEntry); RemoveEntryList(&Thread->Tcb.QueueListEntry);
} }
RemoveEntryList(&Thread->Tcb.ThreadListEntry);
Thread->Tcb.State = THREAD_STATE_TERMINATED_2; Thread->Tcb.State = THREAD_STATE_TERMINATED_2;
Thread->Tcb.DispatcherHeader.SignalState = TRUE; Thread->Tcb.DispatcherHeader.SignalState = TRUE;
KeDispatcherObjectWake(&Thread->Tcb.DispatcherHeader); KeDispatcherObjectWake(&Thread->Tcb.DispatcherHeader);

View file

@ -1,4 +1,4 @@
/* $Id: thread.c,v 1.39 1999/12/12 03:56:53 phreak Exp $ /* $Id: thread.c,v 1.40 1999/12/13 22:04:41 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -46,7 +46,7 @@ KSPIN_LOCK PiThreadListLock;
/* /*
* PURPOSE: List of threads associated with each priority level * PURPOSE: List of threads associated with each priority level
*/ */
static LIST_ENTRY PiThreadListHead = { &PiThreadListHead, &PiThreadListHead }; LIST_ENTRY PiThreadListHead;
static LIST_ENTRY PriorityListHead[NR_THREAD_PRIORITY_LEVELS]; static LIST_ENTRY PriorityListHead[NR_THREAD_PRIORITY_LEVELS];
static BOOLEAN DoneInitYet = FALSE; static BOOLEAN DoneInitYet = FALSE;
ULONG PiNrThreads = 0; ULONG PiNrThreads = 0;
@ -54,8 +54,6 @@ ULONG PiNrRunnableThreads = 0;
static PETHREAD CurrentThread = NULL; static PETHREAD CurrentThread = NULL;
static ULONG PiNextThreadUniqueId = 0;
/* FUNCTIONS ***************************************************************/ /* FUNCTIONS ***************************************************************/
PKTHREAD KeGetCurrentThread(VOID) PKTHREAD KeGetCurrentThread(VOID)
@ -88,7 +86,10 @@ VOID PiTerminateProcessThreads(PEPROCESS Process, NTSTATUS ExitStatus)
if (current->ThreadsProcess == Process && if (current->ThreadsProcess == Process &&
current != PsGetCurrentThread()) current != PsGetCurrentThread())
{ {
KeReleaseSpinLock(&PiThreadListLock, oldlvl);
PsTerminateOtherThread(current, ExitStatus); PsTerminateOtherThread(current, ExitStatus);
KeAcquireSpinLock(&PiThreadListLock, &oldlvl);
current_entry = PiThreadListHead.Flink;
} }
current_entry = current_entry->Flink; current_entry = current_entry->Flink;
} }
@ -104,31 +105,30 @@ static VOID PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread)
InsertTailList(&PriorityListHead[THREAD_PRIORITY_MAX+Priority], InsertTailList(&PriorityListHead[THREAD_PRIORITY_MAX+Priority],
&Thread->Tcb.QueueListEntry); &Thread->Tcb.QueueListEntry);
} PiNrRunnableThreads++;
VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext)
{
NTSTATUS Ret;
// KeReleaseSpinLock(&PiThreadListLock,PASSIVE_LEVEL);
KeLowerIrql(PASSIVE_LEVEL);
Ret = StartRoutine(StartContext);
PsTerminateSystemThread(Ret);
KeBugCheck(0);
} }
VOID PsDumpThreads(VOID) VOID PsDumpThreads(VOID)
{ {
PLIST_ENTRY current_entry; PLIST_ENTRY current_entry;
PETHREAD current; PETHREAD current;
ULONG t;
// return;
current_entry = PiThreadListHead.Flink; current_entry = PiThreadListHead.Flink;
t = 0;
while (current_entry != &PiThreadListHead) while (current_entry != &PiThreadListHead)
{ {
current = CONTAINING_RECORD(current_entry, ETHREAD, current = CONTAINING_RECORD(current_entry, ETHREAD,
Tcb.ThreadListEntry); Tcb.ThreadListEntry);
t++;
if (t >= PiNrThreads)
{
DbgPrint("Too many threads on list\n");
return;
}
DPRINT1("current %x current->Tcb.State %d eip %x ", DPRINT1("current %x current->Tcb.State %d eip %x ",
current, current->Tcb.State, current, current->Tcb.State,
current->Tcb.Context.eip); current->Tcb.Context.eip);
@ -148,6 +148,8 @@ VOID PsReapThreads(VOID)
// DPRINT1("PsReapThreads()\n"); // DPRINT1("PsReapThreads()\n");
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
current_entry = PiThreadListHead.Flink; current_entry = PiThreadListHead.Flink;
while (current_entry != &PiThreadListHead) while (current_entry != &PiThreadListHead)
@ -159,11 +161,16 @@ VOID PsReapThreads(VOID)
if (current->Tcb.State == THREAD_STATE_TERMINATED_1) if (current->Tcb.State == THREAD_STATE_TERMINATED_1)
{ {
RemoveEntryList(&current->Tcb.ThreadListEntry);
DPRINT("Reaping thread %x\n", current); DPRINT("Reaping thread %x\n", current);
current->Tcb.State = THREAD_STATE_TERMINATED_2; current->Tcb.State = THREAD_STATE_TERMINATED_2;
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
ObDereferenceObject(current); ObDereferenceObject(current);
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
current_entry = PiThreadListHead.Flink;
} }
} }
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
} }
static PETHREAD PsScanThreadList (KPRIORITY Priority) static PETHREAD PsScanThreadList (KPRIORITY Priority)
@ -189,16 +196,11 @@ static PETHREAD PsScanThreadList (KPRIORITY Priority)
} }
static VOID PsDispatchThreadNoLock (ULONG NewThreadStatus) VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
{ {
KPRIORITY CurrentPriority; KPRIORITY CurrentPriority;
PETHREAD Candidate; PETHREAD Candidate;
if (!DoneInitYet)
{
return;
}
CurrentThread->Tcb.State = NewThreadStatus; CurrentThread->Tcb.State = NewThreadStatus;
if (CurrentThread->Tcb.State == THREAD_STATE_RUNNABLE) if (CurrentThread->Tcb.State == THREAD_STATE_RUNNABLE)
{ {
@ -213,6 +215,8 @@ static VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
Candidate = PsScanThreadList(CurrentPriority); Candidate = PsScanThreadList(CurrentPriority);
if (Candidate == CurrentThread) if (Candidate == CurrentThread)
{ {
PiNrRunnableThreads--;
KeReleaseSpinLockFromDpcLevel(&PiThreadListLock);
return; return;
} }
if (Candidate != NULL) if (Candidate != NULL)
@ -223,12 +227,10 @@ static VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
CurrentThread = Candidate; CurrentThread = Candidate;
PiNrRunnableThreads--;
KeReleaseSpinLockFromDpcLevel( &PiThreadListLock ); KeReleaseSpinLockFromDpcLevel( &PiThreadListLock );
HalTaskSwitch(&CurrentThread->Tcb); HalTaskSwitch(&CurrentThread->Tcb);
KeAcquireSpinLockAtDpcLevel( &PiThreadListLock );
DPRINT( "Woken up, grabbed lock\n" );
PsReapThreads(); PsReapThreads();
DPRINT( "Reaped\n" );
return; return;
} }
} }
@ -236,200 +238,98 @@ static VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
KeBugCheck(0); KeBugCheck(0);
} }
VOID PiBeforeBeginThread(VOID)
{
DPRINT("PiBeforeBeginThread()\n");
//KeReleaseSpinLock(&PiThreadListLock, PASSIVE_LEVEL);
KeLowerIrql(PASSIVE_LEVEL);
DPRINT("KeGetCurrentIrql() %d\n", KeGetCurrentIrql());
}
VOID PsDispatchThread(ULONG NewThreadStatus) VOID PsDispatchThread(ULONG NewThreadStatus)
{ {
KIRQL oldIrql; KIRQL oldIrql;
KeAcquireSpinLock(&PiThreadListLock, &oldIrql); if (!DoneInitYet)
{
return;
}
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
CurrentThread->Tcb.WaitIrql = oldIrql; // save wait Irql CurrentThread->Tcb.WaitIrql = oldIrql; // save wait Irql
PsDispatchThreadNoLock(NewThreadStatus); PsDispatchThreadNoLock(NewThreadStatus);
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
KeLowerIrql(oldIrql); KeLowerIrql(oldIrql);
// DPRINT("oldIrql %d\n",oldIrql); // DPRINT("oldIrql %d\n",oldIrql);
} }
static VOID PiTimeoutThread( struct _KDPC *dpc, PVOID Context, PVOID arg1, PVOID arg2 ) /*
{ * Suspend and resume may only be called to suspend the current thread, except by apc.c
// wake up the thread, and tell it it timed out */
NTSTATUS Status = STATUS_TIMEOUT;
PsResumeThread( (ETHREAD *)Context, &Status );
}
NTSTATUS PsInitializeThread(HANDLE ProcessHandle, ULONG PsUnfreezeThread(PETHREAD Thread, PNTSTATUS WaitStatus)
PETHREAD * ThreadPtr,
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ThreadAttributes)
{
PETHREAD Thread;
NTSTATUS Status;
PiNrThreads++;
Thread = ObCreateObject(ThreadHandle,
DesiredAccess,
ThreadAttributes,
PsThreadType);
DPRINT("Thread = %x\n",Thread);
Thread->Tcb.State = THREAD_STATE_SUSPENDED;
Thread->Tcb.SuspendCount = 1;
InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[0]);
InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[1]);
Thread->Tcb.KernelApcDisable = 1;
Thread->Tcb.WaitIrql = PASSIVE_LEVEL;
KeInitializeDpc( &Thread->Tcb.TimerDpc, PiTimeoutThread, Thread );
KeInitializeDispatcherHeader(&Thread->Tcb.DispatcherHeader,
InternalThreadType,
sizeof(ETHREAD),
FALSE);
if (ProcessHandle != NULL)
{
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_CREATE_THREAD,
PsProcessType,
UserMode,
(PVOID*)&Thread->ThreadsProcess,
NULL);
if (Status != STATUS_SUCCESS)
{
DPRINT("Failed at %s:%d\n",__FILE__,__LINE__);
ObDereferenceObject( Thread );
PiNrThreads--;
return(Status);
}
}
else
{
Thread->ThreadsProcess = SystemProcess;
ObReferenceObjectByPointer(Thread->ThreadsProcess,
PROCESS_CREATE_THREAD,
PsProcessType,
UserMode);
}
InitializeListHead(&Thread->IrpList);
Thread->Cid.UniqueThread = (HANDLE)InterlockedIncrement(
&PiNextThreadUniqueId);
Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread);
*ThreadPtr = Thread;
InsertTailList(&PiThreadListHead, &Thread->Tcb.ThreadListEntry);
Thread->Tcb.BasePriority = Thread->ThreadsProcess->Pcb.BasePriority;
Thread->Tcb.Priority = Thread->Tcb.BasePriority;
return(STATUS_SUCCESS);
}
// Suspend and resume may only be called to suspend the current thread, except by apc.c
ULONG PsResumeThread(PETHREAD Thread,
PNTSTATUS WaitStatus)
{ {
KIRQL oldIrql; KIRQL oldIrql;
ULONG r; ULONG r;
DPRINT("PsResumeThread(Thread %x) CurrentThread %x \n",Thread, DPRINT("PsUnfreezeThread(Thread %x, WaitStatus %x)\n", Thread, WaitStatus);
PsGetCurrentThread());
DPRINT("Thread->Tcb.SuspendCount %d\n",Thread->Tcb.SuspendCount);
KeAcquireSpinLock(&PiThreadListLock, &oldIrql); KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
DPRINT("Thread->Tcb.SuspendCount %d\n",Thread->Tcb.SuspendCount);
r = Thread->Tcb.SuspendCount; Thread->Tcb.FreezeCount--;
if ( Thread->Tcb.SuspendCount == TRUE ) r = Thread->Tcb.FreezeCount;
if (r <= 0)
{ {
// DPRINT("Marking thread %x as runnable\n",Thread); DPRINT("Resuming thread\n");
Thread->Tcb.SuspendCount = FALSE;
Thread->Tcb.State = THREAD_STATE_RUNNABLE; Thread->Tcb.State = THREAD_STATE_RUNNABLE;
if (WaitStatus != NULL) if (WaitStatus != NULL)
{ {
Thread->Tcb.WaitStatus = *WaitStatus; Thread->Tcb.WaitStatus = *WaitStatus;
} }
PsInsertIntoThreadList(Thread->Tcb.Priority, Thread); PsInsertIntoThreadList(Thread->Tcb.Priority, Thread);
PiNrRunnableThreads++;
} }
DPRINT("About release ThreadListLock = %x\n", &PiThreadListLock);
KeReleaseSpinLock(&PiThreadListLock, oldIrql); KeReleaseSpinLock(&PiThreadListLock, oldIrql);
DPRINT("Finished PsResumeThread()\n"); return(r);
return r;
} }
ULONG PsFreezeThread(PETHREAD Thread, PNTSTATUS Status, UCHAR Alertable,
ULONG PsSuspendThread(PETHREAD Thread, ULONG WaitMode)
PNTSTATUS WaitStatus,
UCHAR Alertable,
ULONG WaitMode)
{ {
KIRQL oldIrql; KIRQL oldIrql;
ULONG r; ULONG r;
DPRINT("PsSuspendThread(Thread %x)\n",Thread);
DPRINT("Thread->Tcb.BasePriority %d\n", Thread->Tcb.BasePriority);
DPRINT("Thread->Tcb.SuspendCount %d\n",Thread->Tcb.SuspendCount);
KeAcquireSpinLock(&PiThreadListLock, &oldIrql); KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
r = Thread->Tcb.SuspendCount;
if ( Thread->Tcb.SuspendCount == FALSE )
{
Thread->Tcb.SuspendCount = TRUE;
if (Thread != PsGetCurrentThread())
{
if (Thread->Tcb.State == THREAD_STATE_RUNNABLE)
RemoveEntryList(&Thread->Tcb.QueueListEntry);
Thread->Tcb.State = THREAD_STATE_SUSPENDED;
Thread->Tcb.Alertable = Alertable;
Thread->Tcb.WaitMode = WaitMode;
PiNrRunnableThreads--;
}
else
{
DPRINT("Suspending current thread\n");
Thread->Tcb.Alertable = Alertable;
Thread->Tcb.WaitMode = WaitMode;
PiNrRunnableThreads--;
Thread->Tcb.WaitIrql = oldIrql; // save wait IRQL
PsDispatchThreadNoLock(THREAD_STATE_SUSPENDED);
if (WaitStatus != NULL)
{
*WaitStatus = PsGetCurrentThread()->Tcb.WaitStatus;
}
}
}
DPRINT("About to release ThreadListLock = %x\n", &PiThreadListLock);
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
DPRINT("PsSuspendThread() finished\n");
return r;
}
VOID PiDeleteThread(PVOID ObjectBody)
{
DPRINT("PiDeleteThread(ObjectBody %x)\n",ObjectBody);
ObDereferenceObject(((PETHREAD)ObjectBody)->ThreadsProcess); Thread->Tcb.FreezeCount++;
((PETHREAD)ObjectBody)->ThreadsProcess = NULL; r = Thread->Tcb.FreezeCount;
PiNrThreads--;
RemoveEntryList(&((PETHREAD)ObjectBody)->Tcb.ThreadListEntry); DPRINT("r %d\n", r);
HalReleaseTask((PETHREAD)ObjectBody);
} if (r == 0)
{
VOID PiCloseThread(PVOID ObjectBody, ULONG HandleCount) DPRINT("Not suspending thread\n");
{ KeReleaseSpinLock(&PiThreadListLock, oldIrql);
DPRINT("PiCloseThread(ObjectBody %x)\n", ObjectBody); return(r);
DPRINT("ObGetReferenceCount(ObjectBody) %d " }
"ObGetHandleCount(ObjectBody) %d\n",
ObGetReferenceCount(ObjectBody), Thread->Tcb.Alertable = Alertable;
ObGetHandleCount(ObjectBody)); Thread->Tcb.WaitMode = WaitMode;
if (PsGetCurrentThread() != Thread)
{
DPRINT("Suspending other\n");
if (Thread->Tcb.State == THREAD_STATE_RUNNABLE)
{
RemoveEntryList(&Thread->Tcb.QueueListEntry);
}
Thread->Tcb.State = THREAD_STATE_FROZEN;
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
}
else
{
DPRINT("Suspending self\n");
Thread->Tcb.WaitIrql = oldIrql;
PsDispatchThreadNoLock(THREAD_STATE_FROZEN);
if (Status != NULL)
{
*Status = Thread->Tcb.WaitStatus;
}
KeLowerIrql(oldIrql);
}
return(r);
} }
VOID PsInitThreadManagment(VOID) VOID PsInitThreadManagment(VOID)
@ -474,8 +374,9 @@ VOID PsInitThreadManagment(VOID)
THREAD_ALL_ACCESS,NULL); THREAD_ALL_ACCESS,NULL);
HalInitFirstTask(FirstThread); HalInitFirstTask(FirstThread);
FirstThread->Tcb.State = THREAD_STATE_RUNNING; FirstThread->Tcb.State = THREAD_STATE_RUNNING;
FirstThread->Tcb.SuspendCount = 0; FirstThread->Tcb.FreezeCount = 0;
ZwClose(FirstThreadHandle);
DPRINT("FirstThread %x\n",FirstThread); DPRINT("FirstThread %x\n",FirstThread);
CurrentThread = FirstThread; CurrentThread = FirstThread;
@ -484,226 +385,10 @@ VOID PsInitThreadManagment(VOID)
} }
static NTSTATUS
PsCreateTeb (HANDLE ProcessHandle,
PNT_TEB *TebPtr,
PETHREAD Thread,
PINITIAL_TEB InitialTeb)
{
MEMORY_BASIC_INFORMATION Info;
NTSTATUS Status;
ULONG ByteCount;
ULONG RegionSize;
ULONG TebSize;
PVOID TebBase;
NT_TEB Teb;
TebBase = (PVOID)0x7FFDE000;
TebSize = PAGESIZE;
while (TRUE)
{
/* The TEB must reside in user space */
Status = NtAllocateVirtualMemory(ProcessHandle,
&TebBase,
0,
&TebSize,
MEM_COMMIT,
PAGE_READWRITE);
if (NT_SUCCESS(Status))
{
DPRINT ("TEB allocated at %x\n", TebBase);
break;
}
else
{
DPRINT ("TEB allocation failed! Status %x\n",Status);
}
TebBase = Info.BaseAddress - TebSize;
}
DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize);
/* set all pointers to and from the TEB */
Teb.Tib.Self = TebBase;
if (Thread->ThreadsProcess)
{
Teb.Peb = Thread->ThreadsProcess->Peb; /* No PEB yet!! */
}
/* store stack information from InitialTeb */
if (InitialTeb != NULL)
{
Teb.Tib.StackBase = InitialTeb->StackBase;
Teb.Tib.StackLimit = InitialTeb->StackLimit;
/*
* I don't know if this is really stored in a WNT-TEB,
* but it's needed to free the thread stack. (Eric Kohl)
*/
Teb.StackCommit = InitialTeb->StackCommit;
Teb.StackCommitMax = InitialTeb->StackCommitMax;
Teb.StackReserved = InitialTeb->StackReserved;
}
/* more initialization */
Teb.Cid.UniqueThread = Thread->Cid.UniqueThread;
Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess;
/* write TEB data into teb page */
Status = NtWriteVirtualMemory(ProcessHandle,
TebBase,
&Teb,
sizeof(NT_TEB),
&ByteCount);
if (!NT_SUCCESS(Status))
{
/* free TEB */
DPRINT ("Writing TEB failed!\n");
RegionSize = 0;
NtFreeVirtualMemory(ProcessHandle,
TebBase,
&RegionSize,
MEM_RELEASE);
return Status;
}
/* FIXME: fs:[0] = TEB */
if (TebPtr != NULL)
{
// *TebPtr = (PNT_TEB)TebBase;
}
DPRINT ("TEB allocated at %p\n", TebBase);
return Status;
}
NTSTATUS STDCALL NtCreateThread (PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
HANDLE ProcessHandle,
PCLIENT_ID Client,
PCONTEXT ThreadContext,
PINITIAL_TEB InitialTeb,
BOOLEAN CreateSuspended)
{
PETHREAD Thread;
PNT_TEB TebBase;
NTSTATUS Status;
DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n",
ThreadHandle,ThreadContext);
Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle,
DesiredAccess,ObjectAttributes);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Status = HalInitTaskWithContext(Thread,ThreadContext);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Status = PsCreateTeb (ProcessHandle,
&TebBase,
Thread,
InitialTeb);
if (!NT_SUCCESS(Status))
{
return(Status);
}
/* Attention: TebBase is in user memory space */
// Thread->Tcb.Teb = TebBase;
Thread->StartAddress=NULL;
if (Client!=NULL)
{
*Client=Thread->Cid;
}
if (!CreateSuspended)
{
DPRINT("Not creating suspended\n");
PsResumeThread(Thread, NULL);
}
DPRINT("Thread %x\n", Thread);
DPRINT("ObGetReferenceCount(Thread) %d ObGetHandleCount(Thread) %x\n",
ObGetReferenceCount(Thread), ObGetHandleCount(Thread));
DPRINT("Finished PsCreateThread()\n");
return(STATUS_SUCCESS);
}
NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
HANDLE ProcessHandle,
PCLIENT_ID ClientId,
PKSTART_ROUTINE StartRoutine,
PVOID StartContext)
/* /*
* FUNCTION: Creates a thread which executes in kernel mode * Sets thread's base priority relative to the process' base priority
* ARGUMENTS: * Should only be passed in THREAD_PRIORITY_ constants in pstypes.h
* ThreadHandle (OUT) = Caller supplied storage for the returned thread
* handle
* DesiredAccess = Requested access to the thread
* ObjectAttributes = Object attributes (optional)
* ProcessHandle = Handle of process thread will run in
* NULL to use system process
* ClientId (OUT) = Caller supplied storage for the returned client id
* of the thread (optional)
* StartRoutine = Entry point for the thread
* StartContext = Argument supplied to the thread when it begins
* execution
* RETURNS: Success or failure status
*/ */
{
PETHREAD Thread;
NTSTATUS Status;
DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n",
ThreadHandle,ProcessHandle);
Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle,
DesiredAccess,ObjectAttributes);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Thread->StartAddress=StartRoutine;
Status = HalInitTask(Thread,StartRoutine,StartContext);
if (!NT_SUCCESS(Status))
{
return(Status);
}
if (ClientId!=NULL)
{
*ClientId=Thread->Cid;
}
PsResumeThread(Thread, NULL);
return(STATUS_SUCCESS);
}
// Sets thread's base priority relative to the process' base priority
// Should only be passed in THREAD_PRIORITY_ constants in pstypes.h
LONG KeSetBasePriorityThread(PKTHREAD Thread, LONG Increment) LONG KeSetBasePriorityThread(PKTHREAD Thread, LONG Increment)
{ {
Thread->BasePriority = ((PETHREAD)Thread)->ThreadsProcess->Pcb.BasePriority + Increment; Thread->BasePriority = ((PETHREAD)Thread)->ThreadsProcess->Pcb.BasePriority + Increment;
@ -758,7 +443,7 @@ NTSTATUS STDCALL NtAlertThread (IN HANDLE ThreadHandle)
} }
ThreadStatus = STATUS_ALERTED; ThreadStatus = STATUS_ALERTED;
(VOID)PsResumeThread(Thread, &ThreadStatus); (VOID)PsUnfreezeThread(Thread, &ThreadStatus);
ObDereferenceObject(Thread); ObDereferenceObject(Thread);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
@ -794,24 +479,8 @@ NTSTATUS STDCALL NtResumeThread (IN HANDLE ThreadHandle,
* RETURNS: Status * RETURNS: Status
*/ */
{ {
PETHREAD Thread; UNIMPLEMENTED;
NTSTATUS Status; return(STATUS_UNSUCCESSFUL);
Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_SUSPEND_RESUME,
PsThreadType,
UserMode,
(PVOID*)&Thread,
NULL);
if (Status != STATUS_SUCCESS)
{
return(Status);
}
(*SuspendCount) = PsResumeThread(Thread, NULL);
ObDereferenceObject(Thread);
return(STATUS_SUCCESS);
} }
@ -838,27 +507,8 @@ NTSTATUS STDCALL NtSuspendThread (IN HANDLE ThreadHandle,
* RETURNS: Status * RETURNS: Status
*/ */
{ {
PETHREAD Thread; UNIMPLEMENTED;
NTSTATUS Status; return(STATUS_UNSUCCESSFUL);
Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_SUSPEND_RESUME,
PsThreadType,
UserMode,
(PVOID*)&Thread,
NULL);
if (Status != STATUS_SUCCESS)
{
return(Status);
}
(*PreviousSuspendCount) = PsSuspendThread(Thread,
NULL,
FALSE,
UserMode);
ObDereferenceObject(Thread);
return(STATUS_SUCCESS);
} }