mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-25 22:14:37 +00:00
Refactor lock related code
This commit is contained in:
parent
c76eb67883
commit
fd292305f6
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user