mirror of
https://github.com/reactos/reactos.git
synced 2025-04-20 20:36:35 +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 EX_MAXIMUM_WAIT_OBJECTS (64)
|
||||
|
||||
#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
|
||||
#
|
||||
|
@ -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 = \
|
||||
|
|
|
@ -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 *************************************************/
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -192,6 +180,7 @@ BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame)
|
|||
(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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
|
||||
|
||||
if (KiIsObjectSignalled(hdr, CurrentThread))
|
||||
{
|
||||
KeReleaseDispatcherDatabaseLock(FALSE);
|
||||
if (Timeout != NULL)
|
||||
{
|
||||
KeCancelTimer(&KeGetCurrentThread()->Timer);
|
||||
}
|
||||
return(STATUS_WAIT_0);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
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;
|
||||
DISPATCHER_HEADER* hdr;
|
||||
PKWAIT_BLOCK blk;
|
||||
PKTHREAD CurrentThread;
|
||||
ULONG CountSignaled;
|
||||
ULONG i;
|
||||
NTSTATUS Status;
|
||||
KIRQL WaitIrql;
|
||||
|
||||
DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
|
||||
"PsGetCurrentThread() %x\n",Count,Object,PsGetCurrentThread());
|
||||
DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
|
||||
"PsGetCurrentThread() %x\n",Count,Object,PsGetCurrentThread());
|
||||
|
||||
CountSignaled = 0;
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
CountSignaled = 0;
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
WaitIrql = KeGetCurrentIrql();
|
||||
|
||||
if (WaitBlockArray == NULL)
|
||||
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);
|
||||
do {
|
||||
KeAcquireDispatcherDatabaseLock(FALSE);
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
hdr = (DISPATCHER_HEADER *)Object[i];
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
hdr = (DISPATCHER_HEADER *)Object[i];
|
||||
|
||||
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
|
||||
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
|
||||
|
||||
if (KiIsObjectSignalled(hdr, CurrentThread))
|
||||
{
|
||||
CountSignaled++;
|
||||
if (KiIsObjectSignalled(hdr, CurrentThread))
|
||||
{
|
||||
CountSignaled++;
|
||||
|
||||
if (WaitType == WaitAny)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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;
|
||||
/* Append wait block to the KTHREAD wait block list */
|
||||
CurrentThread->WaitBlockList = blk;
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
hdr = (DISPATCHER_HEADER *)Object[i];
|
||||
for (i = 0; i < Count; 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->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->Object = Object[i];
|
||||
blk->Thread = CurrentThread;
|
||||
blk->WaitKey = i;
|
||||
blk->WaitType = WaitType;
|
||||
if (i == Count - 1)
|
||||
blk->NextWaitBlock = NULL;
|
||||
else
|
||||
blk->NextWaitBlock = blk + 1;
|
||||
|
||||
blk = blk->NextWaitBlock;
|
||||
}
|
||||
InsertTailList(&(hdr->WaitListHead),&(blk->WaitListEntry));
|
||||
|
||||
KeReleaseDispatcherDatabaseLock(FALSE);
|
||||
blk = blk->NextWaitBlock;
|
||||
}
|
||||
|
||||
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);
|
||||
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,
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
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
|
||||
* 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
|
||||
|
|
Loading…
Reference in a new issue