xref: /llvm-project/libc/test/integration/src/pthread/pthread_spinlock_test.cpp (revision 03841e7ab847b279d65be707a8e0f2799fd69f50)
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