aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs
blob: dec13f75e39abe795cc43e1b8b13d5191d1a5475 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
using ChocolArm64.State;
using Ryujinx.Core.OsHle.Handles;

namespace Ryujinx.Core.OsHle.Svc
{
    partial class SvcHandler
    {
        private void SvcArbitrateLock(AThreadState ThreadState)
        {
            int  OwnerThreadHandle      =  (int)ThreadState.X0;
            long MutexAddress           = (long)ThreadState.X1;
            int  RequestingThreadHandle =  (int)ThreadState.X2;

            HThread RequestingThread = Ns.Os.Handles.GetData<HThread>(RequestingThreadHandle);

            Mutex M = new Mutex(Process, MutexAddress, OwnerThreadHandle);

            M = Ns.Os.Mutexes.GetOrAdd(MutexAddress, M);

            M.WaitForLock(RequestingThread, RequestingThreadHandle);

            ThreadState.X0 = (int)SvcResult.Success;
        }

        private void SvcArbitrateUnlock(AThreadState ThreadState)
        {
            long MutexAddress = (long)ThreadState.X0;

            if (Ns.Os.Mutexes.TryGetValue(MutexAddress, out Mutex M))
            {
                M.Unlock();
            }

            ThreadState.X0 = (int)SvcResult.Success;
        }

        private void SvcWaitProcessWideKeyAtomic(AThreadState ThreadState)
        {
            long MutexAddress   = (long)ThreadState.X0;
            long CondVarAddress = (long)ThreadState.X1;
            int  ThreadHandle   =  (int)ThreadState.X2;
            long Timeout        = (long)ThreadState.X3;

            HThread Thread = Ns.Os.Handles.GetData<HThread>(ThreadHandle);

            Mutex M = new Mutex(Process, MutexAddress, ThreadHandle);

            M = Ns.Os.Mutexes.GetOrAdd(MutexAddress, M);

            M.GiveUpLock(ThreadHandle);

            CondVar Cv = new CondVar(Process, CondVarAddress, Timeout);

            Cv = Ns.Os.CondVars.GetOrAdd(CondVarAddress, Cv);

            Cv.WaitForSignal(Thread);

            M.WaitForLock(Thread, ThreadHandle);

            ThreadState.X0 = (int)SvcResult.Success;
        }

        private void SvcSignalProcessWideKey(AThreadState ThreadState)
        {
            long CondVarAddress = (long)ThreadState.X0;
            int  Count          =  (int)ThreadState.X1;

            HThread CurrThread = Process.GetThread(ThreadState.Tpidr);

            if (Ns.Os.CondVars.TryGetValue(CondVarAddress, out CondVar Cv))
            {
                Cv.SetSignal(CurrThread, Count);
            }

            ThreadState.X0 = (int)SvcResult.Success;
        }
    }
}