3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/kill.c
6 * PURPOSE: Terminating a thread
7 * PROGRAMMER: David Welch (welch@cwcom.net)
12 /* INCLUDES *****************************************************************/
14 #include <ddk/ntddk.h>
15 #include <internal/ps.h>
16 #include <internal/ke.h>
17 #include <internal/mm.h>
18 #include <internal/ob.h>
19 #include <internal/port.h>
20 #include <internal/pool.h>
23 #include <internal/debug.h>
25 /* GLOBALS *******************************************************************/
27 extern ULONG PiNrThreads;
28 extern ULONG PiNrRunnableThreads;
29 extern KSPIN_LOCK PiThreadListLock;
30 extern LIST_ENTRY PiThreadListHead;
31 extern KSPIN_LOCK PiApcLock;
33 VOID PsTerminateCurrentThread(NTSTATUS ExitStatus);
35 #define TAG_TERMINATE_APC TAG('T', 'A', 'P', 'C')
37 /* FUNCTIONS *****************************************************************/
40 PiTerminateProcessThreads(PEPROCESS Process,
44 PLIST_ENTRY current_entry;
47 DPRINT("PiTerminateProcessThreads(Process %x, ExitStatus %x)\n",
50 KeAcquireSpinLock(&PiThreadListLock, &oldlvl);
52 current_entry = Process->ThreadListHead.Flink;
53 while (current_entry != &Process->ThreadListHead)
55 current = CONTAINING_RECORD(current_entry, ETHREAD,
56 Tcb.ProcessThreadListEntry);
57 if (current != PsGetCurrentThread() &&
58 current->DeadThread == 0)
60 DPRINT("Terminating %x, current thread: %x, "
61 "thread's process: %x\n", current, PsGetCurrentThread(),
62 current->ThreadsProcess);
63 KeReleaseSpinLock(&PiThreadListLock, oldlvl);
64 PsTerminateOtherThread(current, ExitStatus);
65 KeAcquireSpinLock(&PiThreadListLock, &oldlvl);
66 current_entry = Process->ThreadListHead.Flink;
70 current_entry = current_entry->Flink;
73 KeReleaseSpinLock(&PiThreadListLock, oldlvl);
74 DPRINT("Finished PiTerminateProcessThreads()\n");
80 PLIST_ENTRY current_entry;
84 KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
86 current_entry = PiThreadListHead.Flink;
88 while (current_entry != &PiThreadListHead)
90 current = CONTAINING_RECORD(current_entry, ETHREAD,
93 current_entry = current_entry->Flink;
95 if (current->Tcb.State == THREAD_STATE_TERMINATED_1)
97 PEPROCESS Process = current->ThreadsProcess;
98 NTSTATUS Status = current->ExitStatus;
100 PiNrThreadsAwaitingReaping--;
101 current->Tcb.State = THREAD_STATE_TERMINATED_2;
102 RemoveEntryList(¤t->Tcb.ProcessThreadListEntry);
103 if (IsListEmpty(&Process->ThreadListHead))
105 KeReleaseSpinLock( &PiThreadListLock, oldIrql );
106 PiTerminateProcess(Process, Status);
107 KeAcquireSpinLock( &PiThreadListLock, &oldIrql );
109 KeReleaseSpinLock(&PiThreadListLock, oldIrql);
110 ObDereferenceObject(current);
111 KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
112 current_entry = PiThreadListHead.Flink;
115 KeReleaseSpinLock(&PiThreadListLock, oldIrql);
119 PsTerminateCurrentThread(NTSTATUS ExitStatus)
121 * FUNCTION: Terminates the current thread
125 PETHREAD CurrentThread;
127 PLIST_ENTRY current_entry;
130 CurrentThread = PsGetCurrentThread();
132 DPRINT("terminating %x\n",CurrentThread);
133 KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
135 CurrentThread->ExitStatus = ExitStatus;
136 Thread = KeGetCurrentThread();
137 KeCancelTimer(&Thread->Timer);
138 KeReleaseSpinLock(&PiThreadListLock, oldIrql);
140 /* abandon all owned mutants */
141 current_entry = Thread->MutantListHead.Flink;
142 while (current_entry != &Thread->MutantListHead)
144 Mutant = CONTAINING_RECORD(current_entry, KMUTANT,
146 KeReleaseMutant(Mutant,
150 current_entry = Thread->MutantListHead.Flink;
153 KeAcquireDispatcherDatabaseLock(FALSE);
154 CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE;
155 KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader);
156 KeReleaseDispatcherDatabaseLock(FALSE);
158 KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
159 PsDispatchThreadNoLock(THREAD_STATE_TERMINATED_1);
164 PiTerminateThreadRundownRoutine(PKAPC Apc)
170 PiTerminateThreadKernelRoutine(PKAPC Apc,
171 PKNORMAL_ROUTINE* NormalRoutine,
172 PVOID* NormalContext,
173 PVOID* SystemArgument1,
174 PVOID* SystemArguemnt2)
180 PiTerminateThreadNormalRoutine(PVOID NormalContext,
181 PVOID SystemArgument1,
182 PVOID SystemArgument2)
184 PsTerminateCurrentThread(PsGetCurrentThread()->ExitStatus);
188 PsTerminateOtherThread(PETHREAD Thread,
191 * FUNCTION: Terminate a thread when calling from another thread's context
192 * NOTES: This function must be called with PiThreadListLock held
197 DPRINT("PsTerminateOtherThread(Thread %x, ExitStatus %x)\n",
200 Thread->DeadThread = 1;
201 Thread->ExitStatus = ExitStatus;
202 Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_TERMINATE_APC);
206 PiTerminateThreadKernelRoutine,
207 PiTerminateThreadRundownRoutine,
208 PiTerminateThreadNormalRoutine,
211 KeInsertQueueApc(Apc,
218 PiTerminateProcess(PEPROCESS Process,
221 DPRINT("PiTerminateProcess(Process %x, ExitStatus %x) PC %d HC %d\n",
222 Process, ExitStatus, ObGetObjectPointerCount(Process),
223 ObGetObjectHandleCount(Process));
225 ObReferenceObject(Process);
226 if (InterlockedExchange((PLONG)&Process->Pcb.State,
227 PROCESS_STATE_TERMINATED) ==
228 PROCESS_STATE_TERMINATED)
230 ObDereferenceObject(Process);
231 return(STATUS_SUCCESS);
233 KeAttachProcess( Process );
234 ObCloseAllHandles(Process);
236 KeAcquireDispatcherDatabaseLock(FALSE);
237 Process->Pcb.DispatcherHeader.SignalState = TRUE;
238 KeDispatcherObjectWake(&Process->Pcb.DispatcherHeader);
239 KeReleaseDispatcherDatabaseLock(FALSE);
240 ObDereferenceObject(Process);
241 return(STATUS_SUCCESS);
245 NtTerminateProcess(IN HANDLE ProcessHandle,
246 IN NTSTATUS ExitStatus)
251 DPRINT("NtTerminateProcess(ProcessHandle %x, ExitStatus %x)\n",
252 ProcessHandle, ExitStatus);
254 Status = ObReferenceObjectByHandle(ProcessHandle,
260 if (!NT_SUCCESS(Status))
264 Process->ExitStatus = ExitStatus;
265 PiTerminateProcessThreads(Process, ExitStatus);
266 if (PsGetCurrentThread()->ThreadsProcess == Process)
268 ObDereferenceObject(Process);
269 PsTerminateCurrentThread(ExitStatus);
271 ObDereferenceObject(Process);
272 return(STATUS_SUCCESS);
277 NtTerminateThread(IN HANDLE ThreadHandle,
278 IN NTSTATUS ExitStatus)
283 Status = ObReferenceObjectByHandle(ThreadHandle,
289 if (Status != STATUS_SUCCESS)
294 ObDereferenceObject(Thread);
296 if (Thread == PsGetCurrentThread())
298 PsTerminateCurrentThread(ExitStatus);
302 PsTerminateOtherThread(Thread, ExitStatus);
304 return(STATUS_SUCCESS);
309 PsTerminateSystemThread(NTSTATUS ExitStatus)
311 * FUNCTION: Terminates the current thread
313 * ExitStatus = Status to pass to the creater
317 PsTerminateCurrentThread(ExitStatus);
318 return(STATUS_SUCCESS);
322 NtCallTerminatePorts(PETHREAD Thread)
325 PLIST_ENTRY current_entry;
326 PEPORT_TERMINATION_REQUEST current;
328 KeAcquireSpinLock(&Thread->ActiveTimerListLock, &oldIrql);
329 while ((current_entry = RemoveHeadList(&Thread->TerminationPortList)) !=
330 &Thread->TerminationPortList);
332 current = CONTAINING_RECORD(current_entry,
333 EPORT_TERMINATION_REQUEST,
335 KeReleaseSpinLock(&Thread->ActiveTimerListLock, oldIrql);
336 LpcSendTerminationPort(current->Port,
338 KeAcquireSpinLock(&Thread->ActiveTimerListLock, &oldIrql);
340 KeReleaseSpinLock(&Thread->ActiveTimerListLock, oldIrql);
341 return(STATUS_SUCCESS);
345 NtRegisterThreadTerminatePort(HANDLE TerminationPortHandle)
348 PEPORT_TERMINATION_REQUEST Request;
349 PEPORT TerminationPort;
353 Status = ObReferenceObjectByHandle(TerminationPortHandle,
357 (PVOID*)&TerminationPort,
359 if (!NT_SUCCESS(Status))
364 Request = ExAllocatePool(NonPagedPool, sizeof(EPORT_TERMINATION_REQUEST));
365 Request->Port = TerminationPort;
366 Thread = PsGetCurrentThread();
367 KeAcquireSpinLock(&Thread->ActiveTimerListLock, &oldIrql);
368 InsertTailList(&Thread->TerminationPortList, &Request->ThreadListEntry);
369 KeReleaseSpinLock(&Thread->ActiveTimerListLock, oldIrql);
371 return(STATUS_SUCCESS);