diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2020-12-01 20:23:43 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-12-02 00:23:43 +0100 |
| commit | cf6cd714884c41e9550757e364c2f4f5b04fc7f3 (patch) | |
| tree | bea748b4d1a350e5b8075d63ec9d39d49693829d /Ryujinx.HLE/HOS/Services/SurfaceFlinger | |
| parent | 461c24092ae6e148d896c18aa3e86220c89981f8 (diff) | |
IPC refactor part 2: Use ReplyAndReceive on HLE services and remove special handling from kernel (#1458)
* IPC refactor part 2: Use ReplyAndReceive on HLE services and remove special handling from kernel
* Fix for applet transfer memory + some nits
* Keep handles if possible to avoid server handle table exhaustion
* Fix IPC ZeroFill bug
* am: Correctly implement CreateManagedDisplayLayer and implement CreateManagedDisplaySeparableLayer
CreateManagedDisplaySeparableLayer is requires since 10.x+ when appletResourceUserId != 0
* Make it exit properly
* Make ServiceNotImplementedException show the full message again
* Allow yielding execution to avoid starving other threads
* Only wait if active
* Merge IVirtualMemoryManager and IAddressSpaceManager
* Fix Ro loading data from the wrong process
Co-authored-by: Thog <me@thog.eu>
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/SurfaceFlinger')
6 files changed, 72 insertions, 30 deletions
diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueue.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueue.cs index 3dd21fde..2a9a6064 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueue.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueue.cs @@ -1,15 +1,15 @@ -using Ryujinx.HLE.HOS.Kernel.Process; - -namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger +namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { - class BufferQueue + static class BufferQueue { - public static void CreateBufferQueue(Switch device, KProcess process, out BufferQueueProducer producer, out BufferQueueConsumer consumer) + public static BufferQueueCore CreateBufferQueue(Switch device, long pid, out BufferQueueProducer producer, out BufferQueueConsumer consumer) { - BufferQueueCore core = new BufferQueueCore(device, process); + BufferQueueCore core = new BufferQueueCore(device, pid); producer = new BufferQueueProducer(core); consumer = new BufferQueueConsumer(core); + + return core; } } } diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs index 7f6f6c31..389a980b 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs @@ -1,5 +1,5 @@ using Ryujinx.Common.Logging; -using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.SurfaceFlinger.Types; using System; @@ -40,11 +40,13 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger private KEvent _waitBufferFreeEvent; private KEvent _frameAvailableEvent; - public KProcess Owner { get; } + public long Owner { get; } + + public bool Active { get; private set; } public const int BufferHistoryArraySize = 8; - public BufferQueueCore(Switch device, KProcess process) + public BufferQueueCore(Switch device, long pid) { Slots = new BufferSlotArray(); IsAbandoned = false; @@ -70,7 +72,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger _waitBufferFreeEvent = new KEvent(device.System.KernelContext); _frameAvailableEvent = new KEvent(device.System.KernelContext); - Owner = process; + Owner = pid; + + Active = true; BufferHistory = new BufferInfo[BufferHistoryArraySize]; EnableExternalEvent = true; @@ -162,6 +166,16 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger } } + public void PrepareForExit() + { + lock (Lock) + { + Active = false; + + Monitor.PulseAll(Lock); + } + } + // TODO: Find an accurate way to handle a regular condvar here as this will wake up unwanted threads in some edge cases. public void SignalDequeueEvent() { @@ -170,7 +184,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger public void WaitDequeueEvent() { - Monitor.Wait(Lock); + Monitor.Exit(Lock); + + KernelStatic.YieldUntilCompletion(WaitForLock); + + Monitor.Enter(Lock); } public void SignalIsAllocatingEvent() @@ -180,7 +198,22 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger public void WaitIsAllocatingEvent() { - Monitor.Wait(Lock); + Monitor.Exit(Lock); + + KernelStatic.YieldUntilCompletion(WaitForLock); + + Monitor.Enter(Lock); + } + + private void WaitForLock() + { + lock (Lock) + { + if (Active) + { + Monitor.Wait(Lock); + } + } } public void FreeBufferLocked(int slot) diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs index 6ef49538..03df04ad 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs @@ -816,6 +816,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger } Core.WaitDequeueEvent(); + + if (!Core.Active) + { + break; + } } } diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs index 8ee943df..b3c81381 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs @@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { abstract class IHOSBinderDriver : IpcService { - public IHOSBinderDriver() {} + public IHOSBinderDriver() { } [Command(0)] // TransactParcel(s32, u32, u32, buffer<unknown, 5, 0>) -> buffer<unknown, 6, 0> diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs index 4713e50b..4927b40e 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs @@ -1,10 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu; -using Ryujinx.HLE.HOS.Kernel.Process; -using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; -using Ryujinx.HLE.HOS.Services.Nv.Types; using System; using System.Collections.Generic; using System.Diagnostics; @@ -40,7 +37,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger public int ProducerBinderId; public IGraphicBufferProducer Producer; public BufferItemConsumer Consumer; - public KProcess Owner; + public BufferQueueCore Core; + public long Owner; } private class TextureCallbackInformation @@ -84,7 +82,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger } } - public IGraphicBufferProducer OpenLayer(KProcess process, long layerId) + public IGraphicBufferProducer OpenLayer(long pid, long layerId) { bool needCreate; @@ -95,13 +93,13 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger if (needCreate) { - CreateLayerFromId(process, layerId); + CreateLayerFromId(pid, layerId); } return GetProducerByLayerId(layerId); } - public IGraphicBufferProducer CreateLayer(KProcess process, out long layerId) + public IGraphicBufferProducer CreateLayer(long pid, out long layerId) { layerId = 1; @@ -116,25 +114,26 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger } } - CreateLayerFromId(process, layerId); + CreateLayerFromId(pid, layerId); return GetProducerByLayerId(layerId); } - private void CreateLayerFromId(KProcess process, long layerId) + private void CreateLayerFromId(long pid, long layerId) { lock (Lock) { Logger.Info?.Print(LogClass.SurfaceFlinger, $"Creating layer {layerId}"); - BufferQueue.CreateBufferQueue(_device, process, out BufferQueueProducer producer, out BufferQueueConsumer consumer); + BufferQueueCore core = BufferQueue.CreateBufferQueue(_device, pid, out BufferQueueProducer producer, out BufferQueueConsumer consumer); _layers.Add(layerId, new Layer { ProducerBinderId = HOSBinderDriverServer.RegisterBinderObject(producer), Producer = producer, Consumer = new BufferItemConsumer(_device, consumer, 0, -1, false, this), - Owner = process + Core = core, + Owner = pid }); LastId = layerId; @@ -345,6 +344,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger public void Dispose() { _isRunning = false; + + foreach (Layer layer in _layers.Values) + { + layer.Core.PrepareForExit(); + } } public void OnFrameAvailable(ref BufferItem item) diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/GraphicBuffer.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/GraphicBuffer.cs index 8d63d9cc..d86ff21e 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/GraphicBuffer.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/GraphicBuffer.cs @@ -42,23 +42,23 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger Buffer = parcel.ReadUnmanagedType<NvGraphicBuffer>(); } - public void IncrementNvMapHandleRefCount(KProcess process) + public void IncrementNvMapHandleRefCount(long pid) { - NvMapDeviceFile.IncrementMapRefCount(process, Buffer.NvMapId); + NvMapDeviceFile.IncrementMapRefCount(pid, Buffer.NvMapId); for (int i = 0; i < Buffer.Surfaces.Length; i++) { - NvMapDeviceFile.IncrementMapRefCount(process, Buffer.Surfaces[i].NvMapHandle); + NvMapDeviceFile.IncrementMapRefCount(pid, Buffer.Surfaces[i].NvMapHandle); } } - public void DecrementNvMapHandleRefCount(KProcess process) + public void DecrementNvMapHandleRefCount(long pid) { - NvMapDeviceFile.DecrementMapRefCount(process, Buffer.NvMapId); + NvMapDeviceFile.DecrementMapRefCount(pid, Buffer.NvMapId); for (int i = 0; i < Buffer.Surfaces.Length; i++) { - NvMapDeviceFile.DecrementMapRefCount(process, Buffer.Surfaces[i].NvMapHandle); + NvMapDeviceFile.DecrementMapRefCount(pid, Buffer.Surfaces[i].NvMapHandle); } } |
