ReactOS Fundraising Campaign 2012
 
€ 11,198 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

thrdini.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         BSD - See COPYING.ARM in the top level directory
00004  * FILE:            ntoskrnl/ke/arm/thrdini.c
00005  * PURPOSE:         Implements thread context setup and startup for ARM machines
00006  * PROGRAMMERS:     ReactOS Portable Systems Group
00007  */
00008 
00009 /* INCLUDES *******************************************************************/
00010 
00011 #include <ntoskrnl.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 /* GLOBALS ********************************************************************/
00016 
00017 typedef struct _KSWITCHFRAME
00018 {
00019     PVOID ExceptionList;
00020     BOOLEAN ApcBypassDisable;
00021     PVOID RetAddr;
00022 } KSWITCHFRAME, *PKSWITCHFRAME;
00023 
00024 typedef struct _KUINIT_FRAME
00025 {
00026     KEXCEPTION_FRAME CtxSwitchFrame;
00027     KEXCEPTION_FRAME ExceptionFrame;
00028     KTRAP_FRAME TrapFrame;
00029 } KUINIT_FRAME, *PKUINIT_FRAME;
00030 
00031 typedef struct _KKINIT_FRAME
00032 {
00033     KEXCEPTION_FRAME CtxSwitchFrame;
00034 } KKINIT_FRAME, *PKKINIT_FRAME;
00035 
00036 /* FUNCTIONS ******************************************************************/
00037 
00038 VOID
00039 NTAPI
00040 KiThreadStartup(VOID);
00041 
00042 VOID
00043 FASTCALL
00044 KiSwitchThreads(
00045     IN PKTHREAD OldThread,
00046     IN PKTHREAD NewThread
00047 );
00048 
00049 
00050 /* FIXME: THIS IS TOTALLY BUSTED NOW */
00051 VOID
00052 NTAPI
00053 KiInitializeContextThread(IN PKTHREAD Thread,
00054                           IN PKSYSTEM_ROUTINE SystemRoutine,
00055                           IN PKSTART_ROUTINE StartRoutine,
00056                           IN PVOID StartContext,
00057                           IN PCONTEXT ContextPointer)
00058 {
00059     PKTRAP_FRAME TrapFrame;
00060     PKEXCEPTION_FRAME ExceptionFrame = NULL, CtxSwitchFrame;
00061 
00062     //
00063     // Check if this is a user thread
00064     //
00065     if (ContextPointer)
00066     {
00067         //
00068         // Setup the initial frame
00069         //
00070         PKUINIT_FRAME InitFrame;
00071         InitFrame = (PKUINIT_FRAME)((ULONG_PTR)Thread->InitialStack -
00072                                     sizeof(KUINIT_FRAME));
00073         
00074         //
00075         // Setup the Trap Frame and Exception frame
00076         //
00077         TrapFrame = &InitFrame->TrapFrame;
00078         ExceptionFrame = &InitFrame->ExceptionFrame;
00079         
00081         // Zero out the trap frame and exception frame
00082         //
00083         RtlZeroMemory(TrapFrame, sizeof(KTRAP_FRAME));
00084         RtlZeroMemory(ExceptionFrame, sizeof(KEXCEPTION_FRAME));
00085                 
00086         //
00087         // Set up a trap frame from the context
00088         //
00089         KeContextToTrapFrame(ContextPointer,
00090                              ExceptionFrame,
00091                              TrapFrame,
00092                              ContextPointer->ContextFlags | CONTEXT_CONTROL,
00093                              UserMode);
00094 
00095         //
00096         // Set the previous mode as user
00097         //
00098         //TrapFrame->PreviousMode = UserMode;
00099         Thread->PreviousMode = UserMode;
00100         
00101         //
00102         // Clear the return address
00103         //
00104         ExceptionFrame->Lr = 0;
00105         
00106         //
00107         // Context switch frame to setup below
00108         //
00109         CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
00110     }
00111     else
00112     {
00113         //
00114         // Set up the Initial Frame for the system thread
00115         //
00116         PKKINIT_FRAME InitFrame;
00117         InitFrame = (PKKINIT_FRAME)((ULONG_PTR)Thread->InitialStack -
00118                                     sizeof(KKINIT_FRAME));
00119         
00120         //
00121         // Set the previous mode as kernel
00122         //
00123         Thread->PreviousMode = KernelMode;
00124         
00125         //
00126         // Context switch frame to setup below
00127         //
00128         CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
00129     }
00130     
00131     //
00132     // Now setup the context switch frame
00133     //
00134     CtxSwitchFrame->Lr = (ULONG)KiThreadStartup;
00135     CtxSwitchFrame->R11 = (ULONG)(ExceptionFrame ? ExceptionFrame : CtxSwitchFrame);
00136 
00137     //
00138     // Set the parameters
00139     //
00140     CtxSwitchFrame->R4 = (ULONG)ContextPointer;
00141     CtxSwitchFrame->R5 = (ULONG)StartContext;
00142     CtxSwitchFrame->R6 = (ULONG)StartRoutine;
00143     CtxSwitchFrame->R7 = (ULONG)SystemRoutine;
00144     
00145     //
00146     // Save back the new value of the kernel stack
00147     //
00148     Thread->KernelStack = (PVOID)CtxSwitchFrame;
00149 }
00150 
00151 VOID
00152 FASTCALL
00153 KiIdleLoop(VOID)
00154 {
00155     PKPRCB Prcb = KeGetCurrentPrcb();
00156     PKTHREAD OldThread, NewThread;
00157 
00158     /* Initialize the idle loop: disable interrupts */
00159     _enable();
00160     YieldProcessor();
00161     YieldProcessor();
00162     _disable();
00163 
00164     /* Now loop forever */
00165     while (TRUE)
00166     {
00167         /* Check for pending timers, pending DPCs, or pending ready threads */
00168         if ((Prcb->DpcData[0].DpcQueueDepth) ||
00169             (Prcb->TimerRequest) ||
00170             (Prcb->DeferredReadyListHead.Next))
00171         {
00172             /* Quiesce the DPC software interrupt */
00173             HalClearSoftwareInterrupt(DISPATCH_LEVEL);
00174 
00175             /* Handle it */
00176             KiRetireDpcList(Prcb);
00177         }
00178 
00179         /* Check if a new thread is scheduled for execution */
00180         if (Prcb->NextThread)
00181         {
00182             /* Enable interupts */
00183             _enable();
00184 
00185             /* Capture current thread data */
00186             OldThread = Prcb->CurrentThread;
00187             NewThread = Prcb->NextThread;
00188 
00189             /* Set new thread data */
00190             Prcb->NextThread = NULL;
00191             Prcb->CurrentThread = NewThread;
00192 
00193             /* The thread is now running */
00194             NewThread->State = Running;
00195 
00196             /* Switch away from the idle thread */
00197             KiSwapContext(APC_LEVEL, OldThread);
00198 
00199             /* We are back in the idle thread -- disable interrupts again */
00200             _enable();
00201             YieldProcessor();
00202             YieldProcessor();
00203             _disable();
00204         }
00205         else
00206         {
00207             /* Continue staying idle. Note the HAL returns with interrupts on */
00208             Prcb->PowerState.IdleFunction(&Prcb->PowerState);
00209         }
00210     }
00211 }
00212 
00213 BOOLEAN
00214 FASTCALL
00215 KiSwapContextExit(IN PKTHREAD OldThread,
00216                   IN PKSWITCHFRAME SwitchFrame)
00217 {
00218     PKIPCR Pcr = (PKIPCR)KeGetPcr();
00219     PKPROCESS OldProcess, NewProcess;
00220     PKTHREAD NewThread;
00221     ARM_TTB_REGISTER TtbRegister;
00222 
00223     /* We are on the new thread stack now */
00224     NewThread = Pcr->PrcbData.CurrentThread;
00225 
00226     /* Now we are the new thread. Check if it's in a new process */
00227     OldProcess = OldThread->ApcState.Process;
00228     NewProcess = NewThread->ApcState.Process;
00229     if (OldProcess != NewProcess)
00230     {
00231         TtbRegister.AsUlong = NewProcess->DirectoryTableBase[0];
00232         ASSERT(TtbRegister.Reserved == 0);
00233         KeArmTranslationTableRegisterSet(TtbRegister);
00234     }
00235 
00236     /* Increase thread context switches */
00237     NewThread->ContextSwitches++;
00238 
00239     /* Load data from switch frame */
00240     Pcr->NtTib.ExceptionList = SwitchFrame->ExceptionList;
00241 
00242     /* DPCs shouldn't be active */
00243     if (Pcr->PrcbData.DpcRoutineActive)
00244     {
00245         /* Crash the machine */
00246         KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC,
00247                      (ULONG_PTR)OldThread,
00248                      (ULONG_PTR)NewThread,
00249                      (ULONG_PTR)OldThread->InitialStack,
00250                      0);
00251     }
00252 
00253     /* Kernel APCs may be pending */
00254     if (NewThread->ApcState.KernelApcPending)
00255     {
00256         /* Are APCs enabled? */
00257         if (!NewThread->SpecialApcDisable)
00258         {
00259             /* Request APC delivery */
00260             if (SwitchFrame->ApcBypassDisable) HalRequestSoftwareInterrupt(APC_LEVEL);
00261             return TRUE;
00262         }
00263     }
00264 
00265     /* Return */
00266     return FALSE;
00267 }
00268 
00269 VOID
00270 FASTCALL
00271 KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame,
00272                    IN ULONG_PTR OldThreadAndApcFlag)
00273 {
00274     PKIPCR Pcr = (PKIPCR)KeGetPcr();
00275     PKTHREAD OldThread, NewThread;
00276 
00277     /* Save APC bypass disable */
00278     SwitchFrame->ApcBypassDisable = OldThreadAndApcFlag & 3;
00279     SwitchFrame->ExceptionList = Pcr->NtTib.ExceptionList;
00280 
00281     /* Increase context switch count and check if tracing is enabled */
00282     Pcr->ContextSwitches++;
00283     if (Pcr->PerfGlobalGroupMask)
00284     {
00285         /* We don't support this yet on x86 either */
00286         DPRINT1("WMI Tracing not supported\n");
00287         ASSERT(FALSE);
00288     }
00289 
00290     /* Get thread pointers */
00291     OldThread = (PKTHREAD)(OldThreadAndApcFlag & ~3);
00292     NewThread = Pcr->PrcbData.CurrentThread;
00293 
00294     /* Get the old thread and set its kernel stack */
00295     OldThread->KernelStack = SwitchFrame;
00296 
00297     /* Do the switch */
00298     KiSwitchThreads(OldThread, NewThread->KernelStack);
00299 }
00300 
00301 VOID
00302 NTAPI
00303 KiDispatchInterrupt(VOID)
00304 {
00305     PKIPCR Pcr = (PKIPCR)KeGetPcr();
00306     PKPRCB Prcb = &Pcr->PrcbData;
00307     PVOID OldHandler;
00308     PKTHREAD NewThread, OldThread;
00309 
00310     /* Disable interrupts */
00311     _disable();
00312 
00313     /* Check for pending timers, pending DPCs, or pending ready threads */
00314     if ((Prcb->DpcData[0].DpcQueueDepth) ||
00315         (Prcb->TimerRequest) ||
00316         (Prcb->DeferredReadyListHead.Next))
00317     {
00318         /* Switch to safe execution context */
00319         OldHandler = Pcr->NtTib.ExceptionList;
00320         Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
00321 
00322         /* Retire DPCs while under the DPC stack */
00323         //KiRetireDpcListInDpcStack(Prcb, Prcb->DpcStack);
00324         // FIXME!!! //
00325         KiRetireDpcList(Prcb);
00326 
00327         /* Restore context */
00328         Pcr->NtTib.ExceptionList = OldHandler;
00329     }
00330 
00331     /* Re-enable interrupts */
00332     _enable();
00333 
00334     /* Check for quantum end */
00335     if (Prcb->QuantumEnd)
00336     {
00337         /* Handle quantum end */
00338         Prcb->QuantumEnd = FALSE;
00339         KiQuantumEnd();
00340     }
00341     else if (Prcb->NextThread)
00342     {       
00343         /* Capture current thread data */
00344         OldThread = Prcb->CurrentThread;
00345         NewThread = Prcb->NextThread;
00346 
00347         /* Set new thread data */
00348         Prcb->NextThread = NULL;
00349         Prcb->CurrentThread = NewThread;
00350 
00351         /* The thread is now running */
00352         NewThread->State = Running;
00353         OldThread->WaitReason = WrDispatchInt;
00354 
00355         /* Make the old thread ready */
00356         KxQueueReadyThread(OldThread, Prcb);
00357 
00358         /* Swap to the new thread */
00359         KiSwapContext(APC_LEVEL, OldThread);
00360     }
00361 }
00362 
00363 /* EOF */

Generated on Thu Oct 25 2012 04:44:02 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.