private static void AssertError(string message, uint arg1 = 0, uint arg2 = 0, uint arg3 = 0) { var sb = new StringBuffer(); sb.Append(message, arg1, arg2, arg3); Panic.Error(sb.CreateString()); }
public unsafe Page *AllocatePages(uint pages, AllocatePageOptions options = default) { if (pages > _FreePages) { Panic.Error("Out of Memory"); return(null); } Page *page; if (AddressSpaceKind == AddressSpaceKind.Virtual || options.Continuous) { page = AllocatePagesContinuous(pages, options); } else { page = AllocatePagesNormal(pages, options); } if (page == null) { KernelMessage.WriteLine("DebugName: {0}", DebugName); KernelMessage.WriteLine("Free pages: {0:X8}, Requested: {1:X8}", FreePages, pages); Panic.Error("Out of Memory"); } KernelMessage.Path(DebugName, "SimpleAlloc: Request {0} Pages, Addr {1:X8}", pages, GetAddress(page)); return(page); }
public static unsafe ElfSections FromSectionName(string name) { bool success; var elf = FromSectionName(name, out success); if (!success) { Panic.Error("Could not find section " + name); } return(elf); }
/// <summary> /// Syscall interrupt handler. Dispatcher for every SysCall. /// </summary> private static void InterruptHandler(ref IDTStack stack, SysCallCallingType callingMethod) { var args = new SystemMessage { Target = (SysCallTarget)stack.EAX, Arg1 = stack.EBX, Arg2 = stack.ECX, Arg3 = stack.EDX, Arg4 = stack.ESI, Arg5 = stack.EDI, Arg6 = stack.EBP, }; var commandNum = GetCommandNum(args.Target); if (KConfig.Log.SysCall) { KernelMessage.WriteLine("Got SysCall cmd={0} arg1={1:X8} arg2={2:X8} arg3={3:X8} arg4={4:X8} arg5={5:X8} arg6={6:X8}", (uint)args.Target, args.Arg1, args.Arg2, args.Arg3, args.Arg4, args.Arg5, args.Arg6); } Scheduler.SaveThreadState(Scheduler.GetCurrentThread().ThreadID, ref stack); var info = Commands[commandNum]; if (info == null) { Panic.Error("Undefined SysCall"); } var ctx = new SysCallContext { CallingType = callingMethod, Debug = info.Debug, }; if (info.Debug) { KDebug.DumpStats(); Debug.Nop(); } var result = info.Handler(ref ctx, ref args); if (KConfig.Log.SysCall) { KernelMessage.WriteLine("Result of Syscall cmd={0}: {1:X8}", (uint)args.Target, result); } stack.EAX = result; }
public static unsafe void Start() { SetThreadID(0); Enabled = true; KernelMessage.WriteLine("Enable Scheduler"); IDTManager.SetPrivilegeLevel((uint)KnownInterrupt.TerminateCurrentThread, 0x03); GDT.Tss->ESP0 = Threads[0].KernelStackBottom; GDT.LoadTaskRegister(); TriggerScheduler(); // Normally, you should never get here Panic.Error("Main-Thread still alive"); }
public static void Setup(ThreadStart followupTask) { ProcessList = new KList <Process>(); Idle = CreateEmptyProcess(new ProcessCreateOptions()); Idle.Path = "/system/idle"; Idle.RunState = ProcessRunState.Running; System = CreateEmptyProcess(new ProcessCreateOptions()); System.Path = "/system/main"; System.RunState = ProcessRunState.Running; Scheduler.Setup(followupTask); Scheduler.Start(); Panic.Error("Should never get here"); }
public Page *AllocatePages(uint pages, AllocatePageOptions options = default) { Page *page = AllocateInternal(pages, options); if (page == null) { //KernelMessage.WriteLine("DebugName: {0}", DebugName); KernelMessage.WriteLine("Free pages: {0:X8}, Requested: {1:X8}", FreePages, pages); Panic.Error("Out of Memory"); } if (FreePages < 1000) { KernelMessage.Path(DebugName, "WARNING: Low pages. Available: {0}", FreePages); } return(page); }
private static void Error(ref IDTStack stack, string message) { Panic.ESP = stack.ESP; Panic.EBP = stack.EBP; Panic.EIP = stack.EIP; Panic.EAX = stack.EAX; Panic.EBX = stack.EBX; Panic.ECX = stack.ECX; Panic.EDX = stack.EDX; Panic.EDI = stack.EDI; Panic.ESI = stack.ESI; Panic.CS = stack.CS; Panic.ErrorCode = stack.ErrorCode; Panic.EFLAGS = stack.EFLAGS; Panic.Interrupt = stack.Interrupt; Panic.CR2 = Native.GetCR2(); Panic.FS = Native.GetFS(); Panic.Error(message); }
public static unsafe Addr AllocatePages(uint pages, AllocatePageOptions options = default) { switch (options.Pool) { case PageAllocationPool.Normal: return(AllocatePagesNormal(pages, options)); case PageAllocationPool.Identity: return(AllocateIdentityMappedPages(pages, options)); case PageAllocationPool.Global: return(AllocateGlobalPages(pages, options)); default: Panic.Error("invalid pool"); break; } return(Addr.Zero); }
/// <summary> /// Setup the <see cref="Scheduler"/> and <see cref="ProcessManager"/> /// </summary> /// <param name="followupTask">After enabling Scheduling, the Kernel will continue with this task.</param> public static void Setup(ThreadStart followupTask) { ProcessList = new KList <Process>(); // Create idle task Idle = CreateEmptyProcess(new ProcessCreateOptions()); Idle.Path = "/system/idle"; Idle.RunState = ProcessRunState.Running; // Create system task System = CreateEmptyProcess(new ProcessCreateOptions()); System.Path = "/system/main"; System.RunState = ProcessRunState.Running; // Initialize scheduler Scheduler.Setup(followupTask); Scheduler.Start(); // If we ever get here, Scheduler as not able to switch to followupTask. Panic.Error("Should never get here"); }
/// <summary> /// Releases a page to the free list /// </summary> public void Free(Page *page) { lock (this) { var head = page; if (head->Status == PageStatus.Reserved) { Panic.Error("Cannot free reserved page"); } //if (head->Free) if (head->Status == PageStatus.Free) { Panic.Error("Double Free?"); return; } var num = head->PagesUsed; //KernelMessage.Write("F:{0};", num); var p = head; for (var n = 0; n < num; n++) { if (p->Free) { Panic.Error("Already Free Page in Compound Page"); return; } p->Status = PageStatus.Free; p->PagesUsed = 0; p->Head = null; p->Tail = null; p = NextPage(p); _FreePages++; } NextTryPage = head; } }
public static void Setup(ThreadStart followupTask) { try { Enabled = false; Threads = new Thread[ThreadCapacity]; ThreadsAllocated = 0; ThreadsMaxAllocated = 0; CurrentThreadID = 0; clockTicks = 0; for (uint i = 0; i < ThreadCapacity; i++) { Threads[i] = new Thread() { ThreadID = i }; } SignalThreadTerminationMethodAddress = GetAddress(SignalKernelThreadTerminationMethod); CreateThread(ProcessManager.Idle, new ThreadStartOptions(IdleThread) { DebugName = "Idle" }).Start(); CreateThread(ProcessManager.System, new ThreadStartOptions(followupTask) { DebugName = "KernelMain" }).Start(); //Debug, for breakpoint //clockTicks++; //AsmDebugFunction.DebugFunction1(); } catch (Exception ex) { Panic.Error(ex.Message); } }
private static void InterruptHandler(IDTStack *stack, CallingType callingMethod) { var args = new SystemMessage { Target = (SysCallTarget)stack->EAX, Arg1 = stack->EBX, Arg2 = stack->ECX, Arg3 = stack->EDX, Arg4 = stack->ESI, Arg5 = stack->EDI, Arg6 = stack->EBP, }; var commandNum = GetCommandNum(args.Target); if (KConfig.Log.SysCall) { KernelMessage.WriteLine("Got SysCall cmd={0} arg1={1} arg2={2} arg3={3} arg4={4} arg5={5} arg6={6}", (uint)args.Target, args.Arg1, args.Arg2, args.Arg3, args.Arg4, args.Arg5, args.Arg6); } Scheduler.SaveThreadState(Scheduler.GetCurrentThread().ThreadID, (IntPtr)stack); var info = Commands[commandNum]; if (info == null) { Panic.Error("Undefined SysCall"); } var ctx = new SysCallContext { CallingType = callingMethod, }; stack->EAX = info.Handler(&ctx, &args); }
public static void Print(string message) { Panic.Error("print"); Screen.Write(message); }
public static void Fail(string message, string detailMessage) { Panic.Error(message); }
private static void AssertError(string message) { Panic.Error(message); }
/// <summary> /// Entry point into the ISR (Interrupt Service Routine) /// </summary> /// <param name="stack">Pointer to the ISR stack</param> private static unsafe void ProcessInterrupt(ref IDTStack stack) { // Switch to Kernel segments ushort dataSelector = KnownSegments.KernelData; Native.SetSegments(dataSelector, dataSelector, KnownSegments.KernelThreadStorage, dataSelector, dataSelector); // Switch to Kernel Adresse space var block = (InterruptControlBlock *)Address.InterruptControlBlock; Native.SetCR3(block->KernelPageTableAddr); // Get the IRQ var irq = stack.Interrupt; // Get the pagetable address of the interrupted process uint pageTableAddr = 0; var thread = Scheduler.GetCurrentThread(); if (thread != null) { dataSelector = (ushort)thread.DataSelector; pageTableAddr = thread.Process.PageTable.GetPageTablePhysAddr(); } // If the IDTManager is not initialized yet or hard disabled, we return now if (!IDTManager.Enabled) { PIC.SendEndOfInterrupt(irq); return; } // Get interrupt info for the IRQ var interruptInfo = IDTManager.Handlers[irq]; if (KConfig.Log.Interrupts && interruptInfo.Trace && thread != null) { KernelMessage.WriteLine("Interrupt {0}, Thread {1}, EIP={2:X8} ESP={3:X8}", irq, (uint)thread.ThreadID, stack.EIP, stack.ESP); } // Some statistics IDTManager.RaisedCount++; if (interruptInfo.CountStatistcs) { IDTManager.RaisedCountCustom++; } if (KConfig.Log.Interrupts) { if (interruptInfo.Trace) { KernelMessage.WriteLine("Interrupt: {0}", irq); } var col = Screen.Column; var row = Screen.Row; Screen.Column = 0; Screen.Goto(2, 35); Screen.Write("Interrupts: "); Screen.Write(IDTManager.RaisedCount); Screen.Goto(3, 35); Screen.Write("IntNoClock: "); Screen.Write(IDTManager.RaisedCountCustom); Screen.Row = row; Screen.Column = col; } // This should never happen if (irq < 0 || irq > 255) { Panic.Error("Invalid Interrupt"); } // Invoke handlers if (interruptInfo.PreHandler != null) { interruptInfo.PreHandler(ref stack); } if (interruptInfo.Handler == null) { Panic.Error("Handler is null"); } else { } interruptInfo.Handler(ref stack); // Important! Otherwise we will get any more interrupts of this kind PIC.SendEndOfInterrupt(irq); // Switch to original address space if (pageTableAddr > 0) { Native.SetCR3(pageTableAddr); } // Switch to original segments Native.SetSegments(dataSelector, dataSelector, KnownSegments.UserThreadStorage, dataSelector, KnownSegments.KernelData); // ISR is completed. The upper ISR stub will re-enable interrupts and resume the original process }
public static unsafe void StartupStage2() { try { if (!KConfig.SingleThread) { Scheduler.CreateThread(ProcessManager.System, new ThreadStartOptions(BackgroundWorker.ThreadMain) { DebugName = "BackgroundWorker", Priority = -5 }).Start(); Scheduler.CreateThread(ProcessManager.System, new ThreadStartOptions(Thread0) { DebugName = "KernelThread0", Priority = -5 }).Start(); var userProc = ProcessManager.CreateEmptyProcess(new ProcessCreateOptions { User = false }); userProc.Path = "/buildin/testproc"; Scheduler.CreateThread(userProc, new ThreadStartOptions(Thread1) { AllowUserModeIOPort = true, DebugName = "UserThread1", Priority = -5 }); Scheduler.CreateThread(userProc, new ThreadStartOptions(Thread2) { AllowUserModeIOPort = true, DebugName = "UserThread2", Priority = -5 }); userProc.Start(); var fileProc = ProcessManager.StartProcess("Service.Basic"); FileServ = fileProc.Service; KernelMessage.WriteLine("Waiting for Service"); while (FileServ.Status != ServiceStatus.Ready) { Scheduler.Sleep(0); } KernelMessage.WriteLine("Service Ready"); //var buf = Abanu.Runtime.SysCalls.RequestMessageBuffer(4096, FileServ.Process.ProcessID); //var kb = Abanu.Runtime.SysCalls.OpenFile(buf, "/dev/keyboard"); //KernelMessage.Write("kb Handle: {0:X8}", kb); //buf.Size = 4; //Abanu.Runtime.SysCalls.WriteFile(kb, buf); //Abanu.Runtime.SysCalls.ReadFile(kb, buf); //var procHostCommunication = ProcessManager.StartProcess("Service.HostCommunication"); //ServHostCommunication = new Service(procHostCommunication); //// TODO: Optimize Registration //SysCallManager.SetCommandProcess(SysCallTarget.HostCommunication_CreateProcess, procHostCommunication); var proc = ProcessManager.StartProcess("App.HelloService"); Serv = proc.Service; var p2 = ProcessManager.StartProcess("App.HelloKernel"); //p2.Threads[0].SetArgument(0, 0x90); //p2.Threads[0].SetArgument(4, 0x94); //p2.Threads[0].SetArgument(8, 0x98); p2.Threads[0].Debug = true; var p3 = ProcessManager.StartProcess("App.Shell"); ProcessManager.System.Threads[0].Status = ThreadStatus.Terminated; } VirtualPageManager.SetTraceOptions(new PageFrameAllocatorTraceOptions { Enabled = true, MinPages = 1 }); KernelMessage.WriteLine("Enter Main Loop"); AppMain(); } catch (Exception ex) { Panic.Error(ex.Message); } }
/// <summary> /// Interrupts the handler. /// </summary> /// <param name="stackStatePointer">The stack state pointer.</param> private static unsafe void ProcessInterrupt(uint stackStatePointer) { ushort dataSelector = 0x10; Native.SetSegments(dataSelector, dataSelector, dataSelector, dataSelector, dataSelector); var block = (InterruptControlBlock *)Address.InterruptControlBlock; Native.SetCR3(block->KernelPageTableAddr); //KernelMessage.WriteLine("Interrupt occurred"); var stack = (IDTStack *)stackStatePointer; var irq = stack->Interrupt; uint pageTableAddr = 0; var thread = Scheduler.GetCurrentThread(); if (thread != null) { dataSelector = (ushort)thread.DataSelector; pageTableAddr = thread.Process.PageTable.GetPageTablePhysAddr(); } if (!IDTManager.Enabled) { PIC.SendEndOfInterrupt(irq); return; } var interruptInfo = IDTManager.Handlers[irq]; if (KConfig.Log.Interrupts && interruptInfo.Trace && thread != null) { KernelMessage.WriteLine("Interrupt {0}, Thread {1}, EIP={2:X8} ESP={3:X8}", irq, thread.ThreadID, stack->EIP, stack->ESP); } IDTManager.RaisedCount++; if (interruptInfo.CountStatistcs) { IDTManager.RaisedCountCustom++; } if (KConfig.Log.Interrupts) { if (interruptInfo.Trace) { KernelMessage.WriteLine("Interrupt: {0}", irq); } var col = Screen.Column; var row = Screen.Row; Screen.Column = 0; Screen.Goto(2, 35); Screen.Write("Interrupts: "); Screen.Write(IDTManager.RaisedCount); Screen.Goto(3, 35); Screen.Write("IntNoClock: "); Screen.Write(IDTManager.RaisedCountCustom); Screen.Row = row; Screen.Column = col; } if (irq < 0 || irq > 255) { Panic.Error("Invalid Interrupt"); } if (interruptInfo.PreHandler != null) { interruptInfo.PreHandler(stack); } if (interruptInfo.Handler == null) { Panic.Error("Handler is null"); } else { } interruptInfo.Handler(stack); PIC.SendEndOfInterrupt(irq); if (pageTableAddr > 0) { Native.SetCR3(pageTableAddr); } Native.SetSegments(dataSelector, dataSelector, dataSelector, dataSelector, 0x10); }
protected override void malloc_abort(string msg) { Panic.Error(msg); }
private Page *AllocateInternal(uint pages, AllocatePageOptions options = default) { if (KConfig.Log.PageAllocation && TraceOptions.Enabled && pages >= TraceOptions.MinPages) { KernelMessage.Path(DebugName, "Requesting Pages: {1}. Available: {2} DebugName={0}", options.DebugName, pages, _FreePages); } if (pages == 256) { Debug.Nop(); } UninterruptableMonitor.Enter(this); try { SelfCheck("SC1"); if (pages > 1 && (AddressSpaceKind == AddressSpaceKind.Virtual || options.Continuous)) { if (!MoveToFreeContinuous(pages)) { // Compact //KernelMessage.Path(DebugName, "Compacting Linked List"); //this.DumpPages(); BuildLinkedLists(); if (!MoveToFreeContinuous(pages)) { this.DumpPages(); KernelMessage.WriteLine("Requesting {0} pages failed", pages); Panic.Error("Requesting pages failed: out of memory"); } } } // --- var head = FreeList; var headPage = (Page *)head; FreeList = head->next; list_head.list_del_init(head); headPage->Status = PageStatus.Used; if (KConfig.Log.PageAllocation) { if (options.DebugName != null) { headPage->DebugTag = (uint)Intrinsic.GetObjectAddress(options.DebugName); } else { headPage->DebugTag = null; } } _FreePages--; // --- for (var i = 1; i < pages; i++) { var tmpNextFree = FreeList->next; list_head.list_move_tail(FreeList, head); var p = (Page *)FreeList; if (p->Status == PageStatus.Used) { this.DumpPages(); this.DumpPage(p); KernelMessage.Path(DebugName, "Double Alloc pages={0} allocs={1} free={2} ptr={3:X8}", pages, (uint)_Requests, _FreePages, (uint)p); Panic.Error("Double Alloc"); } p->Status = PageStatus.Used; FreeList = tmpNextFree; _FreePages--; } if (KConfig.Log.PageAllocation && TraceOptions.Enabled && pages >= TraceOptions.MinPages) { KernelMessage.Path(DebugName, "Allocation done. Addr: {0:X8} Available: {1}", GetAddress(headPage), _FreePages); } _Requests++; CheckAllocation(headPage, pages); SelfCheck("SC2"); return(headPage); } finally { UninterruptableMonitor.Exit(this); } }
public static unsafe void Main() { try { ManagedMemoy.InitializeGCMemory(); StartUp.InitializeAssembly(); KMath.Init(); //Mosa.Runtime.StartUp.InitializeRuntimeMetadata(); BootInfo.SetupStage1(); Memory.InitialKernelProtect(); ApiContext.Current = new ApiHost(); Assert.Setup(AssertError); // Setup some pseudo devices DeviceManager.InitStage1(); //Setup Output and Debug devices DeviceManager.InitStage2(); // Write first output KernelMessage.WriteLine("<KERNEL:CONSOLE:BEGIN>"); PerformanceCounter.Setup(BootInfo.Header->KernelBootStartCycles); KernelMessage.WriteLine("Starting Abanu Kernel..."); KernelMessage.WriteLine("KConfig.UseKernelMemoryProtection: {0}", KConfig.UseKernelMemoryProtection); KernelMessage.WriteLine("KConfig.UsePAE: {0}", KConfig.UsePAE); KernelMessage.WriteLine("Apply PageTableType: {0}", (uint)BootInfo.Header->PageTableType); KernelMessage.WriteLine("GCInitialMemory: {0:X8}-{1:X8}", Address.GCInitialMemory, Address.GCInitialMemory + Address.GCInitialMemorySize - 1); Ulongtest1(); Ulongtest2(); InlineTest(); // Detect environment (Memory Maps, Video Mode, etc.) BootInfo.SetupStage2(); KernelMemoryMapManager.Setup(); //KernelMemoryMapManager.Allocate(0x1000 * 1000, BootInfoMemoryType.PageDirectory); // Read own ELF-Headers and Sections KernelElf.Setup(); // Initialize the embedded code (actually only a little proof of concept code) NativeCalls.Setup(); //InitialKernelProtect(); PhysicalPageManager.Setup(); KernelMessage.WriteLine("Phys free: {0}", PhysicalPageManager.FreePages); PhysicalPageManager.AllocatePages(10); KernelMessage.WriteLine("Phys free: {0}", PhysicalPageManager.FreePages); VirtualPageManager.Setup(); Memory.Setup(); // Now Memory Sub System is working. At this point it's valid // to allocate memory dynamically DeviceManager.InitFrameBuffer(); // Setup Programmable Interrupt Table PIC.Setup(); // Setup Interrupt Descriptor Table // Important Note: IDT depends on GDT. Never setup IDT before GDT. IDTManager.Setup(); InitializeUserMode(); SysCallManager.Setup(); KernelMessage.WriteLine("Initialize Runtime Metadata"); StartUp.InitializeRuntimeMetadata(); KernelMessage.WriteLine("Performing some Non-Thread Tests"); Tests(); } catch (Exception ex) { Panic.Error(ex.Message); } if (KConfig.SingleThread) { StartupStage2(); } else { ProcessManager.Setup(StartupStage2); } }
/// <summary> /// Aborts with the specified message. /// </summary> /// <param name="message">The message.</param> public override void Abort(string message) { Panic.Error(message); }
private static void StartupStage2() { try { if (!KConfig.SingleThread) { Scheduler.CreateThread(ProcessManager.System, new ThreadStartOptions(BackgroundWorker.ThreadMain) { DebugName = "BackgroundWorker", Priority = -5 }).Start(); ThreadTests.StartTestThreads(); // Start some applications var fileProc = ProcessManager.CreateProcess("Service.Basic"); FileServ = fileProc.Service; fileProc.Start(); KernelMessage.WriteLine("Waiting for Service"); while (FileServ.Status != ServiceStatus.Ready) { Scheduler.Sleep(0); } KernelMessage.WriteLine("Service Ready"); var conProc = ProcessManager.CreateProcess("Service.ConsoleServer"); conProc.Start(); var conServ = conProc.Service; KernelMessage.WriteLine("Waiting for ConsoleServer"); while (conServ.Status != ServiceStatus.Ready) { Scheduler.Sleep(0); } KernelMessage.WriteLine("ConsoleServer Ready"); //var buf = Abanu.Runtime.SysCalls.RequestMessageBuffer(4096, FileServ.Process.ProcessID); //var kb = Abanu.Runtime.SysCalls.OpenFile(buf, "/dev/keyboard"); //KernelMessage.Write("kb Handle: {0:X8}", kb); //buf.Size = 4; //Abanu.Runtime.SysCalls.WriteFile(kb, buf); //Abanu.Runtime.SysCalls.ReadFile(kb, buf); //var procHostCommunication = ProcessManager.StartProcess("Service.HostCommunication"); //ServHostCommunication = new Service(procHostCommunication); //// TODO: Optimize Registration //SysCallManager.SetCommandProcess(SysCallTarget.HostCommunication_CreateProcess, procHostCommunication); var proc = ProcessManager.CreateProcess("App.HelloService"); Serv = proc.Service; proc.Start(); var p2 = ProcessManager.CreateProcess("App.HelloKernel"); p2.Start(); //p2.Threads[0].SetArgument(0, 0x90); //p2.Threads[0].SetArgument(4, 0x94); //p2.Threads[0].SetArgument(8, 0x98); p2.Threads[0].Debug = true; var p3 = ProcessManager.CreateProcess("App.Shell"); p3.Start(); ProcessManager.System.Threads[0].Status = ThreadStatus.Terminated; } VirtualPageManager.SetTraceOptions(new PageFrameAllocatorTraceOptions { Enabled = true, MinPages = 1 }); KernelMessage.WriteLine("Enter Main Loop"); AppMain(); } catch (Exception ex) { Panic.Error(ex.Message); } }
public Page *AllocatePages(uint pages, AllocatePageOptions options = default) { lock (this) { if (pages == 0) { KernelMessage.WriteLine("Requesting zero pages"); return(null); } else if (pages > 1 && KConfig.Log.PageAllocation) { KernelMessage.WriteLine("Requesting {0} pages", pages); } //KernelMessage.WriteLine("Request {0} pages...", num); uint statBlocks = 0; uint statFreeBlocks = 0; int statMaxBlockPages = 0; uint statRangeChecks = 0; uint cnt = 0; if (NextTryPage == null) { NextTryPage = PageArray; } Page *p = NextTryPage; while (true) { statBlocks++; if (p == null) { p = PageArray; } if (p->Status == PageStatus.Free) { statFreeBlocks++; var head = p; // Found free Page. Check now free range. for (var i = 0; i < pages; i++) { statRangeChecks++; statMaxBlockPages = Math.Max(statMaxBlockPages, i); if (p == null) { break; // Reached end. Our Range is incomplete } if (p->Status != PageStatus.Free) // Used -> so we can abort the search { break; } if (i == pages - 1) { // all loops successful. So we found our range. if (p == null) { Panic.Error("Tail is null"); } head->Tail = p; head->PagesUsed = pages; p = head; for (var n = 0; n < pages; n++) { if (p->Status != PageStatus.Free) { Panic.Error("Page is not Free. PageFrame Array corrupted?"); } p->Status = PageStatus.Used; p->Head = head; p->Tail = head->Tail; p = NextPage(p); _FreePages--; } // correct version: NextTryPage = p; // TODO: HACK! Currently, we have somewhere a buffer overrun? Fix that! //NextTryPage = p + 1; //var t = head->Tail; //var a = t->Address; //var anum = (uint)a; ////(uint)head->Tail->Address + 4096 - 1 //KernelMessage.Write("<"); //KernelMessage.WriteLine("Allocated from {0:X8} to {1:X8}, Status={2}", (uint)head->Address, anum, (uint)head->Status); //KernelMessage.Write(">"); //if (head->PhysicalAddress == 0x01CA4000) //{ // KernelMessage.WriteLine("DEBUG-MARKER 2"); // DumpPage(head); //} return(head); } p = NextPage(p); } } if (p->Tail != null) { p = p->Tail; } p = NextPage(p); if (++cnt > _TotalPages) { break; } } KernelMessage.WriteLine("Blocks={0} FreeBlocks={1} MaxBlockPages={2} RangeChecks={3} cnt={4}", statBlocks, statFreeBlocks, (uint)statMaxBlockPages, statRangeChecks, cnt); this.DumpPages(); Panic.Error("PageFrameAllocator: Could not allocate " + pages + " Pages."); return(null); } }
/// <summary> /// Aborts with the specified message. /// </summary> /// <param name="message">The message.</param> void IHardwareAbstraction.Abort(string message) { Panic.Error(message); }