1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hc_mutex_test.h"
17
18 #include <hctest.h>
19 #include <pthread.h>
20 #include <securec.h>
21 #include <unistd.h>
22
23 #include "hc_thread_mutex_share.h"
24 #include "print_log.h"
25 #include "test_timer.h"
26
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30
31 #define REQUIRED_MUTEX_COUNT 20
32
TestSpecifiedCount(int count)33 static void TestSpecifiedCount(int count)
34 {
35 pthread_mutex_t mutexes[REQUIRED_MUTEX_COUNT];
36 int res;
37
38 TEST_ASSERT_GREATER_THAN(0, count);
39 TEST_ASSERT_LESS_OR_EQUAL(REQUIRED_MUTEX_COUNT, count);
40
41 res = memset_s(mutexes, sizeof(mutexes), 0, sizeof(mutexes));
42 TEST_ASSERT_EQUAL(0, res);
43
44 for (int i = 0; i < count; ++i) {
45 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_mutex_init(&mutexes[i], NULL));
46 TEST_ASSERT_EQUAL(0, res);
47 }
48
49 for (int i = 0; i < count; ++i) {
50 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_mutex_lock(&mutexes[i]));
51 TEST_ASSERT_EQUAL(0, res);
52 }
53
54 for (int i = 0; i < count; ++i) {
55 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_mutex_unlock(&mutexes[i]));
56 TEST_ASSERT_EQUAL(0, res);
57 }
58
59 for (int i = 0; i < count; ++i) {
60 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_mutex_destroy(&mutexes[i]));
61 TEST_ASSERT_EQUAL(0, res);
62 }
63 }
64
MutexThreadRoutine(void * args)65 static void *MutexThreadRoutine(void *args)
66 {
67 pthread_mutex_t *mtx = (pthread_mutex_t *)args;
68 TEST_ASSERT_NOT_NULL(mtx);
69
70 unsigned long long timeConsumingResult;
71 int res;
72 int sleepSeconds = rand() % (WAIT_IN_MUTEX_SECONDS_MAX - WAIT_IN_MUTEX_SECONDS_MIN) + WAIT_IN_MUTEX_SECONDS_MIN;
73
74 LOGI("in thread begin phase 1 work");
75 RUN_AND_PRINT_ELAPSED_TIME(timeConsumingResult, TimeConsumingOperation());
76
77 LOGI("in thread begin wait for mutex");
78 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_mutex_lock(mtx));
79 TEST_ASSERT_EQUAL(0, res);
80 LOGI("in thread wait for mutex succeed");
81
82 LOGI("in thread begin wait for %d seconds", sleepSeconds);
83 sleep(sleepSeconds);
84 LOGI("in thread wait for %d seconds succeed", sleepSeconds);
85
86 LOGI("in thread begin phase 2 work");
87 RUN_AND_PRINT_ELAPSED_TIME(timeConsumingResult, TimeConsumingOperation());
88
89 LOGI("in thread begin release mutex");
90 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_mutex_unlock(mtx));
91 TEST_ASSERT_EQUAL(0, res);
92 LOGI("in thread release mutex successfully");
93
94 LOGI("in thread begin phase 3 work");
95 RUN_AND_PRINT_ELAPSED_TIME(timeConsumingResult, TimeConsumingOperation());
96
97 (void)(timeConsumingResult);
98 LOGI("in thread all work done");
99 return mtx;
100 }
101
TestMutexInThreads(void)102 static void TestMutexInThreads(void)
103 {
104 pthread_mutex_t mtx;
105 pthread_attr_t attr;
106 int res;
107 pthread_t threads[REQUIRED_THREAD_COUNT];
108 res = memset_s(&mtx, sizeof(mtx), 0, sizeof(mtx));
109 TEST_ASSERT_EQUAL(0, res);
110 res = memset_s(&attr, sizeof(attr), 0, sizeof(attr));
111 TEST_ASSERT_EQUAL(0, res);
112 res = memset_s(&threads, sizeof(threads), 0, sizeof(threads));
113 TEST_ASSERT_EQUAL(0, res);
114
115 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_mutex_init(&mtx, NULL));
116 TEST_ASSERT_EQUAL(0, res);
117
118 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_attr_init(&attr));
119 TEST_ASSERT_EQUAL(0, res);
120
121 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
122 TEST_ASSERT_EQUAL(0, res);
123
124 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_attr_setstacksize(&attr, MAX_THREAD_STACK_SIZE));
125 TEST_ASSERT_EQUAL(0, res);
126
127 for (int i = 0; i < REQUIRED_THREAD_COUNT; ++i) {
128 LOGI("test threads %d/%d", i, REQUIRED_THREAD_COUNT);
129 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_create(&threads[i], &attr, MutexThreadRoutine, &mtx));
130 TEST_ASSERT_EQUAL(0, res);
131 }
132
133 for (int i = 0; i < REQUIRED_THREAD_COUNT; ++i) {
134 LOGI("test threads %d/%d", i, REQUIRED_THREAD_COUNT);
135 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_join(threads[i], NULL));
136 LOGI("pthread_join result = %d", res);
137 TEST_ASSERT_EQUAL(0, res);
138 }
139
140 RUN_AND_PRINT_ELAPSED_TIME(res, pthread_attr_destroy(&attr));
141 TEST_ASSERT_EQUAL(0, res);
142 }
143
TestHcMutex(void)144 void TestHcMutex(void)
145 {
146 LOGI("test one mutex");
147 TestSpecifiedCount(1);
148
149 LOGI("test %d mutexes", REQUIRED_MUTEX_COUNT);
150 TestSpecifiedCount(REQUIRED_MUTEX_COUNT);
151
152 LOGI("test mutexes in threads");
153 TestMutexInThreads();
154 }
155
156 #ifdef __cplusplus
157 }
158 #endif
159