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