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