18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  Generic Timer-queue
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Manages a simple queue of timers, ordered by expiration time.
68c2ecf20Sopenharmony_ci *  Uses rbtrees for quick list adds and expiration.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci *  NOTE: All of the following functions need to be serialized
98c2ecf20Sopenharmony_ci *  to avoid races. No locking is done by this library code.
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/bug.h>
138c2ecf20Sopenharmony_ci#include <linux/timerqueue.h>
148c2ecf20Sopenharmony_ci#include <linux/rbtree.h>
158c2ecf20Sopenharmony_ci#include <linux/export.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/**
188c2ecf20Sopenharmony_ci * timerqueue_add - Adds timer to timerqueue.
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci * @head: head of timerqueue
218c2ecf20Sopenharmony_ci * @node: timer node to be added
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * Adds the timer node to the timerqueue, sorted by the node's expires
248c2ecf20Sopenharmony_ci * value. Returns true if the newly added timer is the first expiring timer in
258c2ecf20Sopenharmony_ci * the queue.
268c2ecf20Sopenharmony_ci */
278c2ecf20Sopenharmony_cibool timerqueue_add(struct timerqueue_head *head, struct timerqueue_node *node)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	struct rb_node **p = &head->rb_root.rb_root.rb_node;
308c2ecf20Sopenharmony_ci	struct rb_node *parent = NULL;
318c2ecf20Sopenharmony_ci	struct timerqueue_node *ptr;
328c2ecf20Sopenharmony_ci	bool leftmost = true;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	/* Make sure we don't add nodes that are already added */
358c2ecf20Sopenharmony_ci	WARN_ON_ONCE(!RB_EMPTY_NODE(&node->node));
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	while (*p) {
388c2ecf20Sopenharmony_ci		parent = *p;
398c2ecf20Sopenharmony_ci		ptr = rb_entry(parent, struct timerqueue_node, node);
408c2ecf20Sopenharmony_ci		if (node->expires < ptr->expires) {
418c2ecf20Sopenharmony_ci			p = &(*p)->rb_left;
428c2ecf20Sopenharmony_ci		} else {
438c2ecf20Sopenharmony_ci			p = &(*p)->rb_right;
448c2ecf20Sopenharmony_ci			leftmost = false;
458c2ecf20Sopenharmony_ci		}
468c2ecf20Sopenharmony_ci	}
478c2ecf20Sopenharmony_ci	rb_link_node(&node->node, parent, p);
488c2ecf20Sopenharmony_ci	rb_insert_color_cached(&node->node, &head->rb_root, leftmost);
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	return leftmost;
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(timerqueue_add);
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/**
558c2ecf20Sopenharmony_ci * timerqueue_del - Removes a timer from the timerqueue.
568c2ecf20Sopenharmony_ci *
578c2ecf20Sopenharmony_ci * @head: head of timerqueue
588c2ecf20Sopenharmony_ci * @node: timer node to be removed
598c2ecf20Sopenharmony_ci *
608c2ecf20Sopenharmony_ci * Removes the timer node from the timerqueue. Returns true if the queue is
618c2ecf20Sopenharmony_ci * not empty after the remove.
628c2ecf20Sopenharmony_ci */
638c2ecf20Sopenharmony_cibool timerqueue_del(struct timerqueue_head *head, struct timerqueue_node *node)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	WARN_ON_ONCE(RB_EMPTY_NODE(&node->node));
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	rb_erase_cached(&node->node, &head->rb_root);
688c2ecf20Sopenharmony_ci	RB_CLEAR_NODE(&node->node);
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	return !RB_EMPTY_ROOT(&head->rb_root.rb_root);
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(timerqueue_del);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci/**
758c2ecf20Sopenharmony_ci * timerqueue_iterate_next - Returns the timer after the provided timer
768c2ecf20Sopenharmony_ci *
778c2ecf20Sopenharmony_ci * @node: Pointer to a timer.
788c2ecf20Sopenharmony_ci *
798c2ecf20Sopenharmony_ci * Provides the timer that is after the given node. This is used, when
808c2ecf20Sopenharmony_ci * necessary, to iterate through the list of timers in a timer list
818c2ecf20Sopenharmony_ci * without modifying the list.
828c2ecf20Sopenharmony_ci */
838c2ecf20Sopenharmony_cistruct timerqueue_node *timerqueue_iterate_next(struct timerqueue_node *node)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	struct rb_node *next;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	if (!node)
888c2ecf20Sopenharmony_ci		return NULL;
898c2ecf20Sopenharmony_ci	next = rb_next(&node->node);
908c2ecf20Sopenharmony_ci	if (!next)
918c2ecf20Sopenharmony_ci		return NULL;
928c2ecf20Sopenharmony_ci	return container_of(next, struct timerqueue_node, node);
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(timerqueue_iterate_next);
95