branch update for HEAD-2003050101
[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       MmUnlockAddressSpace(MmGetKernelAddressSpace());
111       
112       if (!NT_SUCCESS(Status))
113         {
114           DPRINT1("Failed to create thread stack\n");
115           KeBugCheck(0);
116         }
117       for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++)
118         {
119           PHYSICAL_ADDRESS Page;
120           Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page);
121           if (!NT_SUCCESS(Status))
122             {
123               KeBugCheck(0);
124             }
125           Status = MmCreateVirtualMapping(NULL,
126                                           KernelStack + (i * PAGE_SIZE),
127                                           PAGE_EXECUTE_READWRITE,
128                                           Page,
129                                           TRUE);
130         }
131       Thread->InitialStack = KernelStack + MM_STACK_SIZE;
132       Thread->StackBase = KernelStack + MM_STACK_SIZE;
133       Thread->StackLimit = (ULONG)KernelStack;
134       Thread->KernelStack = KernelStack + MM_STACK_SIZE;
135     }
136   else
137     {
138       Thread->InitialStack = (PVOID)&init_stack_top;
139       Thread->StackBase = (PVOID)&init_stack_top;
140       Thread->StackLimit = (ULONG)&init_stack;
141       Thread->KernelStack = (PVOID)&init_stack_top;
142     }
143   
144   /* 
145    * The Native API function will initialize the TEB field later 
146    */
147   Thread->Teb = NULL;
148   Thread->TlsArray = NULL;
149   Thread->DebugActive = 0;
150   Thread->State = THREAD_STATE_INITIALIZED;
151   Thread->Alerted[0] = 0;
152   Thread->Alerted[1] = 0;
153   Thread->Iopl = 0;
154   /*
155    * FIXME: Think how this might work
156    */
157   Thread->NpxState = 0;
158   
159   Thread->Saturation = 0;
160   Thread->Priority = 0; 
161   InitializeListHead(&Thread->ApcState.ApcListHead[0]);
162   InitializeListHead(&Thread->ApcState.ApcListHead[1]);
163   Thread->ApcState.Process = Process;
164   Thread->ApcState.KernelApcInProgress = 0;
165   Thread->ApcState.KernelApcPending = 0;
166   Thread->ApcState.UserApcPending = 0;
167   Thread->ContextSwitches = 0;
168   Thread->WaitStatus = STATUS_SUCCESS;
169   Thread->WaitIrql = 0;
170   Thread->WaitMode = 0;
171   Thread->WaitNext = 0;
172   Thread->WaitBlockList = NULL;
173   Thread->WaitListEntry.Flink = NULL;
174   Thread->WaitListEntry.Blink = NULL;
175   Thread->WaitTime = 0;
176   Thread->BasePriority = 0; 
177   Thread->DecrementCount = 0;
178   Thread->PriorityDecrement = 0;
179   Thread->Quantum = 0;
180   memset(Thread->WaitBlock, 0, sizeof(KWAIT_BLOCK)*4);
181   Thread->LegoData = 0;
182   /*
183    * FIXME: Why this?
184    */
185   Thread->KernelApcDisable = 1;
186   Thread->UserAffinity = Process->Affinity;
187   Thread->SystemAffinityActive = 0;
188   Thread->Queue = NULL;
189   KeInitializeSpinLock(&Thread->ApcQueueLock);
190   memset(&Thread->Timer, 0, sizeof(KTIMER));
191   Thread->QueueListEntry.Flink = NULL;
192   Thread->QueueListEntry.Blink = NULL;
193   Thread->Affinity = Process->Affinity;
194   Thread->Preempted = 0;
195   Thread->ProcessReadyQueue = 0;
196   Thread->KernelStackResident = 1;
197   Thread->NextProcessor = 0;
198   Thread->CallbackStack = NULL;
199   Thread->Win32Thread = 0;
200   Thread->TrapFrame = NULL;
201   Thread->ApcStatePointer[0] = NULL;
202   Thread->ApcStatePointer[1] = NULL;
203   Thread->EnableStackSwap = 0;
204   Thread->LargeStack = 0;
205   Thread->ResourceIndex = 0;
206   Thread->PreviousMode = KernelMode;
207   Thread->KernelTime = 0;
208   Thread->UserTime = 0;
209   memset(&Thread->SavedApcState, 0, sizeof(KAPC_STATE));
210   Thread->Alertable = 1;
211   Thread->ApcStateIndex = 0;
212   Thread->ApcQueueable = 0;
213   Thread->AutoAlignment = 0;
214   KeInitializeApc(&Thread->SuspendApc,
215                   Thread,
216                   0,
217                   PiSuspendThreadKernelRoutine,
218                   PiSuspendThreadRundownRoutine,
219                   PiSuspendThreadNormalRoutine,
220                   KernelMode,
221                   NULL);
222   KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128);
223   Thread->ThreadListEntry.Flink = NULL;
224   Thread->ThreadListEntry.Blink = NULL;
225   Thread->FreezeCount = 0;
226   Thread->SuspendCount = 0;
227   
228   /*
229    * Initialize ReactOS specific members
230    */
231   Thread->ProcessThreadListEntry.Flink = NULL;
232   Thread->ProcessThreadListEntry.Blink = NULL;
233    
234    /*
235     * Do x86 specific part
236     */
237 }
238
239 VOID STDCALL
240 KeRescheduleThread()
241 {
242   PsDispatchThread(THREAD_STATE_READY);
243 }