(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 INVALID_HANDLE_VALUE ((HANDLE)-1)
#define EX_MAXIMUM_WAIT_OBJECTS (64)
#endif /* __INCLUDE_NTDEF_H */ #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 # ReactOS Operating System
# #
@ -186,7 +186,8 @@ OBJECTS_PS = \
ps/psmgr.o \ ps/psmgr.o \
ps/thread.o \ ps/thread.o \
ps/tinfo.o \ ps/tinfo.o \
ps/debug.o ps/debug.o \
ps/suspend.o
# Executive Subsystem (Ex) # Executive Subsystem (Ex)
OBJECTS_EX = \ OBJECTS_EX = \

View file

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

View file

@ -414,7 +414,8 @@ ULONG PsResumeThread(PETHREAD Thread);
#define THREAD_STATE_FROZEN (4) #define THREAD_STATE_FROZEN (4)
#define THREAD_STATE_TERMINATED_1 (5) #define THREAD_STATE_TERMINATED_1 (5)
#define THREAD_STATE_TERMINATED_2 (6) #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); PEPROCESS PsGetNextProcess(PEPROCESS OldProcess);
VOID VOID
Ki386ContextSwitch(PKTHREAD NewThread, PKTHREAD OldThread); 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 */ #endif /* ASSEMBLER */

View file

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

View file

@ -51,12 +51,12 @@ VOID STDCALL KeInitializeEvent (PKEVENT Event,
InitializeListHead(&(Event->Header.WaitListHead)); InitializeListHead(&(Event->Header.WaitListHead));
} }
LONG STDCALL KeReadStateEvent (PKEVENT Event) LONG STDCALL KeReadStateEvent (PKEVENT Event)
{ {
return(Event->Header.SignalState); return(Event->Header.SignalState);
} }
LONG STDCALL KeResetEvent (PKEVENT Event) LONG STDCALL KeResetEvent (PKEVENT Event)
{ {
return(InterlockedExchange(&(Event->Header.SignalState),0)); 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -9,9 +9,12 @@
* ??? * ???
*/ */
/* INCLUDES ******************************************************************/
#include <ddk/ntddk.h> #include <ddk/ntddk.h>
#include <internal/ntoskrnl.h> #include <internal/ntoskrnl.h>
#include <internal/ke.h> #include <internal/ke.h>
#include <internal/ps.h>
#include <internal/i386/segment.h> #include <internal/i386/segment.h>
#include <internal/mmhal.h> #include <internal/mmhal.h>
@ -22,6 +25,12 @@
#include <ddk/defines.h> #include <ddk/defines.h>
#include <internal/ps.h> #include <internal/ps.h>
/* GLOBALS *******************************************************************/
VOID PsTerminateCurrentThread(NTSTATUS ExitStatus);
/* FUNCTIONS *****************************************************************/
VOID KiSystemCallHook(ULONG Nr, ...) VOID KiSystemCallHook(ULONG Nr, ...)
{ {
#if 0 #if 0
@ -44,15 +53,33 @@ VOID KiSystemCallHook(ULONG Nr, ...)
ULONG KiAfterSystemCallHook(ULONG NtStatus, PKTRAP_FRAME TrapFrame) ULONG KiAfterSystemCallHook(ULONG NtStatus, PKTRAP_FRAME TrapFrame)
{ {
assert(KeGetCurrentIrql() == PASSIVE_LEVEL); KIRQL oldIrql;
if (KeGetCurrentThread()->ApcState.UserApcPending == 0 || PETHREAD EThread;
TrapFrame->Cs == KERNEL_CS) extern KSPIN_LOCK PiThreadListLock;
{
return(NtStatus); assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
}
KiDeliverUserApc(TrapFrame); /*
assert(KeGetCurrentIrql() == PASSIVE_LEVEL); * Check if the current thread is terminating
return(NtStatus); */
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 // 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_top;
extern unsigned int init_stack; 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, KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
InternalThreadType, InternalThreadType,
sizeof(ETHREAD), sizeof(ETHREAD),

View file

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

View file

@ -157,7 +157,6 @@ PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus)
*/ */
Thread->DeadThread = 1; Thread->DeadThread = 1;
Thread->ExitStatus = ExitStatus; Thread->ExitStatus = ExitStatus;
Thread->Tcb.ApcState.UserApcPending++;
if (Thread->Tcb.State == THREAD_STATE_FROZEN && if (Thread->Tcb.State == THREAD_STATE_FROZEN &&
(Thread->Tcb.Alertable || Thread->Tcb.WaitMode == UserMode)) (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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -66,7 +66,7 @@ HANDLE STDCALL PsGetCurrentThreadId(VOID)
return(PsGetCurrentThread()->Cid.UniqueThread); 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, // DPRINT("PsInsertIntoThreadList(Priority %x, Thread %x)\n",Priority,
// Thread); // Thread);
@ -151,7 +151,7 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
CurrentThread->Tcb.State = NewThreadStatus; CurrentThread->Tcb.State = NewThreadStatus;
if (CurrentThread->Tcb.State == THREAD_STATE_RUNNABLE) if (CurrentThread->Tcb.State == THREAD_STATE_RUNNABLE)
{ {
PiNrRunnableThreads--; PiNrRunnableThreads++;
PsInsertIntoThreadList(CurrentThread->Tcb.Priority, PsInsertIntoThreadList(CurrentThread->Tcb.Priority,
CurrentThread); CurrentThread);
} }
@ -178,7 +178,6 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
CurrentThread = Candidate; CurrentThread = Candidate;
KeReleaseSpinLockFromDpcLevel(&PiThreadListLock); KeReleaseSpinLockFromDpcLevel(&PiThreadListLock);
// HalTaskSwitch(&CurrentThread->Tcb);
Ki386ContextSwitch(&CurrentThread->Tcb, &OldThread->Tcb); Ki386ContextSwitch(&CurrentThread->Tcb, &OldThread->Tcb);
PsReapThreads(); PsReapThreads();
return; return;
@ -199,211 +198,54 @@ VOID PsDispatchThread(ULONG NewThreadStatus)
KeAcquireSpinLock(&PiThreadListLock, &oldIrql); KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
/* /*
* Save wait IrqL * Save wait IRQL
*/ */
CurrentThread->Tcb.WaitIrql = oldIrql; CurrentThread->Tcb.WaitIrql = oldIrql;
PsDispatchThreadNoLock(NewThreadStatus); PsDispatchThreadNoLock(NewThreadStatus);
KeLowerIrql(oldIrql); 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 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 VOID
PiSuspendThreadKernelRoutine(PKAPC Apc, PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode,
PKNORMAL_ROUTINE* NormalRoutine, BOOLEAN DispatcherLock, KIRQL WaitIrql)
PVOID* NormalContext,
PVOID* SystemArgument1,
PVOID* SystemArguemnt2)
{ {
InterlockedIncrement(&PsGetCurrentThread()->Tcb.SuspendThread); KIRQL oldIrql;
KeWaitForSingleObject((PVOID)&PsGetCurrentThread()->SuspendSemaphore, PETHREAD Thread = PsGetCurrentThread();
0,
UserMode, KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
TRUE,
NULL); if (DispatcherLock)
ExFreePool(Apc); {
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 VOID
PsInitThreadManagment(VOID) PsInitThreadManagment(VOID)
/* /*
@ -510,6 +352,7 @@ NTSTATUS STDCALL NtAlertResumeThread(IN HANDLE ThreadHandle,
NTSTATUS STDCALL NtAlertThread (IN HANDLE ThreadHandle) NTSTATUS STDCALL NtAlertThread (IN HANDLE ThreadHandle)
{ {
#if 0
PETHREAD Thread; PETHREAD Thread;
NTSTATUS Status; NTSTATUS Status;
NTSTATUS ThreadStatus; NTSTATUS ThreadStatus;
@ -526,10 +369,12 @@ NTSTATUS STDCALL NtAlertThread (IN HANDLE ThreadHandle)
} }
ThreadStatus = STATUS_ALERTED; ThreadStatus = STATUS_ALERTED;
(VOID)PsUnfreezeThread(Thread, &ThreadStatus); (VOID)PsUnblockThread(Thread, &ThreadStatus);
ObDereferenceObject(Thread); ObDereferenceObject(Thread);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
#endif
UNIMPLEMENTED;
} }
NTSTATUS STDCALL NTSTATUS STDCALL