mirror of
https://github.com/reactos/reactos.git
synced 2025-04-21 20:50:29 +00:00
(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:
parent
e443f083f2
commit
703924d130
13 changed files with 387 additions and 412 deletions
|
@ -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 */
|
||||||
|
|
|
@ -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 = \
|
||||||
|
|
|
@ -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 *************************************************/
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
130
reactos/ntoskrnl/ps/suspend.c
Normal file
130
reactos/ntoskrnl/ps/suspend.c
Normal 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
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue