mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 11:12:45 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			131 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2021, Brian Gianforcaro <bgianf@serenityos.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #include <LibTest/TestCase.h>
 | |
| #include <errno.h>
 | |
| #include <pthread.h>
 | |
| #include <unistd.h>
 | |
| 
 | |
| TEST_CASE(spin_init_process_scope)
 | |
| {
 | |
|     {
 | |
|         pthread_spinlock_t lock {};
 | |
|         auto result = pthread_spin_init(&lock, PTHREAD_SCOPE_PROCESS);
 | |
|         EXPECT_EQ(0, result);
 | |
|         result = pthread_spin_destroy(&lock);
 | |
|         EXPECT_EQ(0, result);
 | |
|     }
 | |
| 
 | |
|     {
 | |
|         pthread_spinlock_t garbage_lock { 0x1337 };
 | |
|         auto result = pthread_spin_init(&garbage_lock, PTHREAD_SCOPE_PROCESS);
 | |
|         EXPECT_EQ(0, result);
 | |
|         result = pthread_spin_destroy(&garbage_lock);
 | |
|         EXPECT_EQ(0, result);
 | |
|     }
 | |
| }
 | |
| 
 | |
| TEST_CASE(spin_init_system_scope)
 | |
| {
 | |
|     pthread_spinlock_t lock {};
 | |
|     auto result = pthread_spin_init(&lock, PTHREAD_SCOPE_SYSTEM);
 | |
|     EXPECT_EQ(0, result);
 | |
|     pthread_spinlock_t garbage_lock { 0x99999 };
 | |
|     result = pthread_spin_init(&garbage_lock, PTHREAD_SCOPE_PROCESS);
 | |
|     EXPECT_EQ(0, result);
 | |
| }
 | |
| 
 | |
| TEST_CASE(spin_lock)
 | |
| {
 | |
|     pthread_spinlock_t lock {};
 | |
|     auto result = pthread_spin_lock(&lock);
 | |
|     EXPECT_EQ(0, result);
 | |
| 
 | |
|     // We should detect that this thread already holds this lock.
 | |
|     result = pthread_spin_lock(&lock);
 | |
|     EXPECT_EQ(EDEADLK, result);
 | |
| }
 | |
| 
 | |
| TEST_CASE(spin_try_lock)
 | |
| {
 | |
|     {
 | |
|         pthread_spinlock_t lock {};
 | |
|         auto result = pthread_spin_trylock(&lock);
 | |
|         EXPECT_EQ(0, result);
 | |
| 
 | |
|         result = pthread_spin_unlock(&lock);
 | |
|         EXPECT_EQ(0, result);
 | |
|     }
 | |
| 
 | |
|     {
 | |
|         pthread_spinlock_t lock {};
 | |
|         auto result = pthread_spin_trylock(&lock);
 | |
|         EXPECT_EQ(0, result);
 | |
| 
 | |
|         // We should detect that this thread already holds the lock.
 | |
|         result = pthread_spin_trylock(&lock);
 | |
|         EXPECT_EQ(EBUSY, result);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void lock_from_different_thread(pthread_spinlock_t* lock)
 | |
| {
 | |
|     pthread_t thread_id {};
 | |
|     auto result = pthread_create(
 | |
|         &thread_id, nullptr, [](void* param) -> void* {
 | |
|             auto lock = (pthread_spinlock_t*)param;
 | |
|             pthread_spin_lock(lock);
 | |
|             return nullptr;
 | |
|         },
 | |
|         lock);
 | |
|     EXPECT_EQ(0, result);
 | |
| 
 | |
|     result = pthread_join(thread_id, nullptr);
 | |
|     EXPECT_EQ(0, result);
 | |
| }
 | |
| 
 | |
| TEST_CASE(spin_unlock)
 | |
| {
 | |
|     {
 | |
|         pthread_spinlock_t lock {};
 | |
|         auto result = pthread_spin_lock(&lock);
 | |
|         EXPECT_EQ(0, result);
 | |
| 
 | |
|         result = pthread_spin_unlock(&lock);
 | |
|         EXPECT_EQ(0, result);
 | |
|     }
 | |
| 
 | |
|     {
 | |
|         pthread_spinlock_t lock {};
 | |
|         lock_from_different_thread(&lock);
 | |
| 
 | |
|         auto result = pthread_spin_unlock(&lock);
 | |
|         EXPECT_EQ(EPERM, result);
 | |
|     }
 | |
| }
 | |
| 
 | |
| TEST_CASE(spin_destroy)
 | |
| {
 | |
|     {
 | |
|         pthread_spinlock_t lock {};
 | |
|         auto result = pthread_spin_lock(&lock);
 | |
|         EXPECT_EQ(0, result);
 | |
| 
 | |
|         result = pthread_spin_destroy(&lock);
 | |
|         EXPECT_EQ(EBUSY, result);
 | |
| 
 | |
|         result = pthread_spin_unlock(&lock);
 | |
|         EXPECT_EQ(0, result);
 | |
|     }
 | |
| 
 | |
|     {
 | |
|         pthread_spinlock_t lock {};
 | |
|         lock_from_different_thread(&lock);
 | |
| 
 | |
|         auto result = pthread_spin_destroy(&lock);
 | |
|         EXPECT_EQ(EBUSY, result);
 | |
|     }
 | |
| }
 | 
