kernel: Improve spinlock implementation

atomic_or() and atomic_and() are not supported by x86 are need to be
emulated using CAS. Use atomic_get_and_set() and atomic_set() instead.
This commit is contained in:
Pawel Dziepak
2013-11-05 22:47:18 +01:00
parent 077c84eb27
commit 273f2f38cd
2 changed files with 14 additions and 12 deletions
+2 -2
View File
@@ -76,7 +76,7 @@ int smp_intercpu_int_handler(int32 cpu);
static inline bool static inline bool
try_acquire_spinlock_inline(spinlock* lock) try_acquire_spinlock_inline(spinlock* lock)
{ {
return atomic_or((int32*)lock, 1) == 0; return atomic_get_and_set((int32*)lock, 1) == 0;
} }
@@ -92,7 +92,7 @@ acquire_spinlock_inline(spinlock* lock)
static inline void static inline void
release_spinlock_inline(spinlock* lock) release_spinlock_inline(spinlock* lock)
{ {
atomic_and((int32*)lock, 0); atomic_set((int32*)lock, 0);
} }
+12 -10
View File
@@ -313,7 +313,7 @@ try_acquire_spinlock(spinlock* lock)
if (atomic_add(&lock->lock, 1) != 0) if (atomic_add(&lock->lock, 1) != 0)
return false; return false;
#else #else
if (atomic_or((int32*)lock, 1) != 0) if (atomic_get_and_set((int32*)lock, 1) != 0)
return false; return false;
# if DEBUG_SPINLOCKS # if DEBUG_SPINLOCKS
@@ -353,7 +353,7 @@ acquire_spinlock(spinlock* lock)
process_all_pending_ici(currentCPU); process_all_pending_ici(currentCPU);
PAUSE(); PAUSE();
} }
if (atomic_or((int32*)lock, 1) == 0) if (atomic_get_and_set((int32*)lock, 1) == 0)
break; break;
} }
@@ -364,7 +364,7 @@ acquire_spinlock(spinlock* lock)
} else { } else {
#if DEBUG_SPINLOCKS #if DEBUG_SPINLOCKS
int32 oldValue; int32 oldValue;
oldValue = atomic_or((int32*)lock, 1); oldValue = atomic_get_and_set((int32*)lock, 1);
if (oldValue != 0) { if (oldValue != 0) {
panic("acquire_spinlock: attempt to acquire lock %p twice on " panic("acquire_spinlock: attempt to acquire lock %p twice on "
"non-SMP system (last caller: %p, value %" B_PRId32 ")", lock, "non-SMP system (last caller: %p, value %" B_PRId32 ")", lock,
@@ -407,13 +407,13 @@ acquire_spinlock_nocheck(spinlock *lock)
PAUSE(); PAUSE();
} }
if (atomic_or((int32*)lock, 1) == 0) if (atomic_get_and_set((int32*)lock, 1) == 0)
break; break;
} }
#endif #endif
} else { } else {
#if DEBUG_SPINLOCKS #if DEBUG_SPINLOCKS
if (atomic_or((int32*)lock, 1) != 0) { if (atomic_get_and_set((int32*)lock, 1) != 0) {
panic("acquire_spinlock_nocheck: attempt to acquire lock %p twice " panic("acquire_spinlock_nocheck: attempt to acquire lock %p twice "
"on non-SMP system\n", lock); "on non-SMP system\n", lock);
} }
@@ -450,7 +450,7 @@ acquire_spinlock_cpu(int32 currentCPU, spinlock *lock)
process_all_pending_ici(currentCPU); process_all_pending_ici(currentCPU);
PAUSE(); PAUSE();
} }
if (atomic_or((int32*)lock, 1) == 0) if (atomic_get_and_set((int32*)lock, 1) == 0)
break; break;
} }
@@ -461,7 +461,7 @@ acquire_spinlock_cpu(int32 currentCPU, spinlock *lock)
} else { } else {
#if DEBUG_SPINLOCKS #if DEBUG_SPINLOCKS
int32 oldValue; int32 oldValue;
oldValue = atomic_or((int32*)lock, 1); oldValue = atomic_get_and_set((int32*)lock, 1);
if (oldValue != 0) { if (oldValue != 0) {
panic("acquire_spinlock_cpu(): attempt to acquire lock %p twice on " panic("acquire_spinlock_cpu(): attempt to acquire lock %p twice on "
"non-SMP system (last caller: %p, value %" B_PRId32 ")", lock, "non-SMP system (last caller: %p, value %" B_PRId32 ")", lock,
@@ -498,9 +498,11 @@ release_spinlock(spinlock *lock)
} }
} }
} }
#else #elif DEBUG_SPINLOCKS
if (atomic_and((int32*)lock, 0) != 1) if (atomic_get_and_set((int32*)lock, 0) != 1)
panic("release_spinlock: lock %p was already released\n", lock); panic("release_spinlock: lock %p was already released\n", lock);
#else
atomic_set((int32*)lock, 0);
#endif #endif
} else { } else {
#if DEBUG_SPINLOCKS #if DEBUG_SPINLOCKS
@@ -508,7 +510,7 @@ release_spinlock(spinlock *lock)
panic("release_spinlock: attempt to release lock %p with " panic("release_spinlock: attempt to release lock %p with "
"interrupts enabled\n", lock); "interrupts enabled\n", lock);
} }
if (atomic_and((int32*)lock, 0) != 1) if (atomic_get_and_set((int32*)lock, 0) != 1)
panic("release_spinlock: lock %p was already released\n", lock); panic("release_spinlock: lock %p was already released\n", lock);
#endif #endif
#if DEBUG_SPINLOCK_LATENCIES #if DEBUG_SPINLOCK_LATENCIES