Author: ion
Date: Sun Jul 23 21:45:30 2006
New Revision: 23249
URL: http://svn.reactos.org/svn/reactos?rev=23249&view=rev
Log:
- Acquire Process lock when touching the thread list entry and incrementing the process' active threads.
- Set the Thread Create Time on creation, I had forgotten this!
- Handle failures for thread-safety/race conditions. If the process was deleted or the thread terminated behind our back, then go through a manual un-initalization code path.
- Just like previous process patch, add code to now create an access state with SeCreateAccessStateEx.
- Handle failure of ObInsertObject.
Modified:
trunk/reactos/ntoskrnl/include/internal/ke.h
trunk/reactos/ntoskrnl/include/internal/ob.h
trunk/reactos/ntoskrnl/ke/kthread.c
trunk/reactos/ntoskrnl/ps/thread.c
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ke.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h Sun Jul 23 21:45:30 2006
@@ -291,6 +291,12 @@
IN PVOID KernelStack
);
+VOID
+NTAPI
+KeUninitThread(
+ IN PKTHREAD Thread
+);
+
NTSTATUS
NTAPI
KeInitThread(
Modified: trunk/reactos/ntoskrnl/include/internal/ob.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ob.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ob.h Sun Jul 23 21:45:30 2006
@@ -195,6 +195,13 @@
LONG
FASTCALL
+ObDereferenceObjectEx(
+ IN PVOID Object,
+ IN ULONG Count
+);
+
+LONG
+FASTCALL
ObReferenceObjectEx(
IN PVOID Object,
IN ULONG Count
Modified: trunk/reactos/ntoskrnl/ke/kthread.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/kthread.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/kthread.c (original)
+++ trunk/reactos/ntoskrnl/ke/kthread.c Sun Jul 23 21:45:30 2006
@@ -726,6 +726,15 @@
IN PVOID ThreadState)
{
UNIMPLEMENTED;
+}
+
+VOID
+NTAPI
+KeUninitThread(IN PKTHREAD Thread)
+{
+ /* Delete the stack */
+ MmDeleteKernelStack(Thread->StackBase, FALSE);
+ Thread->InitialStack = NULL;
}
NTSTATUS
Modified: trunk/reactos/ntoskrnl/ps/thread.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/thread.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/ps/thread.c (original)
+++ trunk/reactos/ntoskrnl/ps/thread.c Sun Jul 23 21:45:30 2006
@@ -146,6 +146,9 @@
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
HANDLE_TABLE_ENTRY CidEntry;
+ ACCESS_STATE LocalAccessState;
+ PACCESS_STATE AccessState = &LocalAccessState;
+ AUX_DATA AuxData;
PAGED_CODE();
/* If we were called from PsCreateSystemThread, then we're kernel mode */
@@ -299,7 +302,21 @@
return Status;
}
- /* FIXME: Acquire exclusive pushlock */
+ /* Lock the process */
+ KeEnterCriticalRegion();
+ ExAcquirePushLockExclusive(&Process->ProcessLock);
+
+ /* Make sure the proces didn't just die on us */
+ if (Process->ProcessDelete) goto Quickie;
+
+ /* Check if the thread was ours, terminated and it was user mode */
+ if ((Thread->Terminated) &&
+ (ThreadContext) &&
+ (Thread->ThreadsProcess == Process))
+ {
+ /* Cleanup, we don't want to start it up and context switch */
+ goto Quickie;
+ }
/*
* Insert the Thread into the Process's Thread List
@@ -312,7 +329,9 @@
/* Start the thread */
KeStartThread(&Thread->Tcb);
- /* FIXME: Wake pushlock */
+ /* Release the process lock */
+ ExReleasePushLockExclusive(&Process->ProcessLock);
+ KeLeaveCriticalRegion();
/* Release rundown */
ExReleaseRundownProtection(&Process->RundownProtect);
@@ -333,13 +352,43 @@
/* Check if we were already terminated */
if (Thread->Terminated) KeForceResumeThread(&Thread->Tcb);
+ /* Create an access state */
+ Status = SeCreateAccessStateEx(NULL,
+ ThreadContext ?
+ PsGetCurrentProcess() : Process,
+ &LocalAccessState,
+ &AuxData,
+ DesiredAccess,
+ &PsThreadType->TypeInfo.GenericMapping);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Access state failed, thread is dead */
+ InterlockedOr(&Thread->CrossThreadFlags, CT_DEAD_THREAD_BIT);
+
+ /* If we were suspended, wake it up */
+ if (CreateSuspended) KeResumeThread(&Thread->Tcb);
+
+ /* Dispatch thread */
+ OldIrql = KeAcquireDispatcherDatabaseLock ();
+ KiReadyThread(&Thread->Tcb);
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+
+ /* Dereference completely to kill it */
+ ObDereferenceObjectEx(Thread, 2);
+ }
+
/* Insert the Thread into the Object Manager */
Status = ObInsertObject(Thread,
- NULL,
+ AccessState,
DesiredAccess,
0,
NULL,
&hThread);
+
+ /* Delete the access state if we had one */
+ if (AccessState) SeDeleteAccessState(AccessState);
+
+ /* Check for success */
if (NT_SUCCESS(Status))
{
/* Wrap in SEH to protect against bad user-mode pointers */
@@ -356,6 +405,18 @@
}
_SEH_END;
}
+ else
+ {
+ /* Thread insertion failed, thread is dead */
+ InterlockedOr(&Thread->CrossThreadFlags, CT_DEAD_THREAD_BIT);
+
+ /* If we were suspended, wake it up */
+ if (CreateSuspended) KeResumeThread(&Thread->Tcb);
+ }
+
+ /* Get the create time */
+ KeQuerySystemTime(&Thread->CreateTime);
+ ASSERT(!(Thread->CreateTime.HighPart & 0xF0000000));
/* Set the thread access mask */
Thread->GrantedAccess = THREAD_ALL_ACCESS;
@@ -370,6 +431,24 @@
/* Return */
return Status;
+
+ /* Most annoying failure case ever, where we undo almost all manually */
+Quickie:
+ /* When we get here, the process is locked, unlock it */
+ ExReleasePushLockExclusive(&Process->ProcessLock);
+
+ /* Uninitailize it */
+ KeUninitThread(&Thread->Tcb);
+
+ /* If we had a TEB, delete it */
+ if (TebBase) MmDeleteTeb(Process, TebBase);
+
+ /* Release rundown protection, which we also hold */
+ ExReleaseRundownProtection(&Process->RundownProtect);
+
+ /* Dereference the thread and return failure */
+ ObDereferenceObject(Thread);
+ return STATUS_PROCESS_IS_TERMINATING;
}
/* PUBLIC FUNCTIONS **********************************************************/