update for HEAD-2003091401
[reactos.git] / 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$
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                                           KernelStack + (i * PAGE_SIZE),
128                                           PAGE_EXECUTE_READWRITE,
129                                           Page,
130                                           TRUE);
131         }
132       Thread->InitialStack = KernelStack + MM_STACK_SIZE;
133       Thread->StackBase = KernelStack + MM_STACK_SIZE;
134       Thread->StackLimit = (ULONG)KernelStack;
135       Thread->KernelStack = 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    * FIXME: Why this?
185    */
186   Thread->KernelApcDisable = 1;
187   Thread->UserAffinity = Process->Affinity;
188   Thread->SystemAffinityActive = 0;
189   Thread->PowerState = 0;
190   Thread->NpxIrql = 0;
191   Thread->ServiceTable = KeServiceDescriptorTable;
192   Thread->Queue = NULL;
193   KeInitializeSpinLock(&Thread->ApcQueueLock);
194   memset(&Thread->Timer, 0, sizeof(KTIMER));
195   Thread->QueueListEntry.Flink = NULL;
196   Thread->QueueListEntry.Blink = NULL;
197   Thread->Affinity = Process->Affinity;
198   Thread->Preempted = 0;
199   Thread->ProcessReadyQueue = 0;
200   Thread->KernelStackResident = 1;
201   Thread->NextProcessor = 0;
202   Thread->CallbackStack = NULL;
203   Thread->Win32Thread = 0;
204   Thread->TrapFrame = NULL;
205   Thread->ApcStatePointer[0] = NULL;
206   Thread->ApcStatePointer[1] = NULL;
207   Thread->EnableStackSwap = 0;
208   Thread->LargeStack = 0;
209   Thread->ResourceIndex = 0;
210   Thread->PreviousMode = KernelMode;
211   Thread->KernelTime = 0;
212   Thread->UserTime = 0;
213   memset(&Thread->SavedApcState, 0, sizeof(KAPC_STATE));
214   Thread->Alertable = 1;
215   Thread->ApcStateIndex = 0;
216   Thread->ApcQueueable = 0;
217   Thread->AutoAlignment = 0;
218   KeInitializeApc(&Thread->SuspendApc,
219                   Thread,
220                   OriginalApcEnvironment,
221                   PiSuspendThreadKernelRoutine,
222                   PiSuspendThreadRundownRoutine,
223                   PiSuspendThreadNormalRoutine,
224                   KernelMode,
225                   NULL);
226   KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128);
227   Thread->ThreadListEntry.Flink = NULL;
228   Thread->ThreadListEntry.Blink = NULL;
229   Thread->FreezeCount = 0;
230   Thread->SuspendCount = 0;
231   
232   /*
233    * Initialize ReactOS specific members
234    */
235   Thread->ProcessThreadListEntry.Flink = NULL;
236   Thread->ProcessThreadListEntry.Blink = NULL;
237    
238    /*
239     * Do x86 specific part
240     */
241 }
242
243 VOID STDCALL
244 KeRescheduleThread()
245 {
246   PsDispatchThread(THREAD_STATE_READY);
247 }