private KernelResult FreeTlsPage(KTlsPageInfo pageInfo) { KernelResult result = MemoryManager.UnmapForKernel(pageInfo.PageVirtualAddress, 1, MemoryState.ThreadLocal); if (result == KernelResult.Success) { KernelContext.UserSlabHeapPages.Free(pageInfo.PagePhysicalAddress); } return(result); }
public KernelResult AllocateThreadLocalStorage(out ulong address) { System.CriticalSection.Enter(); KernelResult result; if (_freeTlsPages.Count > 0) { // If we have free TLS pages available, just use the first one. KTlsPageInfo pageInfo = _freeTlsPages.Values.First(); if (!pageInfo.TryGetFreePage(out address)) { throw new InvalidOperationException("Unexpected failure getting free TLS page!"); } if (pageInfo.IsFull()) { _freeTlsPages.Remove(pageInfo.PageAddr); _fullTlsPages.Add(pageInfo.PageAddr, pageInfo); } result = KernelResult.Success; } else { // Otherwise, we need to create a new one. result = AllocateTlsPage(out KTlsPageInfo pageInfo); if (result == KernelResult.Success) { if (!pageInfo.TryGetFreePage(out address)) { throw new InvalidOperationException("Unexpected failure getting free TLS page!"); } _freeTlsPages.Add(pageInfo.PageAddr, pageInfo); } else { address = 0; } } System.CriticalSection.Leave(); return(result); }
private KernelResult FreeTlsPage(KTlsPageInfo pageInfo) { if (!MemoryManager.ConvertVaToPa(pageInfo.PageAddr, out ulong tlsPagePa)) { throw new InvalidOperationException("Unexpected failure translating virtual address to physical."); } KernelResult result = MemoryManager.UnmapForKernel(pageInfo.PageAddr, 1, MemoryState.ThreadLocal); if (result == KernelResult.Success) { System.UserSlabHeapPages.Free(tlsPagePa); } return(result); }
public KernelResult FreeThreadLocalStorage(ulong tlsSlotAddr) { ulong tlsPageAddr = BitUtils.AlignDown(tlsSlotAddr, KMemoryManager.PageSize); System.CriticalSection.Enter(); KernelResult result = KernelResult.Success; KTlsPageInfo pageInfo = null; if (_fullTlsPages.TryGetValue(tlsPageAddr, out pageInfo)) { // TLS page was full, free slot and move to free pages tree. _fullTlsPages.Remove(tlsPageAddr); _freeTlsPages.Add(tlsPageAddr, pageInfo); } else if (!_freeTlsPages.TryGetValue(tlsPageAddr, out pageInfo)) { result = KernelResult.InvalidAddress; } if (pageInfo != null) { pageInfo.FreeTlsSlot(tlsSlotAddr); if (pageInfo.IsEmpty()) { // TLS page is now empty, we should ensure it is removed // from all trees, and free the memory it was using. _freeTlsPages.Remove(tlsPageAddr); System.CriticalSection.Leave(); FreeTlsPage(pageInfo); return(KernelResult.Success); } } System.CriticalSection.Leave(); return(result); }
private KernelResult AllocateTlsPage(out KTlsPageInfo pageInfo) { pageInfo = default(KTlsPageInfo); if (!System.UserSlabHeapPages.TryGetItem(out ulong tlsPagePa)) { return(KernelResult.OutOfMemory); } ulong regionStart = MemoryManager.TlsIoRegionStart; ulong regionSize = MemoryManager.TlsIoRegionEnd - regionStart; ulong regionPagesCount = regionSize / KMemoryManager.PageSize; KernelResult result = MemoryManager.AllocateOrMapPa( 1, KMemoryManager.PageSize, tlsPagePa, true, regionStart, regionPagesCount, MemoryState.ThreadLocal, MemoryPermission.ReadAndWrite, out ulong tlsPageVa); if (result != KernelResult.Success) { System.UserSlabHeapPages.Free(tlsPagePa); } else { pageInfo = new KTlsPageInfo(tlsPageVa); MemoryHelper.FillWithZeros(CpuMemory, (long)tlsPageVa, KMemoryManager.PageSize); } return(result); }