1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
3 */
4 /*
5 * Copyright (c) 2022 Huawei Device Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include <signal.h>
20 #include <stdlib.h>
21 #include <threads.h>
22 #include <pthread.h>
23 #include <stdio.h>
24 #include <time.h>
25 #include <errno.h>
26 #include "test.h"
27
28 #define LOCK_SUCCESS (0)
29 #define LOCK_TIMEOUT (-1)
30 #define LOCK_WAIT_MAX_TIME_COUNT (50)
31 #define NSEC_TO_MS (1000000)
32 #define TRYLOCK_FAIL (-2)
33
34 static thrd_t thr;
35 static int count = 0;
36 pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
37
TrylockWithTimeout(pthread_mutex_t *mutex)38 int TrylockWithTimeout(pthread_mutex_t *mutex)
39 {
40 int rc;
41
42 int sleepCount = 0;
43
44 do {
45 rc = pthread_mutex_trylock(mutex);
46 if (rc == 0) {
47 return LOCK_SUCCESS;
48 } else if (rc != EBUSY) {
49 perror("pthread_mutex_trylock");
50 return TRYLOCK_FAIL;
51 }
52
53 struct timespec req = { .tv_sec = 0, .tv_nsec = NSEC_TO_MS * 10 }; // 等待10毫秒
54 nanosleep(&req, NULL);
55
56 sleepCount++;
57 if (sleepCount >= LOCK_WAIT_MAX_TIME_COUNT) {
58 return LOCK_TIMEOUT;
59 }
60 } while (1);
61 }
62
threadfuncA(void *arg)63 int threadfuncA(void *arg)
64 {
65 pthread_mutex_t *mtx = (pthread_mutex_t *)arg;
66 pthread_mutex_lock(mtx);
67 count++;
68 thrd_t id = thrd_current();
69 if (!(thrd_equal(id, thr))) {
70 t_error("%s thrd_current failed", __func__);
71 }
72 pthread_mutex_unlock(mtx);
73 thrd_exit(thrd_success);
74 }
75
threadfuncB(void *arg)76 int threadfuncB(void *arg)
77 {
78 int result = TrylockWithTimeout(&g_mutex);
79 if (result == LOCK_SUCCESS) {
80 count++;
81 pthread_mutex_unlock(&g_mutex);
82 } else if (result == LOCK_TIMEOUT) {
83 t_error("Lock acquisition timed out.\n");
84 } else {
85 t_error("Error pthread_mutex_trylock.\n");
86 }
87
88 thrd_exit(thrd_success);
89 }
90
91 /**
92 * @tc.name : thrd_equal_0100
93 * @tc.desc : Test that two threads have the same ID
94 * @tc.level : Level 0
95 */
thrd_equal_0100(void)96 void thrd_equal_0100(void)
97 {
98 int result;
99 pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
100 pthread_mutex_lock(&mtx);
101 result = thrd_create(&thr, threadfuncA, (void *)&mtx);
102 pthread_mutex_unlock(&mtx);
103 pthread_mutex_destroy(&mtx);
104 if (result != thrd_success) {
105 t_error("%s thrd_create failed", __func__);
106 }
107
108 result = thrd_sleep(&(struct timespec){.tv_sec = 1}, NULL);
109 if (result != 0) {
110 t_error("%s thrd_sleep failed", __func__);
111 }
112
113 result = thrd_join(thr, NULL);
114 if (result != thrd_success) {
115 t_error("%s thrd_join failed", __func__);
116 }
117
118 if (count != 1) {
119 t_error("%s failed, count is %d", __func__, count);
120 }
121 count = 0;
122 }
123
124 /**
125 * @tc.name : thrd_equal_0200
126 * @tc.desc : Test that two threads have different ID
127 * @tc.level : Level 1
128 */
thrd_equal_0200(void)129 void thrd_equal_0200(void)
130 {
131 thrd_t thr1, thr2;
132 int result;
133
134 result = thrd_create(&thr1, threadfuncB, NULL);
135 if (result != thrd_success) {
136 t_error("%s thrd_create failed", __func__);
137 }
138
139 result = thrd_create(&thr2, threadfuncB, NULL);
140 if (result != thrd_success) {
141 t_error("%s thrd_create failed", __func__);
142 }
143
144 result = thrd_sleep(&(struct timespec){.tv_sec = 1}, NULL);
145 if (result != 0) {
146 t_error("%s thrd_sleep failed", __func__);
147 }
148
149 if (thrd_equal(thr1, thr2)) {
150 t_error("%s failed, thr1 and thr2 equal", __func__);
151 }
152
153 if (thrd_equal(thr1, thrd_current())) {
154 t_error("%s failed, thr1 and current thread equal", __func__);
155 }
156
157 if (thrd_equal(thr2, thrd_current())) {
158 t_error("%s failed, thr2 and current thread equal", __func__);
159 }
160
161 result = thrd_join(thr1, NULL);
162 if (result != thrd_success) {
163 t_error("%s thrd_join failed", __func__);
164 }
165
166 result = thrd_join(thr2, NULL);
167 if (result != thrd_success) {
168 t_error("%s thrd_join failed", __func__);
169 }
170
171 if (count != 2) {
172 t_error("%s failed, count is %d", __func__, count);
173 }
174 count = 0;
175 }
176
main(int argc, char *argv[])177 int main(int argc, char *argv[])
178 {
179 thrd_equal_0100();
180 thrd_equal_0200();
181 return t_status;
182 }