Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

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