1*1f5a2479SJohn Stultz /* 2*1f5a2479SJohn Stultz * Generic Timer-queue 3*1f5a2479SJohn Stultz * 4*1f5a2479SJohn Stultz * Manages a simple queue of timers, ordered by expiration time. 5*1f5a2479SJohn Stultz * Uses rbtrees for quick list adds and expiration. 6*1f5a2479SJohn Stultz * 7*1f5a2479SJohn Stultz * NOTE: All of the following functions need to be serialized 8*1f5a2479SJohn Stultz * to avoid races. No locking is done by this libary code. 9*1f5a2479SJohn Stultz * 10*1f5a2479SJohn Stultz * This program is free software; you can redistribute it and/or modify 11*1f5a2479SJohn Stultz * it under the terms of the GNU General Public License as published by 12*1f5a2479SJohn Stultz * the Free Software Foundation; either version 2 of the License, or 13*1f5a2479SJohn Stultz * (at your option) any later version. 14*1f5a2479SJohn Stultz * 15*1f5a2479SJohn Stultz * This program is distributed in the hope that it will be useful, 16*1f5a2479SJohn Stultz * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*1f5a2479SJohn Stultz * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*1f5a2479SJohn Stultz * GNU General Public License for more details. 19*1f5a2479SJohn Stultz * 20*1f5a2479SJohn Stultz * You should have received a copy of the GNU General Public License 21*1f5a2479SJohn Stultz * along with this program; if not, write to the Free Software 22*1f5a2479SJohn Stultz * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23*1f5a2479SJohn Stultz */ 24*1f5a2479SJohn Stultz 25*1f5a2479SJohn Stultz #include <linux/timerqueue.h> 26*1f5a2479SJohn Stultz #include <linux/rbtree.h> 27*1f5a2479SJohn Stultz 28*1f5a2479SJohn Stultz /** 29*1f5a2479SJohn Stultz * timerqueue_add - Adds timer to timerqueue. 30*1f5a2479SJohn Stultz * 31*1f5a2479SJohn Stultz * @head: head of timerqueue 32*1f5a2479SJohn Stultz * @node: timer node to be added 33*1f5a2479SJohn Stultz * 34*1f5a2479SJohn Stultz * Adds the timer node to the timerqueue, sorted by the 35*1f5a2479SJohn Stultz * node's expires value. 36*1f5a2479SJohn Stultz */ 37*1f5a2479SJohn Stultz void timerqueue_add(struct timerqueue_head *head, struct timerqueue_node *node) 38*1f5a2479SJohn Stultz { 39*1f5a2479SJohn Stultz struct rb_node **p = &head->head.rb_node; 40*1f5a2479SJohn Stultz struct rb_node *parent = NULL; 41*1f5a2479SJohn Stultz struct timerqueue_node *ptr; 42*1f5a2479SJohn Stultz 43*1f5a2479SJohn Stultz /* Make sure we don't add nodes that are already added */ 44*1f5a2479SJohn Stultz WARN_ON_ONCE(!RB_EMPTY_NODE(&node->node)); 45*1f5a2479SJohn Stultz 46*1f5a2479SJohn Stultz while (*p) { 47*1f5a2479SJohn Stultz parent = *p; 48*1f5a2479SJohn Stultz ptr = rb_entry(parent, struct timerqueue_node, node); 49*1f5a2479SJohn Stultz if (node->expires.tv64 < ptr->expires.tv64) 50*1f5a2479SJohn Stultz p = &(*p)->rb_left; 51*1f5a2479SJohn Stultz else 52*1f5a2479SJohn Stultz p = &(*p)->rb_right; 53*1f5a2479SJohn Stultz } 54*1f5a2479SJohn Stultz rb_link_node(&node->node, parent, p); 55*1f5a2479SJohn Stultz rb_insert_color(&node->node, &head->head); 56*1f5a2479SJohn Stultz 57*1f5a2479SJohn Stultz if (!head->next || node->expires.tv64 < head->next->expires.tv64) 58*1f5a2479SJohn Stultz head->next = node; 59*1f5a2479SJohn Stultz } 60*1f5a2479SJohn Stultz 61*1f5a2479SJohn Stultz /** 62*1f5a2479SJohn Stultz * timerqueue_del - Removes a timer from the timerqueue. 63*1f5a2479SJohn Stultz * 64*1f5a2479SJohn Stultz * @head: head of timerqueue 65*1f5a2479SJohn Stultz * @node: timer node to be removed 66*1f5a2479SJohn Stultz * 67*1f5a2479SJohn Stultz * Removes the timer node from the timerqueue. 68*1f5a2479SJohn Stultz */ 69*1f5a2479SJohn Stultz void timerqueue_del(struct timerqueue_head *head, struct timerqueue_node *node) 70*1f5a2479SJohn Stultz { 71*1f5a2479SJohn Stultz WARN_ON_ONCE(RB_EMPTY_NODE(&node->node)); 72*1f5a2479SJohn Stultz 73*1f5a2479SJohn Stultz /* update next pointer */ 74*1f5a2479SJohn Stultz if (head->next == node) { 75*1f5a2479SJohn Stultz struct rb_node *rbn = rb_next(&node->node); 76*1f5a2479SJohn Stultz 77*1f5a2479SJohn Stultz head->next = rbn ? 78*1f5a2479SJohn Stultz rb_entry(rbn, struct timerqueue_node, node) : NULL; 79*1f5a2479SJohn Stultz } 80*1f5a2479SJohn Stultz rb_erase(&node->node, &head->head); 81*1f5a2479SJohn Stultz RB_CLEAR_NODE(&node->node); 82*1f5a2479SJohn Stultz } 83*1f5a2479SJohn Stultz 84*1f5a2479SJohn Stultz 85*1f5a2479SJohn Stultz /** 86*1f5a2479SJohn Stultz * timerqueue_getnext - Returns the timer with the earlies expiration time 87*1f5a2479SJohn Stultz * 88*1f5a2479SJohn Stultz * @head: head of timerqueue 89*1f5a2479SJohn Stultz * 90*1f5a2479SJohn Stultz * Returns a pointer to the timer node that has the 91*1f5a2479SJohn Stultz * earliest expiration time. 92*1f5a2479SJohn Stultz */ 93*1f5a2479SJohn Stultz struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head) 94*1f5a2479SJohn Stultz { 95*1f5a2479SJohn Stultz return head->next; 96*1f5a2479SJohn Stultz } 97*1f5a2479SJohn Stultz 98*1f5a2479SJohn Stultz 99*1f5a2479SJohn Stultz /** 100*1f5a2479SJohn Stultz * timerqueue_iterate_next - Returns the timer after the provided timer 101*1f5a2479SJohn Stultz * 102*1f5a2479SJohn Stultz * @node: Pointer to a timer. 103*1f5a2479SJohn Stultz * 104*1f5a2479SJohn Stultz * Provides the timer that is after the given node. This is used, when 105*1f5a2479SJohn Stultz * necessary, to iterate through the list of timers in a timer list 106*1f5a2479SJohn Stultz * without modifying the list. 107*1f5a2479SJohn Stultz */ 108*1f5a2479SJohn Stultz struct timerqueue_node *timerqueue_iterate_next(struct timerqueue_node *node) 109*1f5a2479SJohn Stultz { 110*1f5a2479SJohn Stultz struct rb_node *next; 111*1f5a2479SJohn Stultz 112*1f5a2479SJohn Stultz if (!node) 113*1f5a2479SJohn Stultz return NULL; 114*1f5a2479SJohn Stultz next = rb_next(&node->node); 115*1f5a2479SJohn Stultz if (!next) 116*1f5a2479SJohn Stultz return NULL; 117*1f5a2479SJohn Stultz return container_of(next, struct timerqueue_node, node); 118*1f5a2479SJohn Stultz } 119