- 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:
Alex Ionescu 2004-11-11 22:23:52 +00:00
parent 0cc7d4d22d
commit a9c33470e5
11 changed files with 327 additions and 300 deletions

View file

@ -20,13 +20,14 @@ KeSaveFloatingPointState(
#define KeFlushIoBuffers(Mdl, ReadOperation, DmaOperation)
#endif
VOID STDCALL KeAttachProcess (struct _EPROCESS* Process);
VOID STDCALL KeAttachProcess(struct _KPROCESS *Process);
VOID FASTCALL KiAcquireSpinLock(PKSPIN_LOCK SpinLock);
VOID FASTCALL KiReleaseSpinLock(PKSPIN_LOCK SpinLock);
VOID KeDrainApcQueue(VOID);
struct _KPROCESS* KeGetCurrentProcess(VOID);
/*

View file

@ -122,6 +122,24 @@ typedef struct _KAPC
#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
{
LIST_ENTRY Entry;

View file

@ -96,6 +96,10 @@ VOID KiInitializeUserApc(IN PVOID Reserved,
IN PVOID SystemArgument1,
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
STDCALL
KeTestAlertThread(IN KPROCESSOR_MODE AlertMode);
@ -122,10 +126,10 @@ VOID KeInit2(VOID);
BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame);
VOID FASTCALL
KiSwapApcEnvironment(
struct _KTHREAD* Thread,
struct _KPROCESS* NewProcess);
VOID
STDCALL
KiMoveApcState (PKAPC_STATE OldState,
PKAPC_STATE NewState);
VOID
KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Pc);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* 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
* PURPOSE: Process manager definitions
@ -53,24 +53,6 @@ extern HANDLE SystemProcessHandle;
extern LCID PsDefaultThreadLocaleId;
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>
typedef struct _KTHREAD

View file

@ -123,12 +123,12 @@ KeInsertQueueApc (PKAPC Apc,
PLIST_ENTRY ApcListEntry;
PKAPC QueuedApc;
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
DPRINT ("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
"SystemArgument2 %x)\n",Apc,SystemArgument1,
SystemArgument2);
/* FIXME: Implement Dispatcher Lock */
OldIrql = KeRaiseIrqlToDpcLevel();
OldIrql = KeAcquireDispatcherDatabaseLock();
/* Get the Thread specified in the APC */
Thread = Apc->Thread;
@ -136,7 +136,7 @@ KeInsertQueueApc (PKAPC Apc,
/* Make sure the thread allows APC Queues */
if (Thread->ApcQueueable == FALSE) {
DPRINT("Thread doesn't allow APC Queues\n");
KeLowerIrql(OldIrql);
KeReleaseDispatcherDatabaseLock(OldIrql);
return FALSE;
}
@ -146,7 +146,7 @@ KeInsertQueueApc (PKAPC Apc,
/* Don't do anything if the APC is already inserted */
if (Apc->Inserted) {
KeLowerIrql(OldIrql);
KeReleaseDispatcherDatabaseLock(OldIrql);
return FALSE;
}
@ -208,7 +208,7 @@ KeInsertQueueApc (PKAPC Apc,
}
/* Return Sucess if we are here */
KeLowerIrql(OldIrql);
KeReleaseDispatcherDatabaseLock(OldIrql);
return TRUE;
}
@ -226,10 +226,10 @@ KeRemoveQueueApc (PKAPC Apc)
KIRQL OldIrql;
PKTHREAD Thread = Apc->Thread;
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
DPRINT("KeRemoveQueueApc called for APC: %x \n", Apc);
/* FIXME: Implement Dispatcher Lock */
OldIrql = KeRaiseIrqlToDpcLevel();
OldIrql = KeAcquireDispatcherDatabaseLock();
KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
/* Remove it from the Queue if it's inserted */
@ -247,13 +247,13 @@ KeRemoveQueueApc (PKAPC Apc)
}
} else {
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
KeLowerIrql(OldIrql);
KeReleaseDispatcherDatabaseLock(OldIrql);
return(FALSE);
}
/* Restore IRQL and Return */
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
KeLowerIrql(OldIrql);
KeReleaseDispatcherDatabaseLock(OldIrql);
return(TRUE);
}
@ -269,9 +269,10 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
PKTHREAD Thread = KeGetCurrentThread();
BOOLEAN OldState;
/* FIXME: Implement Dispatcher Lock */
OldIrql = KeRaiseIrqlToDpcLevel();
KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
OldIrql = KeAcquireDispatcherDatabaseLock();
KiAcquireSpinLock(&Thread->ApcQueueLock);
OldState = Thread->Alerted[(int)AlertMode];
@ -283,9 +284,8 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
Thread->ApcState.UserApcPending = TRUE;
}
/* FIXME: Implement Dispatcher Lock */
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
KeLowerIrql(OldIrql);
KiReleaseSpinLock(&Thread->ApcQueueLock);
KeReleaseDispatcherDatabaseLock(OldIrql);
return OldState;
}
@ -444,12 +444,25 @@ KiDeliverApc(KPROCESSOR_MODE PreviousMode,
}
}
VOID KiInitializeUserApc(IN PVOID Reserved,
IN PKTRAP_FRAME TrapFrame,
IN PKNORMAL_ROUTINE NormalRoutine,
IN PVOID NormalContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
VOID
STDCALL
KiFreeApcRoutine(PKAPC Apc,
PKNORMAL_ROUTINE* NormalRoutine,
PVOID* NormalContext,
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
*/
@ -508,77 +521,87 @@ KeAreApcsDisabled(
VOID
)
{
return KeGetCurrentThread()->KernelApcDisable ? FALSE : TRUE;
return KeGetCurrentThread()->KernelApcDisable ? TRUE : FALSE;
}
VOID STDCALL
NtQueueApcRundownRoutine(PKAPC Apc)
{
ExFreePool(Apc);
}
VOID STDCALL
NtQueueApcKernelRoutine(PKAPC Apc,
PKNORMAL_ROUTINE* NormalRoutine,
PVOID* NormalContext,
PVOID* SystemArgument1,
PVOID* SystemArgument2)
{
ExFreePool(Apc);
}
NTSTATUS STDCALL
NTSTATUS
STDCALL
NtQueueApcThread(HANDLE ThreadHandle,
PKNORMAL_ROUTINE ApcRoutine,
PVOID NormalContext,
PVOID SystemArgument1,
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;
Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_ALL_ACCESS, /* FIXME */
PsThreadType,
UserMode,
&ThreadVar,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
/* Get ETHREAD from Handle */
Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_SET_CONTEXT,
PsThreadType,
KeGetPreviousMode(),
(PVOID)&Thread,
NULL);
Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_KAPC);
if (Apc == 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;
}
/* Allocate an APC */
Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_KAPC);
if (Apc == NULL) {
ObDereferenceObject(Thread);
return(STATUS_NO_MEMORY);
}
/* Initialize and Queue */
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);
return(STATUS_NO_MEMORY);
}
KeInitializeApc(Apc,
&Thread->Tcb,
OriginalApcEnvironment,
NtQueueApcKernelRoutine,
NtQueueApcRundownRoutine,
ApcRoutine,
UserMode,
NormalContext);
KeInsertQueueApc(Apc,
SystemArgument1,
SystemArgument2,
IO_NO_INCREMENT);
ObDereferenceObject(Thread);
return(STATUS_SUCCESS);
return Status;
}
NTSTATUS STDCALL NtTestAlert(VOID)
NTSTATUS
STDCALL
NtTestAlert(VOID)
{
/* Check and Alert Thread if needed */
if (KeTestAlertThread(KeGetPreviousMode())) {
return STATUS_ALERTED;
} else {
@ -586,103 +609,31 @@ NTSTATUS STDCALL NtTestAlert(VOID)
}
}
VOID INIT_FUNCTION
PiInitApcManagement(VOID)
static inline VOID RepairList(PLIST_ENTRY Original,
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
RepairList(PLIST_ENTRY Original, PLIST_ENTRY Copy, int Mode)
VOID
STDCALL
KiMoveApcState (PKAPC_STATE OldState,
PKAPC_STATE NewState)
{
if (IsListEmpty(&Original[Mode]))
{
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 */
Thread->ApcState = Thread->SavedApcState;
/* repair lists */
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);
}
/* Restore backup of Original Environment */
*NewState = *OldState;
/* Repair Lists */
RepairList(NewState->ApcListHead, OldState->ApcListHead, KernelMode);
RepairList(NewState->ApcListHead, OldState->ApcListHead, UserMode);
}

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* 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
* FILE: ntoskrnl/ke/process.c
@ -38,79 +38,95 @@
/*
* @implemented
*/
VOID STDCALL
KeAttachProcess (PEPROCESS Process)
VOID
STDCALL
KeAttachProcess(PKPROCESS Process)
{
KIRQL oldlvl;
PETHREAD CurrentThread;
ULONG PageDir;
KIRQL OldIrql;
PKTHREAD Thread = KeGetCurrentThread();
DPRINT("KeAttachProcess(Process %x)\n",Process);
DPRINT("KeAttachProcess: %x\n", Process);
CurrentThread = PsGetCurrentThread();
/* Lock Dispatcher */
OldIrql = KeAcquireDispatcherDatabaseLock();
if (&CurrentThread->ThreadsProcess->Pcb != CurrentThread->Tcb.ApcState.Process)
{
DPRINT1("Invalid attach (thread is already attached)\n");
KEBUGCHECK(INVALID_PROCESS_ATTACH_ATTEMPT);
}
if (&Process->Pcb == CurrentThread->Tcb.ApcState.Process)
{
DPRINT1("Invalid attach (process is the same)\n");
KEBUGCHECK(INVALID_PROCESS_ATTACH_ATTEMPT);
}
/* Crash system if DPC is being executed! */
if (KeIsExecutingDpc()) {
DPRINT1("Invalid attach (Thread is executing a DPC!)\n");
KEBUGCHECK(INVALID_PROCESS_ATTACH_ATTEMPT);
}
/* 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);
/* Check if the Target Process is already attached */
if (Thread->ApcState.Process == Process || Thread->ApcStateIndex != OriginalApcEnvironment) {
DPRINT("Process already Attached. Exitting\n");
KeReleaseDispatcherDatabaseLock(OldIrql);
} else {
KiAttachProcess(Thread, Process, OldIrql, &Thread->SavedApcState);
}
}
/*
* @implemented
*/
VOID STDCALL
KeDetachProcess (VOID)
VOID
STDCALL
KiAttachProcess(PKTHREAD Thread, PKPROCESS Process, KIRQL ApcLock, PRKAPC_STATE SavedApcState)
{
KIRQL oldlvl;
PETHREAD CurrentThread;
ULONG PageDir;
DPRINT("KeDetachProcess()\n");
DPRINT("KiAttachProcess(Thread: %x, Process: %x, SavedApcState: %x\n", Thread, Process, SavedApcState);
CurrentThread = PsGetCurrentThread();
/* 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((PEPROCESS)Process, (PVOID)Thread->StackLimit, MM_STACK_SIZE);
MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
if (&CurrentThread->ThreadsProcess->Pcb == CurrentThread->Tcb.ApcState.Process)
{
DPRINT1("Invalid detach (thread was not attached)\n");
KEBUGCHECK(INVALID_PROCESS_DETACH_ATTEMPT);
}
/* Increase Stack Count */
Process->StackCount++;
KeRaiseIrql(DISPATCH_LEVEL, &oldlvl);
/* Swap the APC Environment */
KiMoveApcState(&Thread->ApcState, SavedApcState);
KiSwapApcEnvironment(&CurrentThread->Tcb, CurrentThread->Tcb.SavedApcState.Process);
PageDir = CurrentThread->Tcb.ApcState.Process->DirectoryTableBase.u.LowPart;
Ke386SetPageTableDirectory(PageDir);
/* 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;
KeLowerIrql(oldlvl);
/* 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");
}
VOID
STDCALL
KiSwapProcess(PKPROCESS NewProcess, PKPROCESS OldProcess)
{
//PKPCR Pcr = KeGetCurrentKpcr();
/* Do they have an LDT? */
if ((NewProcess->LdtDescriptor) || (OldProcess->LdtDescriptor)) {
/* FIXME : SWitch GDT/IDT */
}
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;
PKTHREAD Thread;
PKTHREAD Thread = KeGetCurrentThread();
OldIrql = KeAcquireDispatcherDatabaseLock();
Thread = KeGetCurrentThread();
/* Crash system if DPC is being executed! */
if (KeIsExecutingDpc()) {
@ -151,16 +166,53 @@ KeStackAttachProcess (
if (Thread->ApcState.Process == Process) {
ApcState->Process = (PKPROCESS)1; /* Meaning already attached to the same Process */
} else {
/* Check if the Current Thread is already attached */
if (Thread->ApcStateIndex != 0) {
KeAttachProcess((PEPROCESS)Process); /* FIXME: Re-write function to support stackability and fix it not to use EPROCESS */
/* Check if the Current Thread is already attached and call the Internal Function*/
if (Thread->ApcStateIndex != OriginalApcEnvironment) {
KiAttachProcess(Thread, Process, OldIrql, ApcState);
} else {
KeAttachProcess((PEPROCESS)Process);
ApcState->Process = NULL; /* FIXME: Re-write function to support stackability and fix it not to use EPROCESS */
KiAttachProcess(Thread, Process, OldIrql, &Thread->SavedApcState);
ApcState->Process = NULL;
}
}
}
/* Return to old IRQL*/
/*
* @implemented
*/
VOID STDCALL
KeDetachProcess (VOID)
{
PKTHREAD Thread;
KIRQL OldIrql;
DPRINT("KeDetachProcess()\n");
/* Get Current Thread and Lock */
Thread = KeGetCurrentThread();
OldIrql = KeAcquireDispatcherDatabaseLock();
/* 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);
}
@ -175,7 +227,6 @@ KeUnstackDetachProcess (
{
KIRQL OldIrql;
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 (ApcState->Process == (PKPROCESS)1) return;
@ -184,7 +235,7 @@ KeUnstackDetachProcess (
OldIrql = KeAcquireDispatcherDatabaseLock();
/* 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");
KEBUGCHECK(INVALID_PROCESS_DETACH_ATTEMPT);
}
@ -196,15 +247,16 @@ KeUnstackDetachProcess (
/* The ApcState parameter is useless, so use the saved data and reset it */
RtlMoveMemory(&Thread->SavedApcState, &Thread->ApcState, sizeof(KAPC_STATE));
Thread->SavedApcState.Process = NULL;
Thread->ApcStateIndex = 0;
Thread->ApcStatePointer[0] = &Thread->ApcState;
Thread->ApcStatePointer[1] = &Thread->SavedApcState;
Thread->ApcStateIndex = OriginalApcEnvironment;
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
}
/* Do the Actual Swap */
KiSwapApcEnvironment(Thread, Thread->SavedApcState.Process);
PageDir = Thread->ApcState.Process->DirectoryTableBase.u.LowPart;
Ke386SetPageTableDirectory(PageDir);
/* Restore the APC State */
KiMoveApcState(&Thread->SavedApcState, &Thread->ApcState);
/* Swap Processes */
KiSwapProcess(Thread->ApcState.Process, Thread->ApcState.Process);
/* Return to old IRQL*/
KeReleaseDispatcherDatabaseLock(OldIrql);

View file

@ -197,9 +197,6 @@ VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus, BOOL Unblock)
{
PKWAIT_BLOCK WaitBlock, PrevWaitBlock;
BOOLEAN WasWaiting = FALSE;
KIRQL OldIrql;
OldIrql = KeAcquireDispatcherDatabaseLock ();
WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList;
if (WaitBlock != NULL)
@ -223,8 +220,6 @@ VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus, BOOL Unblock)
{
PsUnblockThread(Thread, &WaitStatus);
}
KeReleaseDispatcherDatabaseLock (OldIrql);
}
static BOOLEAN
@ -542,15 +537,40 @@ KeWaitForMultipleObjects(ULONG Count,
OldIrql = KeAcquireDispatcherDatabaseLock ();
}
/*
* If we are going to wait alertably and a user apc is pending
* then return
/* Alertability 101
* ----------------
* 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()))
{
KeReleaseDispatcherDatabaseLock(OldIrql);
return (STATUS_USER_APC);
}
if (Alertable) {
if (CurrentThread->Alerted[(int)WaitMode]) {
CurrentThread->Alerted[(int)WaitMode] = FALSE;
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

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* 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
* FILE: ntoskrnl/mm/i386/page.c
@ -375,7 +375,7 @@ VOID MmDeletePageTable(PEPROCESS Process, PVOID Address)
if (Process != NULL && Process != CurrentProcess)
{
KeAttachProcess(Process);
KeAttachProcess(&Process->Pcb);
}
if (Ke386Pae)
@ -408,7 +408,7 @@ VOID MmFreePageTable(PEPROCESS Process, PVOID Address)
DPRINT("ProcessId %d, Address %x\n", Process->UniqueProcessId, Address);
if (Process != NULL && Process != CurrentProcess)
{
KeAttachProcess(Process);
KeAttachProcess(&Process->Pcb);
}
if (Ke386Pae)
{

View file

@ -453,7 +453,7 @@ MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
if (AddressSpace->Process != NULL &&
AddressSpace->Process != CurrentProcess)
{
KeAttachProcess(AddressSpace->Process);
KeAttachProcess((PKPROCESS)AddressSpace->Process);
}
EndAddress = (char*)MemoryArea->BaseAddress + PAGE_ROUND_UP(MemoryArea->Length);
for (Address = MemoryArea->BaseAddress; Address < EndAddress; Address += PAGE_SIZE)

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* 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
* FILE: ntoskrnl/mm/virtual.c
@ -425,7 +425,7 @@ NtReadVirtualMemory(IN HANDLE ProcessHandle,
UserMode,
IoWriteAccess);
KeAttachProcess(Process);
KeAttachProcess((PKPROCESS)Process);
SystemAddress = MmGetSystemAddressForMdl(Mdl);
memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
@ -553,7 +553,7 @@ NtWriteVirtualMemory(IN HANDLE ProcessHandle,
ObDereferenceObject(Process);
return(STATUS_NO_MEMORY);
}
KeAttachProcess(Process);
KeAttachProcess((PKPROCESS)Process);
SystemAddress = MmGetSystemAddressForMdl(Mdl);
memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);

View file

@ -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
* PROJECT: ReactOS kernel
@ -32,7 +32,6 @@ PiInitProcessManager(VOID)
PsInitProcessManagment();
PsInitThreadManagment();
PsInitIdleThread();
PiInitApcManagement();
PsInitialiseSuspendImplementation();
PsInitialiseW32Call();
}