1#include "thread/seadSpinLock.h"
2#include "thread/seadThread.h"
3
4namespace sead
5{
6SpinLock::SpinLock() = default;
7
8SpinLock::~SpinLock() = default;
9
10void SpinLock::lock()
11{
12 Thread* current_thread = ThreadMgr::instance()->getCurrentThread();
13 if (mOwnerThread.load() == current_thread)
14 {
15 ++mCount;
16 return;
17 }
18
19 while (!mOwnerThread.compareExchange(expected: nullptr, desired: current_thread))
20 continue;
21
22 SEAD_ASSERT_MSG(mCount == 0, "mCount[%u] must be 0", mCount);
23 mCount = 1;
24}
25
26bool SpinLock::tryLock()
27{
28 Thread* current_thread = ThreadMgr::instance()->getCurrentThread();
29 if (mOwnerThread.load() == current_thread)
30 {
31 ++mCount;
32 return true;
33 }
34
35 if (!mOwnerThread.compareExchange(expected: nullptr, desired: current_thread))
36 return false;
37
38 SEAD_ASSERT_MSG(mCount == 0, "mCount[%u] must be 0", mCount);
39 mCount = 1;
40 return true;
41}
42
43void SpinLock::unlock()
44{
45 Thread* current_thread = ThreadMgr::instance()->getCurrentThread();
46 if (mOwnerThread.load() != current_thread)
47 {
48 SEAD_ASSERT_MSG(false, "This thread[%p] does not have the lock.", current_thread);
49 return;
50 }
51
52 SEAD_ASSERT_MSG(mCount != 0 && current_thread != nullptr,
53 "mCount[%u] must not be 0 and my_thread[%p] must not be nullptr", mCount,
54 current_thread);
55
56 --mCount;
57 if (mCount == 0)
58 mOwnerThread.exchange(value: nullptr);
59}
60} // namespace sead
61