Refactor lock related code

This commit is contained in:
EnderIce2 2024-04-10 06:25:55 +03:00
parent c76eb67883
commit fd292305f6
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
4 changed files with 122 additions and 43 deletions

View File

@ -96,8 +96,7 @@ size_t GetLocksCount() { return LocksCount.load(); }
void LockClass::Yield() void LockClass::Yield()
{ {
if (CPU::Interrupts(CPU::Check) && if (CPU::Interrupts(CPU::Check) && TaskManager &&
TaskManager &&
!TaskManager->IsPanic()) !TaskManager->IsPanic())
{ {
TaskManager->Yield(); TaskManager->Yield();
@ -123,10 +122,8 @@ void LockClass::DeadLock(SpinLockData &Lock)
CCore = CoreData->ID; CCore = CoreData->ID;
warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld held by %ld. (%ld times happened)", warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld held by %ld. (%ld times happened)",
Lock.AttemptingToGet, Lock.CurrentHolder, Lock.AttemptingToGet, Lock.CurrentHolder, Lock.Count, Lock.Count > 1 ? "locks" : "lock",
Lock.Count, Lock.Count > 1 ? "locks" : "lock", CPU::Interrupts(CPU::Check) ? "enabled" : "disabled", CCore, Lock.Core, this->DeadLocks);
CPU::Interrupts(CPU::Check) ? "enabled" : "disabled",
CCore, Lock.Core, this->DeadLocks);
#ifdef PRINT_BACKTRACE #ifdef PRINT_BACKTRACE
PrintStacktrace(&Lock); PrintStacktrace(&Lock);
@ -201,10 +198,8 @@ void LockClass::TimeoutDeadLock(SpinLockData &Lock, uint64_t Timeout)
uint64_t Counter = TimeManager->GetCounter(); uint64_t Counter = TimeManager->GetCounter();
warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld held by %ld. Timeout in %ld (%ld ticks remaining).", warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld held by %ld. Timeout in %ld (%ld ticks remaining).",
Lock.AttemptingToGet, Lock.CurrentHolder, Lock.AttemptingToGet, Lock.CurrentHolder, Lock.Count, Lock.Count > 1 ? "locks" : "lock",
Lock.Count, Lock.Count > 1 ? "locks" : "lock", CPU::Interrupts(CPU::Check) ? "enabled" : "disabled", CCore, Lock.Core, Timeout, Timeout - Counter);
CPU::Interrupts(CPU::Check) ? "enabled" : "disabled",
CCore, Lock.Core, Timeout, Timeout - Counter);
#ifdef PRINT_BACKTRACE #ifdef PRINT_BACKTRACE
PrintStacktrace(&Lock); PrintStacktrace(&Lock);

View File

@ -68,6 +68,32 @@ public:
int TimeoutLock(const char *FunctionName, uint64_t Timeout); int TimeoutLock(const char *FunctionName, uint64_t Timeout);
}; };
class spin_lock
{
private:
LockClass lc;
public:
bool locked()
{
return this->lc.Locked();
}
bool lock(const char *FunctionName)
{
return this->lc.Lock(FunctionName) == 0;
}
bool unlock()
{
return this->lc.Unlock() == 0;
}
spin_lock() = default;
spin_lock(const spin_lock &) = delete;
~spin_lock() = default;
};
/** @brief Please use this macro to create a new smart lock. */ /** @brief Please use this macro to create a new smart lock. */
class SmartLockClass class SmartLockClass
{ {
@ -106,6 +132,7 @@ public:
this->LockPointer = &Lock; this->LockPointer = &Lock;
this->LockPointer->TimeoutLock(FunctionName, Timeout); this->LockPointer->TimeoutLock(FunctionName, Timeout);
} }
~SmartTimeoutLockClass() ~SmartTimeoutLockClass()
{ {
this->LockPointer->Unlock(); this->LockPointer->Unlock();
@ -128,6 +155,7 @@ public:
this->LockPointer = &Lock; this->LockPointer = &Lock;
this->LockPointer->Lock(FunctionName); this->LockPointer->Lock(FunctionName);
} }
~SmartLockCriticalSectionClass() ~SmartLockCriticalSectionClass()
{ {
this->LockPointer->Unlock(); this->LockPointer->Unlock();
@ -153,6 +181,7 @@ public:
InterruptsEnabled = true; InterruptsEnabled = true;
CPU::Interrupts(CPU::Disable); CPU::Interrupts(CPU::Disable);
} }
~SmartCriticalSectionClass() ~SmartCriticalSectionClass()
{ {
if (InterruptsEnabled) if (InterruptsEnabled)

View File

@ -25,6 +25,21 @@
namespace std namespace std
{ {
struct defer_lock_t
{
explicit defer_lock_t() = default;
};
struct try_to_lock_t
{
explicit try_to_lock_t() = default;
};
struct adopt_lock_t
{
explicit adopt_lock_t() = default;
};
/** /**
* A mutex implementation. * A mutex implementation.
* *
@ -35,7 +50,7 @@ namespace std
{ {
private: private:
atomic_bool Locked = false; atomic_bool Locked = false;
vector<Tasking::TCB *> Waiting; list<Tasking::TCB *> Waiting;
Tasking::TCB *Holder = nullptr; Tasking::TCB *Holder = nullptr;
public: public:
@ -43,24 +58,37 @@ namespace std
bool try_lock(); bool try_lock();
void unlock(); void unlock();
mutex() = default; mutex();
mutex(const mutex &) = delete; mutex(const mutex &) = delete;
~mutex() = default; ~mutex();
}; };
template <class Mutex> template <class Mutex>
class lock_guard class lock_guard
{ {
private: private:
Mutex &m; Mutex &mutexRef;
public: public:
explicit lock_guard(Mutex &mutex) explicit lock_guard(Mutex &m)
: m(mutex) { m.lock(); } : mutexRef(m)
{
mutexRef.lock();
}
~lock_guard() { m.unlock(); } lock_guard(Mutex &m, adopt_lock_t t)
: mutexRef(m)
{
/* Do nothing */
}
lock_guard(const lock_guard &) = delete; lock_guard(const lock_guard &) = delete;
~lock_guard()
{
mutexRef.unlock();
}
lock_guard &operator=(const lock_guard &) = delete; lock_guard &operator=(const lock_guard &) = delete;
}; };
} }

View File

@ -29,53 +29,80 @@ namespace std
{ {
void mutex::lock() void mutex::lock()
{ {
RetryLock:
bool Result = this->Locked.exchange(true, std::memory_order_acquire); bool Result = this->Locked.exchange(true, std::memory_order_acquire);
__sync;
if (Result) TCB *tcb = thisThread;
if (Result == true)
{ {
this->Waiting.push_back(thisThread); debug("%#lx: Mutex is locked, blocking task %d (\"%s\" : %d)", this,
thisThread->Block(); tcb->ID, tcb->Parent->Name, tcb->Parent->ID);
this->Waiting.push_back(tcb);
tcb->Block();
TaskManager->Yield(); TaskManager->Yield();
return; goto RetryLock;
} }
this->Holder = thisThread; this->Holder = tcb;
this->Waiting.erase(std::find(this->Waiting.begin(), this->Waiting.remove(tcb);
this->Waiting.end(),
thisThread)); debug("%#lx: Mutex locked by task %d (\"%s\" : %d)", this,
tcb->ID, tcb->Parent->Name, tcb->Parent->ID);
} }
bool mutex::try_lock() bool mutex::try_lock()
{ {
bool Result = this->Locked.exchange(true, std::memory_order_acquire); bool Result = this->Locked.exchange(true, std::memory_order_acquire);
__sync;
if (!Result) TCB *tcb = thisThread;
if (Result == true)
{ {
this->Holder = thisThread; debug("%#lx: Mutex is locked, task %d (\"%s\" : %d) failed to lock", this,
this->Waiting.erase(std::find(this->Waiting.begin(), tcb->ID, tcb->Parent->Name, tcb->Parent->ID);
this->Waiting.end(), return false;
thisThread));
} }
return !Result;
this->Holder = tcb;
this->Waiting.remove(tcb);
debug("%#lx: Mutex locked by task %d (\"%s\" : %d)", this,
tcb->ID, tcb->Parent->Name, tcb->Parent->ID);
return true;
} }
void mutex::unlock() void mutex::unlock()
{ {
__sync; TCB *tcb = thisThread;
assert(this->Holder == tcb);
this->Holder = nullptr;
this->Locked.store(false, std::memory_order_release); this->Locked.store(false, std::memory_order_release);
if (!this->Waiting.empty()) if (this->Waiting.empty())
{ {
this->Holder = this->Waiting[0]; debug("%#lx: Mutex unlocked, no tasks to unblock", this);
return;
this->Holder = this->Waiting.front();
this->Waiting.erase(this->Waiting.begin());
this->Holder->Unblock();
TaskManager->Yield();
} }
else
this->Holder = nullptr; TCB *Next = this->Waiting.front();
this->Waiting.pop_front();
debug("%#lx: Mutex unlocked, task %d (\"%s\" : %d) unblocked", this,
Next->ID, Next->Parent->Name, Next->Parent->ID);
Next->Unblock();
}
mutex::mutex()
{
debug("%#lx: Creating mutex", this);
}
mutex::~mutex()
{
debug("%#lx: Destroying mutex", this);
assert(this->Holder == nullptr);
assert(this->Waiting.empty());
} }
} }