• 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("->>>>>>>>>>>%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