Received: by 2002:a25:ad19:0:0:0:0:0 with SMTP id y25csp9874636ybi; Wed, 24 Jul 2019 11:29:34 -0700 (PDT) X-Google-Smtp-Source: APXvYqz06hjy4KWvbUSASbDehCcrF78fRwXIcdTf+0AU+PE1RI64gmMaaRe6XTOUV8fbzWmJ+yNa X-Received: by 2002:aa7:9293:: with SMTP id j19mr13003641pfa.90.1563992974344; Wed, 24 Jul 2019 11:29:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1563992974; cv=none; d=google.com; s=arc-20160816; b=SoJrGi4wJk63ZHNpti+EFUO1zfvKuWUpXIaMKMmIg9ScOCEYmlPye/XdL+sf5t2ajV g3SZcIYQv5TxIs+RCmXMD/lGQI+s3ziiOs1L7aPfHUh4TmPxKINvRRKpPUCjHqZll2ff gUpTmkULnGmSlAKP+XdSuuRAW5ovhLxnIW9EFQ3Lww/5AFzV/aHT0o0sZAz2JTYt+jwt ok1xOBkyuIR2xAaDcAJWJYLv0hWqnvUz/hK5UubBnTdy/80VCUamXXxG8Um3LzR1MWe4 h9mZS4lY79zHmDtPbvuqd5+wPLsMkGweIfI6hk6aU35OT2S4B3cF0NIU74cnKLNq1Qch GBKQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date; bh=tLUzY5eU91gZ7jKh2XTHoL0PbDHPGlxTIifJGtQe1Go=; b=IVssIpFD71603BoULI6JCUkyLbJYZ4qcTlr4UZMp/dmkys4QD+tL6GHPImNqsZDy6i oA+S2wtgmd9joHneI+CbIE00CrQWhZyLiJ5VRBA0U4NlIWCdRizr82ReYYk+ag7Anku2 FfWGxFmi1/Rp+ngaC9pmrv5TcVlpsXjQOeQbnGD2nO7oQlOnaMwdmRDHGaiC3CixbBDr kjW5mlMD4w5fx+Zv/6NM7aFWX1BWHzERQgtIFLB1AE7bDfkdjQJM78JJAaF4ma5Aqea5 nYI9bwo1sAV4kx2ls9nPG7fiS+PZTUF4VuIlr2bJwMFiUS5ardakFAJhDqlNaaoYhl7N AJRA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p97si15523841pjp.34.2019.07.24.11.29.20; Wed, 24 Jul 2019 11:29:34 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727797AbfGXPXc (ORCPT + 99 others); Wed, 24 Jul 2019 11:23:32 -0400 Received: from mx2.suse.de ([195.135.220.15]:53138 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725870AbfGXPXc (ORCPT ); Wed, 24 Jul 2019 11:23:32 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 2EF19B02A; Wed, 24 Jul 2019 15:23:30 +0000 (UTC) Date: Wed, 24 Jul 2019 08:23:23 -0700 From: Davidlohr Bueso To: Thomas Gleixner Cc: john.stultz@linaro.org, linux-kernel@vger.kernel.org, Davidlohr Bueso Subject: [PATCH] lib/timerqueue: Rely on rbtree semantics for next timer Message-ID: <20190724152323.bojciei3muvfxalm@linux-r8p5> References: <20190618204405.27956-1-dave@stgolabs.net> <20190723054808.2nwg5pu3z36uxmq6@linux-r8p5> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline In-Reply-To: User-Agent: NeoMutt/20180323 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Simplify the timerqueue code by using cached rbtrees and rely on the tree leftmost node semantics to get the timer with earliest expiration time. This is a drop in conversion, and therefore semantics remain untouched. The runtime overhead of cached rbtrees is be pretty much the same as the current head->next method, noting that when removing the leftmost node, a common operation for the timerqueue, the rb_next(leftmost) is O(1) as well, so the next timer will either be the right node or its parent. Therefore no extra pointer chasing. Finally, the size of the struct timerqueue_head remains the same. Passes several hours of rcutorture. Signed-off-by: Davidlohr Bueso --- include/linux/timerqueue.h | 13 ++++++------- lib/timerqueue.c | 28 +++++++++++----------------- 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/include/linux/timerqueue.h b/include/linux/timerqueue.h index 78b8cc73f12f..aff122f1062a 100644 --- a/include/linux/timerqueue.h +++ b/include/linux/timerqueue.h @@ -12,8 +12,7 @@ struct timerqueue_node { }; struct timerqueue_head { - struct rb_root head; - struct timerqueue_node *next; + struct rb_root_cached rb_root; }; @@ -29,13 +28,14 @@ extern struct timerqueue_node *timerqueue_iterate_next( * * @head: head of timerqueue * - * Returns a pointer to the timer node that has the - * earliest expiration time. + * Returns a pointer to the timer node that has the earliest expiration time. */ static inline struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head) { - return head->next; + struct rb_node *leftmost = rb_first_cached(&head->rb_root); + + return rb_entry(leftmost, struct timerqueue_node, node); } static inline void timerqueue_init(struct timerqueue_node *node) @@ -45,7 +45,6 @@ static inline void timerqueue_init(struct timerqueue_node *node) static inline void timerqueue_init_head(struct timerqueue_head *head) { - head->head = RB_ROOT; - head->next = NULL; + head->rb_root = RB_ROOT_CACHED; } #endif /* _LINUX_TIMERQUEUE_H */ diff --git a/lib/timerqueue.c b/lib/timerqueue.c index bc7e64df27df..892d2bdc27f0 100644 --- a/lib/timerqueue.c +++ b/lib/timerqueue.c @@ -26,9 +26,10 @@ */ bool timerqueue_add(struct timerqueue_head *head, struct timerqueue_node *node) { - struct rb_node **p = &head->head.rb_node; + struct rb_node **p = &head->rb_root.rb_root.rb_node; struct rb_node *parent = NULL; - struct timerqueue_node *ptr; + 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)); @@ -38,17 +39,15 @@ bool timerqueue_add(struct timerqueue_head *head, struct timerqueue_node *node) ptr = rb_entry(parent, struct timerqueue_node, node); if (node->expires < ptr->expires) p = &(*p)->rb_left; - else + else { p = &(*p)->rb_right; + leftmost = false; + } } rb_link_node(&node->node, parent, p); - rb_insert_color(&node->node, &head->head); + rb_insert_color_cached(&node->node, &head->rb_root, leftmost); - if (!head->next || node->expires < head->next->expires) { - head->next = node; - return true; - } - return false; + return leftmost; } EXPORT_SYMBOL_GPL(timerqueue_add); @@ -65,15 +64,10 @@ bool timerqueue_del(struct timerqueue_head *head, struct timerqueue_node *node) { WARN_ON_ONCE(RB_EMPTY_NODE(&node->node)); - /* update next pointer */ - if (head->next == node) { - struct rb_node *rbn = rb_next(&node->node); - - head->next = rb_entry_safe(rbn, struct timerqueue_node, node); - } - rb_erase(&node->node, &head->head); + rb_erase_cached(&node->node, &head->rb_root); RB_CLEAR_NODE(&node->node); - return head->next != NULL; + + return !RB_EMPTY_ROOT(&head->rb_root.rb_root); } EXPORT_SYMBOL_GPL(timerqueue_del); -- 2.16.4