• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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