Lock address space before calling MmCreateMemoryArea.
[reactos.git] / reactos / ntoskrnl / ke / kthread.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2000 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /*
20 * FILE: ntoskrnl/ke/kthread.c
21 * PURPOSE: Microkernel thread support
22 * PROGRAMMER: David Welch (welch@cwcom.net)
23 * UPDATE HISTORY:
24 * Created 22/05/98
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #include <ddk/ntddk.h>
30 #include <internal/ke.h>
31 #include <internal/ps.h>
32 #include <internal/id.h>
33 #include <internal/pool.h>
34
35 #define NDEBUG
36 #include <internal/debug.h>
37
38 /* EXTERN ********************************************************************/
39
40 extern VOID
41 PiTimeoutThread(struct _KDPC Dpc, PVOID Context, PVOID Arg1, PVOID Arg2);
42 VOID
43 PiSuspendThreadRundownRoutine(PKAPC Apc);
44 VOID
45 PiSuspendThreadKernelRoutine(PKAPC Apc,
46 PKNORMAL_ROUTINE* NormalRoutine,
47 PVOID* NormalContext,
48 PVOID* SystemArgument1,
49 PVOID* SystemArguemnt2);
50 VOID
51 PiSuspendThreadNormalRoutine(PVOID NormalContext,
52 PVOID SystemArgument1,
53 PVOID SystemArgument2);
54
55 /* FUNCTIONS *****************************************************************/
56
57 VOID
58 KeFreeStackPage(PVOID Context, PVOID Address, ULONG PhysAddr)
59 {
60 if (PhysAddr != 0)
61 {
62 MmDereferencePage((PVOID)PhysAddr);
63 }
64 }
65
66 NTSTATUS
67 HalReleaseTask(PETHREAD Thread)
68 /*
69 * FUNCTION: Releases the resource allocated for a thread by
70 * HalInitTaskWithContext or HalInitTask
71 * NOTE: The thread had better not be running when this is called
72 */
73 {
74 extern unsigned int init_stack;
75
76 if (Thread->Tcb.StackLimit != (ULONG)&init_stack)
77 {
78 MmFreeMemoryArea(MmGetKernelAddressSpace(),
79 (PVOID)Thread->Tcb.StackLimit,
80 MM_STACK_SIZE,
81 KeFreeStackPage,
82 NULL);
83 }
84 Thread->Tcb.StackLimit = 0;
85 Thread->Tcb.InitialStack = NULL;
86 Thread->Tcb.StackBase = NULL;
87 Thread->Tcb.KernelStack = NULL;
88 return(STATUS_SUCCESS);
89 }
90
91 VOID
92 KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
93 /*
94 * FUNCTION: Initialize the microkernel state of the thread
95 */
96 {
97 PVOID KernelStack;
98 NTSTATUS Status;
99 extern unsigned int init_stack_top;
100 extern unsigned int init_stack;
101 PMEMORY_AREA StackArea;
102 ULONG i;
103
104 KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
105 InternalThreadType,
106 sizeof(ETHREAD),
107 FALSE);
108 InitializeListHead(&Thread->MutantListHead);
109 if (!First)
110 {
111 KernelStack = NULL;
112
113 MmLockAddressSpace(MmGetKernelAddressSpace());
114 Status = MmCreateMemoryArea(NULL,
115 MmGetKernelAddressSpace(),
116 MEMORY_AREA_KERNEL_STACK,
117 &KernelStack,
118 MM_STACK_SIZE,
119 0,
120 &StackArea,
121 FALSE);
122 MmUnlockAddressSpace(MmGetKernelAddressSpace());
123
124 if (!NT_SUCCESS(Status))
125 {
126 DPRINT1("Failed to create thread stack\n");
127 KeBugCheck(0);
128 }
129 for (i = 0; i < (MM_STACK_SIZE / PAGESIZE); i++)
130 {
131 Status = MmCreateVirtualMapping(NULL,
132 KernelStack + (i * PAGESIZE),
133 PAGE_EXECUTE_READWRITE,
134 (ULONG)MmAllocPage(0));
135 }
136 Thread->InitialStack = KernelStack + MM_STACK_SIZE;
137 Thread->StackBase = KernelStack + MM_STACK_SIZE;
138 Thread->StackLimit = (ULONG)KernelStack;
139 Thread->KernelStack = KernelStack + MM_STACK_SIZE;
140 }
141 else
142 {
143 Thread->InitialStack = (PVOID)&init_stack_top;
144 Thread->StackBase = (PVOID)&init_stack_top;
145 Thread->StackLimit = (ULONG)&init_stack;
146 Thread->KernelStack = (PVOID)&init_stack_top;
147 }
148
149 /*
150 * The Native API function will initialize the TEB field later
151 */
152 Thread->Teb = NULL;
153 Thread->TlsArray = NULL;
154 Thread->DebugActive = 0;
155 Thread->State = THREAD_STATE_BLOCKED;
156 Thread->Alerted[0] = 0;
157 Thread->Alerted[1] = 0;
158 Thread->Iopl = 0;
159 /*
160 * FIXME: Think how this might work
161 */
162 Thread->NpxState = 0;
163
164 Thread->Saturation = 0;
165 Thread->Priority = 0;
166 InitializeListHead(&Thread->ApcState.ApcListHead[0]);
167 InitializeListHead(&Thread->ApcState.ApcListHead[1]);
168 Thread->ApcState.Process = Process;
169 Thread->ApcState.KernelApcInProgress = 0;
170 Thread->ApcState.KernelApcPending = 0;
171 Thread->ApcState.UserApcPending = 0;
172 Thread->ContextSwitches = 0;
173 Thread->WaitStatus = STATUS_SUCCESS;
174 Thread->WaitIrql = 0;
175 Thread->WaitMode = 0;
176 Thread->WaitNext = 0;
177 Thread->WaitBlockList = NULL;
178 Thread->WaitListEntry.Flink = NULL;
179 Thread->WaitListEntry.Blink = NULL;
180 Thread->WaitTime = 0;
181 Thread->BasePriority = 0;
182 Thread->DecrementCount = 0;
183 Thread->PriorityDecrement = 0;
184 Thread->Quantum = 0;
185 memset(Thread->WaitBlock, 0, sizeof(KWAIT_BLOCK)*4);
186 Thread->LegoData = 0;
187 /*
188 * FIXME: Why this?
189 */
190 Thread->KernelApcDisable = 1;
191 Thread->UserAffinity = Process->Affinity;
192 Thread->SystemAffinityActive = 0;
193 Thread->Queue = NULL;
194 KeInitializeSpinLock(&Thread->ApcQueueLock);
195 memset(&Thread->Timer, 0, sizeof(KTIMER));
196 Thread->QueueListEntry.Flink = NULL;
197 Thread->QueueListEntry.Blink = NULL;
198 Thread->Affinity = Process->Affinity;
199 Thread->Preempted = 0;
200 Thread->ProcessReadyQueue = 0;
201 Thread->KernelStackResident = 1;
202 Thread->NextProcessor = 0;
203 Thread->CallbackStack = NULL;
204 Thread->Win32Thread = 0;
205 Thread->TrapFrame = NULL;
206 Thread->ApcStatePointer[0] = NULL;
207 Thread->ApcStatePointer[1] = NULL;
208 Thread->EnableStackSwap = 0;
209 Thread->LargeStack = 0;
210 Thread->ResourceIndex = 0;
211 Thread->PreviousMode = KernelMode;
212 Thread->KernelTime = 0;
213 Thread->UserTime = 0;
214 memset(&Thread->SavedApcState, 0, sizeof(KAPC_STATE));
215 Thread->Alertable = 1;
216 Thread->ApcStateIndex = 0;
217 Thread->ApcQueueable = 0;
218 Thread->AutoAlignment = 0;
219 KeInitializeApc(&Thread->SuspendApc,
220 Thread,
221 0,
222 PiSuspendThreadKernelRoutine,
223 PiSuspendThreadRundownRoutine,
224 PiSuspendThreadNormalRoutine,
225 KernelMode,
226 NULL);
227 KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 255);
228 Thread->ThreadListEntry.Flink = NULL;
229 Thread->ThreadListEntry.Blink = NULL;
230 Thread->FreezeCount = 0;
231 Thread->SuspendCount = 0;
232
233 /*
234 * Initialize ReactOS specific members
235 */
236 Thread->ProcessThreadListEntry.Flink = NULL;
237 Thread->ProcessThreadListEntry.Blink = NULL;
238 KeInitializeDpc(&Thread->TimerDpc, (PKDEFERRED_ROUTINE)PiTimeoutThread,
239 Thread);
240 Thread->LastEip = 0;
241
242 /*
243 * Do x86 specific part
244 */
245
246 }
247