mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-28 15:34:33 +00:00
Changed how lock works (now it's assembly spinlock)
This commit is contained in:
parent
6a9217c079
commit
42dc78626a
70
Architecture/amd64/LockAssembly.S
Normal file
70
Architecture/amd64/LockAssembly.S
Normal file
@ -0,0 +1,70 @@
|
||||
# https://en.wikipedia.org/wiki/Spinlock
|
||||
|
||||
.text
|
||||
|
||||
# void SpinLock_Lock(volatile uint64_t *LockData)
|
||||
.global SpinLock_Lock
|
||||
|
||||
# void SpinLock_Unlock(volatile uint64_t *LockData)
|
||||
.global SpinLock_Unlock
|
||||
|
||||
# uint64_t SpinLock_CheckAndLock(volatile uint64_t *LockData)
|
||||
.global SpinLock_CheckAndLock
|
||||
|
||||
# uint64_t SpinLock_WithTimeout(volatile uint64_t *LockData, volatile uint64_t Iterations)
|
||||
.global SpinLock_WithTimeout
|
||||
|
||||
# DeadLockHandler(volatile <struct> *LockStructure)
|
||||
.extern DeadLockHandler
|
||||
|
||||
SpinLock_Lock:
|
||||
xorq %rax,%rax
|
||||
lock btsl $0,(%rdi)
|
||||
jc Spin
|
||||
ret
|
||||
Spin:
|
||||
incq %rax
|
||||
cmpq $0x10000000,%rax
|
||||
je Deadlock
|
||||
pause
|
||||
testl $1,(%rdi)
|
||||
jnz Spin
|
||||
jmp SpinLock_Lock
|
||||
|
||||
SpinLock_Unlock:
|
||||
lock btrl $0,(%rdi)
|
||||
ret
|
||||
|
||||
Deadlock:
|
||||
pushq %rdi
|
||||
pushq %rdi
|
||||
xorq %rax,%rax
|
||||
call DeadLockHandler
|
||||
popq %rdi
|
||||
popq %rdi
|
||||
jmp Spin
|
||||
|
||||
SpinLock_CheckAndLock:
|
||||
xorl %eax,%eax
|
||||
lock btsl $0,(%rdi)
|
||||
setcb %al
|
||||
ret
|
||||
|
||||
SpinLock_WithTimeout:
|
||||
xorq %rax,%rax
|
||||
SpinTimeout:
|
||||
incq %rax
|
||||
lock btsl $0,(%rdi)
|
||||
setcb %bl
|
||||
cmpb $0,%bl
|
||||
je LockAquired
|
||||
cmpq %rsi,%rax
|
||||
je LockTimedOut
|
||||
pause
|
||||
jmp SpinTimeout
|
||||
LockAquired:
|
||||
movq $1,%rax
|
||||
ret
|
||||
LockTimedOut:
|
||||
xorq %rax,%rax
|
||||
ret
|
11
Core/Lock.cpp
Normal file
11
Core/Lock.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include <lock.hpp>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
extern "C" void DeadLockHandler(LockClass *Lock)
|
||||
{
|
||||
warn("Potential deadlock in lock '%s' held by '%s'",
|
||||
Lock->GetLockData()->AttemptingToGet,
|
||||
Lock->GetLockData()->CurrentHolder);
|
||||
// TODO: Print on screen too.
|
||||
}
|
@ -1,34 +1,60 @@
|
||||
#ifndef __FENNIX_KERNEL_LOCK_H__
|
||||
#define __FENNIX_KERNEL_LOCK_H__
|
||||
|
||||
/*
|
||||
TODO: Add deadlock detection.
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <atomic.hpp>
|
||||
#include <cpu.hpp>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wvolatile"
|
||||
|
||||
EXTERNC void SpinLock_Lock(volatile uint64_t *LockData);
|
||||
EXTERNC void SpinLock_Unlock(volatile uint64_t *LockData);
|
||||
EXTERNC uint64_t SpinLock_CheckAndLock(volatile uint64_t *LockData);
|
||||
EXTERNC uint64_t SpinLock_WithTimeout(volatile uint64_t *LockData, volatile uint64_t Iterations);
|
||||
|
||||
#ifdef __cplusplus
|
||||
/** @brief Please use this macro to create a new lock. */
|
||||
class LockClass
|
||||
{
|
||||
struct SpinLockData
|
||||
{
|
||||
uint64_t LockData;
|
||||
const char *CurrentHolder;
|
||||
const char *AttemptingToGet;
|
||||
uint64_t Count;
|
||||
};
|
||||
|
||||
private:
|
||||
bool IsLocked = false;
|
||||
SpinLockData LockData;
|
||||
// bool IsLocked = false;
|
||||
|
||||
public:
|
||||
int Lock()
|
||||
SpinLockData *GetLockData() { return &LockData; }
|
||||
|
||||
int Lock(const char *FunctionName = "Unknown")
|
||||
{
|
||||
while (!__sync_bool_compare_and_swap(&IsLocked, false, true))
|
||||
CPU::Pause();
|
||||
__sync_synchronize();
|
||||
LockData.AttemptingToGet = FunctionName;
|
||||
SpinLock_Lock(&LockData.LockData);
|
||||
LockData.CurrentHolder = FunctionName;
|
||||
LockData.Count++;
|
||||
CPU::MemBar::Barrier();
|
||||
|
||||
// while (!__sync_bool_compare_and_swap(&IsLocked, false, true))
|
||||
// CPU::Pause();
|
||||
// __sync_synchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Unlock()
|
||||
{
|
||||
__sync_synchronize();
|
||||
__atomic_store_n(&IsLocked, false, __ATOMIC_SEQ_CST);
|
||||
IsLocked = false;
|
||||
SpinLock_Unlock(&LockData.LockData);
|
||||
LockData.Count--;
|
||||
CPU::MemBar::Barrier();
|
||||
|
||||
// __sync_synchronize();
|
||||
// __atomic_store_n(&IsLocked, false, __ATOMIC_SEQ_CST);
|
||||
// IsLocked = false;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
@ -39,10 +65,10 @@ private:
|
||||
LockClass *LockPointer = nullptr;
|
||||
|
||||
public:
|
||||
SmartLockClass(LockClass &Lock)
|
||||
SmartLockClass(LockClass &Lock, const char *FunctionName)
|
||||
{
|
||||
this->LockPointer = &Lock;
|
||||
this->LockPointer->Lock();
|
||||
this->LockPointer->Lock(FunctionName);
|
||||
}
|
||||
~SmartLockClass() { this->LockPointer->Unlock(); }
|
||||
};
|
||||
@ -54,13 +80,13 @@ private:
|
||||
bool InterruptsEnabled = false;
|
||||
|
||||
public:
|
||||
SmartCriticalSectionClass(LockClass &Lock)
|
||||
SmartCriticalSectionClass(LockClass &Lock, const char *FunctionName)
|
||||
{
|
||||
if (CPU::Interrupts(CPU::Check))
|
||||
InterruptsEnabled = true;
|
||||
CPU::Interrupts(CPU::Disable);
|
||||
this->LockPointer = &Lock;
|
||||
this->LockPointer->Lock();
|
||||
this->LockPointer->Lock(FunctionName);
|
||||
}
|
||||
~SmartCriticalSectionClass()
|
||||
{
|
||||
@ -73,9 +99,9 @@ public:
|
||||
/** @brief Create a new lock (can be used with SmartCriticalSection). */
|
||||
#define NewLock(Name) LockClass Name
|
||||
/** @brief Simple lock that is automatically released when the scope ends. */
|
||||
#define SmartLock(LockClassName) SmartLockClass CONCAT(lock##_, __COUNTER__)(LockClassName)
|
||||
#define SmartLock(LockClassName) SmartLockClass CONCAT(lock##_, __COUNTER__)(LockClassName, __FUNCTION__)
|
||||
/** @brief Simple critical section that is automatically released when the scope ends and interrupts are restored if they were enabled. */
|
||||
#define SmartCriticalSection(LockClassName) SmartCriticalSectionClass CONCAT(lock##_, __COUNTER__)(LockClassName)
|
||||
#define SmartCriticalSection(LockClassName) SmartCriticalSectionClass CONCAT(lock##_, __COUNTER__)(LockClassName, __FUNCTION__)
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // !__FENNIX_KERNEL_LOCK_H__
|
||||
|
Loading…
x
Reference in New Issue
Block a user