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