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>
18 #include <internal/port.h>
21 #include <internal/debug.h>
23 /* GLOBALS *******************************************************************/
25 extern ULONG PiNrThreads
;
26 extern ULONG PiNrRunnableThreads
;
27 extern KSPIN_LOCK PiThreadListLock
;
28 extern LIST_ENTRY PiThreadListHead
;
29 extern KSPIN_LOCK PiApcLock
;
31 VOID
PsTerminateCurrentThread(NTSTATUS ExitStatus
);
33 /* FUNCTIONS *****************************************************************/
35 VOID
PiTerminateProcessThreads(PEPROCESS Process
, NTSTATUS ExitStatus
)
38 PLIST_ENTRY current_entry
;
41 DPRINT("PiTerminateProcessThreads(Process %x, ExitStatus %x)\n",
44 KeAcquireSpinLock(&PiThreadListLock
, &oldlvl
);
46 current_entry
= Process
->ThreadListHead
.Flink
;
47 while (current_entry
!= &Process
->ThreadListHead
)
49 current
= CONTAINING_RECORD(current_entry
,ETHREAD
,Tcb
.ProcessThreadListEntry
);
50 if (current
!= PsGetCurrentThread())
52 DPRINT("Terminating %x, current thread: %x, thread's process: %x\n", current
, PsGetCurrentThread(), current
->ThreadsProcess
);
53 PsTerminateOtherThread(current
, ExitStatus
);
55 current_entry
= current_entry
->Flink
;
57 KeReleaseSpinLock(&PiThreadListLock
, oldlvl
);
58 DPRINT("Finished PiTerminateProcessThreads()\n");
61 VOID
PsReapThreads(VOID
)
63 PLIST_ENTRY current_entry
;
67 // DPRINT1("PsReapThreads()\n");
69 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
71 current_entry
= PiThreadListHead
.Flink
;
73 while (current_entry
!= &PiThreadListHead
)
75 current
= CONTAINING_RECORD(current_entry
, ETHREAD
,
78 current_entry
= current_entry
->Flink
;
80 if (current
->Tcb
.State
== THREAD_STATE_TERMINATED_1
)
82 PEPROCESS Process
= current
->ThreadsProcess
;
83 NTSTATUS Status
= current
->ExitStatus
;
85 DPRINT("PsProcessType %x\n", PsProcessType
);
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 if (IsListEmpty(&Process
->ThreadListHead
))
92 DPRINT("Last thread terminated, terminating process\n");
93 KeReleaseSpinLock( &PiThreadListLock
, oldIrql
);
94 PiTerminateProcess(Process
, Status
);
95 KeAcquireSpinLock( &PiThreadListLock
, &oldIrql
);
97 DPRINT("Ref count %d\n", ObGetReferenceCount(Process
));
98 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
99 ObDereferenceObject(current
);
100 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
101 current_entry
= PiThreadListHead
.Flink
;
104 KeReleaseSpinLock(&PiThreadListLock
, oldIrql
);
107 VOID
PsTerminateCurrentThread(NTSTATUS ExitStatus
)
109 * FUNCTION: Terminates the current thread
113 PETHREAD CurrentThread
;
115 CurrentThread
= PsGetCurrentThread();
117 DPRINT("terminating %x\n",CurrentThread
);
118 KeAcquireSpinLock(&PiThreadListLock
, &oldIrql
);
120 CurrentThread
->ExitStatus
= ExitStatus
;
121 KeAcquireDispatcherDatabaseLock(FALSE
);
122 CurrentThread
->Tcb
.DispatcherHeader
.SignalState
= TRUE
;
123 KeDispatcherObjectWake(&CurrentThread
->Tcb
.DispatcherHeader
);
124 KeReleaseDispatcherDatabaseLock(FALSE
);
126 PsDispatchThreadNoLock(THREAD_STATE_TERMINATED_1
);
130 VOID
PsTerminateOtherThread(PETHREAD Thread
, NTSTATUS ExitStatus
)
132 * FUNCTION: Terminate a thread when calling from another thread's context
137 DPRINT("PsTerminateOtherThread(Thread %x, ExitStatus %x)\n",
140 KeAcquireSpinLock( &PiThreadListLock
, &oldIrql
);
141 Thread
->DeadThread
= 1;
142 Thread
->ExitStatus
= ExitStatus
;
143 if( Thread
->Tcb
.State
== THREAD_STATE_FROZEN
&& (Thread
->Tcb
.Alertable
|| Thread
->Tcb
.WaitMode
== UserMode
) )
144 KeRemoveAllWaitsThread( Thread
, STATUS_ALERTED
);
145 KeReleaseSpinLock( &PiThreadListLock
, oldIrql
);
148 NTSTATUS STDCALL
PiTerminateProcess(PEPROCESS Process
,
151 DPRINT("PiTerminateProcess(Process %x, ExitStatus %x) RC %d HC %d\n",
152 Process
, ExitStatus
, ObGetReferenceCount(Process
),
153 ObGetHandleCount(Process
));
155 if (Process
->Pcb
.ProcessState
== PROCESS_STATE_TERMINATED
)
157 return(STATUS_SUCCESS
);
160 ObCloseAllHandles(Process
);
161 KeAcquireDispatcherDatabaseLock(FALSE
);
162 Process
->Pcb
.ProcessState
= PROCESS_STATE_TERMINATED
;
163 Process
->Pcb
.DispatcherHeader
.SignalState
= TRUE
;
164 KeDispatcherObjectWake(&Process
->Pcb
.DispatcherHeader
);
165 KeReleaseDispatcherDatabaseLock(FALSE
);
166 DPRINT("RC %d\n", ObGetReferenceCount(Process
));
167 return(STATUS_SUCCESS
);
170 NTSTATUS STDCALL
NtTerminateProcess(IN HANDLE ProcessHandle
,
171 IN NTSTATUS ExitStatus
)
176 DPRINT("NtTerminateProcess(ProcessHandle %x, ExitStatus %x)\n",
177 ProcessHandle
, ExitStatus
);
179 Status
= ObReferenceObjectByHandle(ProcessHandle
,
185 if (!NT_SUCCESS(Status
))
190 PiTerminateProcessThreads(Process
, ExitStatus
);
191 if( PsGetCurrentThread()->ThreadsProcess
== Process
)
193 ObDereferenceObject( Process
);
194 PsTerminateCurrentThread( ExitStatus
);
196 ObDereferenceObject(Process
);
197 return(STATUS_SUCCESS
);
201 NTSTATUS STDCALL
NtTerminateThread(IN HANDLE ThreadHandle
,
202 IN NTSTATUS ExitStatus
)
207 Status
= ObReferenceObjectByHandle(ThreadHandle
,
213 if (Status
!= STATUS_SUCCESS
)
218 ObDereferenceObject(Thread
);
220 if (Thread
== PsGetCurrentThread())
222 PsTerminateCurrentThread(ExitStatus
);
226 PsTerminateOtherThread(Thread
, ExitStatus
);
228 return(STATUS_SUCCESS
);
232 NTSTATUS STDCALL
PsTerminateSystemThread(NTSTATUS ExitStatus
)
234 * FUNCTION: Terminates the current thread
236 * ExitStatus = Status to pass to the creater
240 PsTerminateCurrentThread(ExitStatus
);
241 return(STATUS_SUCCESS
);
244 NTSTATUS STDCALL
NtCallTerminatePorts(PETHREAD Thread
)
247 PLIST_ENTRY current_entry
;
248 PEPORT_TERMINATION_REQUEST current
;
250 KeAcquireSpinLock(&Thread
->ActiveTimerListLock
, &oldIrql
);
251 while ((current_entry
= RemoveHeadList(&Thread
->TerminationPortList
)) !=
252 &Thread
->TerminationPortList
);
254 current
= CONTAINING_RECORD(current_entry
,
255 EPORT_TERMINATION_REQUEST
,
257 KeReleaseSpinLock(&Thread
->ActiveTimerListLock
, oldIrql
);
258 LpcSendTerminationPort(current
->Port
,
260 KeAcquireSpinLock(&Thread
->ActiveTimerListLock
, &oldIrql
);
262 KeReleaseSpinLock(&Thread
->ActiveTimerListLock
, oldIrql
);
263 return(STATUS_SUCCESS
);
266 NTSTATUS STDCALL
NtRegisterThreadTerminatePort(HANDLE TerminationPortHandle
)
269 PEPORT_TERMINATION_REQUEST Request
;
270 PEPORT TerminationPort
;
274 Status
= ObReferenceObjectByHandle(TerminationPortHandle
,
278 (PVOID
*)&TerminationPort
,
280 if (!NT_SUCCESS(Status
))
285 Request
= ExAllocatePool(NonPagedPool
, sizeof(Request
));
286 Request
->Port
= TerminationPort
;
287 Thread
= PsGetCurrentThread();
288 KeAcquireSpinLock(&Thread
->ActiveTimerListLock
, &oldIrql
);
289 InsertTailList(&Thread
->TerminationPortList
, &Request
->ThreadListEntry
);
290 KeReleaseSpinLock(&Thread
->ActiveTimerListLock
, oldIrql
);
292 return(STATUS_SUCCESS
);