forked from Mirror/Ryujinx
85dbb9559a
* Rename enum fields
* Naming conventions
* Remove unneeded ".this"
* Remove unneeded semicolons
* Remove unused Usings
* Don't use var
* Remove unneeded enum underlying types
* Explicitly label class visibility
* Remove unneeded @ prefixes
* Remove unneeded commas
* Remove unneeded if expressions
* Method doesn't use unsafe code
* Remove unneeded casts
* Initialized objects don't need an empty constructor
* Remove settings from DotSettings
* Revert "Explicitly label class visibility"
This reverts commit ad5eb5787c
.
* Small changes
* Revert external enum renaming
* Changes from feedback
* Remove unneeded property setters
107 lines
No EOL
2.6 KiB
C#
107 lines
No EOL
2.6 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
|
|
namespace Ryujinx.HLE.HOS.Services.Nv.NvHostCtrl
|
|
{
|
|
class NvHostSyncpt
|
|
{
|
|
public const int SyncptsCount = 192;
|
|
|
|
private int[] _counterMin;
|
|
private int[] _counterMax;
|
|
|
|
private long _eventMask;
|
|
|
|
private ConcurrentDictionary<EventWaitHandle, int> _waiters;
|
|
|
|
public NvHostSyncpt()
|
|
{
|
|
_counterMin = new int[SyncptsCount];
|
|
_counterMax = new int[SyncptsCount];
|
|
|
|
_waiters = new ConcurrentDictionary<EventWaitHandle, int>();
|
|
}
|
|
|
|
public int GetMin(int id)
|
|
{
|
|
return _counterMin[id];
|
|
}
|
|
|
|
public int GetMax(int id)
|
|
{
|
|
return _counterMax[id];
|
|
}
|
|
|
|
public int Increment(int id)
|
|
{
|
|
if (((_eventMask >> id) & 1) != 0)
|
|
{
|
|
Interlocked.Increment(ref _counterMax[id]);
|
|
}
|
|
|
|
return IncrementMin(id);
|
|
}
|
|
|
|
public int IncrementMin(int id)
|
|
{
|
|
int value = Interlocked.Increment(ref _counterMin[id]);
|
|
|
|
WakeUpWaiters(id, value);
|
|
|
|
return value;
|
|
}
|
|
|
|
public int IncrementMax(int id)
|
|
{
|
|
return Interlocked.Increment(ref _counterMax[id]);
|
|
}
|
|
|
|
public void AddWaiter(int threshold, EventWaitHandle waitEvent)
|
|
{
|
|
if (!_waiters.TryAdd(waitEvent, threshold))
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
}
|
|
|
|
public bool RemoveWaiter(EventWaitHandle waitEvent)
|
|
{
|
|
return _waiters.TryRemove(waitEvent, out _);
|
|
}
|
|
|
|
private void WakeUpWaiters(int id, int newValue)
|
|
{
|
|
foreach (KeyValuePair<EventWaitHandle, int> kv in _waiters)
|
|
{
|
|
if (MinCompare(id, newValue, _counterMax[id], kv.Value))
|
|
{
|
|
kv.Key.Set();
|
|
|
|
_waiters.TryRemove(kv.Key, out _);
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool MinCompare(int id, int threshold)
|
|
{
|
|
return MinCompare(id, _counterMin[id], _counterMax[id], threshold);
|
|
}
|
|
|
|
private bool MinCompare(int id, int min, int max, int threshold)
|
|
{
|
|
int minDiff = min - threshold;
|
|
int maxDiff = max - threshold;
|
|
|
|
if (((_eventMask >> id) & 1) != 0)
|
|
{
|
|
return minDiff >= 0;
|
|
}
|
|
else
|
|
{
|
|
return (uint)maxDiff >= (uint)minDiff;
|
|
}
|
|
}
|
|
}
|
|
} |