Continue of MSVC-compiling changes....
[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 /* $Id: kthread.c,v 1.45 2003/12/30 18:52:04 fireball Exp $
20 *
21 * FILE: ntoskrnl/ke/kthread.c
22 * PURPOSE: Microkernel thread support
23 * PROGRAMMER: David Welch (welch@cwcom.net)
24 * UPDATE HISTORY:
25 * Created 22/05/98
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ddk/ntddk.h>
31 #include <internal/ke.h>
32 #include <internal/ps.h>
33 #include <internal/id.h>
34 #include <internal/pool.h>
35
36 #define NDEBUG
37 #include <internal/debug.h>
38
39 /* FUNCTIONS *****************************************************************/
40
41 VOID
42 KeFreeStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
43 PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry, BOOLEAN Dirty)
44 {
45 assert(SwapEntry == 0);
46 if (PhysAddr.QuadPart != 0)
47 {
48 MmReleasePageMemoryConsumer(MC_NPPOOL, PhysAddr);
49 }
50 }
51
52 NTSTATUS
53 KeReleaseThread(PETHREAD Thread)
54 /*
55 * FUNCTION: Releases the resource allocated for a thread by
56 * KeInitializeThread
57 * NOTE: The thread had better not be running when this is called
58 */
59 {
60 extern unsigned int init_stack;
61
62 if (Thread->Tcb.StackLimit != (ULONG)&init_stack)
63 {
64 MmLockAddressSpace(MmGetKernelAddressSpace());
65 MmFreeMemoryArea(MmGetKernelAddressSpace(),
66 (PVOID)Thread->Tcb.StackLimit,
67 MM_STACK_SIZE,
68 KeFreeStackPage,
69 NULL);
70 MmUnlockAddressSpace(MmGetKernelAddressSpace());
71 }
72 Thread->Tcb.StackLimit = 0;
73 Thread->Tcb.InitialStack = NULL;
74 Thread->Tcb.StackBase = NULL;
75 Thread->Tcb.KernelStack = NULL;
76 return(STATUS_SUCCESS);
77 }
78
79 VOID
80 KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
81 /*
82 * FUNCTION: Initialize the microkernel state of the thread
83 */
84 {
85 PVOID KernelStack;
86 NTSTATUS Status;
87 extern unsigned int init_stack_top;
88 extern unsigned int init_stack;
89 PMEMORY_AREA StackArea;
90 ULONG i;
91
92 KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
93 InternalThreadType,
94 sizeof(ETHREAD),
95 FALSE);
96 InitializeListHead(&Thread->MutantListHead);
97 if (!First)
98 {
99 KernelStack = NULL;
100
101 MmLockAddressSpace(MmGetKernelAddressSpace());
102 Status = MmCreateMemoryArea(NULL,
103 MmGetKernelAddressSpace(),
104 MEMORY_AREA_KERNEL_STACK,
105 &KernelStack,
106 MM_STACK_SIZE,
107 0,
108 &StackArea,
109 FALSE,
110 FALSE);
111 MmUnlockAddressSpace(MmGetKernelAddressSpace());
112
113 if (!NT_SUCCESS(Status))
114 {
115 DPRINT1("Failed to create thread stack\n");
116 KEBUGCHECK(0);
117 }
118 for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++)
119 {
120 PHYSICAL_ADDRESS Page;
121 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page);
122 if (!NT_SUCCESS(Status))
123 {
124 KEBUGCHECK(0);
125 }
126 Status = MmCreateVirtualMapping(NULL,
127 (char*)KernelStack + (i * PAGE_SIZE),
128 PAGE_EXECUTE_READWRITE,
129 Page,
130 TRUE);
131 }
132 Thread->InitialStack = (char*)KernelStack + MM_STACK_SIZE;
133 Thread->StackBase = (char*)KernelStack + MM_STACK_SIZE;
134 Thread->StackLimit = (ULONG)KernelStack;
135 Thread->KernelStack = (char*)KernelStack + MM_STACK_SIZE;
136 }
137 else
138 {
139 Thread->InitialStack = (PVOID)&init_stack_top;
140 Thread->StackBase = (PVOID)&init_stack_top;
141 Thread->StackLimit = (ULONG)&init_stack;
142 Thread->KernelStack = (PVOID)&init_stack_top;
143 }
144
145 /*
146 * The Native API function will initialize the TEB field later
147 */
148 Thread->Teb = NULL;
149 Thread->TlsArray = NULL;
150 Thread->DebugActive = 0;
151 Thread->State = THREAD_STATE_INITIALIZED;
152 Thread->Alerted[0] = 0;
153 Thread->Alerted[1] = 0;
154 Thread->Iopl = 0;
155 /*
156 * FIXME: Think how this might work
157 */
158 Thread->NpxState = 0;
159
160 Thread->Saturation = 0;
161 Thread->Priority = 0;
162 InitializeListHead(&Thread->ApcState.ApcListHead[0]);
163 InitializeListHead(&Thread->ApcState.ApcListHead[1]);
164 Thread->ApcState.Process = Process;
165 Thread->ApcState.KernelApcInProgress = 0;
166 Thread->ApcState.KernelApcPending = 0;
167 Thread->ApcState.UserApcPending = 0;
168 Thread->ContextSwitches = 0;
169 Thread->WaitStatus = STATUS_SUCCESS;
170 Thread->WaitIrql = 0;
171 Thread->WaitMode = 0;
172 Thread->WaitNext = 0;
173 Thread->WaitBlockList = NULL;
174 Thread->WaitListEntry.Flink = NULL;
175 Thread->WaitListEntry.Blink = NULL;
176 Thread->WaitTime = 0;
177 Thread->BasePriority = 0;
178 Thread->DecrementCount = 0;
179 Thread->PriorityDecrement = 0;
180 Thread->Quantum = 0;
181 memset(Thread->WaitBlock, 0, sizeof(KWAIT_BLOCK)*4);
182 Thread->LegoData = 0;
183
184 /*
185 * FIXME: Why this?
186 */
187 // Thread->KernelApcDisable = 1;
188 /*
189 It may be correct to have regular kmode APC disabled
190 until the thread has been fully created, BUT the problem is: they are
191 currently never enabled again! So until somone figures out how
192 this really work, I'm setting regular kmode APC's intially enabled.
193 -Gunnar
194
195 UPDATE: After enabling regular kmode APC's I have experienced random
196 crashes. I'm disabling it again, until we fix the APC implementation...
197 -Gunnar
198 */
199
200 Thread->KernelApcDisable = -1;
201
202
203 Thread->UserAffinity = Process->Affinity;
204 Thread->SystemAffinityActive = 0;
205 Thread->PowerState = 0;
206 Thread->NpxIrql = 0;
207 Thread->ServiceTable = KeServiceDescriptorTable;
208 Thread->Queue = NULL;
209 KeInitializeSpinLock(&Thread->ApcQueueLock);
210 memset(&Thread->Timer, 0, sizeof(KTIMER));
211 KeInitializeTimer(&Thread->Timer);
212 Thread->QueueListEntry.Flink = NULL;
213 Thread->QueueListEntry.Blink = NULL;
214 Thread->Affinity = Process->Affinity;
215 Thread->Preempted = 0;
216 Thread->ProcessReadyQueue = 0;
217 Thread->KernelStackResident = 1;
218 Thread->NextProcessor = 0;
219 Thread->CallbackStack = NULL;
220 Thread->Win32Thread = 0;
221 Thread->TrapFrame = NULL;
222 Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
223 Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
224 Thread->EnableStackSwap = 0;
225 Thread->LargeStack = 0;
226 Thread->ResourceIndex = 0;
227 Thread->PreviousMode = KernelMode;
228 Thread->KernelTime = 0;
229 Thread->UserTime = 0;
230 memset(&Thread->SavedApcState, 0, sizeof(KAPC_STATE));
231
232 /* FIXME: is this correct? */
233 Thread->Alertable = 1;
234
235 Thread->ApcStateIndex = OriginalApcEnvironment;
236
237 /* FIXME: not all thread are ApcQueueable! */
238 Thread->ApcQueueable = TRUE;
239
240 Thread->AutoAlignment = 0;
241 KeInitializeApc(&Thread->SuspendApc,
242 Thread,
243 OriginalApcEnvironment,
244 PiSuspendThreadKernelRoutine,
245 PiSuspendThreadRundownRoutine,
246 PiSuspendThreadNormalRoutine,
247 KernelMode,
248 NULL);
249 KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128);
250 Thread->ThreadListEntry.Flink = NULL;
251 Thread->ThreadListEntry.Blink = NULL;
252 Thread->FreezeCount = 0;
253 Thread->SuspendCount = 0;
254
255 /*
256 * Initialize ReactOS specific members
257 */
258 Thread->ProcessThreadListEntry.Flink = NULL;
259 Thread->ProcessThreadListEntry.Blink = NULL;
260
261 /*
262 * Do x86 specific part
263 */
264 }
265
266 VOID STDCALL
267 KeRescheduleThread()
268 {
269 PsDispatchThread(THREAD_STATE_READY);
270 }