Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Avoid unecessarily entering critical in SpinLock
Browse files Browse the repository at this point in the history
  • Loading branch information
byteduck committed Jan 30, 2024
1 parent d92b369 commit a7be17d
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 17 deletions.
30 changes: 15 additions & 15 deletions kernel/tasking/SpinLock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,29 @@ void SpinLock::release() {
}

void SpinLock::acquire() {
acquire_with_mode(AcquireMode::Normal);
acquire_with_mode<AcquireMode::Normal>();
ASSERT(!TaskManager::in_critical() || g_panicking);
}

bool SpinLock::try_acquire() {
return acquire_with_mode(AcquireMode::Try);
return acquire_with_mode<AcquireMode::Try>();
}

void SpinLock::acquire_and_enter_critical() {
acquire_with_mode(AcquireMode::EnterCritical);
acquire_with_mode<AcquireMode::EnterCritical>();
}

inline bool SpinLock::acquire_with_mode(AcquireMode mode) {
template<SpinLock::AcquireMode mode>
inline bool SpinLock::acquire_with_mode() {
auto cur_thread = TaskManager::current_thread();
if(!TaskManager::enabled() || !cur_thread || g_panicking)
return true; //Tasking isn't initialized yet
auto cur_tid = cur_thread->tid();

//Loop while the lock is held
while(true) {
TaskManager::enter_critical();
if constexpr(mode == AcquireMode::EnterCritical)
TaskManager::enter_critical();

// Try locking if no thread is holding
tid_t expected = -1;
Expand All @@ -74,24 +76,22 @@ inline bool SpinLock::acquire_with_mode(AcquireMode mode) {
break;
}

// Try locking if current thread is holding
expected = cur_tid;
if(m_holding_thread.compare_exchange_strong(expected, cur_tid, MemoryOrder::Acquire))
// Current thread is already holding
if(expected == cur_tid)
break;

if(mode == AcquireMode::Try) {
TaskManager::leave_critical();
if constexpr(mode == AcquireMode::Try) {
return false;
}

TaskManager::leave_critical();
ASSERT(!TaskManager::in_critical());
if constexpr(mode == AcquireMode::EnterCritical) {
TaskManager::leave_critical();
ASSERT(!TaskManager::in_critical());
}

TaskManager::yield();
}

if(mode != AcquireMode::EnterCritical)
TaskManager::leave_critical();

// We've got the lock!
m_times_locked.add(1, MemoryOrder::Acquire);
return true;
Expand Down
5 changes: 3 additions & 2 deletions kernel/tasking/SpinLock.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ class SpinLock: public Lock {
[[nodiscard]] int times_locked() const { return m_times_locked.load(); }

private:
inline bool acquire_with_mode(AcquireMode mode);
template<AcquireMode mode>
inline bool acquire_with_mode();

Atomic<tid_t, MemoryOrder::SeqCst> m_holding_thread = -1;
Atomic<int, MemoryOrder::SeqCst> m_times_locked = 0;
Expand All @@ -63,4 +64,4 @@ class ScopedCriticalLocker {
private:
SpinLock& m_lock;
bool m_released = false;
};
};

0 comments on commit a7be17d

Please sign in to comment.