missing initialization of Thread->Tcb.WaitBlockList
[reactos.git] / reactos / ntoskrnl / ps / create.c
1 /* $Id: create.c,v 1.2 1999/12/14 18:35:19 phreak Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/thread.c
6 * PURPOSE: Thread managment
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * REVISION HISTORY:
9 * 23/06/98: Created
10 * 12/10/99: Phillip Susi: Thread priorities, and APC work
11 */
12
13 /*
14 * NOTE:
15 *
16 * All of the routines that manipulate the thread queue synchronize on
17 * a single spinlock
18 *
19 */
20
21 /* INCLUDES ****************************************************************/
22
23 #include <ddk/ntddk.h>
24 #include <internal/ke.h>
25 #include <internal/ob.h>
26 #include <string.h>
27 #include <internal/string.h>
28 #include <internal/hal.h>
29 #include <internal/ps.h>
30 #include <internal/ob.h>
31
32 #define NDEBUG
33 #include <internal/debug.h>
34
35 /* GLOBAL *******************************************************************/
36
37 static ULONG PiNextThreadUniqueId = 0;
38
39 extern KSPIN_LOCK PiThreadListLock;
40 extern ULONG PiNrThreads;
41
42 extern LIST_ENTRY PiThreadListHead;
43
44 /* FUNCTIONS ***************************************************************/
45
46 static VOID PiTimeoutThread( struct _KDPC *dpc, PVOID Context, PVOID arg1, PVOID arg2 )
47 {
48 // wake up the thread, and tell it it timed out
49 NTSTATUS Status = STATUS_TIMEOUT;
50 PsUnfreezeThread( (ETHREAD *)Context, &Status );
51 }
52
53 VOID PiBeforeBeginThread(VOID)
54 {
55 DPRINT("PiBeforeBeginThread()\n");
56 //KeReleaseSpinLock(&PiThreadListLock, PASSIVE_LEVEL);
57 KeLowerIrql(PASSIVE_LEVEL);
58 DPRINT("KeGetCurrentIrql() %d\n", KeGetCurrentIrql());
59 }
60
61 VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext)
62 {
63 NTSTATUS Ret;
64
65 // KeReleaseSpinLock(&PiThreadListLock,PASSIVE_LEVEL);
66 KeLowerIrql(PASSIVE_LEVEL);
67 Ret = StartRoutine(StartContext);
68 PsTerminateSystemThread(Ret);
69 KeBugCheck(0);
70 }
71
72 VOID PiDeleteThread(PVOID ObjectBody)
73 {
74 KIRQL oldIrql;
75 DPRINT("PiDeleteThread(ObjectBody %x)\n",ObjectBody);
76
77 KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
78 ObDereferenceObject(((PETHREAD)ObjectBody)->ThreadsProcess);
79 ((PETHREAD)ObjectBody)->ThreadsProcess = NULL;
80 PiNrThreads--;
81 RemoveEntryList(&((PETHREAD)ObjectBody)->Tcb.ThreadListEntry);
82 HalReleaseTask((PETHREAD)ObjectBody);
83 KeReleaseSpinLock(&PiThreadListLock, oldIrql);
84 }
85
86 VOID PiCloseThread(PVOID ObjectBody, ULONG HandleCount)
87 {
88 DPRINT("PiCloseThread(ObjectBody %x)\n", ObjectBody);
89 DPRINT("ObGetReferenceCount(ObjectBody) %d "
90 "ObGetHandleCount(ObjectBody) %d\n",
91 ObGetReferenceCount(ObjectBody),
92 ObGetHandleCount(ObjectBody));
93 }
94
95 NTSTATUS PsInitializeThread(HANDLE ProcessHandle,
96 PETHREAD * ThreadPtr,
97 PHANDLE ThreadHandle,
98 ACCESS_MASK DesiredAccess,
99 POBJECT_ATTRIBUTES ThreadAttributes)
100 {
101 PETHREAD Thread;
102 NTSTATUS Status;
103 KIRQL oldIrql;
104 PEPROCESS Process;
105
106 /*
107 * Reference process
108 */
109 if (ProcessHandle != NULL)
110 {
111 Status = ObReferenceObjectByHandle(ProcessHandle,
112 PROCESS_CREATE_THREAD,
113 PsProcessType,
114 UserMode,
115 (PVOID*)&Process,
116 NULL);
117 if (Status != STATUS_SUCCESS)
118 {
119 DPRINT("Failed at %s:%d\n",__FILE__,__LINE__);
120 return(Status);
121 }
122 }
123 else
124 {
125 Process = SystemProcess;
126 ObReferenceObjectByPointer(Process,
127 PROCESS_CREATE_THREAD,
128 PsProcessType,
129 UserMode);
130 }
131
132 /*
133 * Create and initialize thread
134 */
135 Thread = ObCreateObject(ThreadHandle,
136 DesiredAccess,
137 ThreadAttributes,
138 PsThreadType);
139 DPRINT("Thread = %x\n",Thread);
140
141 PiNrThreads++;
142
143 Thread->Tcb.State = THREAD_STATE_SUSPENDED;
144 Thread->Tcb.SuspendCount = 0;
145 Thread->Tcb.FreezeCount = 1;
146 InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[0]);
147 InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[1]);
148 Thread->Tcb.KernelApcDisable = 1;
149 Thread->Tcb.WaitIrql = PASSIVE_LEVEL;
150 Thread->ThreadsProcess = Process;
151 KeInitializeDpc( &Thread->Tcb.TimerDpc, PiTimeoutThread, Thread );
152 Thread->Tcb.WaitBlockList = NULL;
153
154 KeInitializeDispatcherHeader(&Thread->Tcb.DispatcherHeader,
155 InternalThreadType,
156 sizeof(ETHREAD),
157 FALSE);
158
159 InitializeListHead(&Thread->IrpList);
160 Thread->Cid.UniqueThread = (HANDLE)InterlockedIncrement(
161 &PiNextThreadUniqueId);
162 Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
163 DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread);
164
165 *ThreadPtr = Thread;
166
167 KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
168 InsertTailList(&PiThreadListHead, &Thread->Tcb.ThreadListEntry);
169 KeReleaseSpinLock(&PiThreadListLock, oldIrql);
170
171 Thread->Tcb.BasePriority = Thread->ThreadsProcess->Pcb.BasePriority;
172 Thread->Tcb.Priority = Thread->Tcb.BasePriority;
173
174 return(STATUS_SUCCESS);
175 }
176
177
178 static NTSTATUS PsCreateTeb (HANDLE ProcessHandle,
179 PNT_TEB *TebPtr,
180 PETHREAD Thread,
181 PINITIAL_TEB InitialTeb)
182 {
183 MEMORY_BASIC_INFORMATION Info;
184 NTSTATUS Status;
185 ULONG ByteCount;
186 ULONG RegionSize;
187 ULONG TebSize;
188 PVOID TebBase;
189 NT_TEB Teb;
190
191 TebBase = (PVOID)0x7FFDE000;
192 TebSize = PAGESIZE;
193
194 while (TRUE)
195 {
196 /* The TEB must reside in user space */
197 Status = NtAllocateVirtualMemory(ProcessHandle,
198 &TebBase,
199 0,
200 &TebSize,
201 MEM_COMMIT,
202 PAGE_READWRITE);
203 if (NT_SUCCESS(Status))
204 {
205 DPRINT ("TEB allocated at %x\n", TebBase);
206 break;
207 }
208 else
209 {
210 DPRINT ("TEB allocation failed! Status %x\n",Status);
211 }
212
213 TebBase = Info.BaseAddress - TebSize;
214 }
215
216 DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize);
217
218 /* set all pointers to and from the TEB */
219 Teb.Tib.Self = TebBase;
220 if (Thread->ThreadsProcess)
221 {
222 Teb.Peb = Thread->ThreadsProcess->Peb; /* No PEB yet!! */
223 }
224
225 /* store stack information from InitialTeb */
226 if (InitialTeb != NULL)
227 {
228 Teb.Tib.StackBase = InitialTeb->StackBase;
229 Teb.Tib.StackLimit = InitialTeb->StackLimit;
230
231 /*
232 * I don't know if this is really stored in a WNT-TEB,
233 * but it's needed to free the thread stack. (Eric Kohl)
234 */
235 Teb.StackCommit = InitialTeb->StackCommit;
236 Teb.StackCommitMax = InitialTeb->StackCommitMax;
237 Teb.StackReserved = InitialTeb->StackReserved;
238 }
239
240
241 /* more initialization */
242 Teb.Cid.UniqueThread = Thread->Cid.UniqueThread;
243 Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess;
244
245 /* write TEB data into teb page */
246 Status = NtWriteVirtualMemory(ProcessHandle,
247 TebBase,
248 &Teb,
249 sizeof(NT_TEB),
250 &ByteCount);
251
252 if (!NT_SUCCESS(Status))
253 {
254 /* free TEB */
255 DPRINT ("Writing TEB failed!\n");
256
257 RegionSize = 0;
258 NtFreeVirtualMemory(ProcessHandle,
259 TebBase,
260 &RegionSize,
261 MEM_RELEASE);
262
263 return Status;
264 }
265
266 /* FIXME: fs:[0] = TEB */
267
268 if (TebPtr != NULL)
269 {
270 // *TebPtr = (PNT_TEB)TebBase;
271 }
272
273 DPRINT ("TEB allocated at %p\n", TebBase);
274
275 return Status;
276 }
277
278
279 NTSTATUS STDCALL NtCreateThread (PHANDLE ThreadHandle,
280 ACCESS_MASK DesiredAccess,
281 POBJECT_ATTRIBUTES ObjectAttributes,
282 HANDLE ProcessHandle,
283 PCLIENT_ID Client,
284 PCONTEXT ThreadContext,
285 PINITIAL_TEB InitialTeb,
286 BOOLEAN CreateSuspended)
287 {
288 PETHREAD Thread;
289 PNT_TEB TebBase;
290 NTSTATUS Status;
291
292 DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n",
293 ThreadHandle,ThreadContext);
294
295 Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle,
296 DesiredAccess,ObjectAttributes);
297 if (!NT_SUCCESS(Status))
298 {
299 return(Status);
300 }
301
302 Status = HalInitTaskWithContext(Thread,ThreadContext);
303 if (!NT_SUCCESS(Status))
304 {
305 return(Status);
306 }
307
308 Status = PsCreateTeb (ProcessHandle,
309 &TebBase,
310 Thread,
311 InitialTeb);
312 if (!NT_SUCCESS(Status))
313 {
314 return(Status);
315 }
316
317 /* Attention: TebBase is in user memory space */
318 // Thread->Tcb.Teb = TebBase;
319
320 Thread->StartAddress=NULL;
321
322 if (Client!=NULL)
323 {
324 *Client=Thread->Cid;
325 }
326
327 if (!CreateSuspended)
328 {
329 DPRINT("Not creating suspended\n");
330 PsUnfreezeThread(Thread, NULL);
331 }
332 DPRINT("Thread %x\n", Thread);
333 DPRINT("ObGetReferenceCount(Thread) %d ObGetHandleCount(Thread) %x\n",
334 ObGetReferenceCount(Thread), ObGetHandleCount(Thread));
335 DPRINT("Finished PsCreateThread()\n");
336 return(STATUS_SUCCESS);
337 }
338
339
340 NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle,
341 ACCESS_MASK DesiredAccess,
342 POBJECT_ATTRIBUTES ObjectAttributes,
343 HANDLE ProcessHandle,
344 PCLIENT_ID ClientId,
345 PKSTART_ROUTINE StartRoutine,
346 PVOID StartContext)
347 /*
348 * FUNCTION: Creates a thread which executes in kernel mode
349 * ARGUMENTS:
350 * ThreadHandle (OUT) = Caller supplied storage for the returned thread
351 * handle
352 * DesiredAccess = Requested access to the thread
353 * ObjectAttributes = Object attributes (optional)
354 * ProcessHandle = Handle of process thread will run in
355 * NULL to use system process
356 * ClientId (OUT) = Caller supplied storage for the returned client id
357 * of the thread (optional)
358 * StartRoutine = Entry point for the thread
359 * StartContext = Argument supplied to the thread when it begins
360 * execution
361 * RETURNS: Success or failure status
362 */
363 {
364 PETHREAD Thread;
365 NTSTATUS Status;
366
367 DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n",
368 ThreadHandle,ProcessHandle);
369
370 Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle,
371 DesiredAccess,ObjectAttributes);
372 if (!NT_SUCCESS(Status))
373 {
374 return(Status);
375 }
376
377 Thread->StartAddress=StartRoutine;
378 Status = HalInitTask(Thread,StartRoutine,StartContext);
379 if (!NT_SUCCESS(Status))
380 {
381 return(Status);
382 }
383
384 if (ClientId!=NULL)
385 {
386 *ClientId=Thread->Cid;
387 }
388
389 PsUnfreezeThread(Thread, NULL);
390
391 return(STATUS_SUCCESS);
392 }
393