1*437bfbebSnyanmisaka /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2*437bfbebSnyanmisaka /*
3*437bfbebSnyanmisaka * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4*437bfbebSnyanmisaka */
5*437bfbebSnyanmisaka
6*437bfbebSnyanmisaka #define MODULE_TAG "mpp_time"
7*437bfbebSnyanmisaka
8*437bfbebSnyanmisaka #include <time.h>
9*437bfbebSnyanmisaka #include <errno.h>
10*437bfbebSnyanmisaka #include <string.h>
11*437bfbebSnyanmisaka #include <sys/timerfd.h>
12*437bfbebSnyanmisaka #include <sys/epoll.h>
13*437bfbebSnyanmisaka
14*437bfbebSnyanmisaka #include "mpp_mem.h"
15*437bfbebSnyanmisaka #include "mpp_time.h"
16*437bfbebSnyanmisaka #include "mpp_debug.h"
17*437bfbebSnyanmisaka #include "mpp_common.h"
18*437bfbebSnyanmisaka #include "mpp_thread.h"
19*437bfbebSnyanmisaka
mpp_time()20*437bfbebSnyanmisaka rk_s64 mpp_time()
21*437bfbebSnyanmisaka {
22*437bfbebSnyanmisaka struct timespec time = {0, 0};
23*437bfbebSnyanmisaka
24*437bfbebSnyanmisaka clock_gettime(CLOCK_MONOTONIC, &time);
25*437bfbebSnyanmisaka return (rk_s64)time.tv_sec * 1000000 + (rk_s64)time.tv_nsec / 1000;
26*437bfbebSnyanmisaka }
27*437bfbebSnyanmisaka
mpp_time_diff(rk_s64 start,rk_s64 end,rk_s64 limit,const char * fmt)28*437bfbebSnyanmisaka void mpp_time_diff(rk_s64 start, rk_s64 end, rk_s64 limit, const char *fmt)
29*437bfbebSnyanmisaka {
30*437bfbebSnyanmisaka rk_s64 diff = end - start;
31*437bfbebSnyanmisaka
32*437bfbebSnyanmisaka if (diff >= limit)
33*437bfbebSnyanmisaka mpp_dbg(MPP_DBG_TIMING, "%s timing %lld us\n", fmt, diff);
34*437bfbebSnyanmisaka }
35*437bfbebSnyanmisaka
36*437bfbebSnyanmisaka typedef struct MppClockImpl_t {
37*437bfbebSnyanmisaka const char *check;
38*437bfbebSnyanmisaka char name[16];
39*437bfbebSnyanmisaka rk_u32 enable;
40*437bfbebSnyanmisaka rk_s64 base;
41*437bfbebSnyanmisaka rk_s64 time;
42*437bfbebSnyanmisaka rk_s64 sum;
43*437bfbebSnyanmisaka rk_s64 count;
44*437bfbebSnyanmisaka } MppClockImpl;
45*437bfbebSnyanmisaka
46*437bfbebSnyanmisaka static const char *clock_name = "mpp_clock";
47*437bfbebSnyanmisaka
check_is_mpp_clock(void * clock)48*437bfbebSnyanmisaka MPP_RET check_is_mpp_clock(void *clock)
49*437bfbebSnyanmisaka {
50*437bfbebSnyanmisaka if (clock && ((MppClockImpl*)clock)->check == clock_name)
51*437bfbebSnyanmisaka return MPP_OK;
52*437bfbebSnyanmisaka
53*437bfbebSnyanmisaka mpp_err_f("pointer %p failed on check\n", clock);
54*437bfbebSnyanmisaka mpp_abort();
55*437bfbebSnyanmisaka return MPP_NOK;
56*437bfbebSnyanmisaka }
57*437bfbebSnyanmisaka
mpp_clock_get(const char * name)58*437bfbebSnyanmisaka MppClock mpp_clock_get(const char *name)
59*437bfbebSnyanmisaka {
60*437bfbebSnyanmisaka MppClockImpl *impl = mpp_calloc(MppClockImpl, 1);
61*437bfbebSnyanmisaka
62*437bfbebSnyanmisaka if (impl) {
63*437bfbebSnyanmisaka impl->check = clock_name;
64*437bfbebSnyanmisaka snprintf(impl->name, sizeof(impl->name) - 1, name, NULL);
65*437bfbebSnyanmisaka } else
66*437bfbebSnyanmisaka mpp_err_f("malloc failed\n");
67*437bfbebSnyanmisaka
68*437bfbebSnyanmisaka return impl;
69*437bfbebSnyanmisaka }
70*437bfbebSnyanmisaka
mpp_clock_put(MppClock clock)71*437bfbebSnyanmisaka void mpp_clock_put(MppClock clock)
72*437bfbebSnyanmisaka {
73*437bfbebSnyanmisaka if (check_is_mpp_clock(clock)) {
74*437bfbebSnyanmisaka mpp_err_f("invalid clock %p\n", clock);
75*437bfbebSnyanmisaka return;
76*437bfbebSnyanmisaka }
77*437bfbebSnyanmisaka
78*437bfbebSnyanmisaka mpp_free(clock);
79*437bfbebSnyanmisaka }
80*437bfbebSnyanmisaka
mpp_clock_enable(MppClock clock,rk_u32 enable)81*437bfbebSnyanmisaka void mpp_clock_enable(MppClock clock, rk_u32 enable)
82*437bfbebSnyanmisaka {
83*437bfbebSnyanmisaka if (check_is_mpp_clock(clock)) {
84*437bfbebSnyanmisaka mpp_err_f("invalid clock %p\n", clock);
85*437bfbebSnyanmisaka } else {
86*437bfbebSnyanmisaka MppClockImpl *p = (MppClockImpl *)clock;
87*437bfbebSnyanmisaka
88*437bfbebSnyanmisaka p->enable = (enable) ? (1) : (0);
89*437bfbebSnyanmisaka }
90*437bfbebSnyanmisaka }
91*437bfbebSnyanmisaka
mpp_clock_start(MppClock clock)92*437bfbebSnyanmisaka rk_s64 mpp_clock_start(MppClock clock)
93*437bfbebSnyanmisaka {
94*437bfbebSnyanmisaka MppClockImpl *p = (MppClockImpl *)clock;
95*437bfbebSnyanmisaka
96*437bfbebSnyanmisaka if (check_is_mpp_clock(p)) {
97*437bfbebSnyanmisaka mpp_err_f("invalid clock %p\n", p);
98*437bfbebSnyanmisaka return 0;
99*437bfbebSnyanmisaka }
100*437bfbebSnyanmisaka
101*437bfbebSnyanmisaka if (!p->enable)
102*437bfbebSnyanmisaka return 0;
103*437bfbebSnyanmisaka
104*437bfbebSnyanmisaka p->base = mpp_time();
105*437bfbebSnyanmisaka p->time = 0;
106*437bfbebSnyanmisaka return p->base;
107*437bfbebSnyanmisaka }
108*437bfbebSnyanmisaka
mpp_clock_pause(MppClock clock)109*437bfbebSnyanmisaka rk_s64 mpp_clock_pause(MppClock clock)
110*437bfbebSnyanmisaka {
111*437bfbebSnyanmisaka MppClockImpl *p = (MppClockImpl *)clock;
112*437bfbebSnyanmisaka rk_s64 time;
113*437bfbebSnyanmisaka
114*437bfbebSnyanmisaka if (check_is_mpp_clock(p)) {
115*437bfbebSnyanmisaka mpp_err_f("invalid clock %p\n", p);
116*437bfbebSnyanmisaka return 0;
117*437bfbebSnyanmisaka }
118*437bfbebSnyanmisaka
119*437bfbebSnyanmisaka if (!p->enable)
120*437bfbebSnyanmisaka return 0;
121*437bfbebSnyanmisaka
122*437bfbebSnyanmisaka time = mpp_time();
123*437bfbebSnyanmisaka
124*437bfbebSnyanmisaka if (!p->time) {
125*437bfbebSnyanmisaka // first pause after start
126*437bfbebSnyanmisaka p->sum += time - p->base;
127*437bfbebSnyanmisaka p->count++;
128*437bfbebSnyanmisaka }
129*437bfbebSnyanmisaka
130*437bfbebSnyanmisaka p->time = time;
131*437bfbebSnyanmisaka
132*437bfbebSnyanmisaka return p->time - p->base;
133*437bfbebSnyanmisaka }
134*437bfbebSnyanmisaka
mpp_clock_reset(MppClock clock)135*437bfbebSnyanmisaka rk_s64 mpp_clock_reset(MppClock clock)
136*437bfbebSnyanmisaka {
137*437bfbebSnyanmisaka MppClockImpl *p = (MppClockImpl *)clock;
138*437bfbebSnyanmisaka
139*437bfbebSnyanmisaka if (check_is_mpp_clock(p)) {
140*437bfbebSnyanmisaka mpp_err_f("invalid clock %p\n", p);
141*437bfbebSnyanmisaka } else {
142*437bfbebSnyanmisaka p->base = 0;
143*437bfbebSnyanmisaka p->time = 0;
144*437bfbebSnyanmisaka p->sum = 0;
145*437bfbebSnyanmisaka p->count = 0;
146*437bfbebSnyanmisaka }
147*437bfbebSnyanmisaka
148*437bfbebSnyanmisaka return 0;
149*437bfbebSnyanmisaka }
150*437bfbebSnyanmisaka
mpp_clock_get_sum(MppClock clock)151*437bfbebSnyanmisaka rk_s64 mpp_clock_get_sum(MppClock clock)
152*437bfbebSnyanmisaka {
153*437bfbebSnyanmisaka MppClockImpl *p = (MppClockImpl *)clock;
154*437bfbebSnyanmisaka
155*437bfbebSnyanmisaka if (check_is_mpp_clock(p)) {
156*437bfbebSnyanmisaka mpp_err_f("invalid clock %p\n", p);
157*437bfbebSnyanmisaka return 0;
158*437bfbebSnyanmisaka }
159*437bfbebSnyanmisaka
160*437bfbebSnyanmisaka return (p->enable) ? (p->sum) : (0);
161*437bfbebSnyanmisaka }
162*437bfbebSnyanmisaka
mpp_clock_get_count(MppClock clock)163*437bfbebSnyanmisaka rk_s64 mpp_clock_get_count(MppClock clock)
164*437bfbebSnyanmisaka {
165*437bfbebSnyanmisaka MppClockImpl *p = (MppClockImpl *)clock;
166*437bfbebSnyanmisaka
167*437bfbebSnyanmisaka if (check_is_mpp_clock(p)) {
168*437bfbebSnyanmisaka mpp_err_f("invalid clock %p\n", p);
169*437bfbebSnyanmisaka return 0;
170*437bfbebSnyanmisaka }
171*437bfbebSnyanmisaka
172*437bfbebSnyanmisaka return (p->enable) ? (p->count) : (0);
173*437bfbebSnyanmisaka }
174*437bfbebSnyanmisaka
mpp_clock_get_name(MppClock clock)175*437bfbebSnyanmisaka const char *mpp_clock_get_name(MppClock clock)
176*437bfbebSnyanmisaka {
177*437bfbebSnyanmisaka MppClockImpl *p = (MppClockImpl *)clock;
178*437bfbebSnyanmisaka
179*437bfbebSnyanmisaka if (check_is_mpp_clock(p)) {
180*437bfbebSnyanmisaka mpp_err_f("invalid clock %p\n", p);
181*437bfbebSnyanmisaka return NULL;
182*437bfbebSnyanmisaka }
183*437bfbebSnyanmisaka
184*437bfbebSnyanmisaka return p->name;
185*437bfbebSnyanmisaka }
186*437bfbebSnyanmisaka
187*437bfbebSnyanmisaka typedef struct MppTimerImpl_t {
188*437bfbebSnyanmisaka const char *check;
189*437bfbebSnyanmisaka char name[16];
190*437bfbebSnyanmisaka
191*437bfbebSnyanmisaka rk_s32 enabled;
192*437bfbebSnyanmisaka rk_s32 initial;
193*437bfbebSnyanmisaka rk_s32 interval;
194*437bfbebSnyanmisaka rk_s32 timer_fd;
195*437bfbebSnyanmisaka rk_s32 epoll_fd;
196*437bfbebSnyanmisaka
197*437bfbebSnyanmisaka MppThread *thd;
198*437bfbebSnyanmisaka MppThreadFunc func;
199*437bfbebSnyanmisaka void *ctx;
200*437bfbebSnyanmisaka } MppTimerImpl;
201*437bfbebSnyanmisaka
202*437bfbebSnyanmisaka static const char *timer_name = "mpp_timer";
203*437bfbebSnyanmisaka
check_is_mpp_timer(void * timer)204*437bfbebSnyanmisaka MPP_RET check_is_mpp_timer(void *timer)
205*437bfbebSnyanmisaka {
206*437bfbebSnyanmisaka if (timer && ((MppTimerImpl*)timer)->check == timer_name)
207*437bfbebSnyanmisaka return MPP_OK;
208*437bfbebSnyanmisaka
209*437bfbebSnyanmisaka mpp_err_f("pointer %p failed on check\n", timer);
210*437bfbebSnyanmisaka mpp_abort();
211*437bfbebSnyanmisaka return MPP_NOK;
212*437bfbebSnyanmisaka }
213*437bfbebSnyanmisaka
mpp_timer_thread(void * ctx)214*437bfbebSnyanmisaka static void *mpp_timer_thread(void *ctx)
215*437bfbebSnyanmisaka {
216*437bfbebSnyanmisaka struct itimerspec ts;
217*437bfbebSnyanmisaka MppTimerImpl *impl = (MppTimerImpl *)ctx;
218*437bfbebSnyanmisaka MppThread *thd = impl->thd;
219*437bfbebSnyanmisaka rk_s32 timer_fd = impl->timer_fd;
220*437bfbebSnyanmisaka rk_s32 ret = 0;
221*437bfbebSnyanmisaka
222*437bfbebSnyanmisaka // first expire time
223*437bfbebSnyanmisaka ts.it_value.tv_sec = impl->initial / 1000;
224*437bfbebSnyanmisaka ts.it_value.tv_nsec = (impl->initial % 1000) * 1000;
225*437bfbebSnyanmisaka
226*437bfbebSnyanmisaka // last expire time
227*437bfbebSnyanmisaka ts.it_interval.tv_sec = impl->interval / 1000;
228*437bfbebSnyanmisaka ts.it_interval.tv_nsec = (impl->interval % 1000) * 1000 * 1000;
229*437bfbebSnyanmisaka
230*437bfbebSnyanmisaka ret = timerfd_settime(timer_fd, 0, &ts, NULL);
231*437bfbebSnyanmisaka if (ret < 0) {
232*437bfbebSnyanmisaka mpp_err("timerfd_settime error, Error:[%d:%s]", errno, strerror(errno));
233*437bfbebSnyanmisaka return NULL;
234*437bfbebSnyanmisaka }
235*437bfbebSnyanmisaka
236*437bfbebSnyanmisaka while (1) {
237*437bfbebSnyanmisaka struct epoll_event events;
238*437bfbebSnyanmisaka rk_s32 fd_cnt;
239*437bfbebSnyanmisaka
240*437bfbebSnyanmisaka if (MPP_THREAD_RUNNING != mpp_thread_get_status(thd, THREAD_WORK))
241*437bfbebSnyanmisaka break;
242*437bfbebSnyanmisaka
243*437bfbebSnyanmisaka memset(&events, 0, sizeof(events));
244*437bfbebSnyanmisaka
245*437bfbebSnyanmisaka /* wait epoll event */
246*437bfbebSnyanmisaka fd_cnt = epoll_wait(impl->epoll_fd, &events, 1, 500);
247*437bfbebSnyanmisaka if (fd_cnt && (events.events & EPOLLIN) && (events.data.fd == timer_fd)) {
248*437bfbebSnyanmisaka rk_u64 exp = 0;
249*437bfbebSnyanmisaka ssize_t cnt = read(timer_fd, &exp, sizeof(exp));
250*437bfbebSnyanmisaka
251*437bfbebSnyanmisaka mpp_assert(cnt == sizeof(exp));
252*437bfbebSnyanmisaka impl->func(impl->ctx);
253*437bfbebSnyanmisaka }
254*437bfbebSnyanmisaka }
255*437bfbebSnyanmisaka
256*437bfbebSnyanmisaka return NULL;
257*437bfbebSnyanmisaka }
258*437bfbebSnyanmisaka
mpp_timer_get(const char * name)259*437bfbebSnyanmisaka MppTimer mpp_timer_get(const char *name)
260*437bfbebSnyanmisaka {
261*437bfbebSnyanmisaka MppTimerImpl *impl = NULL;
262*437bfbebSnyanmisaka rk_s32 timer_fd = -1;
263*437bfbebSnyanmisaka rk_s32 epoll_fd = -1;
264*437bfbebSnyanmisaka
265*437bfbebSnyanmisaka do {
266*437bfbebSnyanmisaka struct epoll_event event;
267*437bfbebSnyanmisaka
268*437bfbebSnyanmisaka impl = mpp_calloc(MppTimerImpl, 1);
269*437bfbebSnyanmisaka if (!impl) {
270*437bfbebSnyanmisaka mpp_err_f("malloc failed\n");
271*437bfbebSnyanmisaka break;
272*437bfbebSnyanmisaka }
273*437bfbebSnyanmisaka
274*437bfbebSnyanmisaka timer_fd = timerfd_create(CLOCK_REALTIME, 0);
275*437bfbebSnyanmisaka if (timer_fd < 0)
276*437bfbebSnyanmisaka break;
277*437bfbebSnyanmisaka
278*437bfbebSnyanmisaka epoll_fd = epoll_create(1);
279*437bfbebSnyanmisaka if (epoll_fd < 0)
280*437bfbebSnyanmisaka break;
281*437bfbebSnyanmisaka
282*437bfbebSnyanmisaka memset(&event, 0, sizeof(event));
283*437bfbebSnyanmisaka event.data.fd = timer_fd;
284*437bfbebSnyanmisaka event.events = EPOLLIN | EPOLLET;
285*437bfbebSnyanmisaka
286*437bfbebSnyanmisaka if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, timer_fd, &event) < 0)
287*437bfbebSnyanmisaka break;
288*437bfbebSnyanmisaka
289*437bfbebSnyanmisaka impl->timer_fd = timer_fd;
290*437bfbebSnyanmisaka impl->epoll_fd = epoll_fd;
291*437bfbebSnyanmisaka /* default 1 second (1000ms) looper */
292*437bfbebSnyanmisaka impl->initial = 1000;
293*437bfbebSnyanmisaka impl->interval = 1000;
294*437bfbebSnyanmisaka impl->check = timer_name;
295*437bfbebSnyanmisaka snprintf(impl->name, sizeof(impl->name) - 1, name, NULL);
296*437bfbebSnyanmisaka
297*437bfbebSnyanmisaka return impl;
298*437bfbebSnyanmisaka } while (0);
299*437bfbebSnyanmisaka
300*437bfbebSnyanmisaka mpp_err_f("failed to create timer\n");
301*437bfbebSnyanmisaka
302*437bfbebSnyanmisaka if (impl) {
303*437bfbebSnyanmisaka mpp_free(impl);
304*437bfbebSnyanmisaka impl = NULL;
305*437bfbebSnyanmisaka }
306*437bfbebSnyanmisaka
307*437bfbebSnyanmisaka if (timer_fd >= 0) {
308*437bfbebSnyanmisaka close(timer_fd);
309*437bfbebSnyanmisaka timer_fd = -1;
310*437bfbebSnyanmisaka }
311*437bfbebSnyanmisaka
312*437bfbebSnyanmisaka if (epoll_fd >= 0) {
313*437bfbebSnyanmisaka close(epoll_fd);
314*437bfbebSnyanmisaka epoll_fd = -1;
315*437bfbebSnyanmisaka }
316*437bfbebSnyanmisaka
317*437bfbebSnyanmisaka return NULL;
318*437bfbebSnyanmisaka }
319*437bfbebSnyanmisaka
mpp_timer_set_callback(MppTimer timer,MppThreadFunc func,void * ctx)320*437bfbebSnyanmisaka void mpp_timer_set_callback(MppTimer timer, MppThreadFunc func, void *ctx)
321*437bfbebSnyanmisaka {
322*437bfbebSnyanmisaka MppTimerImpl *impl = (MppTimerImpl *)timer;
323*437bfbebSnyanmisaka
324*437bfbebSnyanmisaka if (check_is_mpp_timer(impl)) {
325*437bfbebSnyanmisaka mpp_err_f("invalid timer %p\n", impl);
326*437bfbebSnyanmisaka return;
327*437bfbebSnyanmisaka }
328*437bfbebSnyanmisaka
329*437bfbebSnyanmisaka if (!func) {
330*437bfbebSnyanmisaka mpp_err_f("invalid NULL callback\n");
331*437bfbebSnyanmisaka return;
332*437bfbebSnyanmisaka }
333*437bfbebSnyanmisaka
334*437bfbebSnyanmisaka impl->func = func;
335*437bfbebSnyanmisaka impl->ctx = ctx;
336*437bfbebSnyanmisaka }
337*437bfbebSnyanmisaka
mpp_timer_set_timing(MppTimer timer,rk_s32 initial,rk_s32 interval)338*437bfbebSnyanmisaka void mpp_timer_set_timing(MppTimer timer, rk_s32 initial, rk_s32 interval)
339*437bfbebSnyanmisaka {
340*437bfbebSnyanmisaka MppTimerImpl *impl = (MppTimerImpl *)timer;
341*437bfbebSnyanmisaka
342*437bfbebSnyanmisaka if (check_is_mpp_timer(impl)) {
343*437bfbebSnyanmisaka mpp_err_f("invalid timer %p\n", impl);
344*437bfbebSnyanmisaka return;
345*437bfbebSnyanmisaka }
346*437bfbebSnyanmisaka
347*437bfbebSnyanmisaka impl->initial = initial;
348*437bfbebSnyanmisaka impl->interval = interval;
349*437bfbebSnyanmisaka }
350*437bfbebSnyanmisaka
mpp_timer_set_enable(MppTimer timer,rk_s32 enable)351*437bfbebSnyanmisaka void mpp_timer_set_enable(MppTimer timer, rk_s32 enable)
352*437bfbebSnyanmisaka {
353*437bfbebSnyanmisaka MppTimerImpl *impl = (MppTimerImpl *)timer;
354*437bfbebSnyanmisaka
355*437bfbebSnyanmisaka if (check_is_mpp_timer(impl)) {
356*437bfbebSnyanmisaka mpp_err_f("invalid timer %p\n", impl);
357*437bfbebSnyanmisaka return;
358*437bfbebSnyanmisaka }
359*437bfbebSnyanmisaka
360*437bfbebSnyanmisaka if (!impl->func || impl->initial < 0 || impl->interval < 0) {
361*437bfbebSnyanmisaka mpp_err_f("invalid func %p initial %d interval %d\n",
362*437bfbebSnyanmisaka impl->func, impl->initial, impl->interval);
363*437bfbebSnyanmisaka return;
364*437bfbebSnyanmisaka }
365*437bfbebSnyanmisaka
366*437bfbebSnyanmisaka if (enable) {
367*437bfbebSnyanmisaka if (!impl->enabled && !impl->thd) {
368*437bfbebSnyanmisaka MppThread *thd = mpp_thread_create(mpp_timer_thread, impl, impl->name);
369*437bfbebSnyanmisaka
370*437bfbebSnyanmisaka if (thd) {
371*437bfbebSnyanmisaka impl->thd = thd;
372*437bfbebSnyanmisaka impl->enabled = 1;
373*437bfbebSnyanmisaka mpp_thread_start(impl->thd);
374*437bfbebSnyanmisaka }
375*437bfbebSnyanmisaka }
376*437bfbebSnyanmisaka } else {
377*437bfbebSnyanmisaka if (impl->enabled && impl->thd) {
378*437bfbebSnyanmisaka mpp_thread_stop(impl->thd);
379*437bfbebSnyanmisaka impl->enabled = 0;
380*437bfbebSnyanmisaka }
381*437bfbebSnyanmisaka }
382*437bfbebSnyanmisaka }
383*437bfbebSnyanmisaka
mpp_timer_put(MppTimer timer)384*437bfbebSnyanmisaka void mpp_timer_put(MppTimer timer)
385*437bfbebSnyanmisaka {
386*437bfbebSnyanmisaka MppTimerImpl *impl = (MppTimerImpl *)timer;
387*437bfbebSnyanmisaka
388*437bfbebSnyanmisaka if (check_is_mpp_timer(impl)) {
389*437bfbebSnyanmisaka mpp_err_f("invalid timer %p\n", impl);
390*437bfbebSnyanmisaka return;
391*437bfbebSnyanmisaka }
392*437bfbebSnyanmisaka
393*437bfbebSnyanmisaka if (impl->enabled)
394*437bfbebSnyanmisaka mpp_timer_set_enable(impl, 0);
395*437bfbebSnyanmisaka
396*437bfbebSnyanmisaka if (impl->timer_fd >= 0) {
397*437bfbebSnyanmisaka close(impl->timer_fd);
398*437bfbebSnyanmisaka impl->timer_fd = -1;
399*437bfbebSnyanmisaka }
400*437bfbebSnyanmisaka
401*437bfbebSnyanmisaka if (impl->epoll_fd >= 0) {
402*437bfbebSnyanmisaka close(impl->epoll_fd);
403*437bfbebSnyanmisaka impl->epoll_fd = -1;
404*437bfbebSnyanmisaka }
405*437bfbebSnyanmisaka
406*437bfbebSnyanmisaka if (impl->thd) {
407*437bfbebSnyanmisaka mpp_thread_destroy(impl->thd);
408*437bfbebSnyanmisaka impl->thd = NULL;
409*437bfbebSnyanmisaka }
410*437bfbebSnyanmisaka
411*437bfbebSnyanmisaka if (impl) {
412*437bfbebSnyanmisaka mpp_free(impl);
413*437bfbebSnyanmisaka impl = NULL;
414*437bfbebSnyanmisaka }
415*437bfbebSnyanmisaka }
416*437bfbebSnyanmisaka
417*437bfbebSnyanmisaka #define STOPWATCH_TRACE_STR_LEN 64
418*437bfbebSnyanmisaka
419*437bfbebSnyanmisaka typedef struct MppStopwatchNode_t {
420*437bfbebSnyanmisaka char event[STOPWATCH_TRACE_STR_LEN];
421*437bfbebSnyanmisaka rk_s64 time;
422*437bfbebSnyanmisaka } MppStopwatchNode;
423*437bfbebSnyanmisaka
424*437bfbebSnyanmisaka typedef struct MppStopwatchImpl_t {
425*437bfbebSnyanmisaka const char *check;
426*437bfbebSnyanmisaka char name[STOPWATCH_TRACE_STR_LEN];
427*437bfbebSnyanmisaka
428*437bfbebSnyanmisaka rk_s32 max_count;
429*437bfbebSnyanmisaka rk_s32 filled_count;
430*437bfbebSnyanmisaka rk_s32 show_on_exit;
431*437bfbebSnyanmisaka rk_s32 log_len;
432*437bfbebSnyanmisaka rk_s64 time_elipsed;
433*437bfbebSnyanmisaka
434*437bfbebSnyanmisaka MppStopwatchNode *nodes;
435*437bfbebSnyanmisaka } MppStopwatchImpl;
436*437bfbebSnyanmisaka
437*437bfbebSnyanmisaka static const char *stopwatch_name = "mpp_stopwatch";
438*437bfbebSnyanmisaka
check_is_mpp_stopwatch(void * stopwatch)439*437bfbebSnyanmisaka MPP_RET check_is_mpp_stopwatch(void *stopwatch)
440*437bfbebSnyanmisaka {
441*437bfbebSnyanmisaka if (stopwatch && ((MppStopwatchImpl*)stopwatch)->check == stopwatch_name)
442*437bfbebSnyanmisaka return MPP_OK;
443*437bfbebSnyanmisaka
444*437bfbebSnyanmisaka mpp_err_f("pointer %p failed on check\n", stopwatch);
445*437bfbebSnyanmisaka mpp_abort();
446*437bfbebSnyanmisaka return MPP_NOK;
447*437bfbebSnyanmisaka }
448*437bfbebSnyanmisaka
mpp_stopwatch_get(const char * name)449*437bfbebSnyanmisaka MppStopwatch mpp_stopwatch_get(const char *name)
450*437bfbebSnyanmisaka {
451*437bfbebSnyanmisaka MppStopwatchImpl *impl = mpp_calloc(MppStopwatchImpl, 1);
452*437bfbebSnyanmisaka MppStopwatchNode *nodes = mpp_calloc(MppStopwatchNode, 8);
453*437bfbebSnyanmisaka
454*437bfbebSnyanmisaka if (impl && nodes) {
455*437bfbebSnyanmisaka impl->check = stopwatch_name;
456*437bfbebSnyanmisaka snprintf(impl->name, sizeof(impl->name) - 1, name, NULL);
457*437bfbebSnyanmisaka impl->nodes = nodes;
458*437bfbebSnyanmisaka impl->max_count = 8;
459*437bfbebSnyanmisaka } else {
460*437bfbebSnyanmisaka mpp_err_f("malloc failed\n");
461*437bfbebSnyanmisaka MPP_FREE(impl);
462*437bfbebSnyanmisaka MPP_FREE(nodes);
463*437bfbebSnyanmisaka }
464*437bfbebSnyanmisaka
465*437bfbebSnyanmisaka return impl;
466*437bfbebSnyanmisaka }
467*437bfbebSnyanmisaka
mpp_stopwatch_set_show_on_exit(MppStopwatch stopwatch,rk_s32 show_on_exit)468*437bfbebSnyanmisaka void mpp_stopwatch_set_show_on_exit(MppStopwatch stopwatch, rk_s32 show_on_exit)
469*437bfbebSnyanmisaka {
470*437bfbebSnyanmisaka MppStopwatchImpl *impl = (MppStopwatchImpl *)stopwatch;
471*437bfbebSnyanmisaka
472*437bfbebSnyanmisaka if (check_is_mpp_stopwatch(impl)) {
473*437bfbebSnyanmisaka mpp_err_f("invalid stopwatch %p\n", impl);
474*437bfbebSnyanmisaka return;
475*437bfbebSnyanmisaka }
476*437bfbebSnyanmisaka
477*437bfbebSnyanmisaka impl->show_on_exit = show_on_exit;
478*437bfbebSnyanmisaka }
479*437bfbebSnyanmisaka
mpp_stopwatch_record(MppStopwatch stopwatch,const char * event)480*437bfbebSnyanmisaka void mpp_stopwatch_record(MppStopwatch stopwatch, const char *event)
481*437bfbebSnyanmisaka {
482*437bfbebSnyanmisaka MppStopwatchImpl *impl = (MppStopwatchImpl *)stopwatch;
483*437bfbebSnyanmisaka
484*437bfbebSnyanmisaka /* do not print noisy log */
485*437bfbebSnyanmisaka if (!impl)
486*437bfbebSnyanmisaka return;
487*437bfbebSnyanmisaka
488*437bfbebSnyanmisaka if (check_is_mpp_stopwatch(impl)) {
489*437bfbebSnyanmisaka mpp_err_f("invalid stopwatch %p on %s\n", impl, event);
490*437bfbebSnyanmisaka return;
491*437bfbebSnyanmisaka }
492*437bfbebSnyanmisaka
493*437bfbebSnyanmisaka if (impl->filled_count >= impl->max_count) {
494*437bfbebSnyanmisaka rk_s32 max_count = impl->max_count * 2;
495*437bfbebSnyanmisaka MppStopwatchNode *nodes = mpp_realloc(impl->nodes, MppStopwatchNode,
496*437bfbebSnyanmisaka max_count);
497*437bfbebSnyanmisaka
498*437bfbebSnyanmisaka if (nodes) {
499*437bfbebSnyanmisaka impl->nodes = nodes;
500*437bfbebSnyanmisaka impl->max_count = max_count;
501*437bfbebSnyanmisaka }
502*437bfbebSnyanmisaka }
503*437bfbebSnyanmisaka
504*437bfbebSnyanmisaka if (impl->filled_count < impl->max_count) {
505*437bfbebSnyanmisaka MppStopwatchNode *node = impl->nodes + impl->filled_count;
506*437bfbebSnyanmisaka
507*437bfbebSnyanmisaka node->time = mpp_time();
508*437bfbebSnyanmisaka if (event) {
509*437bfbebSnyanmisaka rk_s32 len = snprintf(node->event, sizeof(node->event) - 1, "%s", event);
510*437bfbebSnyanmisaka
511*437bfbebSnyanmisaka if (len > impl->log_len)
512*437bfbebSnyanmisaka impl->log_len = len;
513*437bfbebSnyanmisaka }
514*437bfbebSnyanmisaka impl->filled_count++;
515*437bfbebSnyanmisaka }
516*437bfbebSnyanmisaka }
517*437bfbebSnyanmisaka
mpp_stopwatch_put(MppStopwatch stopwatch)518*437bfbebSnyanmisaka void mpp_stopwatch_put(MppStopwatch stopwatch)
519*437bfbebSnyanmisaka {
520*437bfbebSnyanmisaka MppStopwatchImpl *impl = (MppStopwatchImpl *)stopwatch;
521*437bfbebSnyanmisaka
522*437bfbebSnyanmisaka if (check_is_mpp_stopwatch(impl)) {
523*437bfbebSnyanmisaka mpp_err_f("invalid stopwatch %p\n", impl);
524*437bfbebSnyanmisaka return;
525*437bfbebSnyanmisaka }
526*437bfbebSnyanmisaka
527*437bfbebSnyanmisaka if (impl->show_on_exit && impl->nodes && impl->filled_count) {
528*437bfbebSnyanmisaka MppStopwatchNode *node = impl->nodes;
529*437bfbebSnyanmisaka rk_s64 last_time = node->time;
530*437bfbebSnyanmisaka rk_s32 i;
531*437bfbebSnyanmisaka char fmt[32];
532*437bfbebSnyanmisaka
533*437bfbebSnyanmisaka snprintf(fmt, sizeof(fmt) - 1, "%%s %%-%ds: %%6.2f\n", impl->log_len);
534*437bfbebSnyanmisaka node++;
535*437bfbebSnyanmisaka
536*437bfbebSnyanmisaka for (i = 1; i < impl->filled_count; i++) {
537*437bfbebSnyanmisaka mpp_log(fmt, impl->name, node->event,
538*437bfbebSnyanmisaka (float)(node->time - last_time) / 1000);
539*437bfbebSnyanmisaka last_time = node->time;
540*437bfbebSnyanmisaka node++;
541*437bfbebSnyanmisaka }
542*437bfbebSnyanmisaka }
543*437bfbebSnyanmisaka MPP_FREE(impl->nodes);
544*437bfbebSnyanmisaka MPP_FREE(impl);
545*437bfbebSnyanmisaka }
546*437bfbebSnyanmisaka
mpp_stopwatch_elapsed_time(MppStopwatch stopwatch)547*437bfbebSnyanmisaka rk_s64 mpp_stopwatch_elapsed_time(MppStopwatch stopwatch)
548*437bfbebSnyanmisaka {
549*437bfbebSnyanmisaka MppStopwatchImpl *impl = (MppStopwatchImpl *)stopwatch;
550*437bfbebSnyanmisaka
551*437bfbebSnyanmisaka if (check_is_mpp_stopwatch(impl)) {
552*437bfbebSnyanmisaka mpp_err_f("invalid stopwatch %p\n", impl);
553*437bfbebSnyanmisaka return 0;
554*437bfbebSnyanmisaka }
555*437bfbebSnyanmisaka
556*437bfbebSnyanmisaka if (impl->filled_count < 2)
557*437bfbebSnyanmisaka return 0;
558*437bfbebSnyanmisaka
559*437bfbebSnyanmisaka rk_s64 base_time = impl->nodes[0].time;
560*437bfbebSnyanmisaka rk_s64 curr_time = impl->nodes[impl->filled_count - 1].time;
561*437bfbebSnyanmisaka rk_s64 elapsed_time = curr_time - base_time;
562*437bfbebSnyanmisaka return elapsed_time;
563*437bfbebSnyanmisaka }
564