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