b46c507f626d773e97cd6ec50aaa9cbd91079478
[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
43 /* FUNCTIONS *****************************************************************/
44
45 VOID
46 KeFreeStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr,
47 SWAPENTRY SwapEntry, BOOLEAN Dirty)
48 {
49 assert(SwapEntry == 0);
50 if (PhysAddr != 0)
51 {
52 MmDereferencePage((PVOID)PhysAddr);
53 }
54 }
55
56 NTSTATUS
57 KeReleaseThread(PETHREAD Thread)
58 /*
59 * FUNCTION: Releases the resource allocated for a thread by
60 * KeInitializeThread
61 * NOTE: The thread had better not be running when this is called
62 */
63 {
64 extern unsigned int init_stack;
65
66 if (Thread->Tcb.StackLimit != (ULONG)&init_stack)
67 {
68 MmFreeMemoryArea(MmGetKernelAddressSpace(),
69 (PVOID)Thread->Tcb.StackLimit,
70 MM_STACK_SIZE,
71 KeFreeStackPage,
72 NULL);
73 }
74 Thread->Tcb.StackLimit = 0;
75 Thread->Tcb.InitialStack = NULL;
76 Thread->Tcb.StackBase = NULL;
77 Thread->Tcb.KernelStack = NULL;
78 return(STATUS_SUCCESS);
79 }
80
81 VOID
82 KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
83 /*
84 * FUNCTION: Initialize the microkernel state of the thread
85 */
86 {
87 PVOID KernelStack;
88 NTSTATUS Status;
89 extern unsigned int init_stack_top;
90 extern unsigned int init_stack;
91 PMEMORY_AREA StackArea;
92 ULONG i;
93
94 KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
95 InternalThreadType,
96 sizeof(ETHREAD),
97 FALSE);
98 InitializeListHead(&Thread->MutantListHead);
99 if (!First)
100 {
101 KernelStack = NULL;
102
103 MmLockAddressSpace(MmGetKernelAddressSpace());
104 Status = MmCreateMemoryArea(NULL,
105 MmGetKernelAddressSpace(),
106 MEMORY_AREA_KERNEL_STACK,
107 &KernelStack,
108 MM_STACK_SIZE,
109 0,
110 &StackArea,
111 FALSE);
112 MmUnlockAddressSpace(MmGetKernelAddressSpace());
113
114 if (!NT_SUCCESS(Status))
115 {
116 DPRINT1("Failed to create thread stack\n");
117 KeBugCheck(0);
118 }
119 for (i = 0; i < (MM_STACK_SIZE / PAGESIZE); i++)
120 {
121 PVOID Page;
122 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page);
123 if (!NT_SUCCESS(Status))
124 {
125 KeBugCheck(0);
126 }
127 Status = MmCreateVirtualMapping(NULL,
128 KernelStack + (i * PAGESIZE),
129 PAGE_EXECUTE_READWRITE,
130 (ULONG)Page,
131 TRUE);
132 }
133 Thread->InitialStack = KernelStack + MM_STACK_SIZE;
134 Thread->StackBase = KernelStack + MM_STACK_SIZE;
135 Thread->StackLimit = (ULONG)KernelStack;
136 Thread->KernelStack = KernelStack + MM_STACK_SIZE;
137 }
138 else
139 {
140 Thread->InitialStack = (PVOID)&init_stack_top;
141 Thread->StackBase = (PVOID)&init_stack_top;
142 Thread->StackLimit = (ULONG)&init_stack;
143 Thread->KernelStack = (PVOID)&init_stack_top;
144 }
145
146 /*
147 * The Native API function will initialize the TEB field later
148 */
149 Thread->Teb = NULL;
150 Thread->TlsArray = NULL;
151 Thread->DebugActive = 0;
152 Thread->State = THREAD_STATE_BLOCKED;
153 Thread->Alerted[0] = 0;
154 Thread->Alerted[1] = 0;
155 Thread->Iopl = 0;
156 /*
157 * FIXME: Think how this might work
158 */
159 Thread->NpxState = 0;
160
161 Thread->Saturation = 0;
162 Thread->Priority = 0;
163 InitializeListHead(&Thread->ApcState.ApcListHead[0]);
164 InitializeListHead(&Thread->ApcState.ApcListHead[1]);
165 Thread->ApcState.Process = Process;
166 Thread->ApcState.KernelApcInProgress = 0;
167 Thread->ApcState.KernelApcPending = 0;
168 Thread->ApcState.UserApcPending = 0;
169 Thread->ContextSwitches = 0;
170 Thread->WaitStatus = STATUS_SUCCESS;
171 Thread->WaitIrql = 0;
172 Thread->WaitMode = 0;
173 Thread->WaitNext = 0;
174 Thread->WaitBlockList = NULL;
175 Thread->WaitListEntry.Flink = NULL;
176 Thread->WaitListEntry.Blink = NULL;
177 Thread->WaitTime = 0;
178 Thread->BasePriority = 0;
179 Thread->DecrementCount = 0;
180 Thread->PriorityDecrement = 0;
181 Thread->Quantum = 0;
182 memset(Thread->WaitBlock, 0, sizeof(KWAIT_BLOCK)*4);
183 Thread->LegoData = 0;
184 /*
185 * FIXME: Why this?
186 */
187 Thread->KernelApcDisable = 1;
188 Thread->UserAffinity = Process->Affinity;
189 Thread->SystemAffinityActive = 0;
190 Thread->Queue = NULL;
191 KeInitializeSpinLock(&Thread->ApcQueueLock);
192 memset(&Thread->Timer, 0, sizeof(KTIMER));
193 Thread->QueueListEntry.Flink = NULL;
194 Thread->QueueListEntry.Blink = NULL;
195 Thread->Affinity = Process->Affinity;
196 Thread->Preempted = 0;
197 Thread->ProcessReadyQueue = 0;
198 Thread->KernelStackResident = 1;
199 Thread->NextProcessor = 0;
200 Thread->CallbackStack = NULL;
201 Thread->Win32Thread = 0;
202 Thread->TrapFrame = NULL;
203 Thread->ApcStatePointer[0] = NULL;
204 Thread->ApcStatePointer[1] = NULL;
205 Thread->EnableStackSwap = 0;
206 Thread->LargeStack = 0;
207 Thread->ResourceIndex = 0;
208 Thread->PreviousMode = KernelMode;
209 Thread->KernelTime = 0;
210 Thread->UserTime = 0;
211 memset(&Thread->SavedApcState, 0, sizeof(KAPC_STATE));
212 Thread->Alertable = 1;
213 Thread->ApcStateIndex = 0;
214 Thread->ApcQueueable = 0;
215 Thread->AutoAlignment = 0;
216 KeInitializeApc(&Thread->SuspendApc,
217 Thread,
218 0,
219 PiSuspendThreadKernelRoutine,
220 PiSuspendThreadRundownRoutine,
221 PiSuspendThreadNormalRoutine,
222 KernelMode,
223 NULL);
224 KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 255);
225 Thread->ThreadListEntry.Flink = NULL;
226 Thread->ThreadListEntry.Blink = NULL;
227 Thread->FreezeCount = 0;
228 Thread->SuspendCount = 0;
229
230 /*
231 * Initialize ReactOS specific members
232 */
233 Thread->ProcessThreadListEntry.Flink = NULL;
234 Thread->ProcessThreadListEntry.Blink = NULL;
235 KeInitializeDpc(&Thread->TimerDpc,
236 (PKDEFERRED_ROUTINE)PiTimeoutThread,
237 Thread);
238 Thread->LastEip = 0;
239
240 /*
241 * Do x86 specific part
242 */
243 }
244