3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/ps/suspend.c
23 * PURPOSE: Thread managment
24 * PROGRAMMER: David Welch (welch@mcmail.com)
27 /* INCLUDES ******************************************************************/
29 #include <ddk/ntddk.h>
30 #include <internal/ke.h>
31 #include <internal/ob.h>
32 #include <internal/ps.h>
33 #include <internal/ob.h>
36 #include <internal/debug.h>
38 /* NOTES **********************************************************************
42 /* GLOBALS *******************************************************************/
44 static FAST_MUTEX SuspendMutex;
46 /* FUNCTIONS *****************************************************************/
49 PiSuspendThreadRundownRoutine(PKAPC Apc)
55 PiSuspendThreadKernelRoutine(PKAPC Apc,
56 PKNORMAL_ROUTINE* NormalRoutine,
58 PVOID* SystemArgument1,
59 PVOID* SystemArguemnt2)
65 PiSuspendThreadNormalRoutine(PVOID NormalContext,
66 PVOID SystemArgument1,
67 PVOID SystemArgument2)
69 PETHREAD CurrentThread = PsGetCurrentThread();
70 while (CurrentThread->Tcb.SuspendCount > 0)
72 KeWaitForSingleObject(&CurrentThread->Tcb.SuspendSemaphore,
82 PsResumeThread(PETHREAD Thread, PULONG SuspendCount)
84 ExAcquireFastMutex(&SuspendMutex);
85 if (SuspendCount != NULL)
87 *SuspendCount = Thread->Tcb.SuspendCount;
89 if (Thread->Tcb.SuspendCount > 0)
91 Thread->Tcb.SuspendCount--;
92 if (Thread->Tcb.SuspendCount == 0)
94 KeReleaseSemaphore(&Thread->Tcb.SuspendSemaphore, IO_NO_INCREMENT,
98 ExReleaseFastMutex(&SuspendMutex);
99 return(STATUS_SUCCESS);
104 PsSuspendThread(PETHREAD Thread, PULONG PreviousSuspendCount)
108 ExAcquireFastMutex(&SuspendMutex);
109 OldValue = Thread->Tcb.SuspendCount;
110 Thread->Tcb.SuspendCount++;
111 if (!Thread->Tcb.SuspendApc.Inserted)
113 if (!KeInsertQueueApc(&Thread->Tcb.SuspendApc,
118 Thread->Tcb.SuspendCount--;
119 ExReleaseFastMutex(&SuspendMutex);
120 return(STATUS_THREAD_IS_TERMINATING);
123 ExReleaseFastMutex(&SuspendMutex);
124 if (PreviousSuspendCount != NULL)
126 *PreviousSuspendCount = OldValue;
128 return(STATUS_SUCCESS);
133 NtResumeThread(IN HANDLE ThreadHandle,
134 IN PULONG SuspendCount)
136 * FUNCTION: Decrements a thread's resume count
138 * ThreadHandle = Handle to the thread that should be resumed
139 * ResumeCount = The resulting resume count.
147 DPRINT("NtResumeThead(ThreadHandle %lx SuspendCount %p)\n",
148 ThreadHandle, SuspendCount);
150 Status = ObReferenceObjectByHandle(ThreadHandle,
151 THREAD_SUSPEND_RESUME,
156 if (!NT_SUCCESS(Status))
161 Status = PsResumeThread(Thread, &Count);
162 if (SuspendCount != NULL)
164 *SuspendCount = Count;
167 ObDereferenceObject((PVOID)Thread);
169 return(STATUS_SUCCESS);
174 NtSuspendThread(IN HANDLE ThreadHandle,
175 IN PULONG PreviousSuspendCount)
177 * FUNCTION: Increments a thread's suspend count
179 * ThreadHandle = Handle to the thread that should be resumed
180 * PreviousSuspendCount = The resulting/previous suspend count.
182 * A thread will be suspended if its suspend count is greater than 0.
183 * This procedure maps to the win32 SuspendThread function. (
184 * documentation about the the suspend count can be found here aswell )
185 * The suspend count is not increased if it is greater than
186 * MAXIMUM_SUSPEND_COUNT.
194 Status = ObReferenceObjectByHandle(ThreadHandle,
195 THREAD_SUSPEND_RESUME,
200 if (!NT_SUCCESS(Status))
205 Status = PsSuspendThread(Thread, &Count);
206 if (PreviousSuspendCount != NULL)
208 *PreviousSuspendCount = Count;
211 ObDereferenceObject((PVOID)Thread);
213 return(STATUS_SUCCESS);
217 PsInitialiseSuspendImplementation(VOID)
219 ExInitializeFastMutex(&SuspendMutex);