/// <summary> /// Releases a page to the free list /// </summary> public void Free(Page *page) { var oldFree = _FreePages; string debugName = null; if (page->DebugTag != null) { debugName = (string)Intrinsic.GetObjectFromAddress((Pointer)(uint)page->DebugTag); } UninterruptibleMonitor.Enter(this); try { var debugCount = list_head.list_count((list_head *)page); // DEBUG SelfCheck("SCF1", debugCount); Page *temp = page; uint result = 0; do { result++; if (temp->Status == PageStatus.Free) { //Panic.Error("Double Free"); SelfCheck("SCF3", debugCount); KernelMessage.WriteLine("Double Free. Pages {0} Iteration {1}", debugCount, result); Debug.Break(); } temp->Status = PageStatus.Free; var oldTemp = temp; temp = (Page *)temp->Lru.next; Native.Nop(); _FreePages++; list_head.list_move_tail((list_head *)oldTemp, FreeList); }while (temp != page && result != debugCount); //list_head.list_headless_splice_tail((list_head*)page, FreeList); SelfCheck("SCF2", debugCount); } finally { UninterruptibleMonitor.Exit(this); } var freedPages = _FreePages - oldFree; if (KConfig.Log.PageAllocation && TraceOptions.Enabled && freedPages >= TraceOptions.MinPages) { KernelMessage.Path(DebugName, "Freed Pages: {1}. Addr: {2:X8}. Now available: {3} --> {4}. Allocations={5} DebugName={0}.", debugName, freedPages, GetAddress(page), oldFree, _FreePages, (uint)Requests); } _Releases++; }
public void Start() { UninterruptibleMonitor.Enter(Threads); try { RunState = ProcessRunState.Running; for (var i = 0; i < Threads.Count; i++) { KernelMessage.WriteLine("Starting {0}, ProcessID={1} on Thread {2}", Path, (uint)ProcessID, (uint)Threads[0].ThreadID); Threads[i].Start(); } } finally { UninterruptibleMonitor.Exit(Threads); } }
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(); } UninterruptibleMonitor.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 { UninterruptibleMonitor.Exit(this); } }