2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ps/kill.c
5 * PURPOSE: Terminating a thread
6 * PROGRAMMER: David Welch (welch@cwcom.net)
11 /* INCLUDES *****************************************************************/
13 #include <ddk/ntddk.h>
14 #include <internal/ps.h>
15 #include <internal/ke.h>
16 #include <internal/mm.h>
17 #include <internal/ob.h>
20 #include <internal/debug.h>
22 /* GLOBALS *******************************************************************/
24 extern ULONG PiNrThreads
;
25 extern ULONG PiNrRunnableThreads
;
26 extern KSPIN_LOCK PiThreadListLock
;
27 extern LIST_ENTRY PiThreadListHead
;
29 /* FUNCTIONS *****************************************************************/
31 VOID
PiTerminateProcessThreads(PEPROCESS Process
, NTSTATUS ExitStatus
)
34 PLIST_ENTRY current_entry
;
37 KeAcquireSpinLock(&PiThreadListLock
, &oldlvl
);
39 current_entry
= PiThreadListHead
.Flink
;
40 while (current_entry
!= &PiThreadListHead
)
42 current
= CONTAINING_RECORD(current_entry
,ETHREAD
,Tcb
.QueueListEntry
);
43 if (current
->ThreadsProcess
== Process
&&
44 current
!= PsGetCurrentThread())
46 KeReleaseSpinLock(&PiThreadListLock
, oldlvl
);
47 PsTerminateOtherThread(current
, ExitStatus
);
48 KeAcquireSpinLock(&PiThreadListLock
, &oldlvl
);
49 current_entry
= PiThreadListHead
.Flink
;
51 current_entry
= current_entry
->Flink
;
54 KeReleaseSpinLock(&PiThreadListLock
, oldlvl
);
57 VOID
PsReapThreads(VOID
)
59 PLIST_ENTRY current_entry
;
63 // DPRINT1("PsReapThreads()\n");
65 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
67 current_entry
= PiThreadListHead
.Flink
;
69 while (current_entry
!= &PiThreadListHead
)
71 current
= CONTAINING_RECORD(current_entry
, ETHREAD
,
74 current_entry
= current_entry
->Flink
;
76 if (current
->Tcb
.State
== THREAD_STATE_TERMINATED_1
)
78 PEPROCESS Process
= current
->ThreadsProcess
;
79 NTSTATUS Status
= current
->ExitStatus
;
81 DPRINT("PsProcessType %x\n", PsProcessType
);
82 ObReferenceObjectByPointer(Process
,
86 DPRINT("Reaping thread %x\n", current
);
87 DPRINT("Ref count %d\n", ObGetReferenceCount(Process
));
88 current
->Tcb
.State
= THREAD_STATE_TERMINATED_2
;
89 RemoveEntryList(¤t
->Tcb
.ProcessThreadListEntry
);
90 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
91 ObDereferenceObject(current
);
92 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
93 if(IsListEmpty(&Process
->Pcb
.ThreadListHead
))
96 * TODO: Optimize this so it doesnt jerk the IRQL around so
99 DPRINT("Last thread terminated, terminating process\n");
100 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
101 PiTerminateProcess(Process
, Status
);
102 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
104 DPRINT("Ref count %d\n", ObGetReferenceCount(Process
));
105 ObDereferenceObject(Process
);
106 current_entry
= PiThreadListHead
.Flink
;
109 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
112 VOID
PsTerminateCurrentThread(NTSTATUS ExitStatus
)
114 * FUNCTION: Terminates the current thread
118 PETHREAD CurrentThread
;
120 CurrentThread
= PsGetCurrentThread();
122 DPRINT("terminating %x\n",CurrentThread
);
123 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
125 CurrentThread
->ExitStatus
= ExitStatus
;
127 DPRINT("ObGetReferenceCount(CurrentThread) %d\n",
128 ObGetReferenceCount(CurrentThread
));
129 DPRINT("ObGetHandleCount(CurrentThread) %x\n",
130 ObGetHandleCount(CurrentThread
));
132 CurrentThread
->Tcb
.DispatcherHeader
.SignalState
= TRUE
;
133 KeDispatcherObjectWake(&CurrentThread
->Tcb
.DispatcherHeader
);
136 BODY_TO_HEADER(CurrentThread
->ThreadsProcess
)->ObjectType
);
138 PsDispatchThreadNoLock(THREAD_STATE_TERMINATED_1
);
142 VOID
PsTerminateOtherThread(PETHREAD Thread
, NTSTATUS ExitStatus
)
144 * FUNCTION: Terminate a thread when calling from that thread's context
149 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
150 if (Thread
->Tcb
.State
== THREAD_STATE_RUNNABLE
)
152 RemoveEntryList(&Thread
->Tcb
.QueueListEntry
);
154 RemoveEntryList(&Thread
->Tcb
.ProcessThreadListEntry
);
155 Thread
->Tcb
.State
= THREAD_STATE_TERMINATED_2
;
156 Thread
->Tcb
.DispatcherHeader
.SignalState
= TRUE
;
157 KeDispatcherObjectWake(&Thread
->Tcb
.DispatcherHeader
);
158 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
159 if (IsListEmpty(&Thread
->ThreadsProcess
->Pcb
.ThreadListHead
))
161 PiTerminateProcess(Thread
->ThreadsProcess
, ExitStatus
);
163 ObDereferenceObject(Thread
);
166 NTSTATUS STDCALL
PiTerminateProcess(PEPROCESS Process
,
171 DPRINT("PsTerminateProcess(Process %x, ExitStatus %x)\n",
172 Process
, ExitStatus
);
174 if (Process
->Pcb
.ProcessState
== PROCESS_STATE_TERMINATED
)
176 return(STATUS_SUCCESS
);
179 PiTerminateProcessThreads(Process
, ExitStatus
);
180 ObCloseAllHandles(Process
);
181 KeRaiseIrql(DISPATCH_LEVEL
, &oldlvl
);
182 Process
->Pcb
.ProcessState
= PROCESS_STATE_TERMINATED
;
183 Process
->Pcb
.DispatcherHeader
.SignalState
= TRUE
;
184 DPRINT("Type %x\n", BODY_TO_HEADER(Process
)->ObjectType
);
185 KeDispatcherObjectWake(&Process
->Pcb
.DispatcherHeader
);
187 DPRINT("Type %x\n", BODY_TO_HEADER(Process
)->ObjectType
);
188 return(STATUS_SUCCESS
);
191 NTSTATUS STDCALL
NtTerminateProcess(IN HANDLE ProcessHandle
,
192 IN NTSTATUS ExitStatus
)
197 DPRINT("NtTerminateProcess(ProcessHandle %x, ExitStatus %x)\n",
198 ProcessHandle
, ExitStatus
);
200 Status
= ObReferenceObjectByHandle(ProcessHandle
,
206 if (Status
!= STATUS_SUCCESS
)
211 PiTerminateProcess(Process
, ExitStatus
);
212 if (PsGetCurrentThread()->ThreadsProcess
== Process
)
214 DPRINT("Type %x\n", BODY_TO_HEADER(Process
)->ObjectType
);
215 ObDereferenceObject(Process
);
216 DPRINT("Type %x\n", BODY_TO_HEADER(Process
)->ObjectType
);
217 PsTerminateCurrentThread(ExitStatus
);
219 ObDereferenceObject(Process
);
220 return(STATUS_SUCCESS
);
224 NTSTATUS STDCALL
NtTerminateThread(IN HANDLE ThreadHandle
,
225 IN NTSTATUS ExitStatus
)
230 Status
= ObReferenceObjectByHandle(ThreadHandle
,
236 if (Status
!= STATUS_SUCCESS
)
241 ObDereferenceObject(Thread
);
243 if (Thread
== PsGetCurrentThread())
245 PsTerminateCurrentThread(ExitStatus
);
249 PsTerminateOtherThread(Thread
, ExitStatus
);
251 return(STATUS_SUCCESS
);
255 NTSTATUS
PsTerminateSystemThread(NTSTATUS ExitStatus
)
257 * FUNCTION: Terminates the current thread
259 * ExitStatus = Status to pass to the creater
263 PsTerminateCurrentThread(ExitStatus
);
264 return(STATUS_SUCCESS
);
268 NTSTATUS STDCALL
NtRegisterThreadTerminatePort(HANDLE TerminationPort
)