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     count++;
66     thrd_t id = thrd_current();
67     if (!(thrd_equal(id, thr))) {
68         t_error("%s thrd_current failed", __func__);
69     }
70 
71     thrd_exit(thrd_success);
72 }
73 
threadfuncB(void *arg)74 int threadfuncB(void *arg)
75 {
76     int result = TrylockWithTimeout(&g_mutex);
77     if (result == LOCK_SUCCESS) {
78         count++;
79         pthread_mutex_unlock(&g_mutex);
80     } else if (result == LOCK_TIMEOUT) {
81         t_error("Lock acquisition timed out.\n");
82     } else {
83         t_error("Error pthread_mutex_trylock.\n");
84     }
85 
86     thrd_exit(thrd_success);
87 }
88 
89 /**
90  * @tc.name      : thrd_current_0100
91  * @tc.desc      : Returns the identifier of the calling thread
92  * @tc.level     : Level 0
93  */
thrd_current_0100(void)94 void thrd_current_0100(void)
95 {
96     int result;
97 
98     result = thrd_create(&thr, threadfuncA, NULL);
99     if (result != thrd_success) {
100         t_error("%s thrd_create failed", __func__);
101     }
102 
103     result = thrd_sleep(&(struct timespec){.tv_sec = 1}, NULL);
104     if (result != 0) {
105         t_error("%s thrd_sleep failed", __func__);
106     }
107 
108     result = thrd_join(thr, NULL);
109     if (result != thrd_success) {
110         t_error("%s thrd_join failed", __func__);
111     }
112 
113     if (count != 1) {
114         t_error("%s failed, count is %d", __func__, count);
115     }
116     count = 0;
117 }
118 
119 /**
120  * @tc.name      : thrd_current_0200
121  * @tc.desc      : Create two threads to execute the same func
122  * @tc.level     : Level 1
123  */
thrd_current_0200(void)124 void thrd_current_0200(void)
125 {
126     thrd_t thr1, thr2;
127     int result;
128 
129     result = thrd_create(&thr1, threadfuncB, NULL);
130     if (result != thrd_success) {
131         t_error("%s thrd_create failed", __func__);
132     }
133 
134     result = thrd_create(&thr2, threadfuncB, NULL);
135     if (result != thrd_success) {
136         t_error("%s thrd_create failed", __func__);
137     }
138 
139     result = thrd_sleep(&(struct timespec){.tv_sec = 1}, NULL);
140     if (result != 0) {
141         t_error("%s thrd_sleep failed", __func__);
142     }
143 
144     if (thrd_equal(thr1, thr2)) {
145         t_error("%s equal", __func__);
146     }
147 
148     if (thrd_equal(thr1, thrd_current())) {
149         t_error("%s equal", __func__);
150     }
151 
152     if (thrd_equal(thr2, thrd_current())) {
153         t_error("%s equal", __func__);
154     }
155 
156     result = thrd_join(thr1, NULL);
157     if (result != thrd_success) {
158         t_error("%s thrd_join failed", __func__);
159     }
160 
161     result = thrd_join(thr2, NULL);
162     if (result != thrd_success) {
163         t_error("%s thrd_join failed", __func__);
164     }
165 
166     if (count != 2) {
167         t_error("%s failed, count is %d", __func__, count);
168     }
169     count = 0;
170 }
171 
main(int argc, char *argv[])172 int main(int argc, char *argv[])
173 {
174     thrd_current_0100();
175     thrd_current_0200();
176     return t_status;
177 }