forked from Bananymous/banan-os
				
			Kernel: Make RecursiveSpinLock thread safe
also SpinLock is now implemented with gcc builtins
This commit is contained in:
		
							parent
							
								
									998999a755
								
							
						
					
					
						commit
						ff83f967d8
					
				| 
						 | 
				
			
			@ -69,7 +69,6 @@ if("${BANAN_ARCH}" STREQUAL "x86_64")
 | 
			
		|||
		arch/x86_64/IDT.cpp
 | 
			
		||||
		arch/x86_64/interrupts.S
 | 
			
		||||
		arch/x86_64/MMU.cpp
 | 
			
		||||
		arch/x86_64/SpinLock.S
 | 
			
		||||
		arch/x86_64/Thread.S
 | 
			
		||||
	)
 | 
			
		||||
elseif("${BANAN_ARCH}" STREQUAL "i386")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,17 +0,0 @@
 | 
			
		|||
.global spinlock_lock_asm
 | 
			
		||||
spinlock_lock_asm:
 | 
			
		||||
	lock; btsq $0, (%rdi)
 | 
			
		||||
	jnc .done
 | 
			
		||||
.retry:
 | 
			
		||||
	pause
 | 
			
		||||
	testq $1, (%rdi)
 | 
			
		||||
	jne .retry
 | 
			
		||||
	lock; btsq $0, (%rdi)
 | 
			
		||||
	jc .retry
 | 
			
		||||
.done:
 | 
			
		||||
	ret
 | 
			
		||||
 | 
			
		||||
.global spinlock_unlock_asm
 | 
			
		||||
spinlock_unlock_asm:
 | 
			
		||||
	movl $0, (%rdi)
 | 
			
		||||
	ret
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ namespace Kernel
 | 
			
		|||
		bool is_locked() const;
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		int m_lock = 0;
 | 
			
		||||
		volatile int m_lock = 0;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	class RecursiveSpinLock
 | 
			
		||||
| 
						 | 
				
			
			@ -34,7 +34,7 @@ namespace Kernel
 | 
			
		|||
		bool is_locked() const;
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		pid_t m_locker = 0;
 | 
			
		||||
		pid_t m_locker = -1;
 | 
			
		||||
		uint32_t m_lock_depth = 0;
 | 
			
		||||
		SpinLock m_lock;
 | 
			
		||||
	};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,17 +4,16 @@
 | 
			
		|||
namespace Kernel
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	extern "C" void spinlock_lock_asm(int*);
 | 
			
		||||
	extern "C" void spinlock_unlock_asm(int*);
 | 
			
		||||
 | 
			
		||||
	void SpinLock::lock()
 | 
			
		||||
	{
 | 
			
		||||
		spinlock_lock_asm(&m_lock);
 | 
			
		||||
		while (__sync_lock_test_and_set(&m_lock, 1))
 | 
			
		||||
			while (m_lock)
 | 
			
		||||
				__builtin_ia32_pause();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void SpinLock::unlock()
 | 
			
		||||
	{
 | 
			
		||||
		spinlock_unlock_asm(&m_lock);
 | 
			
		||||
		__sync_lock_release(&m_lock);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool SpinLock::is_locked() const
 | 
			
		||||
| 
						 | 
				
			
			@ -24,35 +23,50 @@ namespace Kernel
 | 
			
		|||
 | 
			
		||||
	void RecursiveSpinLock::lock()
 | 
			
		||||
	{
 | 
			
		||||
		// FIXME: is this thread safe?
 | 
			
		||||
		if (m_locker == Scheduler::current_tid())
 | 
			
		||||
		{
 | 
			
		||||
			m_lock_depth++;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		pid_t tid = Scheduler::current_tid();
 | 
			
		||||
 | 
			
		||||
		while (true)
 | 
			
		||||
		{
 | 
			
		||||
			// Wait for us to be the locker or the lock being free
 | 
			
		||||
			while (m_locker != -1 && m_locker != tid)
 | 
			
		||||
				__builtin_ia32_pause();
 | 
			
		||||
 | 
			
		||||
			m_lock.lock();
 | 
			
		||||
			ASSERT(m_locker == 0);
 | 
			
		||||
			m_locker = Scheduler::current_tid();
 | 
			
		||||
			m_lock_depth = 1;
 | 
			
		||||
			if (m_locker == tid)
 | 
			
		||||
			{
 | 
			
		||||
				m_lock_depth++;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			if (m_locker == -1)
 | 
			
		||||
			{
 | 
			
		||||
				m_locker = tid;
 | 
			
		||||
				m_lock_depth = 1;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			m_lock.unlock();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m_lock.unlock();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void RecursiveSpinLock::unlock()
 | 
			
		||||
	{
 | 
			
		||||
		m_lock.lock();
 | 
			
		||||
		
 | 
			
		||||
		ASSERT(m_lock_depth > 0);
 | 
			
		||||
		ASSERT(m_locker == Scheduler::current_tid());
 | 
			
		||||
 | 
			
		||||
		m_lock_depth--;
 | 
			
		||||
 | 
			
		||||
		if (m_lock_depth == 0)
 | 
			
		||||
		{
 | 
			
		||||
			m_locker = 0;
 | 
			
		||||
			m_lock.unlock();
 | 
			
		||||
		}
 | 
			
		||||
			m_locker = -1;
 | 
			
		||||
		
 | 
			
		||||
		m_lock.unlock();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool RecursiveSpinLock::is_locked() const
 | 
			
		||||
	{
 | 
			
		||||
		return m_lock.is_locked();
 | 
			
		||||
		return m_locker != -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue