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()
{
if (CPU::Interrupts(CPU::Check) &&
TaskManager &&
if (CPU::Interrupts(CPU::Check) && TaskManager &&
!TaskManager->IsPanic())
{
TaskManager->Yield();
@ -123,10 +122,8 @@ void LockClass::DeadLock(SpinLockData &Lock)
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)",
Lock.AttemptingToGet, Lock.CurrentHolder,
Lock.Count, Lock.Count > 1 ? "locks" : "lock",
CPU::Interrupts(CPU::Check) ? "enabled" : "disabled",
CCore, Lock.Core, this->DeadLocks);
Lock.AttemptingToGet, Lock.CurrentHolder, Lock.Count, Lock.Count > 1 ? "locks" : "lock",
CPU::Interrupts(CPU::Check) ? "enabled" : "disabled", CCore, Lock.Core, this->DeadLocks);
#ifdef PRINT_BACKTRACE
PrintStacktrace(&Lock);
@ -201,10 +198,8 @@ void LockClass::TimeoutDeadLock(SpinLockData &Lock, uint64_t Timeout)
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).",
Lock.AttemptingToGet, Lock.CurrentHolder,
Lock.Count, Lock.Count > 1 ? "locks" : "lock",
CPU::Interrupts(CPU::Check) ? "enabled" : "disabled",
CCore, Lock.Core, Timeout, Timeout - Counter);
Lock.AttemptingToGet, Lock.CurrentHolder, Lock.Count, Lock.Count > 1 ? "locks" : "lock",
CPU::Interrupts(CPU::Check) ? "enabled" : "disabled", CCore, Lock.Core, Timeout, Timeout - Counter);
#ifdef PRINT_BACKTRACE
PrintStacktrace(&Lock);

View File

@ -68,6 +68,32 @@ public:
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. */
class SmartLockClass
{
@ -106,6 +132,7 @@ public:
this->LockPointer = &Lock;
this->LockPointer->TimeoutLock(FunctionName, Timeout);
}
~SmartTimeoutLockClass()
{
this->LockPointer->Unlock();
@ -128,6 +155,7 @@ public:
this->LockPointer = &Lock;
this->LockPointer->Lock(FunctionName);
}
~SmartLockCriticalSectionClass()
{
this->LockPointer->Unlock();
@ -153,6 +181,7 @@ public:
InterruptsEnabled = true;
CPU::Interrupts(CPU::Disable);
}
~SmartCriticalSectionClass()
{
if (InterruptsEnabled)

View File

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

View File

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