-/* $Id: kill.c,v 1.83 2004/11/13 22:27:15 hbirr Exp $
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ps/kill.c
* PURPOSE: Terminating a thread
- * PROGRAMMER: David Welch (welch@cwcom.net)
- * UPDATE HISTORY:
- * Created 22/05/98
+ *
+ * PROGRAMMERS: David Welch (welch@cwcom.net)
*/
/* INCLUDES *****************************************************************/
/* GLOBALS *******************************************************************/
-extern KSPIN_LOCK PiThreadLock;
-
VOID PsTerminateCurrentThread(NTSTATUS ExitStatus);
+NTSTATUS STDCALL NtCallTerminatePorts(PETHREAD Thread);
#define TAG_TERMINATE_APC TAG('T', 'A', 'P', 'C')
LIST_ENTRY ThreadsToReapHead;
+#define TERMINATE_PROC 0x1
+#define TERMINATE_APC 0x2
+
/* FUNCTIONS *****************************************************************/
VOID
PETHREAD Thread;
PLIST_ENTRY ListEntry;
- KeAcquireSpinLock(&PiThreadLock, &oldlvl);
+ oldlvl = KeAcquireDispatcherDatabaseLock();
while((ListEntry = RemoveHeadList(&ThreadsToReapHead)) != &ThreadsToReapHead)
{
PiNrThreadsAwaitingReaping--;
- KeReleaseSpinLock(&PiThreadLock, oldlvl);
-
+ KeReleaseDispatcherDatabaseLock(oldlvl);
Thread = CONTAINING_RECORD(ListEntry, ETHREAD, TerminationPortList);
ObDereferenceObject(Thread);
-
- KeAcquireSpinLock(&PiThreadLock, &oldlvl);
+ oldlvl = KeAcquireDispatcherDatabaseLock();
}
- KeReleaseSpinLock(&PiThreadLock, oldlvl);
+ KeReleaseDispatcherDatabaseLock(oldlvl);
}
VOID
DPRINT("PiTerminateProcessThreads(Process %x, ExitStatus %x)\n",
Process, ExitStatus);
+
+ oldlvl = KeAcquireDispatcherDatabaseLock();
- KeAcquireSpinLock(&PiThreadLock, &oldlvl);
-
current_entry = Process->ThreadListHead.Flink;
while (current_entry != &Process->ThreadListHead)
{
DPRINT("Terminating %x, current thread: %x, "
"thread's process: %x\n", current, PsGetCurrentThread(),
current->ThreadsProcess);
- KeReleaseSpinLock(&PiThreadLock, oldlvl);
+ KeReleaseDispatcherDatabaseLock(oldlvl);
PsTerminateOtherThread(current, ExitStatus);
- KeAcquireSpinLock(&PiThreadLock, &oldlvl);
+ oldlvl = KeAcquireDispatcherDatabaseLock();
current_entry = Process->ThreadListHead.Flink;
}
else
current_entry = current_entry->Flink;
}
}
- KeReleaseSpinLock(&PiThreadLock, oldlvl);
+ KeReleaseDispatcherDatabaseLock(oldlvl);
DPRINT("Finished PiTerminateProcessThreads()\n");
}
SIZE_T Length = PAGE_SIZE;
PVOID TebBlock;
- KeLowerIrql(PASSIVE_LEVEL);
+ DPRINT("PsTerminateCurrentThread(ExitStatus %x)\n", ExitStatus);
CurrentThread = PsGetCurrentThread();
+
+ oldIrql = KeAcquireDispatcherDatabaseLock();
+ if (CurrentThread->HasTerminated & TERMINATE_PROC)
+ {
+ KeReleaseDispatcherDatabaseLock(oldIrql);
+ return;
+ }
+ CurrentThread->HasTerminated |= TERMINATE_PROC;
+ KeReleaseDispatcherDatabaseLock(oldIrql);
+
+ KeLowerIrql(PASSIVE_LEVEL);
+
CurrentProcess = CurrentThread->ThreadsProcess;
/* Can't terminate a thread if it attached another process */
(ULONG) CurrentThread);
}
- KeAcquireSpinLock(&PiThreadLock, &oldIrql);
+ KeCancelTimer(&CurrentThread->Tcb.Timer);
+
+ oldIrql = KeAcquireDispatcherDatabaseLock();
DPRINT("terminating %x\n",CurrentThread);
CurrentThread->ExitStatus = ExitStatus;
KeQuerySystemTime((PLARGE_INTEGER)&CurrentThread->ExitTime);
- KeCancelTimer(&CurrentThread->Tcb.Timer);
+
+ /* If the ProcessoR Control Block's NpxThread points to the current thread
+ * unset it.
+ */
+ InterlockedCompareExchangePointer(&KeGetCurrentKPCR()->PrcbData.NpxThread,
+ NULL, ETHREAD_TO_KTHREAD(CurrentThread));
+
+ KeReleaseDispatcherDatabaseLock(oldIrql);
+ PsLockProcess(CurrentProcess, FALSE);
+
/* Remove the thread from the thread list of its process */
RemoveEntryList(&CurrentThread->ThreadListEntry);
Last = IsListEmpty(&CurrentProcess->ThreadListHead);
-
- KeReleaseSpinLock(&PiThreadLock, oldIrql);
+ PsUnlockProcess(CurrentProcess);
/* Notify subsystems of the thread termination */
PspRunCreateThreadNotifyRoutines(CurrentThread, FALSE);
MmReleaseMemoryAreaIfDecommitted(CurrentProcess, &CurrentProcess->AddressSpace, TebBlock);
MmUnlockAddressSpace(&CurrentProcess->AddressSpace);
}
+ CurrentThread->Tcb.Teb = NULL;
ExReleaseFastMutex(&CurrentProcess->TebLock);
}
oldIrql = KeAcquireDispatcherDatabaseLock();
CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE;
- KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader);
+ KiDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader, IO_NO_INCREMENT);
KeReleaseDispatcherDatabaseLock (oldIrql);
/* The last thread shall close the door on exit */
if(Last)
{
+ /* save the last thread exit status */
+ CurrentProcess->LastThreadExitStatus = ExitStatus;
+
PspRunCreateProcessNotifyRoutines(CurrentProcess, FALSE);
PsTerminateWin32Process(CurrentProcess);
PiTerminateProcess(CurrentProcess, ExitStatus);
}
- KeAcquireSpinLock(&PiThreadLock, &oldIrql);
+ oldIrql = KeAcquireDispatcherDatabaseLock();
#ifdef _ENABLE_THRDEVTPAIR
ExpSwapThreadEventPair(CurrentThread, NULL); /* Release the associated eventpair object, if there was one */
#endif /* _ENABLE_THRDEVTPAIR */
- KeRemoveAllWaitsThread (CurrentThread, STATUS_UNSUCCESSFUL, FALSE);
+ ASSERT(CurrentThread->Tcb.WaitBlockList == NULL);
+
PsDispatchThreadNoLock(THREAD_STATE_TERMINATED_1);
DPRINT1("Unexpected return, CurrentThread %x PsGetCurrentThread() %x\n", CurrentThread, PsGetCurrentThread());
KEBUGCHECK(0);
PVOID SystemArgument1,
PVOID SystemArgument2)
{
- PsTerminateCurrentThread(PsGetCurrentThread()->ExitStatus);
+ PsTerminateCurrentThread((NTSTATUS)SystemArgument1);
}
VOID
*/
{
PKAPC Apc;
- NTSTATUS Status;
+ KIRQL OldIrql;
DPRINT("PsTerminateOtherThread(Thread %x, ExitStatus %x)\n",
Thread, ExitStatus);
-
- Thread->HasTerminated = TRUE;
- Thread->ExitStatus = ExitStatus;
+
+ OldIrql = KeAcquireDispatcherDatabaseLock();
+ if (Thread->HasTerminated & TERMINATE_APC)
+ {
+ KeReleaseDispatcherDatabaseLock (OldIrql);
+ return;
+ }
+ Thread->HasTerminated |= TERMINATE_APC;
+ KeReleaseDispatcherDatabaseLock (OldIrql);
Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_TERMINATE_APC);
KeInitializeApc(Apc,
&Thread->Tcb,
KernelMode,
NULL);
KeInsertQueueApc(Apc,
- NULL,
+ (PVOID)ExitStatus,
NULL,
IO_NO_INCREMENT);
+
+ OldIrql = KeAcquireDispatcherDatabaseLock();
if (THREAD_STATE_BLOCKED == Thread->Tcb.State && UserMode == Thread->Tcb.WaitMode)
{
DPRINT("Unblocking thread\n");
- Status = STATUS_THREAD_IS_TERMINATING;
- KeRemoveAllWaitsThread(Thread, Status, TRUE);
+ KiAbortWaitThread((PKTHREAD)Thread, STATUS_THREAD_IS_TERMINATING);
}
+ KeReleaseDispatcherDatabaseLock(OldIrql);
}
NTSTATUS STDCALL
ObGetObjectHandleCount(Process));
ObReferenceObject(Process);
- if (InterlockedExchange((PLONG)&Process->Pcb.State,
- PROCESS_STATE_TERMINATED) ==
+ if (InterlockedExchangeUL(&Process->Pcb.State,
+ PROCESS_STATE_TERMINATED) ==
PROCESS_STATE_TERMINATED)
{
ObDereferenceObject(Process);
}
OldIrql = KeAcquireDispatcherDatabaseLock ();
Process->Pcb.DispatcherHeader.SignalState = TRUE;
- KeDispatcherObjectWake(&Process->Pcb.DispatcherHeader);
+ KiDispatcherObjectWake(&Process->Pcb.DispatcherHeader, IO_NO_INCREMENT);
KeReleaseDispatcherDatabaseLock (OldIrql);
ObDereferenceObject(Process);
return(STATUS_SUCCESS);
NTSTATUS Status;
PEPROCESS Process;
+ PAGED_CODE();
+
DPRINT("NtTerminateProcess(ProcessHandle %x, ExitStatus %x)\n",
ProcessHandle, ExitStatus);
PETHREAD Thread;
NTSTATUS Status;
+ PAGED_CODE();
+
Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_TERMINATE,
PsThreadType,
PLIST_ENTRY current_entry;
PEPORT_TERMINATION_REQUEST current;
+ PAGED_CODE();
+
KeAcquireSpinLock(&Thread->ActiveTimerListLock, &oldIrql);
while ((current_entry = RemoveHeadList(&Thread->TerminationPortList)) !=
&Thread->TerminationPortList);
KIRQL oldIrql;
PETHREAD Thread;
+ PAGED_CODE();
+
Status = ObReferenceObjectByHandle(PortHandle,
PORT_ALL_ACCESS,
- ExPortType,
+ LpcPortObjectType,
KeGetCurrentThread()->PreviousMode,
(PVOID*)&TerminationPort,
NULL);