Skip to content

Commit 00b9fca

Browse files
committed
Use uptime for timers
Unlike wall time, it doesn't jump around #468 #567
1 parent c0e84f1 commit 00b9fca

File tree

1 file changed

+21
-14
lines changed

1 file changed

+21
-14
lines changed

src/mgos_timers.c

+21-14
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ struct timer_data {
5858
static struct timer_data *s_timer_data = NULL;
5959
static struct mgos_rlock_type *s_timer_data_lock = NULL;
6060

61-
static void schedule_next_timer(struct timer_data *td) {
61+
static void schedule_next_timer(struct timer_data *td, double now) {
6262
struct timer_info *ti;
6363
struct timer_info *min_ti = NULL;
6464
LIST_FOREACH(ti, &td->timers, entries) {
@@ -67,7 +67,12 @@ static void schedule_next_timer(struct timer_data *td) {
6767
}
6868
}
6969
td->current = min_ti;
70-
td->nc->ev_timer_time = (min_ti != NULL ? min_ti->next_invocation : 0);
70+
if (min_ti != NULL) {
71+
double diff = min_ti->next_invocation - now;
72+
td->nc->ev_timer_time = mg_time() + diff;
73+
} else {
74+
td->nc->ev_timer_time = 0;
75+
}
7176
}
7277

7378
static void mgos_timer_ev(struct mg_connection *nc, int ev, void *ev_data,
@@ -80,11 +85,11 @@ static void mgos_timer_ev(struct mg_connection *nc, int ev, void *ev_data,
8085
struct timer_data *td = (struct timer_data *) user_data;
8186
struct timer_info *ti = td->current;
8287
/* Current can be NULL if it was the first to fire but was cleared. */
83-
if (ti != NULL) {
88+
const double now = mgos_uptime();
89+
if (ti != NULL && ti->next_invocation <= now) {
8490
cb = ti->cb;
8591
cb_arg = ti->cb_arg;
8692
if (ti->interval_ms >= 0) {
87-
const double now = mg_time();
8893
const double intvl = (ti->interval_ms / 1000.0);
8994
ti->next_invocation += intvl;
9095
/* Polling loop was delayed, re-sync the invocation. */
@@ -94,7 +99,7 @@ static void mgos_timer_ev(struct mg_connection *nc, int ev, void *ev_data,
9499
LIST_REMOVE(ti, entries);
95100
}
96101
}
97-
schedule_next_timer(td);
102+
schedule_next_timer(td, now);
98103
mgos_runlock(s_timer_data_lock);
99104
if (ti != NULL) free(ti);
100105
}
@@ -112,17 +117,18 @@ mgos_timer_id mgos_set_timer(int msecs, int flags, timer_callback cb,
112117
} else {
113118
ti->interval_ms = -1;
114119
}
120+
double now = mgos_uptime();
115121
if (flags & MGOS_TIMER_RUN_NOW) {
116122
ti->next_invocation = 1;
117123
} else {
118-
ti->next_invocation = mg_time() + msecs / 1000.0;
124+
ti->next_invocation = now + msecs / 1000.0;
119125
}
120126
ti->cb = cb;
121127
ti->cb_arg = arg;
122128
{
123129
mgos_rlock(s_timer_data_lock);
124130
LIST_INSERT_HEAD(&s_timer_data->timers, ti, entries);
125-
schedule_next_timer(s_timer_data);
131+
schedule_next_timer(s_timer_data, now);
126132
mgos_runlock(s_timer_data_lock);
127133
}
128134
mongoose_schedule_poll(false /* from_isr */);
@@ -142,7 +148,7 @@ static void mgos_clear_sw_timer(mgos_timer_id id) {
142148
}
143149
LIST_REMOVE(ti, entries);
144150
if (s_timer_data->current == ti) {
145-
schedule_next_timer(s_timer_data);
151+
schedule_next_timer(s_timer_data, mgos_uptime());
146152
/* Removing a timer can only push back invocation, no need to do a poll. */
147153
}
148154
mgos_runlock(s_timer_data_lock);
@@ -180,16 +186,16 @@ bool mgos_get_timer_info(mgos_timer_id id, struct mgos_timer_info *info) {
180186
return true;
181187
}
182188

183-
static void mgos_time_change_cb(int ev, void *evd, void *arg) {
189+
static void mgos_poll_cb(void *arg) {
184190
struct timer_data *td = (struct timer_data *) arg;
185-
struct mgos_time_changed_arg *ev_data = (struct mgos_time_changed_arg *) evd;
186191
mgos_rlock(s_timer_data_lock);
187-
struct timer_info *ti;
188-
LIST_FOREACH(ti, &td->timers, entries) {
189-
ti->next_invocation += ev_data->delta;
190-
}
192+
schedule_next_timer(td, mgos_uptime());
191193
mgos_runlock(s_timer_data_lock);
194+
}
192195

196+
static void mgos_time_change_cb(int ev, void *evd, void *arg) {
197+
mgos_poll_cb(arg);
198+
(void) evd;
193199
(void) ev;
194200
}
195201

@@ -207,5 +213,6 @@ enum mgos_init_result mgos_timers_init(void) {
207213
s_timer_data = td;
208214
s_timer_data_lock = mgos_rlock_create();
209215
mgos_event_add_handler(MGOS_EVENT_TIME_CHANGED, mgos_time_change_cb, td);
216+
mgos_add_poll_cb(mgos_poll_cb, td);
210217
return mgos_hw_timers_init();
211218
}

0 commit comments

Comments
 (0)