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