Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

thredini.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990 Microsoft Corporation 00004 00005 Module Name: 00006 00007 thredini.c 00008 00009 Abstract: 00010 00011 This module implements the machine dependent functions to set the initial 00012 context and data alignment handling mode of a thread object. 00013 00014 Author: 00015 00016 David N. Cutler (davec) 1-Apr-1990 00017 00018 Environment: 00019 00020 Kernel mode only. 00021 00022 Revision History: 00023 00024 Sep 19, 1993 plj Conversion to IBM PowerPC 00025 00026 --*/ 00027 00028 #include "ki.h" 00029 00030 // 00031 // The following assert macros are used to check that an input object is 00032 // really the proper type. 00033 // 00034 00035 #define ASSERT_PROCESS(E) { \ 00036 ASSERT((E)->Header.Type == ProcessObject); \ 00037 } 00038 00039 #define ASSERT_THREAD(E) { \ 00040 ASSERT((E)->Header.Type == ThreadObject); \ 00041 } 00042 00043 00044 VOID 00045 KiInitializeContextThread ( 00046 IN PKTHREAD Thread, 00047 IN PKSYSTEM_ROUTINE SystemRoutine, 00048 IN PKSTART_ROUTINE StartRoutine OPTIONAL, 00049 IN PVOID StartContext OPTIONAL, 00050 IN PCONTEXT ContextRecord OPTIONAL 00051 ) 00052 00053 /*++ 00054 00055 Routine Description: 00056 00057 This function initializes the machine dependent context of a thread object. 00058 00059 Actually, what it does is to lay out the stack for the thread so that 00060 it contains a stack frame that will be picked up by SwapContext and 00061 returned thru, resulting in a transfer of control to KiThreadStartup. 00062 In otherwords, we lay out a stack with a stack frame that looks as if 00063 SwapContext had been called just before the first instruction in 00064 KiThreadStartup. 00065 00066 N.B. This function does not check the accessibility of the context record. 00067 It is assumed the the caller of this routine is either prepared to 00068 handle access violations or has probed and copied the context record 00069 as appropriate. 00070 00071 N.B. Arguments to the new thread are passed in the Swap Frame gprs 00072 16 thru 20 which will be loaded into the thread's gprs when 00073 execution begins. 00074 00075 WARNING: If the thread has a user mode context the Top of stack MUST 00076 be laid out identically to the top of stack laid out when an 00077 interrupt or system call from user mode occurs. 00078 00079 Arguments: 00080 00081 Thread - Supplies a pointer to a dispatcher object of type thread. 00082 00083 SystemRoutine - Supplies a pointer to the system function that is to be 00084 called when the thread is first scheduled for execution. 00085 00086 StartRoutine - Supplies an optional pointer to a function that is to be 00087 called after the system has finished initializing the thread. This 00088 parameter is specified if the thread is a system thread and will 00089 execute totally in kernel mode. 00090 00091 StartContext - Supplies an optional pointer to an arbitrary data structure 00092 which will be passed to the StartRoutine as a parameter. This 00093 parameter is specified if the thread is a system thread and will 00094 execute totally in kernel mode. 00095 00096 ContextRecord - Supplies an optional pointer a context frame which contains 00097 the initial user mode state of the thread. This parameter is specified 00098 if the thread is a user thread and will execute in user mode. If this 00099 parameter is not specified, then the Teb parameter is ignored. 00100 00101 Return Value: 00102 00103 None. 00104 00105 --*/ 00106 00107 { 00108 00109 PKEXCEPTION_FRAME ExFrame; 00110 ULONG InitialStack; 00111 PKTRAP_FRAME TrFrame; 00112 PKSWAP_FRAME SwFrame; 00113 PSTACK_FRAME_HEADER StkFrame, ResumeFrame; 00114 00115 // 00116 // If the initial stack address is in KSEG0, then the stack is not mapped 00117 // and the kernel stack PTEs are set to zero. Otherwise, capture the PTEs 00118 // that map the kernel stack. 00119 // 00120 00121 InitialStack = (LONG)Thread->InitialStack; 00122 00123 // 00124 // If a context frame is specified, then initialize a trap frame and 00125 // and an exception frame with the specified user mode context. 00126 // 00127 00128 if (ARGUMENT_PRESENT(ContextRecord)) { 00129 ExFrame = (PKEXCEPTION_FRAME)(InitialStack - 8 - 00130 sizeof(KEXCEPTION_FRAME)); 00131 TrFrame = (PKTRAP_FRAME)((ULONG)ExFrame - sizeof(KTRAP_FRAME)); 00132 StkFrame = (PSTACK_FRAME_HEADER)((ULONG)TrFrame - (8 * sizeof(ULONG)) - 00133 sizeof(STACK_FRAME_HEADER)); 00134 00135 // 00136 // Zero the exception and trap frames and copy information from the 00137 // specified context frame to the trap and exception frames. 00138 // 00139 00140 RtlZeroMemory((PVOID)ExFrame, sizeof(KEXCEPTION_FRAME)); 00141 RtlZeroMemory((PVOID)TrFrame, sizeof(KTRAP_FRAME)); 00142 KeContextToKframes(TrFrame, ExFrame, 00143 ContextRecord, 00144 ContextRecord->ContextFlags | CONTEXT_CONTROL, 00145 UserMode); 00146 00147 // 00148 // Set the saved previous processor mode in the trap frame and the 00149 // previous processor mode in the thread object to user mode. 00150 // 00151 00152 TrFrame->PreviousMode = UserMode; 00153 Thread->PreviousMode = UserMode; 00154 00155 } else { 00156 00157 StkFrame = (PSTACK_FRAME_HEADER)((InitialStack - 00158 sizeof(STACK_FRAME_HEADER)) & 0xfffffff0); 00159 ExFrame = NULL; 00160 TrFrame = NULL; 00161 00162 // 00163 // Set the previous mode in thread object to kernel. 00164 // 00165 00166 Thread->PreviousMode = KernelMode; 00167 } 00168 00169 StkFrame->BackChain = (ULONG)0; 00170 00171 // 00172 // Initialize the Swap Frame that swap context will use to 00173 // initiate execution of this thread. 00174 // 00175 00176 SwFrame = (PKSWAP_FRAME)(((ULONG)StkFrame - 00177 sizeof(KSWAP_FRAME)) & 0xfffffff0); 00178 00179 // 00180 // Initialize stack frame and set thread start up parameters. 00181 // 00182 00183 if (ExFrame == NULL) { 00184 SwFrame->ExceptionFrame.Gpr20 = (ULONG)ExFrame; 00185 } else { 00186 SwFrame->ExceptionFrame.Gpr20 = (ULONG)TrFrame; 00187 } 00188 00189 SwFrame->ExceptionFrame.Gpr16 = (ULONG)ContextRecord; 00190 SwFrame->ExceptionFrame.Gpr17 = (ULONG)StartContext; 00191 SwFrame->ExceptionFrame.Gpr18 = (ULONG)StartRoutine; 00192 00193 // 00194 // Pass the actual entry point addresses rather than the function 00195 // descriptor's address. 00196 // 00197 00198 SwFrame->ExceptionFrame.Gpr19 = *(ULONG *)SystemRoutine; 00199 00200 SwFrame->SwapReturn = *(ULONG *)KiThreadStartup; 00201 SwFrame->ConditionRegister = 0; 00202 00203 // 00204 // Buy a stack frame so we have the stack frame that will be 00205 // current when SwapContext is running when we resume this 00206 // thread. 00207 00208 00209 ResumeFrame = ((PSTACK_FRAME_HEADER)SwFrame) - 1; 00210 00211 ResumeFrame->BackChain = (ULONG)StkFrame; 00212 00213 // 00214 // Set the initial kernel stack pointer. 00215 // 00216 00217 Thread->KernelStack = (PVOID)ResumeFrame; 00218 ASSERT(!((ULONG)ResumeFrame & 0x7)); // ensure stack is align 8 00219 return; 00220 } 00221 00222 BOOLEAN 00223 KeSetAutoAlignmentProcess ( 00224 IN PKPROCESS Process, 00225 IN BOOLEAN Enable 00226 ) 00227 00228 /*++ 00229 00230 Routine Description: 00231 00232 This function sets the data alignment handling mode for the specified 00233 process and returns the previous data alignment handling mode. 00234 00235 Arguments: 00236 00237 Process - Supplies a pointer to a dispatcher object of type process. 00238 00239 Enable - Supplies a boolean value that determines the handling of data 00240 alignment exceptions for the process. A value of TRUE causes all 00241 data alignment exceptions to be automatically handled by the kernel. 00242 A value of FALSE causes all data alignment exceptions to be actually 00243 raised as exceptions. 00244 00245 Return Value: 00246 00247 A value of TRUE is returned if data alignment exceptions were 00248 previously automatically handled by the kernel. Otherwise, a value 00249 of FALSE is returned. 00250 00251 --*/ 00252 00253 { 00254 00255 KIRQL OldIrql; 00256 BOOLEAN Previous; 00257 00258 ASSERT_PROCESS(Process); 00259 00260 // 00261 // Raise IRQL to dispatcher level and lock dispatcher database. 00262 // 00263 00264 KiLockDispatcherDatabase(&OldIrql); 00265 00266 // 00267 // Capture the previous data alignment handling mode and set the 00268 // specified data alignment mode. 00269 // 00270 00271 Previous = Process->AutoAlignment; 00272 Process->AutoAlignment = Enable; 00273 00274 // 00275 // Unlock dispatcher database, lower IRQL to its previous value, and 00276 // return the previous data alignment mode. 00277 // 00278 00279 KiUnlockDispatcherDatabase(OldIrql); 00280 return Previous; 00281 } 00282 00283 BOOLEAN 00284 KeSetAutoAlignmentThread ( 00285 IN PKTHREAD Thread, 00286 IN BOOLEAN Enable 00287 ) 00288 00289 /*++ 00290 00291 Routine Description: 00292 00293 This function sets the data alignment handling mode for the specified 00294 thread and returns the previous data alignment handling mode. 00295 00296 Arguments: 00297 00298 Thread - Supplies a pointer to a dispatcher object of type thread. 00299 00300 Enable - Supplies a boolean value that determines the handling of data 00301 alignment exceptions for the thread. A value of TRUE causes all 00302 data alignment exceptions to be automatically handled by the kernel. 00303 A value of FALSE causes all data alignment exceptions to be actually 00304 raised as exceptions. 00305 00306 Return Value: 00307 00308 A value of TRUE is returned if data alignment exceptions were 00309 previously automatically handled by the kernel. Otherwise, a value 00310 of FALSE is returned. 00311 00312 --*/ 00313 00314 { 00315 00316 KIRQL OldIrql; 00317 BOOLEAN Previous; 00318 00319 ASSERT_THREAD( Thread ); 00320 00321 // 00322 // Raise IRQL to dispatcher level and lock dispatcher database. 00323 // 00324 00325 KiLockDispatcherDatabase(&OldIrql); 00326 00327 // 00328 // Capture the previous data alignment handling mode and set the 00329 // specified data alignment mode. 00330 // 00331 00332 Previous = Thread->AutoAlignment; 00333 Thread->AutoAlignment = Enable; 00334 00335 // 00336 // Unlock dispatcher database, lower IRQL to its previous value, and 00337 // return the previous data alignment mode. 00338 // 00339 00340 KiUnlockDispatcherDatabase(OldIrql); 00341 return Previous; 00342 }

Generated on Sat May 15 19:41:59 2004 for test by doxygen 1.3.7