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