1 /*
2 * Copyright (c) 2022-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 "timer_test.h"
10 #include "device_resource_if.h"
11 #include "hdf_io_service_if.h"
12 #include "hdf_log.h"
13 #include "osal_mem.h"
14 #include "osal_thread.h"
15 #include "osal_time.h"
16 #include "securec.h"
17 #include "timer_if.h"
18
19 #define HDF_LOG_TAG timer_test_c
20
21 static bool g_theard1Flag = false;
22 static bool g_theard2Flag = false;
23
24 struct TimerTestFunc {
25 int type;
26 int32_t (*Func)(const struct TimerTest *test);
27 };
28
TimerTestcaseCb(uint32_t number)29 static int32_t TimerTestcaseCb(uint32_t number)
30 {
31 static uint16_t num = 0;
32 num++;
33 if (num >= TIMER_TEST_PERIOD_TIMES) {
34 HDF_LOGD("->>>>>>>>>>>%s:num exceed max %d", __func__, number);
35 g_theard2Flag = true;
36 num = 0;
37 }
38 return HDF_SUCCESS;
39 }
40
TimerTestcaseOnceCb(uint32_t number)41 static int32_t TimerTestcaseOnceCb(uint32_t number)
42 {
43 HDF_LOGD("->>>>>>>>>>>%s:%d", __func__, number);
44 g_theard1Flag = true;
45 return HDF_SUCCESS;
46 }
47
TimerSetTest(const struct TimerTest * test)48 static int32_t TimerSetTest(const struct TimerTest *test)
49 {
50 if (test == NULL || test->handle == NULL) {
51 HDF_LOGE("%s: test null", __func__);
52 return HDF_ERR_INVALID_OBJECT;
53 }
54
55 HwTimerSet(test->handle, test->uSecond, TimerTestcaseCb);
56 return HDF_SUCCESS;
57 }
58
TimerSetOnceTest(const struct TimerTest * test)59 static int32_t TimerSetOnceTest(const struct TimerTest *test)
60 {
61 if (test == NULL || test->handle == NULL) {
62 HDF_LOGE("%s: test null", __func__);
63 return HDF_ERR_INVALID_OBJECT;
64 }
65
66 HwTimerSetOnce(test->handle, test->uSecond, TimerTestcaseOnceCb);
67 return HDF_SUCCESS;
68 }
69
TimerGetTest(const struct TimerTest * test)70 static int32_t TimerGetTest(const struct TimerTest *test)
71 {
72 if (test == NULL || test->handle == NULL) {
73 HDF_LOGE("%s: test null", __func__);
74 return HDF_ERR_INVALID_OBJECT;
75 }
76
77 uint32_t uSecond;
78 bool isPeriod;
79
80 if (HwTimerGet(test->handle, &uSecond, &isPeriod) != HDF_SUCCESS) {
81 HDF_LOGE("func: %s, TimerGet dailed", __func__);
82 return HDF_FAILURE;
83 }
84
85 HDF_LOGD("%s:[%u][%d]", __func__, uSecond, isPeriod);
86 return HDF_SUCCESS;
87 }
88
TimerStartTest(const struct TimerTest * test)89 static int32_t TimerStartTest(const struct TimerTest *test)
90 {
91 if (test == NULL || test->handle == NULL) {
92 HDF_LOGE("%s: test null", __func__);
93 return HDF_ERR_INVALID_OBJECT;
94 }
95
96 HwTimerStart(test->handle);
97 return HDF_SUCCESS;
98 }
99
TimerStopTest(const struct TimerTest * test)100 static int32_t TimerStopTest(const struct TimerTest *test)
101 {
102 if (test == NULL || test->handle == NULL) {
103 HDF_LOGE("%s: test null", __func__);
104 return HDF_ERR_INVALID_OBJECT;
105 }
106
107 HwTimerStop(test->handle);
108 return HDF_SUCCESS;
109 }
110
TimerOnceTestThreadFunc(void * param)111 static int TimerOnceTestThreadFunc(void *param)
112 {
113 DevHandle handle = (DevHandle)param;
114 if (handle == NULL) {
115 HDF_LOGE("%s: timer test get handle fail", __func__);
116 g_theard1Flag = true;
117 return HDF_FAILURE;
118 }
119
120 if (HwTimerSetOnce(handle, TIMER_TEST_TIME_USECONDS, TimerTestcaseOnceCb) != HDF_SUCCESS) {
121 HDF_LOGE("%s: TimerSetOnce fail", __func__);
122 g_theard1Flag = true;
123 return HDF_FAILURE;
124 }
125 if (HwTimerStart(handle) != HDF_SUCCESS) {
126 HDF_LOGE("%s: HwTimerStart fail", __func__);
127 g_theard1Flag = true;
128 return HDF_FAILURE;
129 }
130 return HDF_SUCCESS;
131 }
132
TimerPeriodTestThreadFunc(void * param)133 static int TimerPeriodTestThreadFunc(void *param)
134 {
135 DevHandle handle = (DevHandle)param;
136 if (handle == NULL) {
137 HDF_LOGE("%s: timer test get handle fail", __func__);
138 g_theard2Flag = true;
139 return HDF_FAILURE;
140 }
141
142 if (HwTimerSet(handle, TIMER_TEST_TIME_USECONDS, TimerTestcaseCb) != HDF_SUCCESS) {
143 HDF_LOGE("%s: TimerSet fail", __func__);
144 g_theard2Flag = true;
145 return HDF_FAILURE;
146 }
147 if (HwTimerStart(handle) != HDF_SUCCESS) {
148 HDF_LOGE("%s: HwTimerStart fail", __func__);
149 g_theard2Flag = true;
150 return HDF_FAILURE;
151 }
152 return HDF_SUCCESS;
153 }
154
TimerTestStartThread(struct OsalThread * thread1,struct OsalThread * thread2)155 static int32_t TimerTestStartThread(struct OsalThread *thread1, struct OsalThread *thread2)
156 {
157 int32_t ret;
158 uint32_t time = 0;
159 struct OsalThreadParam cfg1;
160 struct OsalThreadParam cfg2;
161
162 if (memset_s(&cfg1, sizeof(cfg1), 0, sizeof(cfg1)) != EOK ||
163 memset_s(&cfg2, sizeof(cfg2), 0, sizeof(cfg2)) != EOK) {
164 HDF_LOGE("%s:memset_s fail.", __func__);
165 return HDF_ERR_IO;
166 }
167
168 cfg1.name = "TimerTestThread-once";
169 cfg2.name = "TimerTestThread-period";
170 cfg1.priority = cfg2.priority = OSAL_THREAD_PRI_DEFAULT;
171 cfg1.stackSize = cfg2.stackSize = TIMER_TEST_STACK_SIZE;
172
173 ret = OsalThreadStart(thread1, &cfg1);
174 if (ret != HDF_SUCCESS) {
175 HDF_LOGE("testing start timer thread1 failed:%d", ret);
176 return ret;
177 }
178
179 ret = OsalThreadStart(thread2, &cfg2);
180 if (ret != HDF_SUCCESS) {
181 HDF_LOGE("testing start timer thread2 failed:%d", ret);
182 }
183
184 while (g_theard1Flag == false || g_theard2Flag == false) {
185 HDF_LOGD("[%d]waitting testing timer thread finish...", time);
186 OsalSleep(TIMER_TEST_WAIT_TIMEOUT);
187 time++;
188 if (time > TIMER_TEST_WAIT_TIMES) {
189 break;
190 }
191 }
192 return ret;
193 }
194
TimerTestCreateThread(struct OsalThread * thread1,struct OsalThread * thread2,DevHandle handle1,DevHandle handle2)195 static int32_t TimerTestCreateThread(struct OsalThread *thread1, struct OsalThread *thread2,
196 DevHandle handle1, DevHandle handle2)
197 {
198 int32_t ret;
199
200 ret = OsalThreadCreate(thread1, (OsalThreadEntry)TimerOnceTestThreadFunc, (void *)handle1);
201 if (ret != HDF_SUCCESS) {
202 HDF_LOGE("create test once timer failed:%d", ret);
203 return ret;
204 }
205
206 ret = OsalThreadCreate(thread2, (OsalThreadEntry)TimerPeriodTestThreadFunc, (void *)handle2);
207 if (ret != HDF_SUCCESS) {
208 HDF_LOGE("create test period timer failed:%d", ret);
209 return ret;
210 }
211
212 return HDF_SUCCESS;
213 }
214
MultiThreadSourceRecycle(struct OsalThread * thread1,struct OsalThread * thread2,DevHandle handle1,DevHandle handle2)215 static void MultiThreadSourceRecycle(struct OsalThread *thread1, struct OsalThread *thread2,
216 DevHandle handle1, DevHandle handle2)
217 {
218 if (handle1 != NULL) {
219 HwTimerClose(handle1);
220 handle1 = NULL;
221 }
222
223 if (handle2 != NULL) {
224 HwTimerClose(handle2);
225 handle2 = NULL;
226 }
227
228 if (thread1->realThread != NULL) {
229 (void)OsalThreadDestroy(thread1);
230 }
231
232 if (thread2->realThread != NULL) {
233 (void)OsalThreadDestroy(thread2);
234 }
235
236 g_theard1Flag = false;
237 g_theard2Flag = false;
238 }
239
TimerTestMultiThread(const struct TimerTest * test)240 static int32_t TimerTestMultiThread(const struct TimerTest *test)
241 {
242 int32_t ret;
243 struct OsalThread thread1;
244 struct OsalThread thread2;
245 DevHandle handle1 = NULL;
246 DevHandle handle2 = NULL;
247 thread1.realThread = NULL;
248 thread2.realThread = NULL;
249
250 if (test == NULL) {
251 HDF_LOGE("%s: timer test NULL", __func__);
252 return HDF_FAILURE;
253 }
254
255 handle1 = HwTimerOpen(TIMER_TEST_TIME_ID_THREAD1);
256 if (handle1 == NULL) {
257 HDF_LOGE("%s: timer test get handle1 failed", __func__);
258 MultiThreadSourceRecycle(&thread1, &thread2, handle1, handle2);
259 return HDF_FAILURE;
260 }
261
262 handle2 = HwTimerOpen(TIMER_TEST_TIME_ID_THREAD2);
263 if (handle2 == NULL) {
264 HDF_LOGE("%s: timer test get handle2 failed", __func__);
265 MultiThreadSourceRecycle(&thread1, &thread2, handle1, handle2);
266 return HDF_FAILURE;
267 }
268
269 ret = TimerTestCreateThread(&thread1, &thread2, handle1, handle2);
270 if (ret != HDF_SUCCESS) {
271 HDF_LOGE("%s: timer test create thread failed", __func__);
272 MultiThreadSourceRecycle(&thread1, &thread2, handle1, handle2);
273 return ret;
274 }
275
276 ret = TimerTestStartThread(&thread1, &thread2);
277 if (ret != HDF_SUCCESS) {
278 HDF_LOGE("timer test start thread failed:%d", ret);
279 MultiThreadSourceRecycle(&thread1, &thread2, handle1, handle2);
280 return ret;
281 }
282
283 MultiThreadSourceRecycle(&thread1, &thread2, handle1, handle2);
284 return HDF_SUCCESS;
285 }
286
TimerTestReliability(const struct TimerTest * test)287 static int32_t TimerTestReliability(const struct TimerTest *test)
288 {
289 if (test == NULL || test->handle == NULL) {
290 HDF_LOGE("%s: test null", __func__);
291 return HDF_ERR_INVALID_OBJECT;
292 }
293
294 HwTimerSet(test->handle, test->uSecond, NULL);
295 HwTimerSetOnce(test->handle, test->uSecond, NULL);
296 HwTimerStart(NULL);
297 return HDF_SUCCESS;
298 }
299
TimerTestGetConfig(struct TimerTestConfig * config)300 static int32_t TimerTestGetConfig(struct TimerTestConfig *config)
301 {
302 int32_t ret;
303 struct HdfSBuf *reply = NULL;
304 struct HdfIoService *service = NULL;
305 const void *buf = NULL;
306 uint32_t len;
307
308 if (config == NULL) {
309 HDF_LOGE("%s: param null", __func__);
310 return HDF_FAILURE;
311 }
312
313 service = HdfIoServiceBind("TIMER_TEST");
314 if (service == NULL) {
315 HDF_LOGE("%s: service TIMER_TEST bind fail", __func__);
316 return HDF_ERR_NOT_SUPPORT;
317 }
318
319 reply = HdfSbufObtain(sizeof(*config) + sizeof(uint64_t));
320 if (reply == NULL) {
321 HDF_LOGE("%s: failed to obtain reply", __func__);
322 HdfIoServiceRecycle(service);
323 return HDF_ERR_MALLOC_FAIL;
324 }
325
326 ret = service->dispatcher->Dispatch(&service->object, 0, NULL, reply);
327 if (ret != HDF_SUCCESS) {
328 HDF_LOGE("%s: remote dispatch failed", __func__);
329 HdfSbufRecycle(reply);
330 HdfIoServiceRecycle(service);
331 return ret;
332 }
333
334 if (!HdfSbufReadBuffer(reply, &buf, &len)) {
335 HDF_LOGE("%s: read buf failed", __func__);
336 HdfSbufRecycle(reply);
337 HdfIoServiceRecycle(service);
338 return HDF_ERR_IO;
339 }
340
341 if (len != sizeof(*config)) {
342 HDF_LOGE("%s: config size:%zu, read size:%u", __func__, sizeof(*config), len);
343 HdfSbufRecycle(reply);
344 HdfIoServiceRecycle(service);
345 return HDF_ERR_IO;
346 }
347
348 if (memcpy_s(config, sizeof(*config), buf, sizeof(*config)) != EOK) {
349 HDF_LOGE("%s: memcpy buf failed", __func__);
350 HdfSbufRecycle(reply);
351 HdfIoServiceRecycle(service);
352 return HDF_ERR_IO;
353 }
354
355 HdfSbufRecycle(reply);
356 HdfIoServiceRecycle(service);
357 return HDF_SUCCESS;
358 }
359
TimerTestGet(void)360 static struct TimerTest *TimerTestGet(void)
361 {
362 int32_t ret;
363 static struct TimerTest tester;
364 static bool hasInit = false;
365
366 if (hasInit) {
367 return &tester;
368 }
369
370 struct TimerTestConfig config;
371 ret = TimerTestGetConfig(&config);
372 if (ret != HDF_SUCCESS) {
373 HDF_LOGE("%s: read config failed:%d", __func__, ret);
374 return NULL;
375 }
376
377 tester.number = config.number;
378 tester.uSecond = config.uSecond;
379 tester.isPeriod = config.isPeriod;
380 hasInit = true;
381 return &tester;
382 }
383
TimerIfPerformanceTest(const struct TimerTest * test)384 static int32_t TimerIfPerformanceTest(const struct TimerTest *test)
385 {
386 #ifdef __LITEOS__
387 // liteos the accuracy of the obtained time is too large and inaccurate.
388 if (test == NULL) {
389 return HDF_FAILURE;
390 }
391 return HDF_SUCCESS;
392 #endif
393
394 uint64_t startMs;
395 uint64_t endMs;
396 uint64_t useTime; // ms
397 uint32_t uSecond;
398 bool isPeriod;
399
400 startMs = OsalGetSysTimeMs();
401 HwTimerGet(test->handle, &uSecond, &isPeriod);
402 endMs = OsalGetSysTimeMs();
403
404 useTime = endMs - startMs;
405 HDF_LOGI("----->interface performance test:[start - end] < 1ms[%s]\r\n", useTime < 1 ? "yes" : "no");
406 return HDF_SUCCESS;
407 }
408
409 static struct TimerTestFunc g_timerTestFunc[] = {
410 {TIMER_TEST_SET, TimerSetTest },
411 {TIMER_TEST_SETONCE, TimerSetOnceTest },
412 {TIMER_TEST_GET, TimerGetTest },
413 {TIMER_TEST_START, TimerStartTest },
414 {TIMER_TEST_STOP, TimerStopTest },
415 {TIMER_MULTI_THREAD_TEST, TimerTestMultiThread },
416 {TIMER_RELIABILITY_TEST, TimerTestReliability },
417 {TIMER_IF_PERFORMANCE_TEST, TimerIfPerformanceTest},
418 };
419
TimerTestExecute(int cmd)420 int32_t TimerTestExecute(int cmd)
421 {
422 uint32_t i;
423 int32_t ret = HDF_ERR_NOT_SUPPORT;
424
425 if (cmd > TIMER_TEST_MAX_CMD) {
426 HDF_LOGE("%s: invalid cmd:%d", __func__, cmd);
427 return HDF_ERR_NOT_SUPPORT;
428 }
429
430 struct TimerTest *test = TimerTestGet();
431 if (test == NULL) {
432 HDF_LOGE("%s: test null cmd %d", __func__, cmd);
433 return HDF_ERR_INVALID_OBJECT;
434 }
435
436 if (cmd != TIMER_MULTI_THREAD_TEST) {
437 test->handle = HwTimerOpen(test->number);
438 if (test->handle == NULL) {
439 HDF_LOGE("%s: timer test get handle fail", __func__);
440 return HDF_FAILURE;
441 }
442 }
443
444 for (i = 0; i < sizeof(g_timerTestFunc) / sizeof(g_timerTestFunc[0]); i++) {
445 if (cmd == g_timerTestFunc[i].type && g_timerTestFunc[i].Func != NULL) {
446 ret = g_timerTestFunc[i].Func(test);
447 break;
448 }
449 }
450
451 if (cmd != TIMER_MULTI_THREAD_TEST) {
452 HwTimerClose(test->handle);
453 }
454
455 return ret;
456 }
457