11 modified files
reactos/include/ddk
diff -u -r1.47 -r1.48
--- kefuncs.h 10 Nov 2004 02:50:59 -0000 1.47
+++ kefuncs.h 11 Nov 2004 22:23:51 -0000 1.48
@@ -20,13 +20,14 @@
#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);
/*
reactos/include/ddk
diff -u -r1.50 -r1.51
--- ketypes.h 10 Nov 2004 02:50:59 -0000 1.50
+++ ketypes.h 11 Nov 2004 22:23:51 -0000 1.51
@@ -122,6 +122,24 @@
#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;
reactos/ntoskrnl/include/internal
diff -u -r1.63 -r1.64
--- ke.h 10 Nov 2004 02:50:59 -0000 1.63
+++ ke.h 11 Nov 2004 22:23:52 -0000 1.64
@@ -96,6 +96,10 @@
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 @@
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);
reactos/ntoskrnl/include/internal
diff -u -r1.73 -r1.74
--- ps.h 10 Nov 2004 02:50:59 -0000 1.73
+++ ps.h 11 Nov 2004 22:23:52 -0000 1.74
@@ -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 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
reactos/ntoskrnl/ke
diff -u -r1.67 -r1.68
--- apc.c 10 Nov 2004 02:50:59 -0000 1.67
+++ apc.c 11 Nov 2004 22:23:52 -0000 1.68
@@ -123,12 +123,12 @@
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 @@
/* 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 @@
/* Don't do anything if the APC is already inserted */
if (Apc->Inserted) {
- KeLowerIrql(OldIrql);
+ KeReleaseDispatcherDatabaseLock(OldIrql);
return FALSE;
}
@@ -208,7 +208,7 @@
}
/* Return Sucess if we are here */
- KeLowerIrql(OldIrql);
+ KeReleaseDispatcherDatabaseLock(OldIrql);
return TRUE;
}
@@ -226,10 +226,10 @@
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 @@
}
} 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 @@
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 @@
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 @@
}
}
-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 @@
VOID
)
{
- return KeGetCurrentThread()->KernelApcDisable ? FALSE : TRUE;
-}
-
-VOID STDCALL
-NtQueueApcRundownRoutine(PKAPC Apc)
-{
- ExFreePool(Apc);
-}
-
-VOID STDCALL
-NtQueueApcKernelRoutine(PKAPC Apc,
- PKNORMAL_ROUTINE* NormalRoutine,
- PVOID* NormalContext,
- PVOID* SystemArgument1,
- PVOID* SystemArgument2)
-{
- ExFreePool(Apc);
+ return KeGetCurrentThread()->KernelApcDisable ? TRUE : FALSE;
}
-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;
-
- Status = ObReferenceObjectByHandle(ThreadHandle,
- THREAD_ALL_ACCESS, /* FIXME */
- PsThreadType,
- UserMode,
- &ThreadVar,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
+ 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;
+ }
- Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_KAPC);
- if (Apc == NULL)
- {
- ObDereferenceObject(Thread);
- return(STATUS_NO_MEMORY);
- }
+ /* Allocate an APC */
+ Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_KAPC);
+ if (Apc == NULL) {
+ ObDereferenceObject(Thread);
+ return(STATUS_NO_MEMORY);
+ }
- KeInitializeApc(Apc,
- &Thread->Tcb,
- OriginalApcEnvironment,
- NtQueueApcKernelRoutine,
- NtQueueApcRundownRoutine,
- ApcRoutine,
- UserMode,
- NormalContext);
- KeInsertQueueApc(Apc,
- SystemArgument1,
- SystemArgument2,
- IO_NO_INCREMENT);
+ /* 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;
+ }
- ObDereferenceObject(Thread);
- return(STATUS_SUCCESS);
+ /* Dereference Thread and Return */
+ ObDereferenceObject(Thread);
+ 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 @@
}
}
-VOID INIT_FUNCTION
-PiInitApcManagement(VOID)
-{
-}
-
-static VOID FASTCALL
-RepairList(PLIST_ENTRY Original, PLIST_ENTRY Copy, int Mode)
-{
- if (IsListEmpty(&Original[Mode]))
- {
- InitializeListHead(&Copy[Mode]);
- }
- else
- {
- Copy[Mode].Flink->Blink = &Copy[Mode];
- Copy[Mode].Blink->Flink = &Copy[Mode];
- }
+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];
+ }
}
-
-VOID FASTCALL
-KiSwapApcEnvironment(
- PKTHREAD Thread,
- PKPROCESS NewProcess)
+VOID
+STDCALL
+KiMoveApcState (PKAPC_STATE OldState,
+ PKAPC_STATE NewState)
{
- 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 */
+ *NewState = *OldState;
- /* 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);
- }
+ /* Repair Lists */
+ RepairList(NewState->ApcListHead, OldState->ApcListHead, KernelMode);
+ RepairList(NewState->ApcListHead, OldState->ApcListHead, UserMode);
}
reactos/ntoskrnl/ke
diff -u -r1.30 -r1.31
--- process.c 17 Oct 2004 03:43:26 -0000 1.30
+++ process.c 11 Nov 2004 22:23:52 -0000 1.31
@@ -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;
-
- DPRINT("KeAttachProcess(Process %x)\n",Process);
-
- CurrentThread = PsGetCurrentThread();
-
- 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);
- }
-
-
- /* 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);
+ KIRQL OldIrql;
+ PKTHREAD Thread = KeGetCurrentThread();
+
+ DPRINT("KeAttachProcess: %x\n", Process);
+
+ /* Lock Dispatcher */
+ OldIrql = KeAcquireDispatcherDatabaseLock();
+
+ /* Crash system if DPC is being executed! */
+ if (KeIsExecutingDpc()) {
+ DPRINT1("Invalid attach (Thread is executing a DPC!)\n");
+ KEBUGCHECK(INVALID_PROCESS_ATTACH_ATTEMPT);
+ }
+
+ /* 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");
-
- CurrentThread = PsGetCurrentThread();
-
- if (&CurrentThread->ThreadsProcess->Pcb == CurrentThread->Tcb.ApcState.Process)
- {
- DPRINT1("Invalid detach (thread was not attached)\n");
- KEBUGCHECK(INVALID_PROCESS_DETACH_ATTEMPT);
- }
+
+ DPRINT("KiAttachProcess(Thread: %x, Process: %x, SavedApcState: %x\n", Thread, Process, SavedApcState);
- KeRaiseIrql(DISPATCH_LEVEL, &oldlvl);
+ /* 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));
+
+ /* 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");
+}
- KiSwapApcEnvironment(&CurrentThread->Tcb, CurrentThread->Tcb.SavedApcState.Process);
- PageDir = CurrentThread->Tcb.ApcState.Process->DirectoryTableBase.u.LowPart;
- Ke386SetPageTableDirectory(PageDir);
+VOID
+STDCALL
+KiSwapProcess(PKPROCESS NewProcess, PKPROCESS OldProcess)
+{
+ //PKPCR Pcr = KeGetCurrentKpcr();
- KeLowerIrql(oldlvl);
+ /* 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 @@
)
{
KIRQL OldIrql;
- PKTHREAD Thread;
+ PKTHREAD Thread = KeGetCurrentThread();
OldIrql = KeAcquireDispatcherDatabaseLock();
- Thread = KeGetCurrentThread();
/* Crash system if DPC is being executed! */
if (KeIsExecutingDpc()) {
@@ -151,16 +166,53 @@
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;
}
}
+}
+
+/*
+ * @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);
}
@@ -175,7 +227,6 @@
{
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 @@
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 @@
/* 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);
reactos/ntoskrnl/ke
diff -u -r1.60 -r1.61
--- wait.c 10 Nov 2004 02:50:59 -0000 1.60
+++ wait.c 11 Nov 2004 22:23:52 -0000 1.61
@@ -197,9 +197,6 @@
{
PKWAIT_BLOCK WaitBlock, PrevWaitBlock;
BOOLEAN WasWaiting = FALSE;
- KIRQL OldIrql;
-
- OldIrql = KeAcquireDispatcherDatabaseLock ();
WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList;
if (WaitBlock != NULL)
@@ -223,8 +220,6 @@
{
PsUnblockThread(Thread, &WaitStatus);
}
-
- KeReleaseDispatcherDatabaseLock (OldIrql);
}
static BOOLEAN
@@ -542,15 +537,40 @@
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
reactos/ntoskrnl/mm
diff -u -r1.70 -r1.71
--- marea.c 22 Oct 2004 20:38:22 -0000 1.70
+++ marea.c 11 Nov 2004 22:23:52 -0000 1.71
@@ -453,7 +453,7 @@
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)
reactos/ntoskrnl/mm
diff -u -r1.83 -r1.84
--- virtual.c 29 Oct 2004 16:48:10 -0000 1.83
+++ virtual.c 11 Nov 2004 22:23:52 -0000 1.84
@@ -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 @@
UserMode,
IoWriteAccess);
- KeAttachProcess(Process);
+ KeAttachProcess((PKPROCESS)Process);
SystemAddress = MmGetSystemAddressForMdl(Mdl);
memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
@@ -553,7 +553,7 @@
ObDereferenceObject(Process);
return(STATUS_NO_MEMORY);
}
- KeAttachProcess(Process);
+ KeAttachProcess((PKPROCESS)Process);
SystemAddress = MmGetSystemAddressForMdl(Mdl);
memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
reactos/ntoskrnl/mm/i386
diff -u -r1.75 -r1.76
--- page.c 5 Oct 2004 18:53:28 -0000 1.75
+++ page.c 11 Nov 2004 22:23:52 -0000 1.76
@@ -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 @@
if (Process != NULL && Process != CurrentProcess)
{
- KeAttachProcess(Process);
+ KeAttachProcess(&Process->Pcb);
}
if (Ke386Pae)
@@ -408,7 +408,7 @@
DPRINT("ProcessId %d, Address %x\n", Process->UniqueProcessId, Address);
if (Process != NULL && Process != CurrentProcess)
{
- KeAttachProcess(Process);
+ KeAttachProcess(&Process->Pcb);
}
if (Ke386Pae)
{
reactos/ntoskrnl/ps
diff -u -r1.23 -r1.24
--- psmgr.c 28 Sep 2004 15:02:29 -0000 1.23
+++ psmgr.c 11 Nov 2004 22:23:52 -0000 1.24
@@ -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 @@
PsInitProcessManagment();
PsInitThreadManagment();
PsInitIdleThread();
- PiInitApcManagement();
PsInitialiseSuspendImplementation();
PsInitialiseW32Call();
}
CVSspam 0.2.8