1*03841e7aSSchrodinger ZHU Yifan //===-- Tests for pthread_spinlock ----------------------------------------===// 2*03841e7aSSchrodinger ZHU Yifan // 3*03841e7aSSchrodinger ZHU Yifan // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*03841e7aSSchrodinger ZHU Yifan // See https://llvm.org/LICENSE.txt for license information. 5*03841e7aSSchrodinger ZHU Yifan // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*03841e7aSSchrodinger ZHU Yifan // 7*03841e7aSSchrodinger ZHU Yifan //===----------------------------------------------------------------------===// 8*03841e7aSSchrodinger ZHU Yifan 9*03841e7aSSchrodinger ZHU Yifan #include "hdr/errno_macros.h" 10*03841e7aSSchrodinger ZHU Yifan #include "src/pthread/pthread_create.h" 11*03841e7aSSchrodinger ZHU Yifan #include "src/pthread/pthread_join.h" 12*03841e7aSSchrodinger ZHU Yifan #include "src/pthread/pthread_spin_destroy.h" 13*03841e7aSSchrodinger ZHU Yifan #include "src/pthread/pthread_spin_init.h" 14*03841e7aSSchrodinger ZHU Yifan #include "src/pthread/pthread_spin_lock.h" 15*03841e7aSSchrodinger ZHU Yifan #include "src/pthread/pthread_spin_trylock.h" 16*03841e7aSSchrodinger ZHU Yifan #include "src/pthread/pthread_spin_unlock.h" 17*03841e7aSSchrodinger ZHU Yifan #include "test/IntegrationTest/test.h" 18*03841e7aSSchrodinger ZHU Yifan #include <pthread.h> 19*03841e7aSSchrodinger ZHU Yifan 20*03841e7aSSchrodinger ZHU Yifan namespace { 21*03841e7aSSchrodinger ZHU Yifan void smoke_test() { 22*03841e7aSSchrodinger ZHU Yifan pthread_spinlock_t lock; 23*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE), 24*03841e7aSSchrodinger ZHU Yifan 0); 25*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_lock(&lock), 0); 26*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_unlock(&lock), 0); 27*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_destroy(&lock), 0); 28*03841e7aSSchrodinger ZHU Yifan } 29*03841e7aSSchrodinger ZHU Yifan 30*03841e7aSSchrodinger ZHU Yifan void trylock_test() { 31*03841e7aSSchrodinger ZHU Yifan pthread_spinlock_t lock; 32*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE), 33*03841e7aSSchrodinger ZHU Yifan 0); 34*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_trylock(&lock), 0); 35*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_trylock(&lock), EBUSY); 36*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_unlock(&lock), 0); 37*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_trylock(&lock), 0); 38*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_unlock(&lock), 0); 39*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_destroy(&lock), 0); 40*03841e7aSSchrodinger ZHU Yifan } 41*03841e7aSSchrodinger ZHU Yifan 42*03841e7aSSchrodinger ZHU Yifan void destroy_held_lock_test() { 43*03841e7aSSchrodinger ZHU Yifan pthread_spinlock_t lock; 44*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE), 45*03841e7aSSchrodinger ZHU Yifan 0); 46*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_lock(&lock), 0); 47*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_destroy(&lock), EBUSY); 48*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_unlock(&lock), 0); 49*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_destroy(&lock), 0); 50*03841e7aSSchrodinger ZHU Yifan } 51*03841e7aSSchrodinger ZHU Yifan 52*03841e7aSSchrodinger ZHU Yifan void use_after_destroy_test() { 53*03841e7aSSchrodinger ZHU Yifan pthread_spinlock_t lock; 54*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE), 55*03841e7aSSchrodinger ZHU Yifan 0); 56*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_destroy(&lock), 0); 57*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_unlock(&lock), EINVAL); 58*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_lock(&lock), EINVAL); 59*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_trylock(&lock), EINVAL); 60*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_destroy(&lock), EINVAL); 61*03841e7aSSchrodinger ZHU Yifan } 62*03841e7aSSchrodinger ZHU Yifan 63*03841e7aSSchrodinger ZHU Yifan void unlock_without_holding_test() { 64*03841e7aSSchrodinger ZHU Yifan pthread_spinlock_t lock; 65*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE), 66*03841e7aSSchrodinger ZHU Yifan 0); 67*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_unlock(&lock), EPERM); 68*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_destroy(&lock), 0); 69*03841e7aSSchrodinger ZHU Yifan } 70*03841e7aSSchrodinger ZHU Yifan 71*03841e7aSSchrodinger ZHU Yifan void deadlock_test() { 72*03841e7aSSchrodinger ZHU Yifan pthread_spinlock_t lock; 73*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE), 74*03841e7aSSchrodinger ZHU Yifan 0); 75*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_lock(&lock), 0); 76*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_lock(&lock), EDEADLK); 77*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_unlock(&lock), 0); 78*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_destroy(&lock), 0); 79*03841e7aSSchrodinger ZHU Yifan } 80*03841e7aSSchrodinger ZHU Yifan 81*03841e7aSSchrodinger ZHU Yifan void null_lock_test() { 82*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_init(nullptr, 0), EINVAL); 83*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_lock(nullptr), EINVAL); 84*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_trylock(nullptr), EINVAL); 85*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_unlock(nullptr), EINVAL); 86*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_destroy(nullptr), EINVAL); 87*03841e7aSSchrodinger ZHU Yifan } 88*03841e7aSSchrodinger ZHU Yifan 89*03841e7aSSchrodinger ZHU Yifan void pshared_attribute_test() { 90*03841e7aSSchrodinger ZHU Yifan pthread_spinlock_t lock; 91*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_init(&lock, PTHREAD_PROCESS_SHARED), 92*03841e7aSSchrodinger ZHU Yifan 0); 93*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_destroy(&lock), 0); 94*03841e7aSSchrodinger ZHU Yifan 95*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE), 96*03841e7aSSchrodinger ZHU Yifan 0); 97*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_destroy(&lock), 0); 98*03841e7aSSchrodinger ZHU Yifan 99*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_init(&lock, -1), EINVAL); 100*03841e7aSSchrodinger ZHU Yifan } 101*03841e7aSSchrodinger ZHU Yifan 102*03841e7aSSchrodinger ZHU Yifan void multi_thread_test() { 103*03841e7aSSchrodinger ZHU Yifan struct shared_data { 104*03841e7aSSchrodinger ZHU Yifan pthread_spinlock_t lock; 105*03841e7aSSchrodinger ZHU Yifan int count = 0; 106*03841e7aSSchrodinger ZHU Yifan } shared; 107*03841e7aSSchrodinger ZHU Yifan pthread_t thread[10]; 108*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_init(&shared.lock, 0), 0); 109*03841e7aSSchrodinger ZHU Yifan for (int i = 0; i < 10; ++i) { 110*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ( 111*03841e7aSSchrodinger ZHU Yifan LIBC_NAMESPACE::pthread_create( 112*03841e7aSSchrodinger ZHU Yifan &thread[i], nullptr, 113*03841e7aSSchrodinger ZHU Yifan [](void *arg) -> void * { 114*03841e7aSSchrodinger ZHU Yifan auto *data = static_cast<shared_data *>(arg); 115*03841e7aSSchrodinger ZHU Yifan for (int j = 0; j < 1000; ++j) { 116*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_lock(&data->lock), 0); 117*03841e7aSSchrodinger ZHU Yifan data->count += j; 118*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_unlock(&data->lock), 0); 119*03841e7aSSchrodinger ZHU Yifan } 120*03841e7aSSchrodinger ZHU Yifan return nullptr; 121*03841e7aSSchrodinger ZHU Yifan }, 122*03841e7aSSchrodinger ZHU Yifan &shared), 123*03841e7aSSchrodinger ZHU Yifan 0); 124*03841e7aSSchrodinger ZHU Yifan } 125*03841e7aSSchrodinger ZHU Yifan for (int i = 0; i < 10; ++i) { 126*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_join(thread[i], nullptr), 0); 127*03841e7aSSchrodinger ZHU Yifan } 128*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(LIBC_NAMESPACE::pthread_spin_destroy(&shared.lock), 0); 129*03841e7aSSchrodinger ZHU Yifan ASSERT_EQ(shared.count, 1000 * 999 * 5); 130*03841e7aSSchrodinger ZHU Yifan } 131*03841e7aSSchrodinger ZHU Yifan 132*03841e7aSSchrodinger ZHU Yifan } // namespace 133*03841e7aSSchrodinger ZHU Yifan 134*03841e7aSSchrodinger ZHU Yifan TEST_MAIN() { 135*03841e7aSSchrodinger ZHU Yifan smoke_test(); 136*03841e7aSSchrodinger ZHU Yifan trylock_test(); 137*03841e7aSSchrodinger ZHU Yifan destroy_held_lock_test(); 138*03841e7aSSchrodinger ZHU Yifan use_after_destroy_test(); 139*03841e7aSSchrodinger ZHU Yifan unlock_without_holding_test(); 140*03841e7aSSchrodinger ZHU Yifan deadlock_test(); 141*03841e7aSSchrodinger ZHU Yifan multi_thread_test(); 142*03841e7aSSchrodinger ZHU Yifan null_lock_test(); 143*03841e7aSSchrodinger ZHU Yifan pshared_attribute_test(); 144*03841e7aSSchrodinger ZHU Yifan return 0; 145*03841e7aSSchrodinger ZHU Yifan } 146