* dotnet format style --severity info Some changes were manually reverted. * dotnet format analyzers --serverity info Some changes have been minimally adapted. * Restore a few unused methods and variables * Silence dotnet format IDE0060 warnings * Silence dotnet format IDE0052 warnings * Address or silence dotnet format IDE1006 warnings * Address dotnet format CA1816 warnings * Address or silence dotnet format CA2208 warnings * Address or silence dotnet format CA1806 and a few CA1854 warnings * Address dotnet format CA2211 warnings * Address dotnet format CA1822 warnings * Address or silence dotnet format CA1069 warnings * Make dotnet format succeed in style mode * Address or silence dotnet format CA2211 warnings * Address review comments * Address dotnet format CA2208 warnings properly * Make ProcessResult readonly * Address most dotnet format whitespace warnings * Apply dotnet format whitespace formatting A few of them have been manually reverted and the corresponding warning was silenced * Add previously silenced warnings back I have no clue how these disappeared * Revert formatting changes for while and for-loops * Format if-blocks correctly * Run dotnet format style after rebase * Run dotnet format whitespace after rebase * Run dotnet format style after rebase * Run dotnet format analyzers after rebase * Run dotnet format after rebase and remove unused usings - analyzers - style - whitespace * Disable 'prefer switch expression' rule * Add comments to disabled warnings * Fix a few disabled warnings * Fix naming rule violation, Convert shader properties to auto-property and convert values to const * Simplify properties and array initialization, Use const when possible, Remove trailing commas * Start working on disabled warnings * Fix and silence a few dotnet-format warnings again * Run dotnet format after rebase * Use using declaration instead of block syntax * Address IDE0251 warnings * Address a few disabled IDE0060 warnings * Silence IDE0060 in .editorconfig * Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas" This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e. * dotnet format whitespace after rebase * First dotnet format pass * Fix naming rule violations * Fix typo * Add trailing commas, use targeted new and use array initializer * Fix build issues * Fix remaining build issues * Remove SuppressMessage for CA1069 where possible * Address dotnet format issues * Address formatting issues Co-authored-by: Ac_K <acoustik666@gmail.com> * Add GetHashCode implementation for RenderingSurfaceInfo * Explicitly silence CA1822 for every affected method in Syscall * Address formatting issues in Demangler.cs * Address review feedback Co-authored-by: Ac_K <acoustik666@gmail.com> * Revert marking service methods as static * Next dotnet format pass * Address review feedback --------- Co-authored-by: Ac_K <acoustik666@gmail.com>
298 lines
7.4 KiB
C#
298 lines
7.4 KiB
C#
using Ryujinx.Common;
|
|
using System;
|
|
using System.Numerics;
|
|
|
|
namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|
{
|
|
class KPageBitmap
|
|
{
|
|
private struct RandomNumberGenerator
|
|
{
|
|
private uint _entropy;
|
|
private uint _bitsAvailable;
|
|
|
|
private void RefreshEntropy()
|
|
{
|
|
_entropy = 0;
|
|
_bitsAvailable = sizeof(uint) * 8;
|
|
}
|
|
|
|
private bool GenerateRandomBit()
|
|
{
|
|
if (_bitsAvailable == 0)
|
|
{
|
|
RefreshEntropy();
|
|
}
|
|
|
|
bool bit = (_entropy & 1) != 0;
|
|
|
|
_entropy >>= 1;
|
|
_bitsAvailable--;
|
|
|
|
return bit;
|
|
}
|
|
|
|
public int SelectRandomBit(ulong bitmap)
|
|
{
|
|
int selected = 0;
|
|
|
|
int bitsCount = UInt64BitSize / 2;
|
|
ulong mask = (1UL << bitsCount) - 1;
|
|
|
|
while (bitsCount != 0)
|
|
{
|
|
ulong low = bitmap & mask;
|
|
ulong high = (bitmap >> bitsCount) & mask;
|
|
|
|
bool chooseLow;
|
|
|
|
if (high == 0)
|
|
{
|
|
chooseLow = true;
|
|
}
|
|
else if (low == 0)
|
|
{
|
|
chooseLow = false;
|
|
}
|
|
else
|
|
{
|
|
chooseLow = GenerateRandomBit();
|
|
}
|
|
|
|
if (chooseLow)
|
|
{
|
|
bitmap = low;
|
|
}
|
|
else
|
|
{
|
|
bitmap = high;
|
|
selected += bitsCount;
|
|
}
|
|
|
|
bitsCount /= 2;
|
|
mask >>= bitsCount;
|
|
}
|
|
|
|
return selected;
|
|
}
|
|
}
|
|
|
|
private const int UInt64BitSize = sizeof(ulong) * 8;
|
|
private const int MaxDepth = 4;
|
|
|
|
private readonly RandomNumberGenerator _rng;
|
|
private readonly ArraySegment<ulong>[] _bitStorages;
|
|
private int _usedDepths;
|
|
|
|
public int BitsCount { get; private set; }
|
|
|
|
public int HighestDepthIndex => _usedDepths - 1;
|
|
|
|
public KPageBitmap()
|
|
{
|
|
_rng = new RandomNumberGenerator();
|
|
_bitStorages = new ArraySegment<ulong>[MaxDepth];
|
|
}
|
|
|
|
public ArraySegment<ulong> Initialize(ArraySegment<ulong> storage, ulong size)
|
|
{
|
|
_usedDepths = GetRequiredDepth(size);
|
|
|
|
for (int depth = HighestDepthIndex; depth >= 0; depth--)
|
|
{
|
|
_bitStorages[depth] = storage;
|
|
size = BitUtils.DivRoundUp<ulong>(size, (ulong)UInt64BitSize);
|
|
storage = storage.Slice((int)size);
|
|
}
|
|
|
|
return storage;
|
|
}
|
|
|
|
public ulong FindFreeBlock(bool random)
|
|
{
|
|
ulong offset = 0;
|
|
int depth = 0;
|
|
|
|
if (random)
|
|
{
|
|
do
|
|
{
|
|
ulong v = _bitStorages[depth][(int)offset];
|
|
|
|
if (v == 0)
|
|
{
|
|
return ulong.MaxValue;
|
|
}
|
|
|
|
offset = offset * UInt64BitSize + (ulong)_rng.SelectRandomBit(v);
|
|
}
|
|
while (++depth < _usedDepths);
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
ulong v = _bitStorages[depth][(int)offset];
|
|
|
|
if (v == 0)
|
|
{
|
|
return ulong.MaxValue;
|
|
}
|
|
|
|
offset = offset * UInt64BitSize + (ulong)BitOperations.TrailingZeroCount(v);
|
|
}
|
|
while (++depth < _usedDepths);
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
public void SetBit(ulong offset)
|
|
{
|
|
SetBit(HighestDepthIndex, offset);
|
|
BitsCount++;
|
|
}
|
|
|
|
public void ClearBit(ulong offset)
|
|
{
|
|
ClearBit(HighestDepthIndex, offset);
|
|
BitsCount--;
|
|
}
|
|
|
|
public bool ClearRange(ulong offset, int count)
|
|
{
|
|
int depth = HighestDepthIndex;
|
|
var bits = _bitStorages[depth];
|
|
|
|
int bitInd = (int)(offset / UInt64BitSize);
|
|
|
|
if (count < UInt64BitSize)
|
|
{
|
|
int shift = (int)(offset % UInt64BitSize);
|
|
|
|
ulong mask = ((1UL << count) - 1) << shift;
|
|
|
|
ulong v = bits[bitInd];
|
|
|
|
if ((v & mask) != mask)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
v &= ~mask;
|
|
bits[bitInd] = v;
|
|
|
|
if (v == 0)
|
|
{
|
|
ClearBit(depth - 1, (ulong)bitInd);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int remaining = count;
|
|
int i = 0;
|
|
|
|
do
|
|
{
|
|
if (bits[bitInd + i++] != ulong.MaxValue)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
remaining -= UInt64BitSize;
|
|
}
|
|
while (remaining > 0);
|
|
|
|
remaining = count;
|
|
i = 0;
|
|
|
|
do
|
|
{
|
|
bits[bitInd + i] = 0;
|
|
ClearBit(depth - 1, (ulong)(bitInd + i));
|
|
i++;
|
|
remaining -= UInt64BitSize;
|
|
}
|
|
while (remaining > 0);
|
|
}
|
|
|
|
BitsCount -= count;
|
|
return true;
|
|
}
|
|
|
|
private void SetBit(int depth, ulong offset)
|
|
{
|
|
while (depth >= 0)
|
|
{
|
|
int ind = (int)(offset / UInt64BitSize);
|
|
int which = (int)(offset % UInt64BitSize);
|
|
|
|
ulong mask = 1UL << which;
|
|
|
|
ulong v = _bitStorages[depth][ind];
|
|
|
|
_bitStorages[depth][ind] = v | mask;
|
|
|
|
if (v != 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
offset = (ulong)ind;
|
|
depth--;
|
|
}
|
|
}
|
|
|
|
private void ClearBit(int depth, ulong offset)
|
|
{
|
|
while (depth >= 0)
|
|
{
|
|
int ind = (int)(offset / UInt64BitSize);
|
|
int which = (int)(offset % UInt64BitSize);
|
|
|
|
ulong mask = 1UL << which;
|
|
|
|
ulong v = _bitStorages[depth][ind];
|
|
|
|
v &= ~mask;
|
|
|
|
_bitStorages[depth][ind] = v;
|
|
|
|
if (v != 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
offset = (ulong)ind;
|
|
depth--;
|
|
}
|
|
}
|
|
|
|
private static int GetRequiredDepth(ulong regionSize)
|
|
{
|
|
int depth = 0;
|
|
|
|
do
|
|
{
|
|
regionSize /= UInt64BitSize;
|
|
depth++;
|
|
}
|
|
while (regionSize != 0);
|
|
|
|
return depth;
|
|
}
|
|
|
|
public static int CalculateManagementOverheadSize(ulong regionSize)
|
|
{
|
|
int overheadBits = 0;
|
|
|
|
for (int depth = GetRequiredDepth(regionSize) - 1; depth >= 0; depth--)
|
|
{
|
|
regionSize = BitUtils.DivRoundUp<ulong>(regionSize, UInt64BitSize);
|
|
overheadBits += (int)regionSize;
|
|
}
|
|
|
|
return overheadBits * sizeof(ulong);
|
|
}
|
|
}
|
|
}
|