• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/usteer/timeout.c

  1 /*
  2  *   This program is free software; you can redistribute it and/or modify
  3  *   it under the terms of the GNU General Public License as published by
  4  *   the Free Software Foundation; either version 2 of the License.
  5  *
  6  *   This program is distributed in the hope that it will be useful,
  7  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  8  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9  *   GNU General Public License for more details.
 10  *
 11  *   You should have received a copy of the GNU General Public License
 12  *   along with this program; if not, write to the Free Software
 13  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 14  *
 15  *   Copyright (C) 2020 embedd.ch 
 16  *   Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> 
 17  *   Copyright (C) 2020 John Crispin <john@phrozen.org> 
 18  */
 19 
 20 #include <string.h>
 21 
 22 #include <libubox/utils.h>
 23 
 24 #include "timeout.h"
 25 
 26 static int usteer_timeout_cmp(const void *k1, const void *k2, void *ptr)
 27 {
 28         uint32_t ref = (uint32_t) (intptr_t) ptr;
 29         int32_t t1 = (uint32_t) (intptr_t) k1 - ref;
 30         int32_t t2 = (uint32_t) (intptr_t) k2 - ref;
 31 
 32         if (t1 < t2)
 33                 return -1;
 34         else if (t1 > t2)
 35                 return 1;
 36         else
 37                 return 0;
 38 }
 39 
 40 static int32_t usteer_timeout_delta(struct usteer_timeout *t, uint32_t time)
 41 {
 42         uint32_t val = (uint32_t) (intptr_t) t->node.key;
 43         return val - time;
 44 }
 45 
 46 static void usteer_timeout_recalc(struct usteer_timeout_queue *q, uint32_t time)
 47 {
 48         struct usteer_timeout *t;
 49         int32_t delta;
 50 
 51         if (avl_is_empty(&q->tree)) {
 52                 uloop_timeout_cancel(&q->timeout);
 53                 return;
 54         }
 55 
 56         t = avl_first_element(&q->tree, t, node);
 57 
 58         delta = usteer_timeout_delta(t, time);
 59         if (delta < 1)
 60                 delta = 1;
 61 
 62         uloop_timeout_set(&q->timeout, delta);
 63 }
 64 
 65 static uint32_t ampgr_timeout_current_time(void)
 66 {
 67         struct timespec ts;
 68         uint32_t val;
 69 
 70         clock_gettime(CLOCK_MONOTONIC, &ts);
 71         val = ts.tv_sec * 1000;
 72         val += ts.tv_nsec / 1000000;
 73 
 74         return val;
 75 }
 76 
 77 static void usteer_timeout_cb(struct uloop_timeout *timeout)
 78 {
 79         struct usteer_timeout_queue *q;
 80         struct usteer_timeout *t, *tmp;
 81         bool found;
 82         uint32_t time;
 83 
 84         q = container_of(timeout, struct usteer_timeout_queue, timeout);
 85         do {
 86                 found = false;
 87                 time = ampgr_timeout_current_time();
 88 
 89                 avl_for_each_element_safe(&q->tree, t, node, tmp) {
 90                         if (usteer_timeout_delta(t, time) > 0)
 91                                 break;
 92 
 93                         usteer_timeout_cancel(q, t);
 94                         if (q->cb)
 95                                 q->cb(q, t);
 96                         found = true;
 97                 }
 98         } while (found);
 99 
100         usteer_timeout_recalc(q, time);
101 }
102 
103 
104 void usteer_timeout_init(struct usteer_timeout_queue *q)
105 {
106         avl_init(&q->tree, usteer_timeout_cmp, true, NULL);
107         q->timeout.cb = usteer_timeout_cb;
108 }
109 
110 static void __usteer_timeout_cancel(struct usteer_timeout_queue *q,
111                                    struct usteer_timeout *t)
112 {
113         avl_delete(&q->tree, &t->node);
114 }
115 
116 void usteer_timeout_set(struct usteer_timeout_queue *q, struct usteer_timeout *t,
117                        int msecs)
118 {
119         uint32_t time = ampgr_timeout_current_time();
120         uint32_t val = time + msecs;
121         bool recalc = false;
122 
123         q->tree.cmp_ptr = (void *) (intptr_t) time;
124         if (usteer_timeout_isset(t)) {
125                 if (avl_is_first(&q->tree, &t->node))
126                         recalc = true;
127 
128                 __usteer_timeout_cancel(q, t);
129         }
130 
131         t->node.key = (void *) (intptr_t) val;
132         avl_insert(&q->tree, &t->node);
133         if (avl_is_first(&q->tree, &t->node))
134                 recalc = true;
135 
136         if (recalc)
137                 usteer_timeout_recalc(q, time);
138 }
139 
140 void usteer_timeout_cancel(struct usteer_timeout_queue *q,
141                           struct usteer_timeout *t)
142 {
143         if (!usteer_timeout_isset(t))
144                 return;
145 
146         __usteer_timeout_cancel(q, t);
147         memset(&t->node.list, 0, sizeof(t->node.list));
148 }
149 
150 void usteer_timeout_flush(struct usteer_timeout_queue *q)
151 {
152         struct usteer_timeout *t, *tmp;
153 
154         uloop_timeout_cancel(&q->timeout);
155         avl_remove_all_elements(&q->tree, t, node, tmp) {
156                 memset(&t->node.list, 0, sizeof(t->node.list));
157                 if (q->cb)
158                         q->cb(q, t);
159         }
160 }
161 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt