1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "clock_test.h"
10 #include "clock_if.h"
11 #include "hdf_base.h"
12 #include "hdf_io_service_if.h"
13 #include "hdf_log.h"
14 #include "osal_mem.h"
15 #include "securec.h"
16 #include "osal_thread.h"
17 #include "osal_time.h"
18
19 #define DEFAULT_RATE 10000
20 #define CLOCK_TEST_STACK_SIZE (1024 * 64)
21 #define CLOCK_TEST_SLEEP_TIME 100
22 #define CLOCK_TEST_WAIT_TIMEOUT 20
23 #define HDF_LOG_TAG clock_test_c
24 DevHandle parent = NULL;
25
ClockTestGetConfig(struct ClockTestConfig * config)26 static int32_t ClockTestGetConfig(struct ClockTestConfig *config)
27 {
28 int32_t ret;
29 struct HdfSBuf *reply = NULL;
30 struct HdfIoService *service = NULL;
31 const void *buf = NULL;
32 uint32_t len;
33
34 HDF_LOGD("ClockTestGetConfig: enter!");
35 service = HdfIoServiceBind("CLOCK_TEST");
36 if (service == NULL) {
37 HDF_LOGE("ClockTestGetConfig: service is null!");
38 return HDF_ERR_NOT_SUPPORT;
39 }
40
41 do {
42 reply = HdfSbufObtain(sizeof(*config) + sizeof(uint64_t));
43 if (reply == NULL) {
44 HDF_LOGE("ClockTestGetConfig: fail to obtain reply!");
45 ret = HDF_ERR_MALLOC_FAIL;
46 break;
47 }
48
49 ret = service->dispatcher->Dispatch(&service->object, 0, NULL, reply);
50 if (ret != HDF_SUCCESS) {
51 HDF_LOGE("ClockTestGetConfig: remote dispatch fail!");
52 break;
53 }
54
55 if (!HdfSbufReadBuffer(reply, &buf, &len)) {
56 HDF_LOGE("ClockTestGetConfig: read buf fail!");
57 ret = HDF_ERR_IO;
58 break;
59 }
60
61 if (len != sizeof(*config)) {
62 HDF_LOGE("ClockTestGetConfig: config size:%zu, read size:%u!", sizeof(*config), len);
63 ret = HDF_ERR_IO;
64 break;
65 }
66
67 if (memcpy_s(config, sizeof(*config), buf, sizeof(*config)) != EOK) {
68 HDF_LOGE("ClockTestGetConfig: memcpy buf fail!");
69 ret = HDF_ERR_IO;
70 break;
71 }
72 HDF_LOGD("ClockTestGetConfig: exit!");
73 ret = HDF_SUCCESS;
74 } while (0);
75 HdfSbufRecycle(reply);
76 HdfIoServiceRecycle(service);
77 return ret;
78 }
79
ClockTesterGet(void)80 static struct ClockTester *ClockTesterGet(void)
81 {
82 int32_t ret;
83 static struct ClockTester tester;
84 static bool hasInit = false;
85
86 HDF_LOGE("ClockTesterGet: enter!");
87 if (hasInit) {
88 return &tester;
89 }
90 ret = ClockTestGetConfig(&tester.config);
91 if (ret != HDF_SUCCESS) {
92 HDF_LOGE("ClockTesterGet: read config fail, ret: %d!", ret);
93 return NULL;
94 }
95 tester.handle = ClockOpen(tester.config.deviceIndex);
96 if (tester.handle == NULL) {
97 HDF_LOGE("ClockTesterGet: open clock device:%u fail!", tester.config.deviceIndex);
98 return NULL;
99 }
100 hasInit = true;
101 HDF_LOGI("ClockTesterGet: done!");
102 return &tester;
103 }
104
ClockTestEnable(void)105 static int32_t ClockTestEnable(void)
106 {
107 struct ClockTester *tester = NULL;
108 int32_t ret;
109
110 HDF_LOGI("ClockTestEnable: enter!");
111 tester = ClockTesterGet();
112 if (tester == NULL) {
113 HDF_LOGE("ClockTestEnable: get tester fail!");
114 return HDF_ERR_INVALID_OBJECT;
115 }
116
117 ret = ClockEnable(tester->handle);
118
119 HDF_LOGI("ClockTestEnable: clock device num is %u!", tester->config.deviceIndex);
120 HDF_LOGI("ClockTestEnable: done!");
121 return ret;
122 }
123
ClockTestThreadFunc(void * param)124 static int ClockTestThreadFunc(void *param)
125 {
126 struct ClockTester *tester = NULL;
127 int32_t ret;
128
129 HDF_LOGI("ClockTestThreadFunc: enter!");
130 tester = ClockTesterGet();
131 if (tester == NULL) {
132 HDF_LOGE("ClockTestThreadFunc: get tester fail!");
133 *((int32_t *)param) = 1;
134 return HDF_ERR_INVALID_OBJECT;
135 }
136
137 ret = ClockEnable(tester->handle);
138 if (ret != HDF_SUCCESS) {
139 HDF_LOGE("ClockTestThreadFunc: clock read fail, ret: %d!", ret);
140 *((int32_t *)param) = 1;
141 return HDF_ERR_IO;
142 }
143
144 *((int32_t *)param) = 1;
145 HDF_LOGI("ClockTestThreadFunc: done!");
146 return HDF_SUCCESS;
147 }
148
ClockTestStartThread(struct OsalThread * thread1,struct OsalThread * thread2,const int32_t * count1,const int32_t * count2)149 static int32_t ClockTestStartThread(struct OsalThread *thread1, struct OsalThread *thread2, const int32_t *count1,
150 const int32_t *count2)
151 {
152 int32_t ret;
153 uint32_t time = 0;
154 struct OsalThreadParam cfg1;
155 struct OsalThreadParam cfg2;
156
157 if (memset_s(&cfg1, sizeof(cfg1), 0, sizeof(cfg1)) != EOK ||
158 memset_s(&cfg2, sizeof(cfg2), 0, sizeof(cfg2)) != EOK) {
159 HDF_LOGE("ClockTestStartThread: memset_s fail!");
160 return HDF_ERR_IO;
161 }
162
163 cfg1.name = "ClockTestThread-1";
164 cfg2.name = "ClockTestThread-2";
165 cfg1.priority = cfg2.priority = OSAL_THREAD_PRI_DEFAULT;
166 cfg1.stackSize = cfg2.stackSize = CLOCK_TEST_STACK_SIZE;
167
168 ret = OsalThreadStart(thread1, &cfg1);
169 if (ret != HDF_SUCCESS) {
170 HDF_LOGE("ClockTestStartThread: start test thread1 fail, ret: %d!", ret);
171 return ret;
172 }
173
174 ret = OsalThreadStart(thread2, &cfg2);
175 if (ret != HDF_SUCCESS) {
176 HDF_LOGE("ClockTestStartThread: start test thread2 fail, ret: %d!", ret);
177 }
178
179 while (*count1 == 0 || *count2 == 0) {
180 HDF_LOGD("ClockTestStartThread: waitting testing thread finish...");
181 OsalMSleep(CLOCK_TEST_SLEEP_TIME);
182 time++;
183 if (time > CLOCK_TEST_WAIT_TIMEOUT) {
184 break;
185 }
186 }
187 return ret;
188 }
189
ClockTestDisable(void)190 static int32_t ClockTestDisable(void)
191 {
192 struct ClockTester *tester = NULL;
193 int32_t ret;
194
195 HDF_LOGI("ClockTestDisable: enter!");
196 tester = ClockTesterGet();
197 if (tester == NULL) {
198 HDF_LOGE("ClockTestDisable: get tester fail!");
199 return HDF_ERR_INVALID_OBJECT;
200 }
201
202 ret = ClockDisable(tester->handle);
203
204 HDF_LOGI("ClockTestDisable: done!");
205 return ret;
206 }
207
ClockTestSetrate(void)208 static int32_t ClockTestSetrate(void)
209 {
210 struct ClockTester *tester = NULL;
211 int32_t ret;
212
213 HDF_LOGI("ClockTestSetrate: enter!");
214 tester = ClockTesterGet();
215 if (tester == NULL) {
216 HDF_LOGE("ClockTestSetrate: get tester fail!");
217 return HDF_ERR_INVALID_OBJECT;
218 }
219
220 ret = ClockSetRate(tester->handle, DEFAULT_RATE);
221
222 HDF_LOGI("ClockTestSetrate: done!");
223 return ret;
224 }
225
ClockTestGetrate(void)226 static int32_t ClockTestGetrate(void)
227 {
228 struct ClockTester *tester = NULL;
229 int32_t ret;
230 uint32_t rate;
231
232 HDF_LOGI("ClockTestGetrate: enter!");
233 tester = ClockTesterGet();
234 if (tester == NULL) {
235 HDF_LOGE("ClockTestGetrate: get tester fail!");
236 return HDF_ERR_INVALID_OBJECT;
237 }
238
239 ret = ClockGetRate(tester->handle, &rate);
240
241 HDF_LOGI("ClockTestGetrate: done!");
242 return ret;
243 }
244
ClockTestGetparent(void)245 static int32_t ClockTestGetparent(void)
246 {
247 struct ClockTester *tester = NULL;
248
249 HDF_LOGI("ClockTestGetparent: enter!");
250 tester = ClockTesterGet();
251 if (tester == NULL) {
252 HDF_LOGE("ClockTestGetparent: get tester fail!");
253 return HDF_ERR_INVALID_OBJECT;
254 }
255
256 parent = ClockGetParent(tester->handle);
257
258 HDF_LOGI("ClockTestGetparent: done!");
259 return HDF_SUCCESS;
260 }
261
ClockTestSetparent(void)262 static int32_t ClockTestSetparent(void)
263 {
264 struct ClockTester *tester = NULL;
265 int32_t ret;
266
267 HDF_LOGI("ClockTestSetparent: enter!");
268 tester = ClockTesterGet();
269 if (tester == NULL) {
270 HDF_LOGE("ClockTestSetparent: get tester fail!");
271 return HDF_ERR_INVALID_OBJECT;
272 }
273
274 ret = ClockSetParent(tester->handle, parent);
275
276 HDF_LOGI("ClockTestSetparent: done!");
277 return ret;
278 }
279
ClockTestMultiThread(void)280 static int32_t ClockTestMultiThread(void)
281 {
282 int32_t ret;
283 struct OsalThread thread1;
284 struct OsalThread thread2;
285 int32_t count1 = 0;
286 int32_t count2 = 0;
287
288 ret = OsalThreadCreate(&thread1, (OsalThreadEntry)ClockTestThreadFunc, (void *)&count1);
289 if (ret != HDF_SUCCESS) {
290 HDF_LOGE("ClockTestMultiThread: create test thread1 fail, ret: %d!", ret);
291 return ret;
292 }
293
294 ret = OsalThreadCreate(&thread2, (OsalThreadEntry)ClockTestThreadFunc, (void *)&count2);
295 if (ret != HDF_SUCCESS) {
296 (void)OsalThreadDestroy(&thread1);
297 HDF_LOGE("ClockTestMultiThread: create test thread2 fail, ret: %d!", ret);
298 return ret;
299 }
300
301 ret = ClockTestStartThread(&thread1, &thread2, &count1, &count2);
302 if (ret != HDF_SUCCESS) {
303 HDF_LOGE("ClockTestStartThread: test start thread fail, ret: %d!", ret);
304 }
305
306 (void)OsalThreadDestroy(&thread1);
307 (void)OsalThreadDestroy(&thread2);
308 return HDF_SUCCESS;
309 }
310
ClockTestReliability(void)311 static int32_t ClockTestReliability(void)
312 {
313 uint32_t rate;
314 HDF_LOGI("ClockTestReliability: enter!");
315 // invalid handle
316 ClockEnable(NULL);
317 // invalid handle
318 ClockDisable(NULL);
319 // invalid handle
320 ClockSetRate(NULL, DEFAULT_RATE);
321 // invalid handle
322 ClockGetRate(NULL, &rate);
323 // invalid handle
324 ClockGetParent(NULL);
325 // invalid handle
326 ClockSetParent(NULL, NULL);
327 HDF_LOGI("ClockTestReliability: done!");
328 return HDF_SUCCESS;
329 }
330
ClockIfPerformanceTest(void)331 static int32_t ClockIfPerformanceTest(void)
332 {
333 #ifdef __LITEOS__
334 // liteos the accuracy of the obtained time is too large and inaccurate.
335 return HDF_SUCCESS;
336 #endif
337 struct ClockTester *tester = NULL;
338 uint64_t startMs;
339 uint64_t endMs;
340 uint64_t useTime; // ms
341 int32_t ret;
342
343 tester = ClockTesterGet();
344 if (tester == NULL || tester->handle == NULL) {
345 HDF_LOGE("ClockIfPerformanceTest: get tester fail!");
346 return HDF_ERR_INVALID_OBJECT;
347 }
348
349 startMs = OsalGetSysTimeMs();
350 ret = ClockEnable(tester->handle);
351 if (ret == HDF_SUCCESS) {
352 endMs = OsalGetSysTimeMs();
353 useTime = endMs - startMs;
354 HDF_LOGI("ClockIfPerformanceTest: ----->interface performance test:[start - end] < 1ms[%s]\r\n",
355 useTime < 1 ? "yes" : "no");
356 return HDF_SUCCESS;
357 }
358 return HDF_SUCCESS;
359 }
360
361 struct ClockTestEntry {
362 int cmd;
363 int32_t (*func)(void);
364 const char *name;
365 };
366
367 static struct ClockTestEntry g_entry[] = {
368 {CLOCK_TEST_CMD_ENABLE, ClockTestEnable, "ClockTestEnable"},
369 {CLOCK_TEST_CMD_DISABLE, ClockTestDisable, "ClockTestDisable"},
370 {CLOCK_TEST_CMD_SET_RATE, ClockTestSetrate, "ClockTestSetrate"},
371 {CLOCK_TEST_CMD_GET_RATE, ClockTestGetrate, "ClockTestGetrate"},
372 {CLOCK_TEST_CMD_GET_PARENT, ClockTestGetparent, "ClockTestGetparent"},
373 {CLOCK_TEST_CMD_SET_PARENT, ClockTestSetparent, "ClockTestSetparent"},
374 {CLOCK_TEST_CMD_MULTI_THREAD, ClockTestMultiThread, "ClockTestMultiThread"},
375 {CLOCK_TEST_CMD_RELIABILITY, ClockTestReliability, "ClockTestReliability"},
376 {CLOCK_IF_PERFORMANCE_TEST, ClockIfPerformanceTest, "ClockIfPerformanceTest"},
377 };
378
ClockTestExecute(int cmd)379 int32_t ClockTestExecute(int cmd)
380 {
381 uint32_t i;
382 int32_t ret = HDF_ERR_NOT_SUPPORT;
383
384 if (cmd > CLOCK_TEST_CMD_MAX) {
385 HDF_LOGE("ClockTestExecute: invalid cmd:%d!", cmd);
386 ret = HDF_ERR_NOT_SUPPORT;
387 HDF_LOGE("[ClockTestExecute][======cmd:%d====ret:%d======]", cmd, ret);
388 return ret;
389 }
390
391 for (i = 0; i < sizeof(g_entry) / sizeof(g_entry[0]); i++) {
392 if (g_entry[i].cmd != cmd || g_entry[i].func == NULL) {
393 continue;
394 }
395 ret = g_entry[i].func();
396 break;
397 }
398
399 HDF_LOGE("[ClockTestExecute][======cmd:%d====ret:%d======]", cmd, ret);
400 return ret;
401 }
402