forked from Mirror/Ryujinx
Fix disposing of IPC sessions server at emulation stop (#2334)
This commit is contained in:
parent
fbb4019ed5
commit
00ce9eea62
28 changed files with 284 additions and 123 deletions
|
@ -133,19 +133,28 @@ namespace Ryujinx.Audio.Backends.OpenAL
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
lock (_lock)
|
_stillRunning = false;
|
||||||
{
|
|
||||||
_stillRunning = false;
|
|
||||||
_updaterThread.Join();
|
|
||||||
|
|
||||||
// Loop against all sessions to dispose them (they will unregister themself)
|
int sessionCount = 0;
|
||||||
while (_sessions.Count > 0)
|
|
||||||
|
// NOTE: This is done in a way to avoid possible situations when the OpenALHardwareDeviceSession is already being dispose in another thread but doesn't hold the lock and tries to Unregister.
|
||||||
|
do
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
{
|
{
|
||||||
OpenALHardwareDeviceSession session = _sessions[0];
|
if (_sessions.Count == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenALHardwareDeviceSession session = _sessions[_sessions.Count - 1];
|
||||||
|
|
||||||
session.Dispose();
|
session.Dispose();
|
||||||
|
|
||||||
|
sessionCount = _sessions.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
while (sessionCount > 0);
|
||||||
|
|
||||||
ALC.DestroyContext(_context);
|
ALC.DestroyContext(_context);
|
||||||
ALC.CloseDevice(_device);
|
ALC.CloseDevice(_device);
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace Ryujinx.Audio.Backends.SoundIo
|
||||||
private SoundIODevice _audioDevice;
|
private SoundIODevice _audioDevice;
|
||||||
private ManualResetEvent _updateRequiredEvent;
|
private ManualResetEvent _updateRequiredEvent;
|
||||||
private List<SoundIoHardwareDeviceSession> _sessions;
|
private List<SoundIoHardwareDeviceSession> _sessions;
|
||||||
|
private int _disposeState;
|
||||||
|
|
||||||
public SoundIoHardwareDeviceDriver()
|
public SoundIoHardwareDeviceDriver()
|
||||||
{
|
{
|
||||||
|
@ -208,19 +209,36 @@ namespace Ryujinx.Audio.Backends.SoundIo
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
if (Interlocked.CompareExchange(ref _disposeState, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
while (_sessions.Count > 0)
|
int sessionCount = 0;
|
||||||
{
|
|
||||||
SoundIoHardwareDeviceSession session = _sessions[_sessions.Count - 1];
|
|
||||||
|
|
||||||
session.Dispose();
|
// NOTE: This is done in a way to avoid possible situations when the SoundIoHardwareDeviceSession is already being dispose in another thread but doesn't hold the lock and tries to Unregister.
|
||||||
|
do
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (_sessions.Count == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundIoHardwareDeviceSession session = _sessions[_sessions.Count - 1];
|
||||||
|
|
||||||
|
session.Dispose();
|
||||||
|
|
||||||
|
sessionCount = _sessions.Count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
while (sessionCount > 0);
|
||||||
|
|
||||||
_audioContext.Disconnect();
|
_audioContext.Disconnect();
|
||||||
_audioContext.Dispose();
|
_audioContext.Dispose();
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace Ryujinx.Audio.Backends.SoundIo
|
||||||
private DynamicRingBuffer _ringBuffer;
|
private DynamicRingBuffer _ringBuffer;
|
||||||
private ulong _playedSampleCount;
|
private ulong _playedSampleCount;
|
||||||
private ManualResetEvent _updateRequiredEvent;
|
private ManualResetEvent _updateRequiredEvent;
|
||||||
|
private int _disposeState;
|
||||||
|
|
||||||
public SoundIoHardwareDeviceSession(SoundIoHardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
|
public SoundIoHardwareDeviceSession(SoundIoHardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
|
||||||
{
|
{
|
||||||
|
@ -435,7 +436,10 @@ namespace Ryujinx.Audio.Backends.SoundIo
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
if (Interlocked.CompareExchange(ref _disposeState, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Input
|
namespace Ryujinx.Audio.Input
|
||||||
{
|
{
|
||||||
|
@ -61,6 +63,11 @@ namespace Ryujinx.Audio.Input
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int _activeSessionCount;
|
private int _activeSessionCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The dispose state.
|
||||||
|
/// </summary>
|
||||||
|
private int _disposeState;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="AudioInputManager"/>.
|
/// Create a new <see cref="AudioInputManager"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -248,14 +255,28 @@ namespace Ryujinx.Audio.Input
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
if (Interlocked.CompareExchange(ref _disposeState, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
// Nothing to do here.
|
// Clone the sessions array to dispose them outside the lock.
|
||||||
|
AudioInputSystem[] sessions;
|
||||||
|
|
||||||
|
lock (_sessionLock)
|
||||||
|
{
|
||||||
|
sessions = _sessions.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (AudioInputSystem input in sessions)
|
||||||
|
{
|
||||||
|
input?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
using Ryujinx.Audio.Common;
|
using Ryujinx.Audio.Common;
|
||||||
using Ryujinx.Audio.Integration;
|
using Ryujinx.Audio.Integration;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Input
|
namespace Ryujinx.Audio.Input
|
||||||
{
|
{
|
||||||
|
@ -62,10 +63,15 @@ namespace Ryujinx.Audio.Input
|
||||||
private AudioInputManager _manager;
|
private AudioInputManager _manager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// THe lock of the parent.
|
/// The lock of the parent.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private object _parentLock;
|
private object _parentLock;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The dispose state.
|
||||||
|
/// </summary>
|
||||||
|
private int _disposeState;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="AudioInputSystem"/>.
|
/// Create a new <see cref="AudioInputSystem"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -384,7 +390,10 @@ namespace Ryujinx.Audio.Input
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
if (Interlocked.CompareExchange(ref _disposeState, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
|
|
|
@ -21,6 +21,8 @@ using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Output
|
namespace Ryujinx.Audio.Output
|
||||||
{
|
{
|
||||||
|
@ -61,6 +63,11 @@ namespace Ryujinx.Audio.Output
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int _activeSessionCount;
|
private int _activeSessionCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The dispose state.
|
||||||
|
/// </summary>
|
||||||
|
private int _disposeState;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="AudioOutputManager"/>.
|
/// Create a new <see cref="AudioOutputManager"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -242,14 +249,28 @@ namespace Ryujinx.Audio.Output
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
if (Interlocked.CompareExchange(ref _disposeState, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
// Nothing to do here.
|
// Clone the sessions array to dispose them outside the lock.
|
||||||
|
AudioOutputSystem[] sessions;
|
||||||
|
|
||||||
|
lock (_sessionLock)
|
||||||
|
{
|
||||||
|
sessions = _sessions.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (AudioOutputSystem output in sessions)
|
||||||
|
{
|
||||||
|
output?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
using Ryujinx.Audio.Common;
|
using Ryujinx.Audio.Common;
|
||||||
using Ryujinx.Audio.Integration;
|
using Ryujinx.Audio.Integration;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Output
|
namespace Ryujinx.Audio.Output
|
||||||
{
|
{
|
||||||
|
@ -66,6 +67,11 @@ namespace Ryujinx.Audio.Output
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private object _parentLock;
|
private object _parentLock;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The dispose state.
|
||||||
|
/// </summary>
|
||||||
|
private int _disposeState;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="AudioOutputSystem"/>.
|
/// Create a new <see cref="AudioOutputSystem"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -357,7 +363,10 @@ namespace Ryujinx.Audio.Output
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
if (Interlocked.CompareExchange(ref _disposeState, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
|
|
|
@ -94,6 +94,8 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||||
|
|
||||||
private AudioRendererManager _manager;
|
private AudioRendererManager _manager;
|
||||||
|
|
||||||
|
private int _disposeState;
|
||||||
|
|
||||||
public AudioRenderSystem(AudioRendererManager manager, IWritableEvent systemEvent)
|
public AudioRenderSystem(AudioRendererManager manager, IWritableEvent systemEvent)
|
||||||
{
|
{
|
||||||
_manager = manager;
|
_manager = manager;
|
||||||
|
@ -811,7 +813,10 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
if (Interlocked.CompareExchange(ref _disposeState, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
|
|
|
@ -82,6 +82,11 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public AudioProcessor Processor { get; }
|
public AudioProcessor Processor { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The dispose state.
|
||||||
|
/// </summary>
|
||||||
|
private int _disposeState;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="AudioRendererManager"/>.
|
/// Create a new <see cref="AudioRendererManager"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -313,7 +318,10 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
if (Interlocked.CompareExchange(ref _disposeState, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
|
|
|
@ -70,6 +70,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
internal List<NfpDevice> NfpDevices { get; private set; }
|
internal List<NfpDevice> NfpDevices { get; private set; }
|
||||||
|
|
||||||
|
internal ServerBase SmServer { get; private set; }
|
||||||
internal ServerBase BsdServer { get; private set; }
|
internal ServerBase BsdServer { get; private set; }
|
||||||
internal ServerBase AudRenServer { get; private set; }
|
internal ServerBase AudRenServer { get; private set; }
|
||||||
internal ServerBase AudOutServer { get; private set; }
|
internal ServerBase AudOutServer { get; private set; }
|
||||||
|
@ -284,13 +285,11 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
public void InitializeServices()
|
public void InitializeServices()
|
||||||
{
|
{
|
||||||
IUserInterface sm = new IUserInterface(KernelContext);
|
SmServer = new ServerBase(KernelContext, "SmServer", () => new IUserInterface(KernelContext));
|
||||||
sm.TrySetServer(new ServerBase(KernelContext, "SmServer", () => new IUserInterface(KernelContext)));
|
|
||||||
|
|
||||||
// Wait until SM server thread is done with initialization,
|
// Wait until SM server thread is done with initialization,
|
||||||
// only then doing connections to SM is safe.
|
// only then doing connections to SM is safe.
|
||||||
sm.Server.InitDone.WaitOne();
|
SmServer.InitDone.WaitOne();
|
||||||
sm.Server.InitDone.Dispose();
|
|
||||||
|
|
||||||
BsdServer = new ServerBase(KernelContext, "BsdServer");
|
BsdServer = new ServerBase(KernelContext, "BsdServer");
|
||||||
AudRenServer = new ServerBase(KernelContext, "AudioRendererServer");
|
AudRenServer = new ServerBase(KernelContext, "AudioRendererServer");
|
||||||
|
@ -419,7 +418,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
SurfaceFlinger.Dispose();
|
SurfaceFlinger.Dispose();
|
||||||
|
|
||||||
// Terminate HLE services (must be done after the application is already terminated,
|
// Terminate HLE services (must be done after the application is already terminated,
|
||||||
// otherwise the application will receive errors due to service termination.
|
// otherwise the application will receive errors due to service termination).
|
||||||
foreach (KProcess process in KernelContext.Processes.Values.Where(x => !x.Flags.HasFlag(ProcessCreationFlags.IsApplication)))
|
foreach (KProcess process in KernelContext.Processes.Values.Where(x => !x.Flags.HasFlag(ProcessCreationFlags.IsApplication)))
|
||||||
{
|
{
|
||||||
process.Terminate();
|
process.Terminate();
|
||||||
|
|
|
@ -8,7 +8,7 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator
|
||||||
{
|
{
|
||||||
class ILibraryAppletAccessor : IpcService, IDisposable
|
class ILibraryAppletAccessor : DisposableIpcService
|
||||||
{
|
{
|
||||||
private KernelContext _kernelContext;
|
private KernelContext _kernelContext;
|
||||||
|
|
||||||
|
@ -241,21 +241,24 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
if (_stateChangedEventHandle != 0)
|
if (isDisposing)
|
||||||
{
|
{
|
||||||
_kernelContext.Syscall.CloseHandle(_stateChangedEventHandle);
|
if (_stateChangedEventHandle != 0)
|
||||||
}
|
{
|
||||||
|
_kernelContext.Syscall.CloseHandle(_stateChangedEventHandle);
|
||||||
|
}
|
||||||
|
|
||||||
if (_normalOutDataEventHandle != 0)
|
if (_normalOutDataEventHandle != 0)
|
||||||
{
|
{
|
||||||
_kernelContext.Syscall.CloseHandle(_normalOutDataEventHandle);
|
_kernelContext.Syscall.CloseHandle(_normalOutDataEventHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_interactiveOutDataEventHandle != 0)
|
if (_interactiveOutDataEventHandle != 0)
|
||||||
{
|
{
|
||||||
_kernelContext.Syscall.CloseHandle(_interactiveOutDataEventHandle);
|
_kernelContext.Syscall.CloseHandle(_interactiveOutDataEventHandle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Audio.AudioIn
|
namespace Ryujinx.HLE.HOS.Services.Audio.AudioIn
|
||||||
{
|
{
|
||||||
class AudioInServer : IpcService, IDisposable
|
class AudioInServer : DisposableIpcService
|
||||||
{
|
{
|
||||||
private IAudioIn _impl;
|
private IAudioIn _impl;
|
||||||
|
|
||||||
|
@ -193,14 +193,9 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioIn
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
Dispose(true);
|
if (isDisposing)
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
{
|
||||||
_impl.Dispose();
|
_impl.Dispose();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Audio.AudioOut
|
namespace Ryujinx.HLE.HOS.Services.Audio.AudioOut
|
||||||
{
|
{
|
||||||
class AudioOutServer : IpcService, IDisposable
|
class AudioOutServer : DisposableIpcService
|
||||||
{
|
{
|
||||||
private IAudioOut _impl;
|
private IAudioOut _impl;
|
||||||
|
|
||||||
|
@ -174,14 +174,9 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioOut
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
Dispose(true);
|
if (isDisposing)
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
{
|
||||||
_impl.Dispose();
|
_impl.Dispose();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ using System.Buffers;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer
|
namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer
|
||||||
{
|
{
|
||||||
class AudioRendererServer : IpcService, IDisposable
|
class AudioRendererServer : DisposableIpcService
|
||||||
{
|
{
|
||||||
private IAudioRenderer _impl;
|
private IAudioRenderer _impl;
|
||||||
|
|
||||||
|
@ -172,14 +172,9 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
Dispose(true);
|
if (isDisposing)
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
{
|
||||||
_impl.Dispose();
|
_impl.Dispose();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
using LibHac;
|
using LibHac;
|
||||||
using LibHac.Bcat;
|
using LibHac.Bcat;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
||||||
{
|
{
|
||||||
class IDeliveryCacheDirectoryService : IpcService, IDisposable
|
class IDeliveryCacheDirectoryService : DisposableIpcService
|
||||||
{
|
{
|
||||||
private LibHac.Bcat.Detail.Ipc.IDeliveryCacheDirectoryService _base;
|
private LibHac.Bcat.Detail.Ipc.IDeliveryCacheDirectoryService _base;
|
||||||
|
|
||||||
|
@ -55,9 +54,12 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
||||||
return (ResultCode)result.Value;
|
return (ResultCode)result.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
_base?.Dispose();
|
if (isDisposing)
|
||||||
|
{
|
||||||
|
_base?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
using LibHac;
|
using LibHac;
|
||||||
using LibHac.Bcat;
|
using LibHac.Bcat;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
||||||
{
|
{
|
||||||
class IDeliveryCacheFileService : IpcService, IDisposable
|
class IDeliveryCacheFileService : DisposableIpcService
|
||||||
{
|
{
|
||||||
private LibHac.Bcat.Detail.Ipc.IDeliveryCacheFileService _base;
|
private LibHac.Bcat.Detail.Ipc.IDeliveryCacheFileService _base;
|
||||||
|
|
||||||
|
@ -68,9 +67,12 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
||||||
return (ResultCode)result.Value;
|
return (ResultCode)result.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
_base?.Dispose();
|
if (isDisposing)
|
||||||
|
{
|
||||||
|
_base?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
using LibHac;
|
using LibHac;
|
||||||
using LibHac.Bcat;
|
using LibHac.Bcat;
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
||||||
{
|
{
|
||||||
class IDeliveryCacheStorageService : IpcService, IDisposable
|
class IDeliveryCacheStorageService : DisposableIpcService
|
||||||
{
|
{
|
||||||
private LibHac.Bcat.Detail.Ipc.IDeliveryCacheStorageService _base;
|
private LibHac.Bcat.Detail.Ipc.IDeliveryCacheStorageService _base;
|
||||||
|
|
||||||
|
@ -60,9 +59,12 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
||||||
return (ResultCode)result.Value;
|
return (ResultCode)result.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
_base?.Dispose();
|
if (isDisposing)
|
||||||
|
{
|
||||||
|
_base?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
20
Ryujinx.HLE/HOS/Services/DisposableIpcService.cs
Normal file
20
Ryujinx.HLE/HOS/Services/DisposableIpcService.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services
|
||||||
|
{
|
||||||
|
abstract class DisposableIpcService : IpcService, IDisposable
|
||||||
|
{
|
||||||
|
private int _disposeState;
|
||||||
|
|
||||||
|
protected abstract void Dispose(bool isDisposing);
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (Interlocked.CompareExchange(ref _disposeState, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
|
namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
|
||||||
{
|
{
|
||||||
class INotificationService : IpcService, IDisposable
|
class INotificationService : DisposableIpcService
|
||||||
{
|
{
|
||||||
private readonly UserId _userId;
|
private readonly UserId _userId;
|
||||||
private readonly FriendServicePermissionLevel _permissionLevel;
|
private readonly FriendServicePermissionLevel _permissionLevel;
|
||||||
|
@ -167,9 +167,12 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
NotificationEventHandler.Instance.UnregisterNotificationService(this);
|
if (isDisposing)
|
||||||
|
{
|
||||||
|
NotificationEventHandler.Instance.UnregisterNotificationService(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,9 @@
|
||||||
using LibHac;
|
using LibHac;
|
||||||
using LibHac.Fs;
|
using LibHac.Fs;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
||||||
{
|
{
|
||||||
class IFile : IpcService, IDisposable
|
class IFile : DisposableIpcService
|
||||||
{
|
{
|
||||||
private LibHac.Fs.Fsa.IFile _baseFile;
|
private LibHac.Fs.Fsa.IFile _baseFile;
|
||||||
|
|
||||||
|
@ -82,14 +81,9 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
||||||
return (ResultCode)result.Value;
|
return (ResultCode)result.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
Dispose(true);
|
if (isDisposing)
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
{
|
||||||
_baseFile?.Dispose();
|
_baseFile?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
using LibHac;
|
using LibHac;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
||||||
{
|
{
|
||||||
class IStorage : IpcService, IDisposable
|
class IStorage : DisposableIpcService
|
||||||
{
|
{
|
||||||
private LibHac.Fs.IStorage _baseStorage;
|
private LibHac.Fs.IStorage _baseStorage;
|
||||||
|
|
||||||
|
@ -53,14 +52,9 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
||||||
return (ResultCode)result.Value;
|
return (ResultCode)result.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
Dispose(true);
|
if (isDisposing)
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
{
|
||||||
_baseStorage?.Dispose();
|
_baseStorage?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ using LibHac;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Fs
|
namespace Ryujinx.HLE.HOS.Services.Fs
|
||||||
{
|
{
|
||||||
class ISaveDataInfoReader : IpcService, IDisposable
|
class ISaveDataInfoReader : DisposableIpcService
|
||||||
{
|
{
|
||||||
private ReferenceCountedDisposable<LibHac.FsSrv.ISaveDataInfoReader> _baseReader;
|
private ReferenceCountedDisposable<LibHac.FsSrv.ISaveDataInfoReader> _baseReader;
|
||||||
|
|
||||||
|
@ -29,9 +29,12 @@ namespace Ryujinx.HLE.HOS.Services.Fs
|
||||||
return (ResultCode)result.Value;
|
return (ResultCode)result.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
_baseReader.Dispose();
|
if (isDisposing)
|
||||||
|
{
|
||||||
|
_baseReader?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,5 +265,18 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
{
|
{
|
||||||
_parent = parent._parent;
|
_parent = parent._parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void DestroyAtExit()
|
||||||
|
{
|
||||||
|
foreach (object domainObject in _domainObjects.Values)
|
||||||
|
{
|
||||||
|
if (domainObject != this && domainObject is IDisposable disposableObj)
|
||||||
|
{
|
||||||
|
disposableObj.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_domainObjects.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ using System.Text;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
|
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
|
||||||
{
|
{
|
||||||
class IGeneralService : IpcService, IDisposable
|
class IGeneralService : DisposableIpcService
|
||||||
{
|
{
|
||||||
private GeneralServiceDetail _generalServiceDetail;
|
private GeneralServiceDetail _generalServiceDetail;
|
||||||
|
|
||||||
|
@ -197,9 +197,12 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
|
||||||
return (targetProperties, targetAddressInfo);
|
return (targetProperties, targetAddressInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
GeneralServiceManager.Remove(_generalServiceDetail.ClientId);
|
if (isDisposing)
|
||||||
|
{
|
||||||
|
GeneralServiceManager.Remove(_generalServiceDetail.ClientId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
{
|
{
|
||||||
[Service("ldr:ro")]
|
[Service("ldr:ro")]
|
||||||
[Service("ro:1")] // 7.0.0+
|
[Service("ro:1")] // 7.0.0+
|
||||||
class IRoInterface : IpcService, IDisposable
|
class IRoInterface : DisposableIpcService
|
||||||
{
|
{
|
||||||
private const int MaxNrr = 0x40;
|
private const int MaxNrr = 0x40;
|
||||||
private const int MaxNro = 0x40;
|
private const int MaxNro = 0x40;
|
||||||
|
@ -571,14 +571,17 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
foreach (NroInfo info in _nroInfos)
|
if (isDisposing)
|
||||||
{
|
{
|
||||||
UnmapNroFromInfo(info);
|
foreach (NroInfo info in _nroInfos)
|
||||||
}
|
{
|
||||||
|
UnmapNroFromInfo(info);
|
||||||
|
}
|
||||||
|
|
||||||
_nroInfos.Clear();
|
_nroInfos.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,6 +4,7 @@ using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Sm;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -12,7 +13,7 @@ using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services
|
namespace Ryujinx.HLE.HOS.Services
|
||||||
{
|
{
|
||||||
class ServerBase
|
class ServerBase : IDisposable
|
||||||
{
|
{
|
||||||
// Must be the maximum value used by services (highest one know is the one used by nvservices = 0x8000).
|
// Must be the maximum value used by services (highest one know is the one used by nvservices = 0x8000).
|
||||||
// Having a size that is too low will cause failures as data copy will fail if the receiving buffer is
|
// Having a size that is too low will cause failures as data copy will fail if the receiving buffer is
|
||||||
|
@ -67,6 +68,9 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
|
|
||||||
public void AddSessionObj(KServerSession serverSession, IpcService obj)
|
public void AddSessionObj(KServerSession serverSession, IpcService obj)
|
||||||
{
|
{
|
||||||
|
// Ensure that the sever loop is running.
|
||||||
|
InitDone.WaitOne();
|
||||||
|
|
||||||
_selfProcess.HandleTable.GenerateHandle(serverSession, out int serverSessionHandle);
|
_selfProcess.HandleTable.GenerateHandle(serverSession, out int serverSessionHandle);
|
||||||
AddSessionObj(serverSessionHandle, obj);
|
AddSessionObj(serverSessionHandle, obj);
|
||||||
}
|
}
|
||||||
|
@ -86,13 +90,9 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
_context.Syscall.ManageNamedPort("sm:", 50, out int serverPortHandle);
|
_context.Syscall.ManageNamedPort("sm:", 50, out int serverPortHandle);
|
||||||
|
|
||||||
AddPort(serverPortHandle, SmObjectFactory);
|
AddPort(serverPortHandle, SmObjectFactory);
|
||||||
|
}
|
||||||
|
|
||||||
InitDone.Set();
|
InitDone.Set();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
InitDone.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
KThread thread = KernelStatic.GetCurrentThread();
|
KThread thread = KernelStatic.GetCurrentThread();
|
||||||
ulong messagePtr = thread.TlsAddress;
|
ulong messagePtr = thread.TlsAddress;
|
||||||
|
@ -153,6 +153,8 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
_selfProcess.CpuMemory.Write(messagePtr + 0x8, heapAddr | ((ulong)PointerBufferSize << 48));
|
_selfProcess.CpuMemory.Write(messagePtr + 0x8, heapAddr | ((ulong)PointerBufferSize << 48));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Process(int serverSessionHandle, ulong recvListAddr)
|
private bool Process(int serverSessionHandle, ulong recvListAddr)
|
||||||
|
@ -349,5 +351,30 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
foreach (IpcService service in _sessions.Values)
|
||||||
|
{
|
||||||
|
if (service is IDisposable disposableObj)
|
||||||
|
{
|
||||||
|
disposableObj.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
service.DestroyAtExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
_sessions.Clear();
|
||||||
|
|
||||||
|
InitDone.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -245,5 +245,12 @@ namespace Ryujinx.HLE.HOS.Services.Sm
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void DestroyAtExit()
|
||||||
|
{
|
||||||
|
_commonServer.Dispose();
|
||||||
|
|
||||||
|
base.DestroyAtExit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,10 +4,12 @@ using System.Security.Cryptography;
|
||||||
namespace Ryujinx.HLE.HOS.Services.Spl
|
namespace Ryujinx.HLE.HOS.Services.Spl
|
||||||
{
|
{
|
||||||
[Service("csrng")]
|
[Service("csrng")]
|
||||||
class IRandomInterface : IpcService, IDisposable
|
class IRandomInterface : DisposableIpcService
|
||||||
{
|
{
|
||||||
private RNGCryptoServiceProvider _rng;
|
private RNGCryptoServiceProvider _rng;
|
||||||
|
|
||||||
|
private object _lock = new object();
|
||||||
|
|
||||||
public IRandomInterface(ServiceCtx context)
|
public IRandomInterface(ServiceCtx context)
|
||||||
{
|
{
|
||||||
_rng = new RNGCryptoServiceProvider();
|
_rng = new RNGCryptoServiceProvider();
|
||||||
|
@ -26,14 +28,9 @@ namespace Ryujinx.HLE.HOS.Services.Spl
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
Dispose(true);
|
if (isDisposing)
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
{
|
||||||
_rng.Dispose();
|
_rng.Dispose();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue