mirror of
https://github.com/reactos/reactos.git
synced 2025-06-13 07:28:32 +00:00
Kernel:
- apc.c: Fixed some bugs and used Dispatcher Lock. Simplified some functions and renamed/inlined others. - wait.c: Fixed some assumptions about Dispatcher Lock and Waiting/Alertability - process.c: Fully implemented KeStackAttachProcess and KeStackDetachProcess. Made all functions use PKPROCESS and not PEPROCESS. Memory Manager: Fixed calls to KeAttachProcess/DetachProcess to typecast PKPROCESS Process Manager: Removed call to empty function in apc.c svn path=/trunk/; revision=11622
This commit is contained in:
parent
0cc7d4d22d
commit
a9c33470e5
11 changed files with 327 additions and 300 deletions
|
@ -20,13 +20,14 @@ KeSaveFloatingPointState(
|
||||||
#define KeFlushIoBuffers(Mdl, ReadOperation, DmaOperation)
|
#define KeFlushIoBuffers(Mdl, ReadOperation, DmaOperation)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VOID STDCALL KeAttachProcess (struct _EPROCESS* Process);
|
VOID STDCALL KeAttachProcess(struct _KPROCESS *Process);
|
||||||
|
|
||||||
VOID FASTCALL KiAcquireSpinLock(PKSPIN_LOCK SpinLock);
|
VOID FASTCALL KiAcquireSpinLock(PKSPIN_LOCK SpinLock);
|
||||||
|
|
||||||
VOID FASTCALL KiReleaseSpinLock(PKSPIN_LOCK SpinLock);
|
VOID FASTCALL KiReleaseSpinLock(PKSPIN_LOCK SpinLock);
|
||||||
|
|
||||||
VOID KeDrainApcQueue(VOID);
|
VOID KeDrainApcQueue(VOID);
|
||||||
|
|
||||||
struct _KPROCESS* KeGetCurrentProcess(VOID);
|
struct _KPROCESS* KeGetCurrentProcess(VOID);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -122,6 +122,24 @@ typedef struct _KAPC
|
||||||
|
|
||||||
#include <poppack.h>
|
#include <poppack.h>
|
||||||
|
|
||||||
|
#ifndef __USE_W32API
|
||||||
|
|
||||||
|
#include <pshpack1.h>
|
||||||
|
|
||||||
|
typedef struct _KAPC_STATE
|
||||||
|
{
|
||||||
|
LIST_ENTRY ApcListHead[2];
|
||||||
|
struct _KPROCESS* Process;
|
||||||
|
UCHAR KernelApcInProgress;
|
||||||
|
UCHAR KernelApcPending;
|
||||||
|
UCHAR UserApcPending;
|
||||||
|
UCHAR Reserved;
|
||||||
|
} KAPC_STATE, *PKAPC_STATE, *__restrict PRKAPC_STATE;
|
||||||
|
|
||||||
|
#include <poppack.h>
|
||||||
|
|
||||||
|
#endif /* __USE_W32API */
|
||||||
|
|
||||||
typedef struct _KBUGCHECK_CALLBACK_RECORD
|
typedef struct _KBUGCHECK_CALLBACK_RECORD
|
||||||
{
|
{
|
||||||
LIST_ENTRY Entry;
|
LIST_ENTRY Entry;
|
||||||
|
|
|
@ -96,6 +96,10 @@ VOID KiInitializeUserApc(IN PVOID Reserved,
|
||||||
IN PVOID SystemArgument1,
|
IN PVOID SystemArgument1,
|
||||||
IN PVOID SystemArgument2);
|
IN PVOID SystemArgument2);
|
||||||
|
|
||||||
|
VOID STDCALL KiAttachProcess(struct _KTHREAD *Thread, struct _KPROCESS *Process, KIRQL ApcLock, struct _KAPC_STATE *SavedApcState);
|
||||||
|
|
||||||
|
VOID STDCALL KiSwapProcess(struct _KPROCESS *NewProcess, struct _KPROCESS *OldProcess);
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
STDCALL
|
STDCALL
|
||||||
KeTestAlertThread(IN KPROCESSOR_MODE AlertMode);
|
KeTestAlertThread(IN KPROCESSOR_MODE AlertMode);
|
||||||
|
@ -122,10 +126,10 @@ VOID KeInit2(VOID);
|
||||||
|
|
||||||
BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame);
|
BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame);
|
||||||
|
|
||||||
VOID FASTCALL
|
VOID
|
||||||
KiSwapApcEnvironment(
|
STDCALL
|
||||||
struct _KTHREAD* Thread,
|
KiMoveApcState (PKAPC_STATE OldState,
|
||||||
struct _KPROCESS* NewProcess);
|
PKAPC_STATE NewState);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Pc);
|
KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Pc);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: ps.h,v 1.73 2004/11/10 02:50:59 ion Exp $
|
/* $Id: ps.h,v 1.74 2004/11/11 22:23:52 ion Exp $
|
||||||
*
|
*
|
||||||
* FILE: ntoskrnl/ke/kthread.c
|
* FILE: ntoskrnl/ke/kthread.c
|
||||||
* PURPOSE: Process manager definitions
|
* PURPOSE: Process manager definitions
|
||||||
|
@ -53,24 +53,6 @@ extern HANDLE SystemProcessHandle;
|
||||||
extern LCID PsDefaultThreadLocaleId;
|
extern LCID PsDefaultThreadLocaleId;
|
||||||
extern LCID PsDefaultSystemLocaleId;
|
extern LCID PsDefaultSystemLocaleId;
|
||||||
|
|
||||||
#ifndef __USE_W32API
|
|
||||||
|
|
||||||
#include <pshpack1.h>
|
|
||||||
|
|
||||||
typedef struct _KAPC_STATE
|
|
||||||
{
|
|
||||||
LIST_ENTRY ApcListHead[2];
|
|
||||||
struct _KPROCESS* Process;
|
|
||||||
UCHAR KernelApcInProgress;
|
|
||||||
UCHAR KernelApcPending;
|
|
||||||
UCHAR UserApcPending;
|
|
||||||
UCHAR Reserved;
|
|
||||||
} KAPC_STATE, *PKAPC_STATE, *__restrict PRKAPC_STATE;
|
|
||||||
|
|
||||||
#include <poppack.h>
|
|
||||||
|
|
||||||
#endif /* __USE_W32API */
|
|
||||||
|
|
||||||
#include <pshpack1.h>
|
#include <pshpack1.h>
|
||||||
|
|
||||||
typedef struct _KTHREAD
|
typedef struct _KTHREAD
|
||||||
|
|
|
@ -123,12 +123,12 @@ KeInsertQueueApc (PKAPC Apc,
|
||||||
PLIST_ENTRY ApcListEntry;
|
PLIST_ENTRY ApcListEntry;
|
||||||
PKAPC QueuedApc;
|
PKAPC QueuedApc;
|
||||||
|
|
||||||
|
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
||||||
DPRINT ("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
|
DPRINT ("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
|
||||||
"SystemArgument2 %x)\n",Apc,SystemArgument1,
|
"SystemArgument2 %x)\n",Apc,SystemArgument1,
|
||||||
SystemArgument2);
|
SystemArgument2);
|
||||||
|
|
||||||
/* FIXME: Implement Dispatcher Lock */
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
||||||
|
|
||||||
/* Get the Thread specified in the APC */
|
/* Get the Thread specified in the APC */
|
||||||
Thread = Apc->Thread;
|
Thread = Apc->Thread;
|
||||||
|
@ -136,7 +136,7 @@ KeInsertQueueApc (PKAPC Apc,
|
||||||
/* Make sure the thread allows APC Queues */
|
/* Make sure the thread allows APC Queues */
|
||||||
if (Thread->ApcQueueable == FALSE) {
|
if (Thread->ApcQueueable == FALSE) {
|
||||||
DPRINT("Thread doesn't allow APC Queues\n");
|
DPRINT("Thread doesn't allow APC Queues\n");
|
||||||
KeLowerIrql(OldIrql);
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ KeInsertQueueApc (PKAPC Apc,
|
||||||
|
|
||||||
/* Don't do anything if the APC is already inserted */
|
/* Don't do anything if the APC is already inserted */
|
||||||
if (Apc->Inserted) {
|
if (Apc->Inserted) {
|
||||||
KeLowerIrql(OldIrql);
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@ KeInsertQueueApc (PKAPC Apc,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return Sucess if we are here */
|
/* Return Sucess if we are here */
|
||||||
KeLowerIrql(OldIrql);
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,10 +226,10 @@ KeRemoveQueueApc (PKAPC Apc)
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PKTHREAD Thread = Apc->Thread;
|
PKTHREAD Thread = Apc->Thread;
|
||||||
|
|
||||||
|
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
||||||
DPRINT("KeRemoveQueueApc called for APC: %x \n", Apc);
|
DPRINT("KeRemoveQueueApc called for APC: %x \n", Apc);
|
||||||
|
|
||||||
/* FIXME: Implement Dispatcher Lock */
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
||||||
KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
|
KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
|
||||||
|
|
||||||
/* Remove it from the Queue if it's inserted */
|
/* Remove it from the Queue if it's inserted */
|
||||||
|
@ -247,13 +247,13 @@ KeRemoveQueueApc (PKAPC Apc)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
||||||
KeLowerIrql(OldIrql);
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore IRQL and Return */
|
/* Restore IRQL and Return */
|
||||||
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
||||||
KeLowerIrql(OldIrql);
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,9 +269,10 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
|
||||||
PKTHREAD Thread = KeGetCurrentThread();
|
PKTHREAD Thread = KeGetCurrentThread();
|
||||||
BOOLEAN OldState;
|
BOOLEAN OldState;
|
||||||
|
|
||||||
/* FIXME: Implement Dispatcher Lock */
|
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
||||||
OldIrql = KeRaiseIrqlToDpcLevel();
|
|
||||||
KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
|
KiAcquireSpinLock(&Thread->ApcQueueLock);
|
||||||
|
|
||||||
OldState = Thread->Alerted[(int)AlertMode];
|
OldState = Thread->Alerted[(int)AlertMode];
|
||||||
|
|
||||||
|
@ -283,9 +284,8 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
|
||||||
Thread->ApcState.UserApcPending = TRUE;
|
Thread->ApcState.UserApcPending = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Implement Dispatcher Lock */
|
KiReleaseSpinLock(&Thread->ApcQueueLock);
|
||||||
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
KeLowerIrql(OldIrql);
|
|
||||||
return OldState;
|
return OldState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,12 +444,25 @@ KiDeliverApc(KPROCESSOR_MODE PreviousMode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID KiInitializeUserApc(IN PVOID Reserved,
|
VOID
|
||||||
IN PKTRAP_FRAME TrapFrame,
|
STDCALL
|
||||||
IN PKNORMAL_ROUTINE NormalRoutine,
|
KiFreeApcRoutine(PKAPC Apc,
|
||||||
IN PVOID NormalContext,
|
PKNORMAL_ROUTINE* NormalRoutine,
|
||||||
IN PVOID SystemArgument1,
|
PVOID* NormalContext,
|
||||||
IN PVOID SystemArgument2)
|
PVOID* SystemArgument1,
|
||||||
|
PVOID* SystemArgument2)
|
||||||
|
{
|
||||||
|
/* Free the APC and do nothing else */
|
||||||
|
ExFreePool(Apc);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
KiInitializeUserApc(IN PVOID Reserved,
|
||||||
|
IN PKTRAP_FRAME TrapFrame,
|
||||||
|
IN PKNORMAL_ROUTINE NormalRoutine,
|
||||||
|
IN PVOID NormalContext,
|
||||||
|
IN PVOID SystemArgument1,
|
||||||
|
IN PVOID SystemArgument2)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Prepares the Context for a user mode APC through ntdll.dll
|
* FUNCTION: Prepares the Context for a user mode APC through ntdll.dll
|
||||||
*/
|
*/
|
||||||
|
@ -508,77 +521,87 @@ KeAreApcsDisabled(
|
||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return KeGetCurrentThread()->KernelApcDisable ? FALSE : TRUE;
|
return KeGetCurrentThread()->KernelApcDisable ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID STDCALL
|
NTSTATUS
|
||||||
NtQueueApcRundownRoutine(PKAPC Apc)
|
STDCALL
|
||||||
{
|
|
||||||
ExFreePool(Apc);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID STDCALL
|
|
||||||
NtQueueApcKernelRoutine(PKAPC Apc,
|
|
||||||
PKNORMAL_ROUTINE* NormalRoutine,
|
|
||||||
PVOID* NormalContext,
|
|
||||||
PVOID* SystemArgument1,
|
|
||||||
PVOID* SystemArgument2)
|
|
||||||
{
|
|
||||||
ExFreePool(Apc);
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
|
||||||
NtQueueApcThread(HANDLE ThreadHandle,
|
NtQueueApcThread(HANDLE ThreadHandle,
|
||||||
PKNORMAL_ROUTINE ApcRoutine,
|
PKNORMAL_ROUTINE ApcRoutine,
|
||||||
PVOID NormalContext,
|
PVOID NormalContext,
|
||||||
PVOID SystemArgument1,
|
PVOID SystemArgument1,
|
||||||
PVOID SystemArgument2)
|
PVOID SystemArgument2)
|
||||||
|
/*
|
||||||
|
* FUNCTION:
|
||||||
|
* This function is used to queue an APC from user-mode for the specified thread.
|
||||||
|
* The thread must enter an alertable wait before the APC will be delivered.
|
||||||
|
*
|
||||||
|
* ARGUMENTS:
|
||||||
|
* Thread Handle - Handle to the Thread. This handle must have THREAD_SET_CONTEXT privileges.
|
||||||
|
* ApcRoutine - Pointer to the APC Routine to call when the APC executes.
|
||||||
|
* NormalContext - User-defined value to pass to the APC Routine
|
||||||
|
* SystemArgument1 - User-defined value to pass to the APC Routine
|
||||||
|
* SystemArgument2 - User-defined value to pass to the APC Routine
|
||||||
|
*
|
||||||
|
* RETURNS: NTSTATUS SUCCESS or Failure Code from included calls.
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
PKAPC Apc;
|
|
||||||
PETHREAD Thread;
|
|
||||||
NTSTATUS Status;
|
|
||||||
PVOID ThreadVar;
|
|
||||||
|
|
||||||
ThreadVar = &Thread;
|
PKAPC Apc;
|
||||||
|
PETHREAD Thread;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* Get ETHREAD from Handle */
|
||||||
|
Status = ObReferenceObjectByHandle(ThreadHandle,
|
||||||
|
THREAD_SET_CONTEXT,
|
||||||
|
PsThreadType,
|
||||||
|
KeGetPreviousMode(),
|
||||||
|
(PVOID)&Thread,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Fail if the Handle is invalid for some reason */
|
||||||
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is a Kernel or System Thread, then fail */
|
||||||
|
if (Thread->Tcb.Teb == NULL) {
|
||||||
|
ObDereferenceObject(Thread);
|
||||||
|
return STATUS_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(ThreadHandle,
|
/* Allocate an APC */
|
||||||
THREAD_ALL_ACCESS, /* FIXME */
|
Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_KAPC);
|
||||||
PsThreadType,
|
if (Apc == NULL) {
|
||||||
UserMode,
|
ObDereferenceObject(Thread);
|
||||||
&ThreadVar,
|
return(STATUS_NO_MEMORY);
|
||||||
NULL);
|
}
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_KAPC);
|
/* Initialize and Queue */
|
||||||
if (Apc == NULL)
|
KeInitializeApc(Apc,
|
||||||
{
|
&Thread->Tcb,
|
||||||
|
OriginalApcEnvironment,
|
||||||
|
KiFreeApcRoutine,
|
||||||
|
NULL,
|
||||||
|
ApcRoutine,
|
||||||
|
UserMode,
|
||||||
|
NormalContext);
|
||||||
|
if (!KeInsertQueueApc(Apc, SystemArgument1, SystemArgument2, IO_NO_INCREMENT)) {
|
||||||
|
Status = STATUS_UNSUCCESSFUL;
|
||||||
|
} else {
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dereference Thread and Return */
|
||||||
ObDereferenceObject(Thread);
|
ObDereferenceObject(Thread);
|
||||||
return(STATUS_NO_MEMORY);
|
return Status;
|
||||||
}
|
|
||||||
|
|
||||||
KeInitializeApc(Apc,
|
|
||||||
&Thread->Tcb,
|
|
||||||
OriginalApcEnvironment,
|
|
||||||
NtQueueApcKernelRoutine,
|
|
||||||
NtQueueApcRundownRoutine,
|
|
||||||
ApcRoutine,
|
|
||||||
UserMode,
|
|
||||||
NormalContext);
|
|
||||||
KeInsertQueueApc(Apc,
|
|
||||||
SystemArgument1,
|
|
||||||
SystemArgument2,
|
|
||||||
IO_NO_INCREMENT);
|
|
||||||
|
|
||||||
ObDereferenceObject(Thread);
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS STDCALL NtTestAlert(VOID)
|
STDCALL
|
||||||
|
NtTestAlert(VOID)
|
||||||
{
|
{
|
||||||
|
/* Check and Alert Thread if needed */
|
||||||
if (KeTestAlertThread(KeGetPreviousMode())) {
|
if (KeTestAlertThread(KeGetPreviousMode())) {
|
||||||
return STATUS_ALERTED;
|
return STATUS_ALERTED;
|
||||||
} else {
|
} else {
|
||||||
|
@ -586,103 +609,31 @@ NTSTATUS STDCALL NtTestAlert(VOID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID INIT_FUNCTION
|
static inline VOID RepairList(PLIST_ENTRY Original,
|
||||||
PiInitApcManagement(VOID)
|
PLIST_ENTRY Copy,
|
||||||
|
KPROCESSOR_MODE Mode)
|
||||||
{
|
{
|
||||||
|
/* Copy Source to Desination */
|
||||||
|
if (IsListEmpty(&Original[(int)Mode])) {
|
||||||
|
InitializeListHead(&Copy[(int)Mode]);
|
||||||
|
} else {
|
||||||
|
Copy[(int)Mode].Flink = Original[(int)Mode].Flink;
|
||||||
|
Copy[(int)Mode].Blink = Original[(int)Mode].Blink;
|
||||||
|
Original[(int)Mode].Flink->Blink = &Copy[(int)Mode];
|
||||||
|
Original[(int)Mode].Blink->Flink = &Copy[(int)Mode];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID FASTCALL
|
VOID
|
||||||
RepairList(PLIST_ENTRY Original, PLIST_ENTRY Copy, int Mode)
|
STDCALL
|
||||||
|
KiMoveApcState (PKAPC_STATE OldState,
|
||||||
|
PKAPC_STATE NewState)
|
||||||
{
|
{
|
||||||
if (IsListEmpty(&Original[Mode]))
|
/* Restore backup of Original Environment */
|
||||||
{
|
*NewState = *OldState;
|
||||||
InitializeListHead(&Copy[Mode]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Copy[Mode].Flink->Blink = &Copy[Mode];
|
|
||||||
Copy[Mode].Blink->Flink = &Copy[Mode];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VOID FASTCALL
|
|
||||||
KiSwapApcEnvironment(
|
|
||||||
PKTHREAD Thread,
|
|
||||||
PKPROCESS NewProcess)
|
|
||||||
{
|
|
||||||
if (Thread->ApcStateIndex == AttachedApcEnvironment)
|
|
||||||
{
|
|
||||||
/* NewProcess must be the same as in the original-environment */
|
|
||||||
ASSERT(NewProcess == Thread->ApcStatePointer[OriginalApcEnvironment]->Process);
|
|
||||||
|
|
||||||
/*
|
|
||||||
FIXME: Deliver any pending apc's queued to the attached environment before
|
|
||||||
switching back to the original environment.
|
|
||||||
This is not crucial thou, since i don't think we'll ever target apc's
|
|
||||||
to attached environments (or?)...
|
|
||||||
Remove the following asserts if implementing this.
|
|
||||||
-Gunnar
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* we don't support targeting apc's at attached-environments (yet)... */
|
|
||||||
ASSERT(IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode]));
|
|
||||||
ASSERT(IsListEmpty(&Thread->ApcState.ApcListHead[UserMode]));
|
|
||||||
ASSERT(Thread->ApcState.KernelApcInProgress == FALSE);
|
|
||||||
ASSERT(Thread->ApcState.KernelApcPending == FALSE);
|
|
||||||
ASSERT(Thread->ApcState.UserApcPending == FALSE);
|
|
||||||
|
|
||||||
/* restore backup of original environment */
|
/* Repair Lists */
|
||||||
Thread->ApcState = Thread->SavedApcState;
|
RepairList(NewState->ApcListHead, OldState->ApcListHead, KernelMode);
|
||||||
/* repair lists */
|
RepairList(NewState->ApcListHead, OldState->ApcListHead, UserMode);
|
||||||
RepairList(Thread->SavedApcState.ApcListHead, Thread->ApcState.ApcListHead,
|
|
||||||
KernelMode);
|
|
||||||
RepairList(Thread->SavedApcState.ApcListHead, Thread->ApcState.ApcListHead,
|
|
||||||
UserMode);
|
|
||||||
|
|
||||||
/* update environment pointers */
|
|
||||||
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
|
|
||||||
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
|
|
||||||
|
|
||||||
/* update current-environment index */
|
|
||||||
Thread->ApcStateIndex = OriginalApcEnvironment;
|
|
||||||
}
|
|
||||||
else if (Thread->ApcStateIndex == OriginalApcEnvironment)
|
|
||||||
{
|
|
||||||
/* backup original environment */
|
|
||||||
Thread->SavedApcState = Thread->ApcState;
|
|
||||||
/* repair lists */
|
|
||||||
RepairList(Thread->ApcState.ApcListHead, Thread->SavedApcState.ApcListHead,
|
|
||||||
KernelMode);
|
|
||||||
RepairList(Thread->ApcState.ApcListHead, Thread->SavedApcState.ApcListHead,
|
|
||||||
UserMode);
|
|
||||||
|
|
||||||
/*
|
|
||||||
FIXME: Is it possible to target an apc to an attached environment even if the
|
|
||||||
thread is not currently attached???? If so, then this is bougus since it
|
|
||||||
reinitializes the attached apc environment then located in SavedApcState.
|
|
||||||
-Gunnar
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* setup a fresh new attached environment */
|
|
||||||
InitializeListHead(&Thread->ApcState.ApcListHead[KernelMode]);
|
|
||||||
InitializeListHead(&Thread->ApcState.ApcListHead[UserMode]);
|
|
||||||
Thread->ApcState.Process = NewProcess;
|
|
||||||
Thread->ApcState.KernelApcInProgress = FALSE;
|
|
||||||
Thread->ApcState.KernelApcPending = FALSE;
|
|
||||||
Thread->ApcState.UserApcPending = FALSE;
|
|
||||||
|
|
||||||
/* update environment pointers */
|
|
||||||
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->SavedApcState;
|
|
||||||
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->ApcState;
|
|
||||||
|
|
||||||
/* update current-environment index */
|
|
||||||
Thread->ApcStateIndex = AttachedApcEnvironment;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* FIXME: Is this the correct bug code? */
|
|
||||||
KEBUGCHECK(APC_INDEX_MISMATCH);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: process.c,v 1.30 2004/10/17 03:43:26 ion Exp $
|
/* $Id: process.c,v 1.31 2004/11/11 22:23:52 ion Exp $
|
||||||
*
|
*
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ke/process.c
|
* FILE: ntoskrnl/ke/process.c
|
||||||
|
@ -38,79 +38,95 @@
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
VOID STDCALL
|
VOID
|
||||||
KeAttachProcess (PEPROCESS Process)
|
STDCALL
|
||||||
|
KeAttachProcess(PKPROCESS Process)
|
||||||
{
|
{
|
||||||
KIRQL oldlvl;
|
KIRQL OldIrql;
|
||||||
PETHREAD CurrentThread;
|
PKTHREAD Thread = KeGetCurrentThread();
|
||||||
ULONG PageDir;
|
|
||||||
|
DPRINT("KeAttachProcess: %x\n", Process);
|
||||||
DPRINT("KeAttachProcess(Process %x)\n",Process);
|
|
||||||
|
/* Lock Dispatcher */
|
||||||
CurrentThread = PsGetCurrentThread();
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
|
|
||||||
if (&CurrentThread->ThreadsProcess->Pcb != CurrentThread->Tcb.ApcState.Process)
|
/* Crash system if DPC is being executed! */
|
||||||
{
|
if (KeIsExecutingDpc()) {
|
||||||
DPRINT1("Invalid attach (thread is already attached)\n");
|
DPRINT1("Invalid attach (Thread is executing a DPC!)\n");
|
||||||
KEBUGCHECK(INVALID_PROCESS_ATTACH_ATTEMPT);
|
KEBUGCHECK(INVALID_PROCESS_ATTACH_ATTEMPT);
|
||||||
}
|
}
|
||||||
if (&Process->Pcb == CurrentThread->Tcb.ApcState.Process)
|
|
||||||
{
|
/* Check if the Target Process is already attached */
|
||||||
DPRINT1("Invalid attach (process is the same)\n");
|
if (Thread->ApcState.Process == Process || Thread->ApcStateIndex != OriginalApcEnvironment) {
|
||||||
KEBUGCHECK(INVALID_PROCESS_ATTACH_ATTEMPT);
|
DPRINT("Process already Attached. Exitting\n");
|
||||||
}
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
|
} else {
|
||||||
|
KiAttachProcess(Thread, Process, OldIrql, &Thread->SavedApcState);
|
||||||
/* The stack and the thread structure of the current process may be
|
}
|
||||||
located in a page which is not present in the page directory of
|
|
||||||
the process we're attaching to. That would lead to a page fault
|
|
||||||
when this function returns. However, since the processor can't
|
|
||||||
call the page fault handler 'cause it can't push EIP on the stack,
|
|
||||||
this will show up as a stack fault which will crash the entire system.
|
|
||||||
To prevent this, make sure the page directory of the process we're
|
|
||||||
attaching to is up-to-date. */
|
|
||||||
|
|
||||||
MmUpdatePageDir(Process, (PVOID)CurrentThread->Tcb.StackLimit, MM_STACK_SIZE);
|
|
||||||
MmUpdatePageDir(Process, (PVOID)CurrentThread, sizeof(ETHREAD));
|
|
||||||
|
|
||||||
KeRaiseIrql(DISPATCH_LEVEL, &oldlvl);
|
|
||||||
|
|
||||||
KiSwapApcEnvironment(&CurrentThread->Tcb, &Process->Pcb);
|
|
||||||
|
|
||||||
CurrentThread->Tcb.ApcState.Process = &Process->Pcb;
|
|
||||||
PageDir = Process->Pcb.DirectoryTableBase.u.LowPart;
|
|
||||||
DPRINT("Switching process context to %x\n",PageDir);
|
|
||||||
Ke386SetPageTableDirectory(PageDir);
|
|
||||||
KeLowerIrql(oldlvl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
VOID
|
||||||
* @implemented
|
STDCALL
|
||||||
*/
|
KiAttachProcess(PKTHREAD Thread, PKPROCESS Process, KIRQL ApcLock, PRKAPC_STATE SavedApcState)
|
||||||
VOID STDCALL
|
|
||||||
KeDetachProcess (VOID)
|
|
||||||
{
|
{
|
||||||
KIRQL oldlvl;
|
|
||||||
PETHREAD CurrentThread;
|
DPRINT("KiAttachProcess(Thread: %x, Process: %x, SavedApcState: %x\n", Thread, Process, SavedApcState);
|
||||||
ULONG PageDir;
|
|
||||||
|
|
||||||
DPRINT("KeDetachProcess()\n");
|
/* The stack and the thread structure of the current process may be
|
||||||
|
located in a page which is not present in the page directory of
|
||||||
CurrentThread = PsGetCurrentThread();
|
the process we're attaching to. That would lead to a page fault
|
||||||
|
when this function returns. However, since the processor can't
|
||||||
|
call the page fault handler 'cause it can't push EIP on the stack,
|
||||||
|
this will show up as a stack fault which will crash the entire system.
|
||||||
|
To prevent this, make sure the page directory of the process we're
|
||||||
|
attaching to is up-to-date. */
|
||||||
|
MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread->StackLimit, MM_STACK_SIZE);
|
||||||
|
MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
|
||||||
|
|
||||||
|
/* Increase Stack Count */
|
||||||
|
Process->StackCount++;
|
||||||
|
|
||||||
|
/* Swap the APC Environment */
|
||||||
|
KiMoveApcState(&Thread->ApcState, SavedApcState);
|
||||||
|
|
||||||
|
/* Reinitialize Apc State */
|
||||||
|
InitializeListHead(&Thread->ApcState.ApcListHead[KernelMode]);
|
||||||
|
InitializeListHead(&Thread->ApcState.ApcListHead[UserMode]);
|
||||||
|
Thread->ApcState.Process = Process;
|
||||||
|
Thread->ApcState.KernelApcInProgress = FALSE;
|
||||||
|
Thread->ApcState.KernelApcPending = FALSE;
|
||||||
|
Thread->ApcState.UserApcPending = FALSE;
|
||||||
|
|
||||||
|
/* Update Environment Pointers if needed*/
|
||||||
|
if (SavedApcState == &Thread->SavedApcState) {
|
||||||
|
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->SavedApcState;
|
||||||
|
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->ApcState;
|
||||||
|
Thread->ApcStateIndex = AttachedApcEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Swap the Processes */
|
||||||
|
KiSwapProcess(Process, SavedApcState->Process);
|
||||||
|
|
||||||
|
/* Return to old IRQL*/
|
||||||
|
KeReleaseDispatcherDatabaseLock(ApcLock);
|
||||||
|
|
||||||
|
DPRINT("KiAttachProcess Completed Sucesfully\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (&CurrentThread->ThreadsProcess->Pcb == CurrentThread->Tcb.ApcState.Process)
|
VOID
|
||||||
{
|
STDCALL
|
||||||
DPRINT1("Invalid detach (thread was not attached)\n");
|
KiSwapProcess(PKPROCESS NewProcess, PKPROCESS OldProcess)
|
||||||
KEBUGCHECK(INVALID_PROCESS_DETACH_ATTEMPT);
|
{
|
||||||
}
|
//PKPCR Pcr = KeGetCurrentKpcr();
|
||||||
|
|
||||||
KeRaiseIrql(DISPATCH_LEVEL, &oldlvl);
|
|
||||||
|
|
||||||
KiSwapApcEnvironment(&CurrentThread->Tcb, CurrentThread->Tcb.SavedApcState.Process);
|
/* Do they have an LDT? */
|
||||||
PageDir = CurrentThread->Tcb.ApcState.Process->DirectoryTableBase.u.LowPart;
|
if ((NewProcess->LdtDescriptor) || (OldProcess->LdtDescriptor)) {
|
||||||
Ke386SetPageTableDirectory(PageDir);
|
/* FIXME : SWitch GDT/IDT */
|
||||||
|
}
|
||||||
KeLowerIrql(oldlvl);
|
DPRINT("Switching CR3 to: %x\n", NewProcess->DirectoryTableBase.u.LowPart);
|
||||||
|
Ke386SetPageTableDirectory(NewProcess->DirectoryTableBase.u.LowPart);
|
||||||
|
|
||||||
|
/* FIXME: Set IopmOffset in TSS */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -136,10 +152,9 @@ KeStackAttachProcess (
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PKTHREAD Thread;
|
PKTHREAD Thread = KeGetCurrentThread();
|
||||||
|
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
Thread = KeGetCurrentThread();
|
|
||||||
|
|
||||||
/* Crash system if DPC is being executed! */
|
/* Crash system if DPC is being executed! */
|
||||||
if (KeIsExecutingDpc()) {
|
if (KeIsExecutingDpc()) {
|
||||||
|
@ -151,16 +166,53 @@ KeStackAttachProcess (
|
||||||
if (Thread->ApcState.Process == Process) {
|
if (Thread->ApcState.Process == Process) {
|
||||||
ApcState->Process = (PKPROCESS)1; /* Meaning already attached to the same Process */
|
ApcState->Process = (PKPROCESS)1; /* Meaning already attached to the same Process */
|
||||||
} else {
|
} else {
|
||||||
/* Check if the Current Thread is already attached */
|
/* Check if the Current Thread is already attached and call the Internal Function*/
|
||||||
if (Thread->ApcStateIndex != 0) {
|
if (Thread->ApcStateIndex != OriginalApcEnvironment) {
|
||||||
KeAttachProcess((PEPROCESS)Process); /* FIXME: Re-write function to support stackability and fix it not to use EPROCESS */
|
KiAttachProcess(Thread, Process, OldIrql, ApcState);
|
||||||
} else {
|
} else {
|
||||||
KeAttachProcess((PEPROCESS)Process);
|
KiAttachProcess(Thread, Process, OldIrql, &Thread->SavedApcState);
|
||||||
ApcState->Process = NULL; /* FIXME: Re-write function to support stackability and fix it not to use EPROCESS */
|
ApcState->Process = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
VOID STDCALL
|
||||||
|
KeDetachProcess (VOID)
|
||||||
|
{
|
||||||
|
PKTHREAD Thread;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
DPRINT("KeDetachProcess()\n");
|
||||||
|
|
||||||
|
/* Get Current Thread and Lock */
|
||||||
|
Thread = KeGetCurrentThread();
|
||||||
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
|
|
||||||
/* Return to old IRQL*/
|
/* Check if it's attached */
|
||||||
|
DPRINT("Current ApcStateIndex: %x\n", Thread->ApcStateIndex);
|
||||||
|
|
||||||
|
if (Thread->ApcStateIndex == OriginalApcEnvironment) {
|
||||||
|
DPRINT1("Invalid detach (thread was not attached)\n");
|
||||||
|
KEBUGCHECK(INVALID_PROCESS_DETACH_ATTEMPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decrease Stack Count */
|
||||||
|
Thread->ApcState.Process->StackCount--;
|
||||||
|
|
||||||
|
/* Restore the APC State */
|
||||||
|
KiMoveApcState(&Thread->SavedApcState, &Thread->ApcState);
|
||||||
|
Thread->SavedApcState.Process = NULL;
|
||||||
|
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
|
||||||
|
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
|
||||||
|
Thread->ApcStateIndex = OriginalApcEnvironment;
|
||||||
|
|
||||||
|
/* Swap Processes */
|
||||||
|
KiSwapProcess(Thread->ApcState.Process, Thread->ApcState.Process);
|
||||||
|
|
||||||
|
/* Unlock Dispatcher */
|
||||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +227,6 @@ KeUnstackDetachProcess (
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PKTHREAD Thread;
|
PKTHREAD Thread;
|
||||||
ULONG PageDir;
|
|
||||||
|
|
||||||
/* If the special "We tried to attach to the process already being attached to" flag is there, don't do anything */
|
/* If the special "We tried to attach to the process already being attached to" flag is there, don't do anything */
|
||||||
if (ApcState->Process == (PKPROCESS)1) return;
|
if (ApcState->Process == (PKPROCESS)1) return;
|
||||||
|
@ -184,7 +235,7 @@ KeUnstackDetachProcess (
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
|
|
||||||
/* Sorry Buddy, can't help you if you've got APCs or just aren't attached */
|
/* Sorry Buddy, can't help you if you've got APCs or just aren't attached */
|
||||||
if ((Thread->ApcStateIndex == 0) || (Thread->ApcState.KernelApcInProgress)) {
|
if ((Thread->ApcStateIndex == OriginalApcEnvironment) || (Thread->ApcState.KernelApcInProgress)) {
|
||||||
DPRINT1("Invalid detach (Thread not Attached, or Kernel APC in Progress!)\n");
|
DPRINT1("Invalid detach (Thread not Attached, or Kernel APC in Progress!)\n");
|
||||||
KEBUGCHECK(INVALID_PROCESS_DETACH_ATTEMPT);
|
KEBUGCHECK(INVALID_PROCESS_DETACH_ATTEMPT);
|
||||||
}
|
}
|
||||||
|
@ -196,15 +247,16 @@ KeUnstackDetachProcess (
|
||||||
/* The ApcState parameter is useless, so use the saved data and reset it */
|
/* The ApcState parameter is useless, so use the saved data and reset it */
|
||||||
RtlMoveMemory(&Thread->SavedApcState, &Thread->ApcState, sizeof(KAPC_STATE));
|
RtlMoveMemory(&Thread->SavedApcState, &Thread->ApcState, sizeof(KAPC_STATE));
|
||||||
Thread->SavedApcState.Process = NULL;
|
Thread->SavedApcState.Process = NULL;
|
||||||
Thread->ApcStateIndex = 0;
|
Thread->ApcStateIndex = OriginalApcEnvironment;
|
||||||
Thread->ApcStatePointer[0] = &Thread->ApcState;
|
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
|
||||||
Thread->ApcStatePointer[1] = &Thread->SavedApcState;
|
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do the Actual Swap */
|
/* Restore the APC State */
|
||||||
KiSwapApcEnvironment(Thread, Thread->SavedApcState.Process);
|
KiMoveApcState(&Thread->SavedApcState, &Thread->ApcState);
|
||||||
PageDir = Thread->ApcState.Process->DirectoryTableBase.u.LowPart;
|
|
||||||
Ke386SetPageTableDirectory(PageDir);
|
/* Swap Processes */
|
||||||
|
KiSwapProcess(Thread->ApcState.Process, Thread->ApcState.Process);
|
||||||
|
|
||||||
/* Return to old IRQL*/
|
/* Return to old IRQL*/
|
||||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
|
|
|
@ -197,9 +197,6 @@ VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus, BOOL Unblock)
|
||||||
{
|
{
|
||||||
PKWAIT_BLOCK WaitBlock, PrevWaitBlock;
|
PKWAIT_BLOCK WaitBlock, PrevWaitBlock;
|
||||||
BOOLEAN WasWaiting = FALSE;
|
BOOLEAN WasWaiting = FALSE;
|
||||||
KIRQL OldIrql;
|
|
||||||
|
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock ();
|
|
||||||
|
|
||||||
WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList;
|
WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList;
|
||||||
if (WaitBlock != NULL)
|
if (WaitBlock != NULL)
|
||||||
|
@ -223,8 +220,6 @@ VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus, BOOL Unblock)
|
||||||
{
|
{
|
||||||
PsUnblockThread(Thread, &WaitStatus);
|
PsUnblockThread(Thread, &WaitStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
KeReleaseDispatcherDatabaseLock (OldIrql);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
|
@ -542,15 +537,40 @@ KeWaitForMultipleObjects(ULONG Count,
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock ();
|
OldIrql = KeAcquireDispatcherDatabaseLock ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Alertability 101
|
||||||
* If we are going to wait alertably and a user apc is pending
|
* ----------------
|
||||||
* then return
|
* A Wait can either be Alertable, or Non-Alertable.
|
||||||
|
* An Alertable Wait means that APCs can "Wake" the Thread, also called UnWaiting
|
||||||
|
* If an APC is Pending however, we must refuse an Alertable Wait. Such a wait would
|
||||||
|
* be pointless since an APC is just about to be delivered.
|
||||||
|
*
|
||||||
|
* There are many ways to check if it's safe to be alertable, and these are the ones
|
||||||
|
* that I could think of:
|
||||||
|
* - The Thread is already Alerted. So someone beat us to the punch and we bail out.
|
||||||
|
* - The Thread is Waiting in User-Mode, the APC Queue is not-empty.
|
||||||
|
* It's defintely clear that we have incoming APCs, so we need to bail out and let the system
|
||||||
|
* know that there are Pending User APCs (so they can be Delivered and maybe we can try again)
|
||||||
|
*
|
||||||
|
* Furthermore, wether or not we want to be Alertable, if the Thread is waiting in User-Mode, and there
|
||||||
|
* are Pending User APCs, we should bail out, since APCs will be delivered any second.
|
||||||
*/
|
*/
|
||||||
if (Alertable && KeTestAlertThread(KeGetPreviousMode()))
|
if (Alertable) {
|
||||||
{
|
if (CurrentThread->Alerted[(int)WaitMode]) {
|
||||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
CurrentThread->Alerted[(int)WaitMode] = FALSE;
|
||||||
return (STATUS_USER_APC);
|
DPRINT("Alertability failed\n");
|
||||||
}
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
|
return (STATUS_ALERTED);
|
||||||
|
} else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) && (WaitMode == UserMode)) {
|
||||||
|
DPRINT1("Alertability failed\n");
|
||||||
|
CurrentThread->ApcState.UserApcPending = TRUE;
|
||||||
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
|
return (STATUS_USER_APC);
|
||||||
|
}
|
||||||
|
} else if ((CurrentThread->ApcState.UserApcPending) && (WaitMode != KernelMode)) {
|
||||||
|
DPRINT1("Alertability failed\n");
|
||||||
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
|
return (STATUS_USER_APC);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the wait is (already) satisfied
|
* Check if the wait is (already) satisfied
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: page.c,v 1.75 2004/10/05 18:53:28 hbirr Exp $
|
/* $Id: page.c,v 1.76 2004/11/11 22:23:52 ion Exp $
|
||||||
*
|
*
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/mm/i386/page.c
|
* FILE: ntoskrnl/mm/i386/page.c
|
||||||
|
@ -375,7 +375,7 @@ VOID MmDeletePageTable(PEPROCESS Process, PVOID Address)
|
||||||
|
|
||||||
if (Process != NULL && Process != CurrentProcess)
|
if (Process != NULL && Process != CurrentProcess)
|
||||||
{
|
{
|
||||||
KeAttachProcess(Process);
|
KeAttachProcess(&Process->Pcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Ke386Pae)
|
if (Ke386Pae)
|
||||||
|
@ -408,7 +408,7 @@ VOID MmFreePageTable(PEPROCESS Process, PVOID Address)
|
||||||
DPRINT("ProcessId %d, Address %x\n", Process->UniqueProcessId, Address);
|
DPRINT("ProcessId %d, Address %x\n", Process->UniqueProcessId, Address);
|
||||||
if (Process != NULL && Process != CurrentProcess)
|
if (Process != NULL && Process != CurrentProcess)
|
||||||
{
|
{
|
||||||
KeAttachProcess(Process);
|
KeAttachProcess(&Process->Pcb);
|
||||||
}
|
}
|
||||||
if (Ke386Pae)
|
if (Ke386Pae)
|
||||||
{
|
{
|
||||||
|
|
|
@ -453,7 +453,7 @@ MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
|
||||||
if (AddressSpace->Process != NULL &&
|
if (AddressSpace->Process != NULL &&
|
||||||
AddressSpace->Process != CurrentProcess)
|
AddressSpace->Process != CurrentProcess)
|
||||||
{
|
{
|
||||||
KeAttachProcess(AddressSpace->Process);
|
KeAttachProcess((PKPROCESS)AddressSpace->Process);
|
||||||
}
|
}
|
||||||
EndAddress = (char*)MemoryArea->BaseAddress + PAGE_ROUND_UP(MemoryArea->Length);
|
EndAddress = (char*)MemoryArea->BaseAddress + PAGE_ROUND_UP(MemoryArea->Length);
|
||||||
for (Address = MemoryArea->BaseAddress; Address < EndAddress; Address += PAGE_SIZE)
|
for (Address = MemoryArea->BaseAddress; Address < EndAddress; Address += PAGE_SIZE)
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: virtual.c,v 1.83 2004/10/29 16:48:10 chorns Exp $
|
/* $Id: virtual.c,v 1.84 2004/11/11 22:23:52 ion Exp $
|
||||||
*
|
*
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/mm/virtual.c
|
* FILE: ntoskrnl/mm/virtual.c
|
||||||
|
@ -425,7 +425,7 @@ NtReadVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
UserMode,
|
UserMode,
|
||||||
IoWriteAccess);
|
IoWriteAccess);
|
||||||
|
|
||||||
KeAttachProcess(Process);
|
KeAttachProcess((PKPROCESS)Process);
|
||||||
|
|
||||||
SystemAddress = MmGetSystemAddressForMdl(Mdl);
|
SystemAddress = MmGetSystemAddressForMdl(Mdl);
|
||||||
memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
|
memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
|
||||||
|
@ -553,7 +553,7 @@ NtWriteVirtualMemory(IN HANDLE ProcessHandle,
|
||||||
ObDereferenceObject(Process);
|
ObDereferenceObject(Process);
|
||||||
return(STATUS_NO_MEMORY);
|
return(STATUS_NO_MEMORY);
|
||||||
}
|
}
|
||||||
KeAttachProcess(Process);
|
KeAttachProcess((PKPROCESS)Process);
|
||||||
|
|
||||||
SystemAddress = MmGetSystemAddressForMdl(Mdl);
|
SystemAddress = MmGetSystemAddressForMdl(Mdl);
|
||||||
memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
|
memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: psmgr.c,v 1.23 2004/09/28 15:02:29 weiden Exp $
|
/* $Id: psmgr.c,v 1.24 2004/11/11 22:23:52 ion Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -32,7 +32,6 @@ PiInitProcessManager(VOID)
|
||||||
PsInitProcessManagment();
|
PsInitProcessManagment();
|
||||||
PsInitThreadManagment();
|
PsInitThreadManagment();
|
||||||
PsInitIdleThread();
|
PsInitIdleThread();
|
||||||
PiInitApcManagement();
|
|
||||||
PsInitialiseSuspendImplementation();
|
PsInitialiseSuspendImplementation();
|
||||||
PsInitialiseW32Call();
|
PsInitialiseW32Call();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue