7e1d56ec5a539ce6914a91b7e7f2409e40d31177
[reactos.git] / reactos / ntoskrnl / ps / suspend.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/suspend.c
6 * PURPOSE: Thread managment
7 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* NOTES **********************************************************************
18 *
19 */
20
21 /* GLOBALS *******************************************************************/
22
23 static FAST_MUTEX SuspendMutex;
24
25 /* FUNCTIONS *****************************************************************/
26
27 VOID STDCALL
28 PiSuspendThreadRundownRoutine(PKAPC Apc)
29 {
30 }
31
32
33 VOID STDCALL
34 PiSuspendThreadKernelRoutine(PKAPC Apc,
35 PKNORMAL_ROUTINE* NormalRoutine,
36 PVOID* NormalContext,
37 PVOID* SystemArgument1,
38 PVOID* SystemArguemnt2)
39 {
40 }
41
42
43 VOID STDCALL
44 PiSuspendThreadNormalRoutine(PVOID NormalContext,
45 PVOID SystemArgument1,
46 PVOID SystemArgument2)
47 {
48 PETHREAD CurrentThread = PsGetCurrentThread();
49 while (CurrentThread->Tcb.SuspendCount > 0)
50 {
51 KeWaitForSingleObject(&CurrentThread->Tcb.SuspendSemaphore,
52 0,
53 UserMode,
54 TRUE,
55 NULL);
56 }
57 }
58
59
60 NTSTATUS
61 PsResumeThread (PETHREAD Thread,
62 PULONG SuspendCount)
63 {
64 DPRINT("PsResumeThread (Thread %p SuspendCount %p) called\n");
65
66 ExAcquireFastMutex (&SuspendMutex);
67
68 if (SuspendCount != NULL)
69 {
70 *SuspendCount = Thread->Tcb.SuspendCount;
71 }
72
73 if (Thread->Tcb.SuspendCount > 0)
74 {
75 Thread->Tcb.SuspendCount--;
76 if (Thread->Tcb.SuspendCount == 0)
77 {
78 KeReleaseSemaphore (&Thread->Tcb.SuspendSemaphore,
79 IO_NO_INCREMENT,
80 1,
81 FALSE);
82 }
83 }
84
85 ExReleaseFastMutex (&SuspendMutex);
86
87 return STATUS_SUCCESS;
88 }
89
90
91 NTSTATUS
92 PsSuspendThread(PETHREAD Thread, PULONG PreviousSuspendCount)
93 {
94 ULONG OldValue;
95
96 ExAcquireFastMutex(&SuspendMutex);
97 OldValue = Thread->Tcb.SuspendCount;
98 Thread->Tcb.SuspendCount++;
99 if (!Thread->Tcb.SuspendApc.Inserted)
100 {
101 if (!KeInsertQueueApc(&Thread->Tcb.SuspendApc,
102 NULL,
103 NULL,
104 IO_NO_INCREMENT))
105 {
106 Thread->Tcb.SuspendCount--;
107 ExReleaseFastMutex(&SuspendMutex);
108 return(STATUS_THREAD_IS_TERMINATING);
109 }
110 }
111 ExReleaseFastMutex(&SuspendMutex);
112 if (PreviousSuspendCount != NULL)
113 {
114 *PreviousSuspendCount = OldValue;
115 }
116 return(STATUS_SUCCESS);
117 }
118
119
120 NTSTATUS STDCALL
121 NtResumeThread(IN HANDLE ThreadHandle,
122 IN PULONG SuspendCount OPTIONAL)
123 /*
124 * FUNCTION: Decrements a thread's resume count
125 * ARGUMENTS:
126 * ThreadHandle = Handle to the thread that should be resumed
127 * ResumeCount = The resulting resume count.
128 * RETURNS: Status
129 */
130 {
131 PETHREAD Thread;
132 NTSTATUS Status;
133 ULONG Count;
134
135 PAGED_CODE();
136
137 DPRINT("NtResumeThead(ThreadHandle %lx SuspendCount %p)\n",
138 ThreadHandle, SuspendCount);
139
140 Status = ObReferenceObjectByHandle (ThreadHandle,
141 THREAD_SUSPEND_RESUME,
142 PsThreadType,
143 UserMode,
144 (PVOID*)&Thread,
145 NULL);
146 if (!NT_SUCCESS(Status))
147 {
148 return Status;
149 }
150
151 Status = PsResumeThread (Thread, &Count);
152 if (!NT_SUCCESS(Status))
153 {
154 ObDereferenceObject ((PVOID)Thread);
155 return Status;
156 }
157
158 if (SuspendCount != NULL)
159 {
160 *SuspendCount = Count;
161 }
162
163 ObDereferenceObject ((PVOID)Thread);
164
165 return STATUS_SUCCESS;
166 }
167
168
169 NTSTATUS STDCALL
170 NtSuspendThread(IN HANDLE ThreadHandle,
171 IN PULONG PreviousSuspendCount OPTIONAL)
172 /*
173 * FUNCTION: Increments a thread's suspend count
174 * ARGUMENTS:
175 * ThreadHandle = Handle to the thread that should be resumed
176 * PreviousSuspendCount = The resulting/previous suspend count.
177 * REMARK:
178 * A thread will be suspended if its suspend count is greater than 0.
179 * This procedure maps to the win32 SuspendThread function. (
180 * documentation about the the suspend count can be found here aswell )
181 * The suspend count is not increased if it is greater than
182 * MAXIMUM_SUSPEND_COUNT.
183 * RETURNS: Status
184 */
185 {
186 PETHREAD Thread;
187 NTSTATUS Status;
188 ULONG Count;
189
190 PAGED_CODE();
191
192 Status = ObReferenceObjectByHandle(ThreadHandle,
193 THREAD_SUSPEND_RESUME,
194 PsThreadType,
195 UserMode,
196 (PVOID*)&Thread,
197 NULL);
198 if (!NT_SUCCESS(Status))
199 {
200 return(Status);
201 }
202
203 Status = PsSuspendThread(Thread, &Count);
204 if (!NT_SUCCESS(Status))
205 {
206 ObDereferenceObject ((PVOID)Thread);
207 return Status;
208 }
209
210 if (PreviousSuspendCount != NULL)
211 {
212 *PreviousSuspendCount = Count;
213 }
214
215 ObDereferenceObject ((PVOID)Thread);
216
217 return STATUS_SUCCESS;
218 }
219
220 VOID INIT_FUNCTION
221 PsInitialiseSuspendImplementation(VOID)
222 {
223 ExInitializeFastMutex(&SuspendMutex);
224 }
225
226 /* EOF */