(Finally) implemented Philip Susi's suggestion for non-counting block

Moved suspend/resume code to seperate file

svn path=/trunk/; revision=1543
This commit is contained in:
David Welch 2001-01-19 15:09:01 +00:00
parent e443f083f2
commit 703924d130
13 changed files with 387 additions and 412 deletions

View file

@ -22,4 +22,6 @@
#define INVALID_HANDLE_VALUE ((HANDLE)-1)
#define EX_MAXIMUM_WAIT_OBJECTS (64)
#endif /* __INCLUDE_NTDEF_H */

View file

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.6 2000/12/26 05:32:43 dwelch Exp $
# $Id: Makefile,v 1.7 2001/01/19 15:09:01 dwelch Exp $
#
# ReactOS Operating System
#
@ -186,7 +186,8 @@ OBJECTS_PS = \
ps/psmgr.o \
ps/thread.o \
ps/tinfo.o \
ps/debug.o
ps/debug.o \
ps/suspend.o
# Executive Subsystem (Ex)
OBJECTS_EX = \

View file

@ -101,6 +101,7 @@ VOID KeRemoveAllWaitsThread(struct _ETHREAD* Thread, NTSTATUS WaitStatus);
PULONG KeGetStackTopThread(struct _ETHREAD* Thread);
VOID KeContextToTrapFrame(PCONTEXT Context,
PKTRAP_FRAME TrapFrame);
VOID KeReleaseDispatcherDatabaseLockAtDpcLevel(BOOLEAN Wait);
/* INITIALIZATION FUNCTIONS *************************************************/

View file

@ -414,7 +414,8 @@ ULONG PsResumeThread(PETHREAD Thread);
#define THREAD_STATE_FROZEN (4)
#define THREAD_STATE_TERMINATED_1 (5)
#define THREAD_STATE_TERMINATED_2 (6)
#define THREAD_STATE_MAX (7)
#define THREAD_STATE_BLOCKED (7)
#define THREAD_STATE_MAX (8)
/*
@ -447,6 +448,11 @@ VOID PsUnfreezeProcessThreads(PEPROCESS Process);
PEPROCESS PsGetNextProcess(PEPROCESS OldProcess);
VOID
Ki386ContextSwitch(PKTHREAD NewThread, PKTHREAD OldThread);
VOID
PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode,
BOOLEAN DispatcherLock, KIRQL WaitIrql);
VOID
PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus);
#endif /* ASSEMBLER */

View file

@ -64,12 +64,12 @@ BOOLEAN KiTestAlert(VOID)
KIRQL oldIrql;
KeAcquireSpinLock(&PiApcLock, &oldIrql);
if (IsListEmpty(&KeGetCurrentThread()->ApcState.ApcListHead[1]))
if (KeGetCurrentThread()->ApcState.UserApcPending == 0)
{
KeReleaseSpinLock(&PiApcLock, oldIrql);
return(FALSE);
}
KeGetCurrentThread()->ApcState.UserApcPending++;
KeGetCurrentThread()->Alerted[0] = 1;
KeReleaseSpinLock(&PiApcLock, oldIrql);
return(TRUE);
}
@ -89,7 +89,6 @@ BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame)
PCONTEXT Context;
KIRQL oldlvl;
PKTHREAD Thread;
PETHREAD EThread;
DPRINT("KiDeliverUserApc(TrapFrame %x/%x)\n", TrapFrame,
KeGetCurrentThread()->TrapFrame);
@ -98,17 +97,6 @@ BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame)
/*
* Check for thread termination
*/
KeAcquireSpinLock(&PiThreadListLock, &oldlvl);
EThread = CONTAINING_RECORD(Thread, ETHREAD, Tcb);
if (EThread->DeadThread)
{
KeReleaseSpinLock(&PiThreadListLock, oldlvl);
PsTerminateCurrentThread(EThread->ExitStatus);
}
else
{
KeReleaseSpinLock(&PiThreadListLock, oldlvl);
}
KeAcquireSpinLock(&PiApcLock, &oldlvl);
@ -191,7 +179,8 @@ BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame)
(PVOID*)&Esp[2],
(PVOID*)&Esp[3],
(PVOID*)&Esp[4]);
Thread->Alerted[0] = 0;
return(TRUE);
}
@ -273,6 +262,7 @@ KeInsertQueueApc (PKAPC Apc,
{
InsertTailList(&TargetThread->ApcState.ApcListHead[1],
&Apc->ApcListEntry);
TargetThread->ApcState.UserApcPending++;
}
Apc->Inserted = TRUE;
@ -298,8 +288,8 @@ KeInsertQueueApc (PKAPC Apc,
DPRINT("Resuming thread for user APC\n");
TargetThread->ApcState.UserApcPending++;
Status = STATUS_USER_APC;
TargetThread->Alerted[0] = 1;
KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb),
STATUS_USER_APC);
}

View file

@ -51,12 +51,12 @@ VOID STDCALL KeInitializeEvent (PKEVENT Event,
InitializeListHead(&(Event->Header.WaitListHead));
}
LONG STDCALL KeReadStateEvent (PKEVENT Event)
LONG STDCALL KeReadStateEvent (PKEVENT Event)
{
return(Event->Header.SignalState);
}
LONG STDCALL KeResetEvent (PKEVENT Event)
LONG STDCALL KeResetEvent (PKEVENT Event)
{
return(InterlockedExchange(&(Event->Header.SignalState),0));
}

View file

@ -1,4 +1,4 @@
/* $Id: usercall.c,v 1.17 2001/01/18 15:00:08 dwelch Exp $
/* $Id: usercall.c,v 1.18 2001/01/19 15:09:01 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -9,9 +9,12 @@
* ???
*/
/* INCLUDES ******************************************************************/
#include <ddk/ntddk.h>
#include <internal/ntoskrnl.h>
#include <internal/ke.h>
#include <internal/ps.h>
#include <internal/i386/segment.h>
#include <internal/mmhal.h>
@ -22,6 +25,12 @@
#include <ddk/defines.h>
#include <internal/ps.h>
/* GLOBALS *******************************************************************/
VOID PsTerminateCurrentThread(NTSTATUS ExitStatus);
/* FUNCTIONS *****************************************************************/
VOID KiSystemCallHook(ULONG Nr, ...)
{
#if 0
@ -44,15 +53,33 @@ VOID KiSystemCallHook(ULONG Nr, ...)
ULONG KiAfterSystemCallHook(ULONG NtStatus, PKTRAP_FRAME TrapFrame)
{
assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
if (KeGetCurrentThread()->ApcState.UserApcPending == 0 ||
TrapFrame->Cs == KERNEL_CS)
{
return(NtStatus);
}
KiDeliverUserApc(TrapFrame);
assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
return(NtStatus);
KIRQL oldIrql;
PETHREAD EThread;
extern KSPIN_LOCK PiThreadListLock;
assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
/*
* Check if the current thread is terminating
*/
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
EThread = PsGetCurrentThread();
if (EThread->DeadThread)
{
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
PsTerminateCurrentThread(EThread->ExitStatus);
}
else
{
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
}
if (KeGetCurrentThread()->Alerted[0] == 0 || TrapFrame->Cs == KERNEL_CS)
{
return(NtStatus);
}
KiDeliverUserApc(TrapFrame);
return(NtStatus);
}
// This function should be used by win32k.sys to add its own user32/gdi32 services

View file

@ -51,13 +51,6 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
extern unsigned int init_stack_top;
extern unsigned int init_stack;
#if 0
DbgPrint("Thread %x &Thread->MutantListHead %x &Thread->TrapFrame %x "
"&Thread->PreviousMode %x &Thread->DisableBoost %x\n",
Thread, &Thread->MutantListHead, &Thread->TrapFrame,
&Thread->PreviousMode, &Thread->DisableBoost);
#endif
KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
InternalThreadType,
sizeof(ETHREAD),

View file

@ -6,8 +6,8 @@
* PROGRAMMER: David Welch (welch@mcmail.com)
* REVISION HISTORY:
* 21/07/98: Created
* 12/1/99: Phillip Susi: Fixed wake code in KeDispatcherObjectWake
* so that things like KeWaitForXXX() return the correct value
* 12/1/99: Phillip Susi: Fixed wake code in KeDispatcherObjectWake
* so that things like KeWaitForXXX() return the correct value
*/
/* NOTES ********************************************************************
@ -21,6 +21,7 @@
#include <internal/ps.h>
#include <internal/ob.h>
#include <internal/id.h>
#include <ntos/ntdef.h>
#define NDEBUG
#include <internal/debug.h>
@ -57,11 +58,22 @@ VOID KeAcquireDispatcherDatabaseLock(BOOLEAN Wait)
{
return;
}
KeAcquireSpinLock(&DispatcherDatabaseLock,&oldlvl);
KeAcquireSpinLock(&DispatcherDatabaseLock, &oldlvl);
WaitSet = Wait;
Owner = KeGetCurrentThread();
}
VOID KeReleaseDispatcherDatabaseLockAtDpcLevel(BOOLEAN Wait)
{
DPRINT("KeReleaseDispatcherDatabaseLockAtDpcLevel(Wait %x)\n", Wait);
assert(Wait == WaitSet);
if (!Wait)
{
Owner = NULL;
KeReleaseSpinLockFromDpcLevel(&DispatcherDatabaseLock);
}
}
VOID KeReleaseDispatcherDatabaseLock(BOOLEAN Wait)
{
DPRINT("KeReleaseDispatcherDatabaseLock(Wait %x)\n",Wait);
@ -110,9 +122,7 @@ VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr,
{
PKMUTEX Mutex;
Mutex = CONTAINING_RECORD(hdr,
KMUTEX,
Header);
Mutex = CONTAINING_RECORD(hdr, KMUTEX, Header);
hdr->SignalState--;
assert(hdr->SignalState <= 1);
Mutex->OwnerThread = Thread;
@ -134,9 +144,7 @@ static BOOLEAN KiIsObjectSignalled(DISPATCHER_HEADER* hdr,
{
PKMUTEX Mutex;
Mutex = CONTAINING_RECORD(hdr,
KMUTEX,
Header);
Mutex = CONTAINING_RECORD(hdr, KMUTEX, Header);
assert(hdr->SignalState <= 1);
if ((hdr->SignalState < 1 && Mutex->OwnerThread == Thread) ||
@ -183,7 +191,7 @@ VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus)
if (WasWaiting)
{
PsUnfreezeThread(Thread, &WaitStatus);
PsUnblockThread(Thread, &WaitStatus);
}
KeReleaseDispatcherDatabaseLock(FALSE);
@ -245,8 +253,8 @@ static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr)
Status = current->WaitKey;
if (current->Thread->WaitBlockList == NULL)
{
PsUnfreezeThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
&Status);
PsUnblockThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
&Status);
}
}
return(TRUE);
@ -306,8 +314,8 @@ static BOOLEAN KeDispatcherObjectWakeOne(DISPATCHER_HEADER* hdr)
DPRINT("Waking %x\n",current->Thread);
KiSideEffectsBeforeWake(hdr, current->Thread);
Status = current->WaitKey;
PsUnfreezeThread(CONTAINING_RECORD(current->Thread, ETHREAD, Tcb),
&Status);
PsUnblockThread(CONTAINING_RECORD(current->Thread, ETHREAD, Tcb),
&Status);
return(TRUE);
}
@ -388,66 +396,57 @@ NTSTATUS STDCALL KeWaitForSingleObject (PVOID Object,
DISPATCHER_HEADER* hdr = (DISPATCHER_HEADER *)Object;
PKTHREAD CurrentThread;
NTSTATUS Status;
KIRQL WaitIrql;
DPRINT("Entering KeWaitForSingleObject(Object %x) "
"PsGetCurrentThread() %x\n",Object,PsGetCurrentThread());
CurrentThread = KeGetCurrentThread();
if (Alertable && !IsListEmpty(&CurrentThread->ApcState.ApcListHead[1]))
{
DPRINT("Thread is alertable and user APCs are pending\n");
KiTestAlert();
return(STATUS_USER_APC);
}
WaitIrql = KeGetCurrentIrql();
if (Timeout != NULL)
{
KeAddThreadTimeout(CurrentThread,Timeout);
KeAddThreadTimeout(CurrentThread, Timeout);
}
do
{
KeAcquireDispatcherDatabaseLock(FALSE);
KeAcquireDispatcherDatabaseLock(FALSE);
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
if (KiIsObjectSignalled(hdr, CurrentThread))
{
KeReleaseDispatcherDatabaseLock(FALSE);
if (Timeout != NULL)
{
KeCancelTimer(&KeGetCurrentThread()->Timer);
}
return(STATUS_WAIT_0);
}
CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL;
/* Append wait block to the KTHREAD wait block list */
CurrentThread->WaitBlockList = &CurrentThread->WaitBlock[0];
CurrentThread->WaitBlock[0].Object = Object;
CurrentThread->WaitBlock[0].Thread = CurrentThread;
CurrentThread->WaitBlock[0].WaitKey = 0;
CurrentThread->WaitBlock[0].WaitType = WaitAny;
CurrentThread->WaitBlock[0].NextWaitBlock = NULL;
InsertTailList(&hdr->WaitListHead,
&CurrentThread->WaitBlock[0].WaitListEntry);
KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("Waiting for %x with irql %d\n", Object, KeGetCurrentIrql());
Status = STATUS_SUCCESS;
PsFreezeThread(PsGetCurrentThread(),
&Status,
(UCHAR)Alertable,
WaitMode);
if (!NT_SUCCESS(Status))
{
DPRINT1("Woke from wait with status %x\n", Status);
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
if (Alertable && KiTestAlert())
{
KeReleaseDispatcherDatabaseLock(FALSE);
return(STATUS_USER_APC);
}
if (KiIsObjectSignalled(hdr, CurrentThread))
{
KeReleaseDispatcherDatabaseLock(FALSE);
if (Timeout != NULL)
{
KeCancelTimer(&KeGetCurrentThread()->Timer);
}
return(STATUS_WAIT_0);
}
CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL;
/* Append wait block to the KTHREAD wait block list */
CurrentThread->WaitBlockList = &CurrentThread->WaitBlock[0];
CurrentThread->WaitBlock[0].Object = Object;
CurrentThread->WaitBlock[0].Thread = CurrentThread;
CurrentThread->WaitBlock[0].WaitKey = 0;
CurrentThread->WaitBlock[0].WaitType = WaitAny;
CurrentThread->WaitBlock[0].NextWaitBlock = NULL;
InsertTailList(&hdr->WaitListHead,
&CurrentThread->WaitBlock[0].WaitListEntry);
PsBlockThread(&Status, (UCHAR)Alertable, WaitMode, TRUE, WaitIrql);
} while (Status == STATUS_KERNEL_APC);
if (Timeout != NULL)
{
KeCancelTimer(&KeGetCurrentThread()->Timer);
KeCancelTimer(&KeGetCurrentThread()->Timer);
}
DPRINT("Returning from KeWaitForSingleObject()\n");
@ -455,125 +454,114 @@ NTSTATUS STDCALL KeWaitForSingleObject (PVOID Object,
}
NTSTATUS
STDCALL
KeWaitForMultipleObjects (
ULONG Count,
PVOID Object[],
WAIT_TYPE WaitType,
KWAIT_REASON WaitReason,
KPROCESSOR_MODE WaitMode,
BOOLEAN Alertable,
PLARGE_INTEGER Timeout,
PKWAIT_BLOCK WaitBlockArray
)
NTSTATUS STDCALL
KeWaitForMultipleObjects (ULONG Count,
PVOID Object[],
WAIT_TYPE WaitType,
KWAIT_REASON WaitReason,
KPROCESSOR_MODE WaitMode,
BOOLEAN Alertable,
PLARGE_INTEGER Timeout,
PKWAIT_BLOCK WaitBlockArray)
{
DISPATCHER_HEADER* hdr;
PKWAIT_BLOCK blk;
PKTHREAD CurrentThread;
ULONG CountSignaled;
ULONG i;
NTSTATUS Status;
DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
"PsGetCurrentThread() %x\n",Count,Object,PsGetCurrentThread());
DISPATCHER_HEADER* hdr;
PKWAIT_BLOCK blk;
PKTHREAD CurrentThread;
ULONG CountSignaled;
ULONG i;
NTSTATUS Status;
KIRQL WaitIrql;
CountSignaled = 0;
CurrentThread = KeGetCurrentThread();
DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
"PsGetCurrentThread() %x\n",Count,Object,PsGetCurrentThread());
if (WaitBlockArray == NULL)
CountSignaled = 0;
CurrentThread = KeGetCurrentThread();
WaitIrql = KeGetCurrentIrql();
if (WaitBlockArray == NULL)
{
if (Count > 4)
if (Count > 4)
{
DbgPrint("(%s:%d) Too many objects!\n",
__FILE__,__LINE__);
return STATUS_UNSUCCESSFUL;
DbgPrint("(%s:%d) Too many objects!\n",
__FILE__,__LINE__);
return STATUS_UNSUCCESSFUL;
}
blk = &CurrentThread->WaitBlock[0];
blk = &CurrentThread->WaitBlock[0];
}
else
else
{
if (Count > 64)
if (Count > 64)
{
DbgPrint("(%s:%d) Too many objects!\n",
__FILE__,__LINE__);
return STATUS_UNSUCCESSFUL;
DbgPrint("(%s:%d) Too many objects!\n",
__FILE__,__LINE__);
return STATUS_UNSUCCESSFUL;
}
blk = WaitBlockArray;
blk = WaitBlockArray;
}
if (Timeout != NULL)
if (Timeout != NULL)
{
KeAddThreadTimeout(CurrentThread,Timeout);
KeAddThreadTimeout(CurrentThread,Timeout);
}
do {
KeAcquireDispatcherDatabaseLock(FALSE);
for (i = 0; i < Count; i++)
{
hdr = (DISPATCHER_HEADER *)Object[i];
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
if (KiIsObjectSignalled(hdr, CurrentThread))
{
CountSignaled++;
if (WaitType == WaitAny)
{
do {
KeAcquireDispatcherDatabaseLock(FALSE);
for (i = 0; i < Count; i++)
{
hdr = (DISPATCHER_HEADER *)Object[i];
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
if (KiIsObjectSignalled(hdr, CurrentThread))
{
CountSignaled++;
if (WaitType == WaitAny)
{
KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("One object is already signaled!\n");
return(STATUS_WAIT_0 + i);
}
}
}
if ((WaitType == WaitAll) && (CountSignaled == Count))
{
KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("All objects are already signaled!\n");
return(STATUS_WAIT_0);
}
/* Append wait block to the KTHREAD wait block list */
CurrentThread->WaitBlockList = blk;
for (i = 0; i < Count; i++)
{
hdr = (DISPATCHER_HEADER *)Object[i];
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
blk->Object = Object[i];
blk->Thread = CurrentThread;
blk->WaitKey = i;
blk->WaitType = WaitType;
if (i == Count - 1)
blk->NextWaitBlock = NULL;
else
blk->NextWaitBlock = blk + 1;
DPRINT("blk %p blk->NextWaitBlock %p\n",
blk, blk->NextWaitBlock);
InsertTailList(&(hdr->WaitListHead),&(blk->WaitListEntry));
// DPRINT("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x\n",
// hdr->WaitListHead.Flink,hdr->WaitListHead.Blink);
blk = blk->NextWaitBlock;
}
KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("Waiting at %s:%d with irql %d\n", __FILE__, __LINE__,
KeGetCurrentIrql());
PsFreezeThread(PsGetCurrentThread(),
&Status,
Alertable,
WaitMode);
} while( Status == STATUS_KERNEL_APC );
if (Timeout != NULL)
KeCancelTimer(&KeGetCurrentThread()->Timer);
DPRINT("Returning from KeWaitForMultipleObjects()\n");
return(Status);
}
}
}
if ((WaitType == WaitAll) && (CountSignaled == Count))
{
KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("All objects are already signaled!\n");
return(STATUS_WAIT_0);
}
/* Append wait block to the KTHREAD wait block list */
CurrentThread->WaitBlockList = blk;
for (i = 0; i < Count; i++)
{
hdr = (DISPATCHER_HEADER *)Object[i];
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
blk->Object = Object[i];
blk->Thread = CurrentThread;
blk->WaitKey = i;
blk->WaitType = WaitType;
if (i == Count - 1)
blk->NextWaitBlock = NULL;
else
blk->NextWaitBlock = blk + 1;
InsertTailList(&(hdr->WaitListHead),&(blk->WaitListEntry));
blk = blk->NextWaitBlock;
}
PsBlockThread(&Status, Alertable, WaitMode, TRUE, WaitIrql);
} while( Status == STATUS_KERNEL_APC );
if (Timeout != NULL)
KeCancelTimer(&KeGetCurrentThread()->Timer);
DPRINT("Returning from KeWaitForMultipleObjects()\n");
return(Status);
}
VOID KeInitializeDispatcher(VOID)
@ -587,16 +575,16 @@ NTSTATUS STDCALL NtWaitForMultipleObjects(IN ULONG Count,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Time)
{
KWAIT_BLOCK WaitBlockArray[64]; /* FIXME: use MAXIMUM_WAIT_OBJECTS instead */
PVOID ObjectPtrArray[64]; /* FIXME: use MAXIMUM_WAIT_OBJECTS instead */
KWAIT_BLOCK WaitBlockArray[EX_MAXIMUM_WAIT_OBJECTS];
PVOID ObjectPtrArray[EX_MAXIMUM_WAIT_OBJECTS];
NTSTATUS Status;
ULONG i, j;
DPRINT("NtWaitForMultipleObjects(Count %lu Object[] %x, Alertable %d, Time %x)\n",
Count,Object,Alertable,Time);
DPRINT("NtWaitForMultipleObjects(Count %lu Object[] %x, Alertable %d, "
"Time %x)\n", Count,Object,Alertable,Time);
if (Count > 64) /* FIXME: use MAXIMUM_WAIT_OBJECTS instead */
return STATUS_UNSUCCESSFUL;
if (Count > EX_MAXIMUM_WAIT_OBJECTS)
return STATUS_UNSUCCESSFUL;
/* reference all objects */
for (i = 0; i < Count; i++)
@ -659,17 +647,12 @@ NTSTATUS STDCALL NtWaitForSingleObject (IN HANDLE Object,
return(Status);
}
DPRINT("ObjectPtr %x\n", ObjectPtr);
Status = KeWaitForSingleObject(ObjectPtr,
UserMode,
UserMode,
Alertable,
Time);
DPRINT("Returned from wait (status is %x) ObjectPtr %x(%d)\n",
Status, ObjectPtr, ObGetReferenceCount(ObjectPtr));
ObDereferenceObject(ObjectPtr);
return(Status);
@ -688,7 +671,7 @@ NtSignalAndWaitForSingleObject(IN HANDLE SignalObject,
PVOID WaitObj;
NTSTATUS Status;
ProcessorMode = CURRENT_KPCR->CurrentThread->PreviousMode;
ProcessorMode = ExGetPreviousMode();
Status = ObReferenceObjectByHandle(SignalObject,
0,
NULL,

View file

@ -1,4 +1,4 @@
/* $Id: create.c,v 1.27 2000/12/28 20:38:27 ekohl Exp $
/* $Id: create.c,v 1.28 2001/01/19 15:09:01 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -549,7 +549,6 @@ NTSTATUS STDCALL NtCreateThread (PHANDLE ThreadHandle,
ThreadContext->Eip = LdrpGetSystemDllEntryPoint;
#endif
// Status = HalInitTaskWithContext(Thread,ThreadContext);
Status = Ke386InitThreadWithContext(&Thread->Tcb, ThreadContext);
if (!NT_SUCCESS(Status))
{
@ -570,7 +569,7 @@ NTSTATUS STDCALL NtCreateThread (PHANDLE ThreadHandle,
Thread->StartAddress=NULL;
if (Client!=NULL)
if (Client != NULL)
{
*Client=Thread->Cid;
}
@ -650,7 +649,6 @@ NTSTATUS STDCALL PsCreateSystemThread(PHANDLE ThreadHandle,
}
Thread->StartAddress=StartRoutine;
// Status = HalInitTask(Thread,StartRoutine,StartContext);
Status = Ke386InitThread(&Thread->Tcb, StartRoutine, StartContext);
if (!NT_SUCCESS(Status))
{

View file

@ -157,7 +157,6 @@ PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus)
*/
Thread->DeadThread = 1;
Thread->ExitStatus = ExitStatus;
Thread->Tcb.ApcState.UserApcPending++;
if (Thread->Tcb.State == THREAD_STATE_FROZEN &&
(Thread->Tcb.Alertable || Thread->Tcb.WaitMode == UserMode))
{

View file

@ -0,0 +1,130 @@
/* $Id: suspend.c,v 1.1 2001/01/19 15:09:01 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ps/suspend.c
* PURPOSE: Thread managment
* PROGRAMMER: David Welch (welch@mcmail.com)
*/
/* INCLUDES ******************************************************************/
#include <ddk/ntddk.h>
#include <internal/ke.h>
#include <internal/ob.h>
#include <internal/hal.h>
#include <internal/ps.h>
#include <internal/ob.h>
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS *******************************************************************/
extern KSPIN_LOCK PiThreadListLock;
VOID PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread);
/* FUNCTIONS *****************************************************************/
#if 1
ULONG PsResumeThread(PETHREAD Thread)
{
KIRQL oldIrql;
ULONG SuspendCount;
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
if (Thread->Tcb.SuspendCount > 0)
{
Thread->Tcb.SuspendCount--;
SuspendCount = Thread->Tcb.SuspendCount;
Thread->Tcb.State = THREAD_STATE_RUNNABLE;
PsInsertIntoThreadList(Thread->Tcb.Priority, Thread);
}
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
return SuspendCount;
}
#endif
#if 0
VOID
PiSuspendThreadRundownRoutine(PKAPC Apc)
{
ExFreePool(Apc);
}
VOID
PiSuspendThreadKernelRoutine(PKAPC Apc,
PKNORMAL_ROUTINE* NormalRoutine,
PVOID* NormalContext,
PVOID* SystemArgument1,
PVOID* SystemArguemnt2)
{
InterlockedIncrement(&PsGetCurrentThread()->Tcb.SuspendThread);
KeWaitForSingleObject((PVOID)&PsGetCurrentThread()->SuspendSemaphore,
0,
UserMode,
TRUE,
NULL);
ExFreePool(Apc);
}
NTSTATUS
PsSuspendThread(PETHREAD Thread, PULONG SuspendCount)
{
PKAPC Apc;
Apc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
if (Apc == NULL)
{
return(STATUS_NO_MORE_MEMORY);
}
*SuspendCount = Thread->Tcb.SuspendCount;
KeInitializeApc(Apc,
&Thread->Tcb,
NULL,
PiSuspendThreadKernelRoutine,
PiSuspendThreadRundownRoutine,
NULL,
KernelMode,
NULL);
KeInsertQueueApc(Apc,
NULL,
NULL,
0);
return(STATUS_SUCCESS);
}
#endif
#if 1
ULONG
PsSuspendThread(PETHREAD Thread)
{
KIRQL oldIrql;
ULONG PreviousSuspendCount;
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
PreviousSuspendCount = Thread->Tcb.SuspendCount;
if (Thread->Tcb.SuspendCount < MAXIMUM_SUSPEND_COUNT)
{
Thread->Tcb.SuspendCount++;
}
if (PsGetCurrentThread() == Thread)
{
DbgPrint("Cannot suspend self\n");
KeBugCheck(0);
}
Thread->Tcb.State = THREAD_STATE_SUSPENDED;
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
return PreviousSuspendCount;
}
#endif

View file

@ -1,4 +1,4 @@
/* $Id: thread.c,v 1.65 2001/01/18 15:00:09 dwelch Exp $
/* $Id: thread.c,v 1.66 2001/01/19 15:09:01 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -66,7 +66,7 @@ HANDLE STDCALL PsGetCurrentThreadId(VOID)
return(PsGetCurrentThread()->Cid.UniqueThread);
}
static VOID PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread)
VOID PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread)
{
// DPRINT("PsInsertIntoThreadList(Priority %x, Thread %x)\n",Priority,
// Thread);
@ -151,7 +151,7 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
CurrentThread->Tcb.State = NewThreadStatus;
if (CurrentThread->Tcb.State == THREAD_STATE_RUNNABLE)
{
PiNrRunnableThreads--;
PiNrRunnableThreads++;
PsInsertIntoThreadList(CurrentThread->Tcb.Priority,
CurrentThread);
}
@ -178,7 +178,6 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
CurrentThread = Candidate;
KeReleaseSpinLockFromDpcLevel(&PiThreadListLock);
// HalTaskSwitch(&CurrentThread->Tcb);
Ki386ContextSwitch(&CurrentThread->Tcb, &OldThread->Tcb);
PsReapThreads();
return;
@ -199,211 +198,54 @@ VOID PsDispatchThread(ULONG NewThreadStatus)
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
/*
* Save wait IrqL
* Save wait IRQL
*/
CurrentThread->Tcb.WaitIrql = oldIrql;
PsDispatchThreadNoLock(NewThreadStatus);
KeLowerIrql(oldIrql);
}
/*
* Suspend and resume may only be called to suspend the current thread, except
* by apc.c
*/
ULONG PsUnfreezeThread(PETHREAD Thread, PNTSTATUS WaitStatus)
{
KIRQL oldIrql;
ULONG r;
DPRINT("PsUnfreezeThread(Thread %x, WaitStatus %x)\n", Thread, WaitStatus);
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
Thread->Tcb.FreezeCount--;
r = Thread->Tcb.FreezeCount;
if (WaitStatus != NULL)
{
if (!NT_SUCCESS((*WaitStatus)))
{
KeBugCheck(0);
}
Thread->Tcb.WaitStatus = *WaitStatus;
}
if (r <= 0)
{
DPRINT("Resuming thread\n");
Thread->Tcb.State = THREAD_STATE_RUNNABLE;
PsInsertIntoThreadList(Thread->Tcb.Priority, Thread);
}
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
return(r);
}
VOID PsUnfreezeOtherThread(PETHREAD Thread)
{
ULONG r;
Thread->Tcb.FreezeCount--;
r = Thread->Tcb.FreezeCount;
if (r <= 0)
{
Thread->Tcb.State = THREAD_STATE_RUNNABLE;
PsInsertIntoThreadList(Thread->Tcb.Priority, Thread);
}
}
ULONG PsFreezeThread(PETHREAD Thread,
PNTSTATUS Status,
UCHAR Alertable,
ULONG WaitMode)
{
KIRQL oldIrql;
ULONG r;
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
Thread->Tcb.FreezeCount++;
r = Thread->Tcb.FreezeCount;
DPRINT("r %d\n", r);
if (r == 0)
{
DPRINT("Not suspending thread\n");
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
return(r);
}
Thread->Tcb.Alertable = Alertable;
Thread->Tcb.WaitMode = WaitMode;
if (PsGetCurrentThread() != Thread)
{
DbgPrint("Suspending other\n");
KeBugCheck(0);
}
else
{
DPRINT("Suspending self\n");
Thread->Tcb.WaitIrql = oldIrql;
PsDispatchThreadNoLock(THREAD_STATE_FROZEN);
if (Status != NULL)
{
*Status = Thread->Tcb.WaitStatus;
}
KeLowerIrql(oldIrql);
}
return(r);
}
#if 1
ULONG PsResumeThread(PETHREAD Thread)
{
KIRQL oldIrql;
ULONG SuspendCount;
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
if (Thread->Tcb.SuspendCount > 0)
{
Thread->Tcb.SuspendCount--;
SuspendCount = Thread->Tcb.SuspendCount;
Thread->Tcb.State = THREAD_STATE_RUNNABLE;
PsInsertIntoThreadList(Thread->Tcb.Priority, Thread);
}
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
return SuspendCount;
}
#endif
#if 0
VOID
PiSuspendThreadRundownRoutine(PKAPC Apc)
PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus)
{
ExFreePool(Apc);
KIRQL oldIrql;
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
if (WaitStatus != NULL)
{
Thread->Tcb.WaitStatus = *WaitStatus;
}
Thread->Tcb.State = THREAD_STATE_RUNNABLE;
PsInsertIntoThreadList(Thread->Tcb.Priority, Thread);
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
}
VOID
PiSuspendThreadKernelRoutine(PKAPC Apc,
PKNORMAL_ROUTINE* NormalRoutine,
PVOID* NormalContext,
PVOID* SystemArgument1,
PVOID* SystemArguemnt2)
PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode,
BOOLEAN DispatcherLock, KIRQL WaitIrql)
{
InterlockedIncrement(&PsGetCurrentThread()->Tcb.SuspendThread);
KeWaitForSingleObject((PVOID)&PsGetCurrentThread()->SuspendSemaphore,
0,
UserMode,
TRUE,
NULL);
ExFreePool(Apc);
KIRQL oldIrql;
PETHREAD Thread = PsGetCurrentThread();
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
if (DispatcherLock)
{
KeReleaseDispatcherDatabaseLockAtDpcLevel(FALSE);
}
Thread->Tcb.Alertable = Alertable;
Thread->Tcb.WaitMode = WaitMode;
Thread->Tcb.WaitIrql = WaitIrql;
PsDispatchThreadNoLock(THREAD_STATE_BLOCKED);
if (Status != NULL)
{
*Status = Thread->Tcb.WaitStatus;
}
KeLowerIrql(WaitIrql);
}
NTSTATUS
PsSuspendThread(PETHREAD Thread, PULONG SuspendCount)
{
PKAPC Apc;
Apc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
if (Apc == NULL)
{
return(STATUS_NO_MORE_MEMORY);
}
*SuspendCount = Thread->Tcb.SuspendCount;
KeInitializeApc(Apc,
&Thread->Tcb,
NULL,
PiSuspendThreadKernelRoutine,
PiSuspendThreadRundownRoutine,
NULL,
KernelMode,
NULL);
KeInsertQueueApc(Apc,
NULL,
NULL,
0);
return(STATUS_SUCCESS);
}
#endif
#if 1
ULONG
PsSuspendThread(PETHREAD Thread)
{
KIRQL oldIrql;
ULONG PreviousSuspendCount;
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
PreviousSuspendCount = Thread->Tcb.SuspendCount;
if (Thread->Tcb.SuspendCount < MAXIMUM_SUSPEND_COUNT)
{
Thread->Tcb.SuspendCount++;
}
if (PsGetCurrentThread() == Thread)
{
DbgPrint("Cannot suspend self\n");
KeBugCheck(0);
}
Thread->Tcb.State = THREAD_STATE_SUSPENDED;
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
return PreviousSuspendCount;
}
#endif
VOID
PsInitThreadManagment(VOID)
/*
@ -510,6 +352,7 @@ NTSTATUS STDCALL NtAlertResumeThread(IN HANDLE ThreadHandle,
NTSTATUS STDCALL NtAlertThread (IN HANDLE ThreadHandle)
{
#if 0
PETHREAD Thread;
NTSTATUS Status;
NTSTATUS ThreadStatus;
@ -526,10 +369,12 @@ NTSTATUS STDCALL NtAlertThread (IN HANDLE ThreadHandle)
}
ThreadStatus = STATUS_ALERTED;
(VOID)PsUnfreezeThread(Thread, &ThreadStatus);
(VOID)PsUnblockThread(Thread, &ThreadStatus);
ObDereferenceObject(Thread);
return(STATUS_SUCCESS);
#endif
UNIMPLEMENTED;
}
NTSTATUS STDCALL