aboutsummaryrefslogtreecommitdiffstats
path: root/lib/timerqueue.c
blob: c5271096459306fb22f63699422fa4b7495783ab (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Generic Timer-queue
 *
 *  Manages a simple queue of timers, ordered by expiration time.
 *  Uses rbtrees for quick list adds and expiration.
 *
 *  NOTE: All of the following functions need to be serialized
 *  to avoid races. No locking is done by this library code.
 */

#include <linux/bug.h>
#include <linux/timerqueue.h>
#include <linux/rbtree.h>
#include <linux/export.h>

/**
 * timerqueue_add - Adds timer to timerqueue.
 *
 * @head: head of timerqueue
 * @node: timer node to be added
 *
 * Adds the timer node to the timerqueue, sorted by the node's expires
 * value. Returns true if the newly added timer is the first expiring timer in
 * the queue.
 */
bool timerqueue_add(struct timerqueue_head *head, struct timerqueue_node *node)
{
	struct rb_node **p = &head->rb_root.rb_root.rb_node;
	struct rb_node *parent = NULL;
	struct timerqueue_node *ptr;
	bool leftmost = true;

	/* Make sure we don't add nodes that are already added */
	WARN_ON_ONCE(!RB_EMPTY_NODE(&node->node));

	while (*p) {
		parent = *p;
		ptr = rb_entry(parent, struct timerqueue_node, node);
		if (node->expires < ptr->expires) {
			p = &(*p)->rb_left;
		} else {
			p = &(*p)->rb_right;
			leftmost = false;
		}
	}
	rb_link_node(&node->node, parent, p);
	rb_insert_color_cached(&node->node, &head->rb_root, leftmost);

	return leftmost;
}
EXPORT_SYMBOL_GPL(timerqueue_add);

/**
 * timerqueue_del - Removes a timer from the timerqueue.
 *
 * @head: head of timerqueue
 * @node: timer node to be removed
 *
 * Removes the timer node from the timerqueue. Returns true if the queue is
 * not empty after the remove.
 */
bool timerqueue_del(struct timerqueue_head *head, struct timerqueue_node *node)
{
	WARN_ON_ONCE(RB_EMPTY_NODE(&node->node));

	rb_erase_cached(&node->node, &head->rb_root);
	RB_CLEAR_NODE(&node->node);

	return !RB_EMPTY_ROOT(&head->rb_root.rb_root);
}
EXPORT_SYMBOL_GPL(timerqueue_del);

/**
 * timerqueue_iterate_next - Returns the timer after the provided timer
 *
 * @node: Pointer to a timer.
 *
 * Provides the timer that is after the given node. This is used, when
 * necessary, to iterate through the list of timers in a timer list
 * without modifying the list.
 */
struct timerqueue_node *timerqueue_iterate_next(struct timerqueue_node *node)
{
	struct rb_node *next;

	if (!node)
		return NULL;
	next = rb_next(&node->node);
	if (!next)
		return NULL;
	return container_of(next, struct timerqueue_node, node);
}
EXPORT_SYMBOL_GPL(timerqueue_iterate_next);
nsertions'>+9 2019-03-03tls: Fix write space handlingBoris Pismenny4-9/+39 2019-03-03tls: Fix tls_device handling of partial recordsBoris Pismenny3-33/+9 2019-03-03net: phy: remove gen10g_no_soft_resetHeiner Kallweit5-13/+5 2019-03-03net: phy: don't export gen10g_read_statusHeiner Kallweit2-3/+1 2019-03-03net: phy: remove gen10g_config_initHeiner Kallweit4-17/+0 2019-03-03net: phy: remove gen10g_suspend and gen10g_resumeHeiner Kallweit2-16/+0 2019-03-03net: phy: use genphy_c45_aneg_done in genphy_aneg_doneHeiner Kallweit1-8/+4 2019-03-03fsl/fman: Use vsprintf extension %pMJoe Perches1-3/+1 2019-03-03net: ipv6: add socket option IPV6_ROUTER_ALERT_ISOLATEFrancesco Ruggeri4-1/+19 2019-03-03net: fixup address-space warnings in compat_mc_{get,set}sockopt()Ben Dooks1-4/+4 2019-03-03net: dsa: Use prepare/commit phase in dsa_slave_vlan_rx_add_vid()Florian Fainelli1-3/+6 2019-03-03dpaa2-eth: add XDP_REDIRECT supportIoana Radulescu3-14/+176 2019-03-03dpaa2-eth: Add software annotation typesIoana Radulescu2-22/+40 2019-03-03sch_cake: Simplify logic in cake_select_tin()Toke Høiland-Jørgensen1-38/+23 2019-03-03sch_cake: Permit use of connmarks as tin classifiersKevin Darbyshire-Bryant2-7/+28 2019-03-03sch_cake: Make the dual modes fairerGeorge Amanakis1-29/+63 2019-03-03net: macb: Add support for suspend/resume with full power downHarini Katakam1-2/+38 2019-03-03net: macb: Add pm runtime supportHarini Katakam1-36/+112 2019-03-03net: macb: Support clock management for tsu_clkHarini Katakam2-6/+27 2019-03-03net: macb: Check MDIO state before read/write and use timeoutsHarini Katakam2-6/+29 2019-03-03net: dsa: microchip: add KSZ9893 switch supportTristram Ha3-15/+235 2019-03-03net: dsa: add KSZ9893 switch tagging supportTristram Ha4-0/+38 2019-03-03dt-bindings: net: dsa: document additional Microchip KSZ9477 family switchesTristram Ha1-0/+43 2019-03-02selftests: bpf: break up test_progs - miscStanislav Fomichev11-735/+754 2019-03-02selftests: bpf: break up test_progs - spinlockStanislav Fomichev4-103/+106 2019-03-02selftests: bpf: break up test_progs - tracepointStanislav Fomichev5-427/+431 2019-03-02selftests: bpf: break up test_progs - stackmapStanislav Fomichev6-476/+483 2019-03-02selftests: bpf: break up test_progs - xdpStanislav Fomichev5-162/+163 2019-03-02selftests: bpf: break up test_progs - pkt accessStanislav Fomichev3-51/+53 2019-03-02selftests: bpf: break up test_progs - preparationsStanislav Fomichev4-76/+119 2019-03-02Bluetooth: mediatek: add support for MediaTek MT7663U and MT7668U UART devicesSean Wang1-10/+271