1 /* $Id: kill.c,v 1.56 2002/09/07 15:13:05 chorns Exp $
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 *****************************************************************/
17 #include <internal/debug.h>
20 /* GLOBALS *******************************************************************/
22 extern ULONG PiNrThreads
;
23 extern ULONG PiNrRunnableThreads
;
24 extern KSPIN_LOCK PiThreadListLock
;
25 extern LIST_ENTRY PiThreadListHead
;
26 extern KSPIN_LOCK PiApcLock
;
28 VOID
PsTerminateCurrentThread(NTSTATUS ExitStatus
);
30 #define TAG_TERMINATE_APC TAG('T', 'A', 'P', 'C')
32 /* FUNCTIONS *****************************************************************/
35 PiTerminateProcessThreads(PEPROCESS Process
,
39 PLIST_ENTRY current_entry
;
42 DPRINT("PiTerminateProcessThreads(Process %x, ExitStatus %x)\n",
45 KeAcquireSpinLock(&PiThreadListLock
, &oldlvl
);
47 current_entry
= Process
->ThreadListHead
.Flink
;
48 while (current_entry
!= &Process
->ThreadListHead
)
50 current
= CONTAINING_RECORD(current_entry
, ETHREAD
,
51 Tcb
.ProcessThreadListEntry
);
52 if (current
!= PsGetCurrentThread() &&
53 current
->DeadThread
== 0)
55 DPRINT("Terminating %x, current thread: %x, "
56 "thread's process: %x\n", current
, PsGetCurrentThread(),
57 current
->ThreadsProcess
);
58 KeReleaseSpinLock(&PiThreadListLock
, oldlvl
);
59 PsTerminateOtherThread(current
, ExitStatus
);
60 KeAcquireSpinLock(&PiThreadListLock
, &oldlvl
);
61 current_entry
= Process
->ThreadListHead
.Flink
;
65 current_entry
= current_entry
->Flink
;
68 KeReleaseSpinLock(&PiThreadListLock
, oldlvl
);
69 DPRINT("Finished PiTerminateProcessThreads()\n");
75 PLIST_ENTRY current_entry
;
79 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
81 current_entry
= PiThreadListHead
.Flink
;
83 while (current_entry
!= &PiThreadListHead
)
85 current
= CONTAINING_RECORD(current_entry
, ETHREAD
,
88 current_entry
= current_entry
->Flink
;
90 if (current
->Tcb
.State
== THREAD_STATE_TERMINATED_1
)
92 PEPROCESS Process
= current
->ThreadsProcess
;
93 NTSTATUS Status
= current
->ExitStatus
;
95 PiNrThreadsAwaitingReaping
--;
96 current
->Tcb
.State
= THREAD_STATE_TERMINATED_2
;
97 RemoveEntryList(¤t
->Tcb
.ProcessThreadListEntry
);
98 if (IsListEmpty(&Process
->ThreadListHead
))
100 KeReleaseSpinLock( &PiThreadListLock
, oldIrql
);
101 PiTerminateProcess(Process
, Status
);
102 KeAcquireSpinLock( &PiThreadListLock
, &oldIrql
);
104 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
105 ObDereferenceObject(current
);
106 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
107 current_entry
= PiThreadListHead
.Flink
;
110 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
114 PsTerminateCurrentThread(NTSTATUS ExitStatus
)
116 * FUNCTION: Terminates the current thread
120 PETHREAD CurrentThread
;
122 PLIST_ENTRY current_entry
;
125 CurrentThread
= PsGetCurrentThread();
127 DPRINT("terminating %x\n",CurrentThread
);
128 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
130 CurrentThread
->ExitStatus
= ExitStatus
;
131 Thread
= KeGetCurrentThread();
132 KeCancelTimer(&Thread
->Timer
);
133 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
135 /* abandon all owned mutants */
136 current_entry
= Thread
->MutantListHead
.Flink
;
137 while (current_entry
!= &Thread
->MutantListHead
)
139 Mutant
= CONTAINING_RECORD(current_entry
, KMUTANT
,
141 KeReleaseMutant(Mutant
,
145 current_entry
= Thread
->MutantListHead
.Flink
;
148 KeAcquireDispatcherDatabaseLock(FALSE
);
149 CurrentThread
->Tcb
.DispatcherHeader
.SignalState
= TRUE
;
150 KeDispatcherObjectWake(&CurrentThread
->Tcb
.DispatcherHeader
);
151 KeReleaseDispatcherDatabaseLock(FALSE
);
153 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
154 PsDispatchThreadNoLock(THREAD_STATE_TERMINATED_1
);
159 PiTerminateThreadRundownRoutine(PKAPC Apc
)
165 PiTerminateThreadKernelRoutine(PKAPC Apc
,
166 PKNORMAL_ROUTINE
* NormalRoutine
,
167 PVOID
* NormalContext
,
168 PVOID
* SystemArgument1
,
169 PVOID
* SystemArguemnt2
)
175 PiTerminateThreadNormalRoutine(PVOID NormalContext
,
176 PVOID SystemArgument1
,
177 PVOID SystemArgument2
)
179 PsTerminateCurrentThread(PsGetCurrentThread()->ExitStatus
);
183 PsTerminateOtherThread(PETHREAD Thread
,
186 * FUNCTION: Terminate a thread when calling from another thread's context
187 * NOTES: This function must be called with PiThreadListLock held
192 DPRINT("PsTerminateOtherThread(Thread %x, ExitStatus %x)\n",
195 Thread
->DeadThread
= 1;
196 Thread
->ExitStatus
= ExitStatus
;
197 Apc
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KAPC
), TAG_TERMINATE_APC
);
201 PiTerminateThreadKernelRoutine
,
202 PiTerminateThreadRundownRoutine
,
203 PiTerminateThreadNormalRoutine
,
206 KeInsertQueueApc(Apc
,
213 PiTerminateProcess(PEPROCESS Process
,
216 DPRINT("PiTerminateProcess(Process %x, ExitStatus %x) PC %d HC %d\n",
217 Process
, ExitStatus
, ObGetObjectPointerCount(Process
),
218 ObGetObjectHandleCount(Process
));
220 ObReferenceObject(Process
);
221 if (InterlockedExchange((PLONG
)&Process
->Pcb
.State
,
222 PROCESS_STATE_TERMINATED
) ==
223 PROCESS_STATE_TERMINATED
)
225 ObDereferenceObject(Process
);
226 return(STATUS_SUCCESS
);
228 KeAttachProcess( Process
);
229 ObCloseAllHandles(Process
);
231 KeAcquireDispatcherDatabaseLock(FALSE
);
232 Process
->Pcb
.DispatcherHeader
.SignalState
= TRUE
;
233 KeDispatcherObjectWake(&Process
->Pcb
.DispatcherHeader
);
234 KeReleaseDispatcherDatabaseLock(FALSE
);
235 ObDereferenceObject(Process
);
236 return(STATUS_SUCCESS
);
240 NtTerminateProcess(IN HANDLE ProcessHandle
,
241 IN NTSTATUS ExitStatus
)
246 DPRINT("NtTerminateProcess(ProcessHandle %x, ExitStatus %x)\n",
247 ProcessHandle
, ExitStatus
);
249 Status
= ObReferenceObjectByHandle(ProcessHandle
,
255 if (!NT_SUCCESS(Status
))
259 Process
->ExitStatus
= ExitStatus
;
260 PiTerminateProcessThreads(Process
, ExitStatus
);
261 if (PsGetCurrentThread()->ThreadsProcess
== Process
)
263 ObDereferenceObject(Process
);
264 PsTerminateCurrentThread(ExitStatus
);
266 ObDereferenceObject(Process
);
267 return(STATUS_SUCCESS
);
272 NtTerminateThread(IN HANDLE ThreadHandle
,
273 IN NTSTATUS ExitStatus
)
278 Status
= ObReferenceObjectByHandle(ThreadHandle
,
284 if (Status
!= STATUS_SUCCESS
)
289 ObDereferenceObject(Thread
);
291 if (Thread
== PsGetCurrentThread())
293 PsTerminateCurrentThread(ExitStatus
);
297 PsTerminateOtherThread(Thread
, ExitStatus
);
299 return(STATUS_SUCCESS
);
304 PsTerminateSystemThread(NTSTATUS ExitStatus
)
306 * FUNCTION: Terminates the current thread
308 * ExitStatus = Status to pass to the creater
312 PsTerminateCurrentThread(ExitStatus
);
313 return(STATUS_SUCCESS
);
317 NtCallTerminatePorts(PETHREAD Thread
)
320 PLIST_ENTRY current_entry
;
321 PEPORT_TERMINATION_REQUEST current
;
323 KeAcquireSpinLock(&Thread
->ActiveTimerListLock
, &oldIrql
);
324 while ((current_entry
= RemoveHeadList(&Thread
->TerminationPortList
)) !=
325 &Thread
->TerminationPortList
);
327 current
= CONTAINING_RECORD(current_entry
,
328 EPORT_TERMINATION_REQUEST
,
330 KeReleaseSpinLock(&Thread
->ActiveTimerListLock
, oldIrql
);
331 LpcSendTerminationPort(current
->Port
,
333 KeAcquireSpinLock(&Thread
->ActiveTimerListLock
, &oldIrql
);
335 KeReleaseSpinLock(&Thread
->ActiveTimerListLock
, oldIrql
);
336 return(STATUS_SUCCESS
);
340 NtRegisterThreadTerminatePort(HANDLE TerminationPortHandle
)
343 PEPORT_TERMINATION_REQUEST Request
;
344 PEPORT TerminationPort
;
348 Status
= ObReferenceObjectByHandle(TerminationPortHandle
,
352 (PVOID
*)&TerminationPort
,
354 if (!NT_SUCCESS(Status
))
359 Request
= ExAllocatePool(NonPagedPool
, sizeof(EPORT_TERMINATION_REQUEST
));
360 Request
->Port
= TerminationPort
;
361 Thread
= PsGetCurrentThread();
362 KeAcquireSpinLock(&Thread
->ActiveTimerListLock
, &oldIrql
);
363 InsertTailList(&Thread
->TerminationPortList
, &Request
->ThreadListEntry
);
364 KeReleaseSpinLock(&Thread
->ActiveTimerListLock
, oldIrql
);
366 return(STATUS_SUCCESS
);