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