Received: by 2002:ac0:bc90:0:0:0:0:0 with SMTP id a16csp937577img; Thu, 21 Mar 2019 12:06:37 -0700 (PDT) X-Google-Smtp-Source: APXvYqxXCZlPiTIztM7ajH+LXxxk+D0512v4mgV72DgU0E7hWfqPgugdTAywveJC5NF8iufVyYys X-Received: by 2002:a63:fe0a:: with SMTP id p10mr561634pgh.86.1553195197590; Thu, 21 Mar 2019 12:06:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1553195197; cv=none; d=google.com; s=arc-20160816; b=VHGbJL09/eevNZeI+09rclMeij1NIt/8bLkA1EpISE2xV8FMqVYNxDLjWytQk795AI GGaRu5dR5v2L6x81vpehzZnf6T9mhuvV6LLbQL5y+EtMnR1PrC55VeLpO6EXC7pdlCqz vBBa8ea1+cO1IdlliRd4sKAoz/zmvpj5MSEn13PC1n9X5x3/cuozZiKd1OlkqTGjAZo3 WlYlp4zGY5wAscR+aVtnzpnz4q2SDlh329mqtVlbcgLEzftWK9RlMomIBDWyN5nHHGUe H2bXGCP+Q3noDTDEz1SYouEtT4gzcXBSUt9+yJrU2Bwoj0b8kqnMxWpcvsMqQ+qHIo4W +Jag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=+A1kI0LhwTz+Eynh3staSonMalmN5X3nJ5WlbXgpv48=; b=bdycpOTaY5siJqijvfTG8SmmntfoJtMgpr9SezGviqsNl+XqW6W/h+tFlyF2+NQ+S3 DuG2zDOWNhDu7dJB9epA8MwLIYbEmHO9OR5C7ALvbqqJGQ3B0kWFVpPiqepRT7sGs1p8 JoOTc+jqhUL/UwUVWbf1A0O4037NyQzxw4P2b8TtkVIDf9WDdU4DMWr/5tOkkZ3qII0W S3jX7YrriikDyAr4CtKCxYDlkxun1mLpdtnYAoFN8jKuqWXhaayA5suiiACXW4L9uswJ UVcGQ4e4g9gvdYhzOvhPzBLF4UiqQhTOoKMhMhOfV6OxKeK9vFfexbyABQruTxFBwmBj MxRw== 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 p6si5054049plo.4.2019.03.21.12.06.19; Thu, 21 Mar 2019 12:06:37 -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 S1728950AbfCUTFT (ORCPT + 99 others); Thu, 21 Mar 2019 15:05:19 -0400 Received: from smtp.nue.novell.com ([195.135.221.5]:51849 "EHLO smtp.nue.novell.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728417AbfCUTFS (ORCPT ); Thu, 21 Mar 2019 15:05:18 -0400 Received: from emea4-mta.ukb.novell.com ([10.120.13.87]) by smtp.nue.novell.com with ESMTP (TLS encrypted); Thu, 21 Mar 2019 20:05:16 +0100 Received: from localhost.localdomain (nwb-a10-snat.microfocus.com [10.120.13.202]) by emea4-mta.ukb.novell.com with ESMTP (TLS encrypted); Thu, 21 Mar 2019 19:04:44 +0000 From: Davidlohr Bueso To: akpm@linux-foundation.org Cc: manfred@colorfullife.com, dave@stgolabs.net, linux-kernel@vger.kernel.org, Davidlohr Bueso Subject: [PATCH -next 2/2] ipc/mqueue: optimize msg_get() Date: Thu, 21 Mar 2019 12:02:16 -0700 Message-Id: <20190321190216.1719-2-dave@stgolabs.net> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20190321190216.1719-1-dave@stgolabs.net> References: <20190321190216.1719-1-dave@stgolabs.net> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Our msg priorities became an rbtree as of d6629859b36d ("ipc/mqueue: improve performance of send/recv") however, consuming a msg in msg_get() remains logarithmic (still being better than the case before of course). By applying well known techniques to cache pointers we can have the node with the highest priority in O(1), which is specially nice for the rt cases. Furthermore, some callers can call msg_get() in a loop. A new msg_tree_erase() helper is also added to encapsulate the tree removal and node_cache game. Passes ltp mq testcases. Signed-off-by: Davidlohr Bueso --- ipc/mqueue.c | 60 +++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/ipc/mqueue.c b/ipc/mqueue.c index be3f599e90ed..0c68d8d4b1a9 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -76,6 +76,7 @@ struct mqueue_inode_info { wait_queue_head_t wait_q; struct rb_root msg_tree; + struct rb_node *msg_tree_rightmost; struct posix_msg_tree_node *node_cache; struct mq_attr attr; @@ -131,6 +132,7 @@ static int msg_insert(struct msg_msg *msg, struct mqueue_inode_info *info) { struct rb_node **p, *parent = NULL; struct posix_msg_tree_node *leaf; + bool rightmost = true; p = &info->msg_tree.rb_node; while (*p) { @@ -139,9 +141,10 @@ static int msg_insert(struct msg_msg *msg, struct mqueue_inode_info *info) if (likely(leaf->priority == msg->m_type)) goto insert_msg; - else if (msg->m_type < leaf->priority) + else if (msg->m_type < leaf->priority) { p = &(*p)->rb_left; - else + rightmost = false; + } else p = &(*p)->rb_right; } if (info->node_cache) { @@ -154,6 +157,10 @@ static int msg_insert(struct msg_msg *msg, struct mqueue_inode_info *info) INIT_LIST_HEAD(&leaf->msg_list); } leaf->priority = msg->m_type; + + if (rightmost) + info->msg_tree_rightmost = &leaf->rb_node; + rb_link_node(&leaf->rb_node, parent, p); rb_insert_color(&leaf->rb_node, &info->msg_tree); insert_msg: @@ -163,23 +170,35 @@ static int msg_insert(struct msg_msg *msg, struct mqueue_inode_info *info) return 0; } +static inline void msg_tree_erase(struct posix_msg_tree_node *leaf, + struct mqueue_inode_info *info) +{ + struct rb_node *node = &leaf->rb_node; + + if (info->msg_tree_rightmost == node) + info->msg_tree_rightmost = rb_prev(node); + + rb_erase(node, &info->msg_tree); + if (info->node_cache) { + kfree(leaf); + } else { + info->node_cache = leaf; + } +} + static inline struct msg_msg *msg_get(struct mqueue_inode_info *info) { - struct rb_node **p, *parent = NULL; + struct rb_node *parent = NULL; struct posix_msg_tree_node *leaf; struct msg_msg *msg; try_again: - p = &info->msg_tree.rb_node; - while (*p) { - parent = *p; - /* - * During insert, low priorities go to the left and high to the - * right. On receive, we want the highest priorities first, so - * walk all the way to the right. - */ - p = &(*p)->rb_right; - } + /* + * During insert, low priorities go to the left and high to the + * right. On receive, we want the highest priorities first, so + * walk all the way to the right. + */ + parent = info->msg_tree_rightmost; if (!parent) { if (info->attr.mq_curmsgs) { pr_warn_once("Inconsistency in POSIX message queue, " @@ -194,24 +213,14 @@ static inline struct msg_msg *msg_get(struct mqueue_inode_info *info) pr_warn_once("Inconsistency in POSIX message queue, " "empty leaf node but we haven't implemented " "lazy leaf delete!\n"); - rb_erase(&leaf->rb_node, &info->msg_tree); - if (info->node_cache) { - kfree(leaf); - } else { - info->node_cache = leaf; - } + msg_tree_erase(leaf, info); goto try_again; } else { msg = list_first_entry(&leaf->msg_list, struct msg_msg, m_list); list_del(&msg->m_list); if (list_empty(&leaf->msg_list)) { - rb_erase(&leaf->rb_node, &info->msg_tree); - if (info->node_cache) { - kfree(leaf); - } else { - info->node_cache = leaf; - } + msg_tree_erase(leaf, info); } } info->attr.mq_curmsgs--; @@ -254,6 +263,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb, info->qsize = 0; info->user = NULL; /* set when all is ok */ info->msg_tree = RB_ROOT; + info->msg_tree_rightmost = NULL; info->node_cache = NULL; memset(&info->attr, 0, sizeof(info->attr)); info->attr.mq_maxmsg = min(ipc_ns->mq_msg_max, -- 2.16.4