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__
|
#ifndef __FENNIX_KERNEL_LOCK_H__
|
||||||
#define __FENNIX_KERNEL_LOCK_H__
|
#define __FENNIX_KERNEL_LOCK_H__
|
||||||
|
|
||||||
/*
|
|
||||||
TODO: Add deadlock detection.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
|
#include <atomic.hpp>
|
||||||
#include <cpu.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
|
#ifdef __cplusplus
|
||||||
/** @brief Please use this macro to create a new lock. */
|
/** @brief Please use this macro to create a new lock. */
|
||||||
class LockClass
|
class LockClass
|
||||||
{
|
{
|
||||||
|
struct SpinLockData
|
||||||
|
{
|
||||||
|
uint64_t LockData;
|
||||||
|
const char *CurrentHolder;
|
||||||
|
const char *AttemptingToGet;
|
||||||
|
uint64_t Count;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool IsLocked = false;
|
SpinLockData LockData;
|
||||||
|
// bool IsLocked = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int Lock()
|
SpinLockData *GetLockData() { return &LockData; }
|
||||||
|
|
||||||
|
int Lock(const char *FunctionName = "Unknown")
|
||||||
{
|
{
|
||||||
while (!__sync_bool_compare_and_swap(&IsLocked, false, true))
|
LockData.AttemptingToGet = FunctionName;
|
||||||
CPU::Pause();
|
SpinLock_Lock(&LockData.LockData);
|
||||||
__sync_synchronize();
|
LockData.CurrentHolder = FunctionName;
|
||||||
|
LockData.Count++;
|
||||||
|
CPU::MemBar::Barrier();
|
||||||
|
|
||||||
|
// while (!__sync_bool_compare_and_swap(&IsLocked, false, true))
|
||||||
|
// CPU::Pause();
|
||||||
|
// __sync_synchronize();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Unlock()
|
int Unlock()
|
||||||
{
|
{
|
||||||
__sync_synchronize();
|
SpinLock_Unlock(&LockData.LockData);
|
||||||
__atomic_store_n(&IsLocked, false, __ATOMIC_SEQ_CST);
|
LockData.Count--;
|
||||||
IsLocked = false;
|
CPU::MemBar::Barrier();
|
||||||
|
|
||||||
|
// __sync_synchronize();
|
||||||
|
// __atomic_store_n(&IsLocked, false, __ATOMIC_SEQ_CST);
|
||||||
|
// IsLocked = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -39,10 +65,10 @@ private:
|
|||||||
LockClass *LockPointer = nullptr;
|
LockClass *LockPointer = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SmartLockClass(LockClass &Lock)
|
SmartLockClass(LockClass &Lock, const char *FunctionName)
|
||||||
{
|
{
|
||||||
this->LockPointer = &Lock;
|
this->LockPointer = &Lock;
|
||||||
this->LockPointer->Lock();
|
this->LockPointer->Lock(FunctionName);
|
||||||
}
|
}
|
||||||
~SmartLockClass() { this->LockPointer->Unlock(); }
|
~SmartLockClass() { this->LockPointer->Unlock(); }
|
||||||
};
|
};
|
||||||
@ -54,13 +80,13 @@ private:
|
|||||||
bool InterruptsEnabled = false;
|
bool InterruptsEnabled = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SmartCriticalSectionClass(LockClass &Lock)
|
SmartCriticalSectionClass(LockClass &Lock, const char *FunctionName)
|
||||||
{
|
{
|
||||||
if (CPU::Interrupts(CPU::Check))
|
if (CPU::Interrupts(CPU::Check))
|
||||||
InterruptsEnabled = true;
|
InterruptsEnabled = true;
|
||||||
CPU::Interrupts(CPU::Disable);
|
CPU::Interrupts(CPU::Disable);
|
||||||
this->LockPointer = &Lock;
|
this->LockPointer = &Lock;
|
||||||
this->LockPointer->Lock();
|
this->LockPointer->Lock(FunctionName);
|
||||||
}
|
}
|
||||||
~SmartCriticalSectionClass()
|
~SmartCriticalSectionClass()
|
||||||
{
|
{
|
||||||
@ -73,9 +99,9 @@ public:
|
|||||||
/** @brief Create a new lock (can be used with SmartCriticalSection). */
|
/** @brief Create a new lock (can be used with SmartCriticalSection). */
|
||||||
#define NewLock(Name) LockClass Name
|
#define NewLock(Name) LockClass Name
|
||||||
/** @brief Simple lock that is automatically released when the scope ends. */
|
/** @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. */
|
/** @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 // __cplusplus
|
||||||
#endif // !__FENNIX_KERNEL_LOCK_H__
|
#endif // !__FENNIX_KERNEL_LOCK_H__
|
||||||
|
Loading…
x
Reference in New Issue
Block a user