mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-25 20:28:48 +08:00
86 lines
2.7 KiB
C#
86 lines
2.7 KiB
C#
// Copyright (C) 2026 SharpEmu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
using System.Collections.Concurrent;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
using SharpEmu.HLE;
|
|
|
|
namespace SharpEmu.Libs.Kernel;
|
|
|
|
internal static class KernelPthreadState
|
|
{
|
|
private const int ThreadObjectSize = 0x1000;
|
|
|
|
private static readonly ConcurrentDictionary<ulong, ThreadIdentity> Threads = new();
|
|
private static readonly byte[] ZeroThreadObject = new byte[ThreadObjectSize];
|
|
private static long _nextUniqueThreadId = 1;
|
|
|
|
[ThreadStatic]
|
|
private static ulong _currentThreadHandle;
|
|
|
|
[ThreadStatic]
|
|
private static ulong _currentThreadUniqueId;
|
|
|
|
internal readonly record struct ThreadIdentity(ulong UniqueId, string Name);
|
|
|
|
internal static ulong GetCurrentThreadHandle()
|
|
{
|
|
var guestThreadHandle = GuestThreadExecution.CurrentGuestThreadHandle;
|
|
if (guestThreadHandle != 0 && TryGetThreadIdentity(guestThreadHandle, out _))
|
|
{
|
|
return guestThreadHandle;
|
|
}
|
|
|
|
EnsureCurrentThreadRegistered();
|
|
return _currentThreadHandle;
|
|
}
|
|
|
|
internal static ulong GetCurrentThreadUniqueId()
|
|
{
|
|
var guestThreadHandle = GuestThreadExecution.CurrentGuestThreadHandle;
|
|
if (guestThreadHandle != 0 && TryGetThreadIdentity(guestThreadHandle, out var identity))
|
|
{
|
|
return identity.UniqueId;
|
|
}
|
|
|
|
EnsureCurrentThreadRegistered();
|
|
return _currentThreadUniqueId;
|
|
}
|
|
|
|
internal static ulong CreateThreadHandle(string name)
|
|
{
|
|
var uniqueId = unchecked((ulong)Interlocked.Increment(ref _nextUniqueThreadId));
|
|
return AllocateThreadHandle(uniqueId, name);
|
|
}
|
|
|
|
internal static bool TryGetThreadIdentity(ulong threadHandle, out ThreadIdentity identity)
|
|
{
|
|
return Threads.TryGetValue(threadHandle, out identity);
|
|
}
|
|
|
|
private static void EnsureCurrentThreadRegistered()
|
|
{
|
|
if (_currentThreadHandle != 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var uniqueId = unchecked((ulong)Interlocked.Increment(ref _nextUniqueThreadId));
|
|
var name = $"Thread-{uniqueId:X}";
|
|
_currentThreadHandle = AllocateThreadHandle(uniqueId, name);
|
|
_currentThreadUniqueId = uniqueId;
|
|
}
|
|
|
|
private static ulong AllocateThreadHandle(ulong uniqueId, string name)
|
|
{
|
|
var pointer = Marshal.AllocHGlobal(ThreadObjectSize);
|
|
Marshal.Copy(ZeroThreadObject, 0, pointer, ThreadObjectSize);
|
|
|
|
var handle = unchecked((ulong)pointer.ToInt64());
|
|
Threads[handle] = new ThreadIdentity(uniqueId, string.IsNullOrWhiteSpace(name) ? $"Thread-{uniqueId:X}" : name);
|
|
|
|
return handle;
|
|
}
|
|
}
|