1 /* $Id: kill.c,v 1.52 2002/04/27 19:25:16 hbirr 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 *****************************************************************/
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 // DPRINT1("PsReapThreads()\n");
86 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
88 current_entry
= PiThreadListHead
.Flink
;
90 while (current_entry
!= &PiThreadListHead
)
92 current
= CONTAINING_RECORD(current_entry
, ETHREAD
,
95 current_entry
= current_entry
->Flink
;
97 if (current
->Tcb
.State
== THREAD_STATE_TERMINATED_1
)
99 PEPROCESS Process
= current
->ThreadsProcess
;
100 NTSTATUS Status
= current
->ExitStatus
;
102 DPRINT("PsProcessType %x\n", PsProcessType
);
103 DPRINT("Reaping thread %x\n", current
);
104 DPRINT("Pointer count %d\n", ObGetObjectPointerCount(Process
));
105 current
->Tcb
.State
= THREAD_STATE_TERMINATED_2
;
106 RemoveEntryList(¤t
->Tcb
.ProcessThreadListEntry
);
107 if (IsListEmpty(&Process
->ThreadListHead
))
109 DPRINT("Last thread terminated, terminating process\n");
110 KeReleaseSpinLock( &PiThreadListLock
, oldIrql
);
111 PiTerminateProcess(Process
, Status
);
112 KeAcquireSpinLock( &PiThreadListLock
, &oldIrql
);
114 DPRINT("Pointer count %d\n", ObGetObjectPointerCount(Process
));
115 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
116 ObDereferenceObject(current
);
117 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
118 current_entry
= PiThreadListHead
.Flink
;
121 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
125 PsTerminateCurrentThread(NTSTATUS ExitStatus
)
127 * FUNCTION: Terminates the current thread
131 PETHREAD CurrentThread
;
133 PLIST_ENTRY current_entry
;
136 CurrentThread
= PsGetCurrentThread();
138 DPRINT("terminating %x\n",CurrentThread
);
139 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
141 CurrentThread
->ExitStatus
= ExitStatus
;
142 Thread
= KeGetCurrentThread();
143 KeCancelTimer(&Thread
->Timer
);
144 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
146 /* abandon all owned mutants */
147 current_entry
= Thread
->MutantListHead
.Flink
;
148 while (current_entry
!= &Thread
->MutantListHead
)
150 Mutant
= CONTAINING_RECORD(current_entry
, KMUTANT
,
152 KeReleaseMutant(Mutant
,
156 current_entry
= Thread
->MutantListHead
.Flink
;
159 KeAcquireDispatcherDatabaseLock(FALSE
);
160 CurrentThread
->Tcb
.DispatcherHeader
.SignalState
= TRUE
;
161 KeDispatcherObjectWake(&CurrentThread
->Tcb
.DispatcherHeader
);
162 KeReleaseDispatcherDatabaseLock(FALSE
);
164 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
165 PsDispatchThreadNoLock(THREAD_STATE_TERMINATED_1
);
170 PiTerminateThreadRundownRoutine(PKAPC Apc
)
176 PiTerminateThreadKernelRoutine(PKAPC Apc
,
177 PKNORMAL_ROUTINE
* NormalRoutine
,
178 PVOID
* NormalContext
,
179 PVOID
* SystemArgument1
,
180 PVOID
* SystemArguemnt2
)
186 PiTerminateThreadNormalRoutine(PVOID NormalContext
,
187 PVOID SystemArgument1
,
188 PVOID SystemArgument2
)
190 PsTerminateCurrentThread(PsGetCurrentThread()->ExitStatus
);
194 PsTerminateOtherThread(PETHREAD Thread
,
197 * FUNCTION: Terminate a thread when calling from another thread's context
198 * NOTES: This function must be called with PiThreadListLock held
203 DPRINT("PsTerminateOtherThread(Thread %x, ExitStatus %x)\n",
206 Thread
->DeadThread
= 1;
207 Thread
->ExitStatus
= ExitStatus
;
208 Apc
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KAPC
), TAG_TERMINATE_APC
);
212 PiTerminateThreadKernelRoutine
,
213 PiTerminateThreadRundownRoutine
,
214 PiTerminateThreadNormalRoutine
,
217 KeInsertQueueApc(Apc
,
224 PiTerminateProcess(PEPROCESS Process
,
227 DPRINT("PiTerminateProcess(Process %x, ExitStatus %x) PC %d HC %d\n",
228 Process
, ExitStatus
, ObGetObjectPointerCount(Process
),
229 ObGetObjectHandleCount(Process
));
231 if (InterlockedExchange((PLONG
)&Process
->Pcb
.State
,
232 PROCESS_STATE_TERMINATED
) ==
233 PROCESS_STATE_TERMINATED
)
235 return(STATUS_SUCCESS
);
237 KeAttachProcess( Process
);
238 ObCloseAllHandles(Process
);
240 KeAcquireDispatcherDatabaseLock(FALSE
);
241 Process
->Pcb
.DispatcherHeader
.SignalState
= TRUE
;
242 KeDispatcherObjectWake(&Process
->Pcb
.DispatcherHeader
);
243 KeReleaseDispatcherDatabaseLock(FALSE
);
244 return(STATUS_SUCCESS
);
248 NtTerminateProcess(IN HANDLE ProcessHandle
,
249 IN NTSTATUS ExitStatus
)
254 DPRINT("NtTerminateProcess(ProcessHandle %x, ExitStatus %x)\n",
255 ProcessHandle
, ExitStatus
);
257 Status
= ObReferenceObjectByHandle(ProcessHandle
,
263 if (!NT_SUCCESS(Status
))
267 Process
->ExitStatus
= ExitStatus
;
268 PiTerminateProcessThreads(Process
, ExitStatus
);
269 if (PsGetCurrentThread()->ThreadsProcess
== Process
)
271 ObDereferenceObject(Process
);
272 PsTerminateCurrentThread(ExitStatus
);
274 ObDereferenceObject(Process
);
275 return(STATUS_SUCCESS
);
280 NtTerminateThread(IN HANDLE ThreadHandle
,
281 IN NTSTATUS ExitStatus
)
286 Status
= ObReferenceObjectByHandle(ThreadHandle
,
292 if (Status
!= STATUS_SUCCESS
)
297 ObDereferenceObject(Thread
);
299 if (Thread
== PsGetCurrentThread())
301 PsTerminateCurrentThread(ExitStatus
);
305 PsTerminateOtherThread(Thread
, ExitStatus
);
307 return(STATUS_SUCCESS
);
312 PsTerminateSystemThread(NTSTATUS ExitStatus
)
314 * FUNCTION: Terminates the current thread
316 * ExitStatus = Status to pass to the creater
320 PsTerminateCurrentThread(ExitStatus
);
321 return(STATUS_SUCCESS
);
325 NtCallTerminatePorts(PETHREAD Thread
)
328 PLIST_ENTRY current_entry
;
329 PEPORT_TERMINATION_REQUEST current
;
331 KeAcquireSpinLock(&Thread
->ActiveTimerListLock
, &oldIrql
);
332 while ((current_entry
= RemoveHeadList(&Thread
->TerminationPortList
)) !=
333 &Thread
->TerminationPortList
);
335 current
= CONTAINING_RECORD(current_entry
,
336 EPORT_TERMINATION_REQUEST
,
338 KeReleaseSpinLock(&Thread
->ActiveTimerListLock
, oldIrql
);
339 LpcSendTerminationPort(current
->Port
,
341 KeAcquireSpinLock(&Thread
->ActiveTimerListLock
, &oldIrql
);
343 KeReleaseSpinLock(&Thread
->ActiveTimerListLock
, oldIrql
);
344 return(STATUS_SUCCESS
);
348 NtRegisterThreadTerminatePort(HANDLE TerminationPortHandle
)
351 PEPORT_TERMINATION_REQUEST Request
;
352 PEPORT TerminationPort
;
356 Status
= ObReferenceObjectByHandle(TerminationPortHandle
,
360 (PVOID
*)&TerminationPort
,
362 if (!NT_SUCCESS(Status
))
367 Request
= ExAllocatePool(NonPagedPool
, sizeof(Request
));
368 Request
->Port
= TerminationPort
;
369 Thread
= PsGetCurrentThread();
370 KeAcquireSpinLock(&Thread
->ActiveTimerListLock
, &oldIrql
);
371 InsertTailList(&Thread
->TerminationPortList
, &Request
->ThreadListEntry
);
372 KeReleaseSpinLock(&Thread
->ActiveTimerListLock
, oldIrql
);
374 return(STATUS_SUCCESS
);