TestLibPthreadSpinLocks.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. * Copyright (c) 2021, Brian Gianforcaro <bgianf@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibPthread/pthread.h>
  7. #include <LibTest/TestCase.h>
  8. #include <unistd.h>
  9. TEST_CASE(spin_init_process_scope)
  10. {
  11. {
  12. pthread_spinlock_t lock {};
  13. auto result = pthread_spin_init(&lock, PTHREAD_SCOPE_PROCESS);
  14. EXPECT_EQ(0, result);
  15. result = pthread_spin_destroy(&lock);
  16. EXPECT_EQ(0, result);
  17. }
  18. {
  19. pthread_spinlock_t garbage_lock { 0x1337 };
  20. auto result = pthread_spin_init(&garbage_lock, PTHREAD_SCOPE_PROCESS);
  21. EXPECT_EQ(0, result);
  22. result = pthread_spin_destroy(&garbage_lock);
  23. EXPECT_EQ(0, result);
  24. }
  25. }
  26. TEST_CASE(spin_init_system_scope)
  27. {
  28. pthread_spinlock_t lock {};
  29. auto result = pthread_spin_init(&lock, PTHREAD_SCOPE_SYSTEM);
  30. EXPECT_EQ(0, result);
  31. pthread_spinlock_t garbage_lock { 0x99999 };
  32. result = pthread_spin_init(&garbage_lock, PTHREAD_SCOPE_PROCESS);
  33. EXPECT_EQ(0, result);
  34. }
  35. TEST_CASE(spin_lock)
  36. {
  37. pthread_spinlock_t lock {};
  38. auto result = pthread_spin_lock(&lock);
  39. EXPECT_EQ(0, result);
  40. // We should detect that this thread already holds this lock.
  41. result = pthread_spin_lock(&lock);
  42. EXPECT_EQ(EDEADLK, result);
  43. }
  44. TEST_CASE(spin_try_lock)
  45. {
  46. {
  47. pthread_spinlock_t lock {};
  48. auto result = pthread_spin_trylock(&lock);
  49. EXPECT_EQ(0, result);
  50. result = pthread_spin_unlock(&lock);
  51. EXPECT_EQ(0, result);
  52. }
  53. {
  54. pthread_spinlock_t lock {};
  55. auto result = pthread_spin_trylock(&lock);
  56. EXPECT_EQ(0, result);
  57. // We should detect that this thread already holds the lock.
  58. result = pthread_spin_trylock(&lock);
  59. EXPECT_EQ(EBUSY, result);
  60. }
  61. }
  62. static void lock_from_different_thread(pthread_spinlock_t* lock)
  63. {
  64. pthread_t thread_id {};
  65. auto result = pthread_create(
  66. &thread_id, nullptr, [](void* param) -> void* {
  67. auto lock = (pthread_spinlock_t*)param;
  68. pthread_spin_lock(lock);
  69. return nullptr;
  70. },
  71. lock);
  72. EXPECT_EQ(0, result);
  73. result = pthread_join(thread_id, nullptr);
  74. EXPECT_EQ(0, result);
  75. }
  76. TEST_CASE(spin_unlock)
  77. {
  78. {
  79. pthread_spinlock_t lock {};
  80. auto result = pthread_spin_lock(&lock);
  81. EXPECT_EQ(0, result);
  82. result = pthread_spin_unlock(&lock);
  83. EXPECT_EQ(0, result);
  84. }
  85. {
  86. pthread_spinlock_t lock {};
  87. lock_from_different_thread(&lock);
  88. auto result = pthread_spin_unlock(&lock);
  89. EXPECT_EQ(EPERM, result);
  90. }
  91. }
  92. TEST_CASE(spin_destroy)
  93. {
  94. {
  95. pthread_spinlock_t lock {};
  96. auto result = pthread_spin_lock(&lock);
  97. EXPECT_EQ(0, result);
  98. result = pthread_spin_destroy(&lock);
  99. EXPECT_EQ(EBUSY, result);
  100. result = pthread_spin_unlock(&lock);
  101. EXPECT_EQ(0, result);
  102. }
  103. {
  104. pthread_spinlock_t lock {};
  105. lock_from_different_thread(&lock);
  106. auto result = pthread_spin_destroy(&lock);
  107. EXPECT_EQ(EBUSY, result);
  108. }
  109. }