- last_te = NULL;
- for (cur_te = ev->timer_events; cur_te; cur_te = cur_te->next) {
- /* if the new event comes before the current one break */
- if (tevent_timeval_compare(&te->next_event, &cur_te->next_event) < 0) {
+ prev_te = NULL;
+ if (tevent_timeval_is_zero(&te->next_event)) {
+ /*
+ * Some callers use zero tevent_timer
+ * instead of tevent_immediate events.
+ *
+ * As these can happen very often,
+ * we remember the last zero timer
+ * in the list.
+ */
+ prev_te = ev->last_zero_timer;
+ ev->last_zero_timer = te;
+ } else {
+ struct tevent_timer *cur_te = NULL;
+ int ret;
+
+ /*
+ * we traverse the list from the tail
+ * because it's much more likely that
+ * timers are added at the end of the list
+ */
+ for (cur_te = DLIST_TAIL(ev->timer_events);
+ cur_te != NULL;
+ cur_te = DLIST_PREV(cur_te))
+ {
+ /*
+ * if the new event comes before the current
+ * we continue searching
+ */
+ ret = tevent_timeval_compare(&te->next_event,
+ &cur_te->next_event);
+ if (ret < 0) {
+ continue;
+ }
+