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
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
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;
KSEMAPHORE SuspendSemaphore;
LIST_ENTRY ThreadListEntry;
UCHAR FreezeCount;
CHAR FreezeCount;
ULONG SuspendCount;
UCHAR IdealProcessor;
UCHAR DisableBoost;

View file

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

View file

@ -17,6 +17,7 @@ VOID PsInitThreadManagment(VOID);
VOID PsInitProcessManagment(VOID);
VOID PsInitIdleThread(VOID);
VOID PsDispatchThread(ULONG NewThreadStatus);
VOID PsDispatchThreadNoLock(ULONG NewThreadStatus);
VOID PiTerminateProcessThreads(PEPROCESS Process, NTSTATUS ExitStatus);
VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus);
VOID PsReleaseThread(PETHREAD Thread);
@ -24,14 +25,26 @@ VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext);
VOID PsBeginThreadWithContextInternal(VOID);
VOID PiKillMostProcesses(VOID);
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_RUNNABLE (1)
#define THREAD_STATE_RUNNING (2)
#define THREAD_STATE_SUSPENDED (3)
#define THREAD_STATE_TERMINATED_1 (4)
#define THREAD_STATE_TERMINATED_2 (5)
#define THREAD_STATE_MAX (6)
#define THREAD_STATE_FROZEN (4)
#define THREAD_STATE_TERMINATED_1 (5)
#define THREAD_STATE_TERMINATED_2 (6)
#define THREAD_STATE_MAX (7)
// 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/lpc/lpcsrv.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
#
@ -197,7 +197,7 @@ $(TARGET).dll: $(DLLMAIN) $(OBJECTS) $(TARGET).def
-o $(TARGET).dll \
$(TARGET).o \
../kernel32/kernel32.a \
-Wl,--image-base,0x20000000 \
-Wl,--image-base,0x77630000 \
-Wl,--file-alignment,0x1000 \
-Wl,--section-alignment,0x1000 \
-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
* PROJECT: ReactOS system libraries
@ -290,36 +290,27 @@ WaitForInputIdle (
}
VOID
STDCALL
Sleep (
DWORD dwMilliseconds
)
VOID STDCALL Sleep (DWORD dwMilliseconds)
{
SleepEx (dwMilliseconds, FALSE);
return;
SleepEx (dwMilliseconds, FALSE);
return;
}
DWORD
STDCALL
SleepEx (
DWORD dwMilliseconds,
BOOL bAlertable
)
DWORD STDCALL SleepEx(DWORD dwMilliseconds,
BOOL bAlertable)
{
TIME Interval;
NTSTATUS errCode;
TIME Interval;
NTSTATUS errCode;
Interval.QuadPart = dwMilliseconds * 1000;
Interval.QuadPart = dwMilliseconds * 1000;
errCode = NtDelayExecution(bAlertable,&Interval);
if ( !NT_SUCCESS(errCode) )
{
SetLastError(RtlNtStatusToDosError(errCode));
return -1;
}
return 0;
errCode = NtDelayExecution(bAlertable,&Interval);
if (!NT_SUCCESS(errCode))
{
SetLastError(RtlNtStatusToDosError(errCode));
return -1;
}
return 0;
}

View file

@ -17,7 +17,7 @@
#include <string.h>
#include <internal/i386/segment.h>
//#define NDEBUG
#define NDEBUG
#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
* PROJECT: ReactOS kernel
@ -698,7 +698,7 @@ static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders,
PDLL Module;
NTSTATUS Status;
DPRINT1("LdrFixupImports(NTHeaders %x, ImageBase %x)\n", NTHeaders,
DPRINT("LdrFixupImports(NTHeaders %x, ImageBase %x)\n", NTHeaders,
ImageBase);
/*
@ -708,7 +708,7 @@ static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders,
ImageBase + NTHeaders->OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
.VirtualAddress);
DPRINT1("ImportModuleDirectory %x\n", ImportModuleDirectory);
DPRINT("ImportModuleDirectory %x\n", ImportModuleDirectory);
while (ImportModuleDirectory->dwRVAModuleName)
{
@ -717,7 +717,7 @@ static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders,
DWORD pName;
PWORD pHint;
DPRINT1("ImportModule->Directory->dwRVAModuleName %s\n",
DPRINT("ImportModule->Directory->dwRVAModuleName %s\n",
(PCHAR)(ImageBase + ImportModuleDirectory->dwRVAModuleName));
Status = LdrLoadDll(&Module,

View file

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

View file

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

View file

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

View file

@ -16,19 +16,32 @@
#include <internal/string.h>
#include <internal/i386/segment.h>
#include <internal/ps.h>
#include <internal/ke.h>
#define NDEBUG
#include <internal/debug.h>
extern VOID KeApcProlog(VOID);
/* GLOBALS *******************************************************************/
static KSPIN_LOCK PiApcLock;
/* PROTOTYPES ****************************************************************/
VOID KeApcProlog3(PKAPC Apc);
/* 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,
PCONTEXT UserContext)
/*
@ -77,81 +90,41 @@ BOOLEAN KiTestAlert(PKTHREAD Thread,
* Now call for the kernel routine for the APC, which will free
* the APC data structure
*/
KeApcProlog3(Apc);
KeCallKernelRoutineApc(Apc);
}
UserContext->Esp = (ULONG)Esp;
InitializeListHead(&Thread->ApcState.ApcListHead[1]);
return(TRUE);
}
VOID KeApcProlog2()
VOID KeCallApcsThread(VOID)
{
PETHREAD Thread = PsGetCurrentThread();
PLIST_ENTRY current;
PKAPC Apc;
KIRQL oldlvl;
DPRINT( "KeApcProlog2()\n" );
KeLowerIrql( APC_LEVEL );
KeAcquireSpinLock( &PiApcLock, &oldlvl );
while( !IsListEmpty( &(Thread->Tcb.ApcState.ApcListHead[0]) ) )
DPRINT("KeCallApcsThread()\n");
KeAcquireSpinLock(&PiApcLock, &oldlvl);
while(!IsListEmpty(&(Thread->Tcb.ApcState.ApcListHead[0])))
{
DPRINT( "Delivering APC\n" );
current = RemoveTailList( &(Thread->Tcb.ApcState.ApcListHead[0]) );
KeReleaseSpinLock( &PiApcLock, oldlvl );
Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry);
KeApcProlog3(Apc);
KeAcquireSpinLock( &PiApcLock, &oldlvl );
DPRINT("Delivering APC\n");
current = RemoveTailList(&(Thread->Tcb.ApcState.ApcListHead[0]));
Thread->Tcb.ApcState.KernelApcInProgress++;
Thread->Tcb.ApcState.KernelApcPending--;
KeReleaseSpinLock(&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 );
Thread->Tcb.WaitStatus = STATUS_ALERTED;
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);
KeReleaseSpinLock(&PiApcLock, oldlvl);
// Thread->Tcb.WaitStatus = STATUS_KERNEL_APC;
}
VOID KeInsertQueueApc(PKAPC Apc,
@ -173,7 +146,7 @@ VOID KeInsertQueueApc(PKAPC Apc,
"SystemArgument2 %x, Mode %d)\n",Apc,SystemArgument1,
SystemArgument2,Mode);
KeAcquireSpinLock( &PiApcLock, &oldlvl );
KeAcquireSpinLock(&PiApcLock, &oldlvl);
Apc->SystemArgument1 = SystemArgument1;
Apc->SystemArgument2 = SystemArgument2;
@ -200,25 +173,12 @@ VOID KeInsertQueueApc(PKAPC Apc,
}
Apc->Inserted = TRUE;
DPRINT("TargetThread->KernelApcDisable %d\n",
TargetThread->KernelApcDisable);
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
if (Apc->ApcMode == KernelMode && TargetThread->KernelApcDisable >= 1 &&
TargetThread->WaitIrql < APC_LEVEL)
{
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 &&
TargetThread->WaitMode == UserMode)
@ -228,8 +188,9 @@ VOID KeInsertQueueApc(PKAPC Apc,
DPRINT("Resuming thread for user APC\n");
Status = STATUS_USER_APC;
PsResumeThread((PETHREAD)TargetThread,
&Status);
KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb),
STATUS_USER_APC);
KeReleaseSpinLock(&PiApcLock, oldlvl);
}
}
@ -332,8 +293,8 @@ NTSTATUS STDCALL NtTestAlert(VOID)
return(STATUS_SUCCESS);
}
VOID PiInitApcManagement()
VOID PiInitApcManagement(VOID)
{
KeInitializeSpinLock( &PiApcLock );
KeInitializeSpinLock(&PiApcLock);
}

View file

@ -19,6 +19,7 @@
/* GLOBALS ******************************************************************/
static LIST_ENTRY BugcheckCallbackListHead = {NULL,NULL};
static ULONG InBugCheck;
VOID PsDumpThreads(VOID);
@ -32,6 +33,7 @@ BOOLEAN KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
VOID KeInitializeBugCheck(VOID)
{
InitializeListHead(&BugcheckCallbackListHead);
InBugCheck = 0;
}
VOID KeInitializeCallbackRecord(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
@ -72,7 +74,7 @@ VOID KeBugCheckEx(ULONG BugCheckCode,
BugCheckParameter1,BugCheckParameter2,BugCheckParameter3,
BugCheckParameter4);
PsDumpThreads();
KeDumpStackFrames(0,64);
KeDumpStackFrames(&((&BugCheckCode)[-1]),64);
for(;;)
__asm__("hlt\n\t"); //PJS: use HLT instruction, rather than busy wait
@ -87,6 +89,19 @@ VOID KeBugCheck(ULONG BugCheckCode)
* 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:", cs&0xffff);
print_address(eip);
print_address((PVOID)eip);
DbgPrint("\n");
__asm__("movl %%cr2,%0\n\t"
: "=d" (cr2));
@ -302,7 +302,7 @@ asmlinkage void exception_handler(unsigned int edi,
stack[i] <= ((ULONG)&init_stack_top)))
{
// DbgPrint(" %.8x", stack[i]);
print_address(stack[i]);
print_address((PVOID)stack[i]);
DbgPrint(" ");
}
}
@ -328,6 +328,7 @@ asmlinkage void exception_handler(unsigned int edi,
DbgPrint("\n");
DbgPrint("Killing current task\n");
// for(;;);
KeLowerIrql(PASSIVE_LEVEL);
if ((cs&0xffff) == USER_CS)
{
@ -338,12 +339,13 @@ asmlinkage void exception_handler(unsigned int edi,
for(;;);
}
VOID KeDumpStackFrames(ULONG DummyArg, ULONG NrFrames)
VOID KeDumpStackFrames(PVOID _Stack, ULONG NrFrames)
{
PULONG Stack = &((&DummyArg)[-1]);
PULONG Stack = (PULONG)_Stack;
ULONG i;
Stack = (PVOID)(((ULONG)Stack) & (~0x3));
DbgPrint("Stack: %x\n", Stack);
DbgPrint("Frames:\n");
for (i=0; i<NrFrames; i++)
@ -352,7 +354,7 @@ VOID KeDumpStackFrames(ULONG DummyArg, ULONG NrFrames)
if (Stack[i] > KERNEL_BASE)
{
// DbgPrint("%.8x ",Stack[i]);
print_address(Stack[i]);
print_address((PVOID)Stack[i]);
DbgPrint(" ");
}
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
* PROJECT: ReactOS kernel
@ -26,7 +26,7 @@
#include <internal/mmhal.h>
#include <internal/i386/segment.h>
#define NDEBUG
//#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS ****************************************************************/
@ -128,70 +128,6 @@ unsigned int old_idt[256][2];
//extern unsigned int idt[];
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)
/*
* 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
*/
DPRINT("%d files loaded\n",bp.nr_files);
DPRINT1("%d files loaded\n",bp.nr_files);
/* Pass 1: load registry chunks passed in */
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"))
{
DPRINT("process registry chunk at %08lx\n", start);
DPRINT1("process registry chunk at %08lx\n", start);
CmImportHive((PCHAR) start);
}
start = start + bp.module_length[i];
@ -292,7 +228,7 @@ asmlinkage void _main(boot_param* _bp)
{
if (strcmp ((PCHAR) start, "REGEDIT4"))
{
DPRINT("process module at %08lx\n", start);
DPRINT1("process module at %08lx\n", start);
LdrProcessDriver((PVOID)start);
}
start = start + bp.module_length[i];
@ -301,12 +237,14 @@ asmlinkage void _main(boot_param* _bp)
/*
* Load Auto configured drivers
*/
CHECKPOINT;
LdrLoadAutoConfigDrivers();
/*
* Launch initial process
*/
LdrLoadInitialProcess();
CHECKPOINT;
LdrLoadInitialProcess();
/*
* 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
* PROJECT: ReactOS kernel
@ -132,8 +132,11 @@ NTSTATUS KeAddThreadTimeout(PKTHREAD Thread, PLARGE_INTEGER Interval)
NTSTATUS STDCALL NtDelayExecution(IN BOOLEAN Alertable,
IN TIME* Interval)
{
UNIMPLEMENTED;
return(STATUS_UNSUCCESSFUL);
NTSTATUS Status;
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->Flink %x\n",current_entry->Flink->Flink);
KeRaiseIrql( HIGH_LEVEL, &oldlvl );
KeRaiseIrql(HIGH_LEVEL, &oldlvl);
KeAcquireSpinLockAtDpcLevel(&TimerListLock);
while (current_entry!=(&TimerListHead))
@ -411,7 +414,7 @@ VOID KeExpireTimers(VOID)
}
}
KeReleaseSpinLock( &TimerListLock, oldlvl );
KeReleaseSpinLock(&TimerListLock, oldlvl);
// DPRINT("Finished KeExpireTimers()\n");
}
@ -429,7 +432,7 @@ VOID KiTimerInterrupt(VOID)
extern unsigned int EiFreeNonPagedPool;
extern unsigned int EiUsedNonPagedPool;
extern ULONG PiNrThreads;
extern ULONG MiNrFreePages;
// extern ULONG MiNrFreePages;
if (TimerInitDone == FALSE)
{
@ -462,7 +465,8 @@ VOID KiTimerInterrupt(VOID)
// sprintf(str,"%.8u %.8u",(unsigned int)EiNrUsedBlocks,
// (unsigned int)EiFreeNonPagedPool);
// 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,
// (unsigned int)MiNrFreePages);
for (i=0;i<17;i++)

View file

@ -18,6 +18,7 @@
#include <ddk/ntddk.h>
#include <internal/ke.h>
#include <internal/ps.h>
#define NDEBUG
#include <internal/debug.h>
@ -120,6 +121,32 @@ static BOOLEAN KiIsObjectSignalled(DISPATCHER_HEADER* hdr)
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)
{
@ -136,21 +163,21 @@ static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr)
while (!IsListEmpty(&(hdr->WaitListHead)))
{
NTSTATUS Status = STATUS_WAIT_0;
current_entry = RemoveHeadList(&hdr->WaitListHead);
current = CONTAINING_RECORD(current_entry,KWAIT_BLOCK,
WaitListEntry);
NTSTATUS Status = STATUS_WAIT_0;
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");
//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 )
if( PrevBlock == current )
break;
if( PrevBlock == 0 )
DbgPrint( "WaitOne: Wait Block not in list! Wait result will be corrupt\n" );
//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 )
if( PrevBlock == current )
break;
if( PrevBlock == 0 )
DbgPrint( "WaitOne: Wait Block not in list! Wait result will be corrupt\n" );
current->Thread->WaitBlockList = NULL;
}
else
@ -188,8 +215,8 @@ static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr)
KiSideEffectsBeforeWake(hdr);
PsResumeThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
&Status);
PsUnfreezeThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
&Status);
};
return(TRUE);
}
@ -261,8 +288,8 @@ static BOOLEAN KeDispatcherObjectWakeOne(DISPATCHER_HEADER* hdr)
KiSideEffectsBeforeWake(hdr);
PsResumeThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
&Status);
PsUnfreezeThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
&Status);
return(TRUE);
}
@ -356,42 +383,52 @@ NTSTATUS KeWaitForSingleObject(PVOID Object,
return(STATUS_USER_APC);
}
KeAcquireDispatcherDatabaseLock(FALSE);
if (Timeout != NULL)
{
KeAddThreadTimeout(CurrentThread,Timeout);
}
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
do
{
KeAcquireDispatcherDatabaseLock(FALSE);
if (KiIsObjectSignalled(hdr))
{
KeReleaseDispatcherDatabaseLock(FALSE);
return(STATUS_WAIT_0);
}
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
if (KiIsObjectSignalled(hdr))
{
KeReleaseDispatcherDatabaseLock(FALSE);
if (Timeout != NULL)
{
KeCancelTimer(&KeGetCurrentThread()->Timer);
}
return(STATUS_WAIT_0);
}
/* Append wait block to the KTHREAD wait block list */
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)
{
KeAddThreadTimeout(CurrentThread,Timeout);
}
/* Append wait block to the KTHREAD wait block list */
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 at %s:%d with irql %d\n", __FILE__, __LINE__,
KeGetCurrentIrql());
PsSuspendThread(PsGetCurrentThread(),
&Status,
(UCHAR)Alertable,
WaitMode);
if (Timeout != NULL)
KeCancelTimer(&KeGetCurrentThread()->Timer);
}
DPRINT("Returning from KeWaitForSingleObject()\n");
return Status;
@ -505,7 +542,7 @@ NTSTATUS KeWaitForMultipleObjects(ULONG Count,
DPRINT("Waiting at %s:%d with irql %d\n", __FILE__, __LINE__,
KeGetCurrentIrql());
PsSuspendThread(PsGetCurrentThread(),
PsFreezeThread(PsGetCurrentThread(),
&Status,
Alertable,
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
* PROJECT: ReactOS kernel
@ -467,7 +467,7 @@ LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING pModuleName)
unsigned int DriverSize, Idx, Idx2;
ULONG RelocDelta, NumRelocs;
DWORD CurrentSize, TotalRelocs;
PVOID DriverBase, CurrentBase;
PVOID DriverBase;
PULONG PEMagic;
PIMAGE_DOS_HEADER PEDosHeader;
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
#
@ -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/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/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_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
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/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
WIN32_LEAN_AND_MEAN = yes
#WARNINGS_ARE_ERRORS = yes
WARNINGS_ARE_ERRORS = yes
include ../rules.mak

View file

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

View file

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

View file

@ -57,7 +57,7 @@ NTSTATUS MmReleaseMmInfo(PEPROCESS Process)
PLIST_ENTRY CurrentEntry;
PMEMORY_AREA Current;
DbgPrint("MmReleaseMmInfo(Process %x)\n",Process);
DPRINT("MmReleaseMmInfo(Process %x)\n",Process);
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
* PROJECT: ReactOS kernel
@ -351,7 +351,7 @@ NTSTATUS STDCALL NtAcceptConnectPort (PHANDLE ServerPortHandle,
{
NTSTATUS Status;
PEPORT NamedPort;
PEPORT OurPort;
PEPORT OurPort = NULL;
PQUEUEDMESSAGE ConnectionRequest;
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/ob.h>
//#define NDEBUG
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS *******************************************************************/
@ -32,17 +32,17 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus)
* FUNCTION: Terminates the current thread
*/
{
KIRQL oldlvl;
KIRQL oldIrql;
PETHREAD CurrentThread;
PiNrRunnableThreads--;
CurrentThread = PsGetCurrentThread();
CurrentThread->ExitStatus = ExitStatus;
DPRINT("terminating %x\n",CurrentThread);
KeRaiseIrql(DISPATCH_LEVEL,&oldlvl);
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
CurrentThread->ExitStatus = ExitStatus;
DPRINT("ObGetReferenceCount(CurrentThread) %d\n",
ObGetReferenceCount(CurrentThread));
@ -52,7 +52,7 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus)
CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE;
KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader);
PsDispatchThread(THREAD_STATE_TERMINATED_1);
PsDispatchThreadNoLock(THREAD_STATE_TERMINATED_1);
KeBugCheck(0);
}
@ -69,6 +69,7 @@ VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus)
PiNrRunnableThreads--;
RemoveEntryList(&Thread->Tcb.QueueListEntry);
}
RemoveEntryList(&Thread->Tcb.ThreadListEntry);
Thread->Tcb.State = THREAD_STATE_TERMINATED_2;
Thread->Tcb.DispatcherHeader.SignalState = TRUE;
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
* PROJECT: ReactOS kernel
@ -46,7 +46,7 @@ KSPIN_LOCK PiThreadListLock;
/*
* 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 BOOLEAN DoneInitYet = FALSE;
ULONG PiNrThreads = 0;
@ -54,8 +54,6 @@ ULONG PiNrRunnableThreads = 0;
static PETHREAD CurrentThread = NULL;
static ULONG PiNextThreadUniqueId = 0;
/* FUNCTIONS ***************************************************************/
PKTHREAD KeGetCurrentThread(VOID)
@ -88,7 +86,10 @@ VOID PiTerminateProcessThreads(PEPROCESS Process, NTSTATUS ExitStatus)
if (current->ThreadsProcess == Process &&
current != PsGetCurrentThread())
{
KeReleaseSpinLock(&PiThreadListLock, oldlvl);
PsTerminateOtherThread(current, ExitStatus);
KeAcquireSpinLock(&PiThreadListLock, &oldlvl);
current_entry = PiThreadListHead.Flink;
}
current_entry = current_entry->Flink;
}
@ -104,31 +105,30 @@ static VOID PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread)
InsertTailList(&PriorityListHead[THREAD_PRIORITY_MAX+Priority],
&Thread->Tcb.QueueListEntry);
}
VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext)
{
NTSTATUS Ret;
// KeReleaseSpinLock(&PiThreadListLock,PASSIVE_LEVEL);
KeLowerIrql(PASSIVE_LEVEL);
Ret = StartRoutine(StartContext);
PsTerminateSystemThread(Ret);
KeBugCheck(0);
PiNrRunnableThreads++;
}
VOID PsDumpThreads(VOID)
{
PLIST_ENTRY current_entry;
PETHREAD current;
ULONG t;
// return;
current_entry = PiThreadListHead.Flink;
t = 0;
while (current_entry != &PiThreadListHead)
{
current = CONTAINING_RECORD(current_entry, ETHREAD,
Tcb.ThreadListEntry);
t++;
if (t >= PiNrThreads)
{
DbgPrint("Too many threads on list\n");
return;
}
DPRINT1("current %x current->Tcb.State %d eip %x ",
current, current->Tcb.State,
current->Tcb.Context.eip);
@ -148,6 +148,8 @@ VOID PsReapThreads(VOID)
// DPRINT1("PsReapThreads()\n");
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
current_entry = PiThreadListHead.Flink;
while (current_entry != &PiThreadListHead)
@ -159,11 +161,16 @@ VOID PsReapThreads(VOID)
if (current->Tcb.State == THREAD_STATE_TERMINATED_1)
{
RemoveEntryList(&current->Tcb.ThreadListEntry);
DPRINT("Reaping thread %x\n", current);
current->Tcb.State = THREAD_STATE_TERMINATED_2;
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
ObDereferenceObject(current);
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
current_entry = PiThreadListHead.Flink;
}
}
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
}
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;
PETHREAD Candidate;
if (!DoneInitYet)
{
return;
}
CurrentThread->Tcb.State = NewThreadStatus;
if (CurrentThread->Tcb.State == THREAD_STATE_RUNNABLE)
{
@ -213,6 +215,8 @@ static VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
Candidate = PsScanThreadList(CurrentPriority);
if (Candidate == CurrentThread)
{
PiNrRunnableThreads--;
KeReleaseSpinLockFromDpcLevel(&PiThreadListLock);
return;
}
if (Candidate != NULL)
@ -223,12 +227,10 @@ static VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
CurrentThread = Candidate;
PiNrRunnableThreads--;
KeReleaseSpinLockFromDpcLevel( &PiThreadListLock );
HalTaskSwitch(&CurrentThread->Tcb);
KeAcquireSpinLockAtDpcLevel( &PiThreadListLock );
DPRINT( "Woken up, grabbed lock\n" );
HalTaskSwitch(&CurrentThread->Tcb);
PsReapThreads();
DPRINT( "Reaped\n" );
return;
}
}
@ -236,200 +238,98 @@ static VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
KeBugCheck(0);
}
VOID PiBeforeBeginThread(VOID)
{
DPRINT("PiBeforeBeginThread()\n");
//KeReleaseSpinLock(&PiThreadListLock, PASSIVE_LEVEL);
KeLowerIrql(PASSIVE_LEVEL);
DPRINT("KeGetCurrentIrql() %d\n", KeGetCurrentIrql());
}
VOID PsDispatchThread(ULONG NewThreadStatus)
{
KIRQL oldIrql;
if (!DoneInitYet)
{
return;
}
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
CurrentThread->Tcb.WaitIrql = oldIrql; // save wait Irql
PsDispatchThreadNoLock(NewThreadStatus);
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
KeLowerIrql(oldIrql);
// DPRINT("oldIrql %d\n",oldIrql);
}
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;
PsResumeThread( (ETHREAD *)Context, &Status );
}
/*
* Suspend and resume may only be called to suspend the current thread, except by apc.c
*/
NTSTATUS PsInitializeThread(HANDLE ProcessHandle,
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)
ULONG PsUnfreezeThread(PETHREAD Thread, PNTSTATUS WaitStatus)
{
KIRQL oldIrql;
ULONG r;
DPRINT("PsResumeThread(Thread %x) CurrentThread %x \n",Thread,
PsGetCurrentThread());
DPRINT("Thread->Tcb.SuspendCount %d\n",Thread->Tcb.SuspendCount);
DPRINT("PsUnfreezeThread(Thread %x, WaitStatus %x)\n", Thread, WaitStatus);
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
DPRINT("Thread->Tcb.SuspendCount %d\n",Thread->Tcb.SuspendCount);
r = Thread->Tcb.SuspendCount;
if ( Thread->Tcb.SuspendCount == TRUE )
Thread->Tcb.FreezeCount--;
r = Thread->Tcb.FreezeCount;
if (r <= 0)
{
// DPRINT("Marking thread %x as runnable\n",Thread);
Thread->Tcb.SuspendCount = FALSE;
DPRINT("Resuming thread\n");
Thread->Tcb.State = THREAD_STATE_RUNNABLE;
if (WaitStatus != NULL)
{
Thread->Tcb.WaitStatus = *WaitStatus;
}
PsInsertIntoThreadList(Thread->Tcb.Priority, Thread);
PiNrRunnableThreads++;
}
DPRINT("About release ThreadListLock = %x\n", &PiThreadListLock);
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
DPRINT("Finished PsResumeThread()\n");
return r;
return(r);
}
ULONG PsSuspendThread(PETHREAD Thread,
PNTSTATUS WaitStatus,
UCHAR Alertable,
ULONG WaitMode)
ULONG PsFreezeThread(PETHREAD Thread, PNTSTATUS Status, UCHAR Alertable,
ULONG WaitMode)
{
KIRQL oldIrql;
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);
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);
Thread->Tcb.FreezeCount++;
r = Thread->Tcb.FreezeCount;
DPRINT("r %d\n", r);
if (r == 0)
{
DPRINT("Not suspending thread\n");
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
DPRINT("PsSuspendThread() finished\n");
return r;
}
return(r);
}
Thread->Tcb.Alertable = Alertable;
Thread->Tcb.WaitMode = WaitMode;
VOID PiDeleteThread(PVOID ObjectBody)
{
DPRINT("PiDeleteThread(ObjectBody %x)\n",ObjectBody);
ObDereferenceObject(((PETHREAD)ObjectBody)->ThreadsProcess);
((PETHREAD)ObjectBody)->ThreadsProcess = NULL;
PiNrThreads--;
RemoveEntryList(&((PETHREAD)ObjectBody)->Tcb.ThreadListEntry);
HalReleaseTask((PETHREAD)ObjectBody);
}
VOID PiCloseThread(PVOID ObjectBody, ULONG HandleCount)
{
DPRINT("PiCloseThread(ObjectBody %x)\n", ObjectBody);
DPRINT("ObGetReferenceCount(ObjectBody) %d "
"ObGetHandleCount(ObjectBody) %d\n",
ObGetReferenceCount(ObjectBody),
ObGetHandleCount(ObjectBody));
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)
@ -474,7 +374,8 @@ VOID PsInitThreadManagment(VOID)
THREAD_ALL_ACCESS,NULL);
HalInitFirstTask(FirstThread);
FirstThread->Tcb.State = THREAD_STATE_RUNNING;
FirstThread->Tcb.SuspendCount = 0;
FirstThread->Tcb.FreezeCount = 0;
ZwClose(FirstThreadHandle);
DPRINT("FirstThread %x\n",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
* 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
* Sets thread's base priority relative to the process' base priority
* Should only be passed in THREAD_PRIORITY_ constants in pstypes.h
*/
{
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)
{
Thread->BasePriority = ((PETHREAD)Thread)->ThreadsProcess->Pcb.BasePriority + Increment;
@ -758,7 +443,7 @@ NTSTATUS STDCALL NtAlertThread (IN HANDLE ThreadHandle)
}
ThreadStatus = STATUS_ALERTED;
(VOID)PsResumeThread(Thread, &ThreadStatus);
(VOID)PsUnfreezeThread(Thread, &ThreadStatus);
ObDereferenceObject(Thread);
return(STATUS_SUCCESS);
@ -794,24 +479,8 @@ NTSTATUS STDCALL NtResumeThread (IN HANDLE ThreadHandle,
* RETURNS: Status
*/
{
PETHREAD Thread;
NTSTATUS Status;
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);
UNIMPLEMENTED;
return(STATUS_UNSUCCESSFUL);
}
@ -838,27 +507,8 @@ NTSTATUS STDCALL NtSuspendThread (IN HANDLE ThreadHandle,
* RETURNS: Status
*/
{
PETHREAD Thread;
NTSTATUS Status;
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);
UNIMPLEMENTED;
return(STATUS_UNSUCCESSFUL);
}