Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp3501498ybi; Tue, 18 Jun 2019 01:42:23 -0700 (PDT) X-Google-Smtp-Source: APXvYqz0HqmskvIVHhv4mm/qW2PsOfwZ+EBWiCpeMpmlFQOQcLRez8kGe6CL2WgqomO6iR4ZvOMC X-Received: by 2002:a17:902:b202:: with SMTP id t2mr109580750plr.69.1560847343186; Tue, 18 Jun 2019 01:42:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1560847343; cv=none; d=google.com; s=arc-20160816; b=dN87oRFB0y9xAoBlONGgBolKs5hGm+tK8S4JO9zpp9R2zwHa1q3/e63YxKW/IlC1Vr 4QyTeDvWPIjH+C6es82/ke0HPNiMuleKXJ4J//WEDksrkviGlEbFnm5OWghdaL0WclyH PKkpo+hwwTmIBybN4x0kg4QdFSJE5Q8QsqyCnxUnHwK0+bylT3ISBoyYqMDMPV8LKNce x/5g4R6qTpFcxKRFX45SgVkY7sh96pj8gRpv0RoObsR3bvHMZ9CB5q8gEDUPakZDMxYU 5gaTuf3dExrQNHa2zh2Yu8YBGVJm7pNuviaNg1zklYv6moCwKMAaA98VJR78VlvEc/UB NzBA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :organization:references:in-reply-to:message-id:subject:cc:to:from :date; bh=qLzomXysqtMFRCH4OF61lS1xIaUdaYBB1tGojDfJLkE=; b=TFAdx92CzhHMhDZv36FeNAsSv9sfw4colmPqyiS0EPwvKde8M28Gp5P1c9RBRn9eak y4d0nRo/cRGr196ixNyMn2Hm6y6w+S9g5o0zkMBSyh9hf+YIT4KrdUGYIUieXLIOiVsj 83iVOD/YnRoP2mlZY4oR+2BhhoOvFeBepZwYTRg9CQ9il2a4oCB+Ho7C3hoRsbHN1Phb wZFTh3i4C2Kloq4MP1lOb+4q++f2jx5RzqJaPvQAQjAOXuSlmNEwP4X7sZXCatVNRqrV RzUDuZ6GCMFpGl7s3RkKMmO0yKikTYbmBdDB2gHLqCW0oJ1qkqyuUHx+UT7CiUi4l4mX dC5w== 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=collabora.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f4si1712531pjo.97.2019.06.18.01.42.04; Tue, 18 Jun 2019 01:42:23 -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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=collabora.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729187AbfFRIkZ (ORCPT + 99 others); Tue, 18 Jun 2019 04:40:25 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:59804 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726330AbfFRIkY (ORCPT ); Tue, 18 Jun 2019 04:40:24 -0400 Received: from localhost (unknown [IPv6:2a01:e0a:2c:6930:5cf4:84a1:2763:fe0d]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: bbrezillon) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id ADC1426023F; Tue, 18 Jun 2019 09:40:22 +0100 (BST) Date: Tue, 18 Jun 2019 10:40:19 +0200 From: Boris Brezillon To: Rasmus Villemoes Cc: Andrew Morton , George Spelvin , Andrey Abramov , Andy Shevchenko , Randy Dunlap , kernel@collabora.com, linux-kernel@vger.kernel.org Subject: Re: [PATCH] lib/sort.c: implement sort() variant taking context argument Message-ID: <20190618104019.316dce06@collabora.com> In-Reply-To: <20190617211453.31928-1-linux@rasmusvillemoes.dk> References: <20190617155125.62da2946@collabora.com> <20190617211453.31928-1-linux@rasmusvillemoes.dk> Organization: Collabora X-Mailer: Claws Mail 3.17.3 (GTK+ 2.24.32; x86_64-redhat-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Rasmus, On Mon, 17 Jun 2019 23:14:52 +0200 Rasmus Villemoes wrote: > Our list_sort() utility has always supported a context argument that > is passed through to the comparison routine. Now there's a use case > for the similar thing for sort(). > > This implements sort_r by simply extending the existing sort function > in the obvious way. To avoid code duplication, we want to implement > sort() in terms of sort_r(). The naive way to do that is > > static int cmp_wrapper(const void *a, const void *b, const void *ctx) > { > int (*real_cmp)(const void*, const void*) = ctx; > return real_cmp(a, b); > } > > sort(..., cmp) { sort_r(..., cmp_wrapper, cmp) } > > but this would do two indirect calls for each comparison. Instead, do > as is done for the default swap functions - that only adds a cost of a > single easily predicted branch to each comparison call. > > Aside from introducing support for the context argument, this also > serves as preparation for patches that will eliminate the indirect > comparison calls in common cases. > > Requested-by: Boris Brezillon > Signed-off-by: Rasmus Villemoes > --- > Hi Boris > > Sorry, completely dropped the ball on this one. No problem. > Here's a formal patch > with change log. I won't have time to do the other changes I mention > this side of the merge window, so it's perfectly fine if you carry > this as part of your series. Not sure my series will make it for the next release, but I'll let you know either way. > It's only been tested by booting a kernel > in qemu with CONFIG_TEST_SORT=y, and nothing exploded. Thanks for the patch. Boris > > include/linux/sort.h | 5 +++++ > lib/sort.c | 34 ++++++++++++++++++++++++++++------ > 2 files changed, 33 insertions(+), 6 deletions(-) > > diff --git a/include/linux/sort.h b/include/linux/sort.h > index 2b99a5dd073d..61b96d0ebc44 100644 > --- a/include/linux/sort.h > +++ b/include/linux/sort.h > @@ -4,6 +4,11 @@ > > #include > > +void sort_r(void *base, size_t num, size_t size, > + int (*cmp)(const void *, const void *, const void *), > + void (*swap)(void *, void *, int), > + const void *priv); > + > void sort(void *base, size_t num, size_t size, > int (*cmp)(const void *, const void *), > void (*swap)(void *, void *, int)); > diff --git a/lib/sort.c b/lib/sort.c > index cf408aec3733..36fcc2040be5 100644 > --- a/lib/sort.c > +++ b/lib/sort.c > @@ -144,6 +144,18 @@ static void do_swap(void *a, void *b, size_t size, swap_func_t swap_func) > swap_func(a, b, (int)size); > } > > +typedef int (*cmp_func_t)(const void *, const void *); > +typedef int (*cmp_r_func_t)(const void *, const void *, const void *); > +#define _CMP_WRAPPER ((cmp_r_func_t)0L) > + > +static int do_cmp(const void *a, const void *b, > + cmp_r_func_t cmp, const void *priv) > +{ > + if (cmp == _CMP_WRAPPER) > + return ((cmp_func_t)(priv))(a, b); > + return cmp(a, b, priv); > +} > + > /** > * parent - given the offset of the child, find the offset of the parent. > * @i: the offset of the heap element whose parent is sought. Non-zero. > @@ -171,12 +183,13 @@ static size_t parent(size_t i, unsigned int lsbit, size_t size) > } > > /** > - * sort - sort an array of elements > + * sort_r - sort an array of elements > * @base: pointer to data to sort > * @num: number of elements > * @size: size of each element > * @cmp_func: pointer to comparison function > * @swap_func: pointer to swap function or NULL > + * @priv: third argument passed to comparison function > * > * This function does a heapsort on the given array. You may provide > * a swap_func function if you need to do something more than a memory > @@ -188,9 +201,10 @@ static size_t parent(size_t i, unsigned int lsbit, size_t size) > * O(n*n) worst-case behavior and extra memory requirements that make > * it less suitable for kernel use. > */ > -void sort(void *base, size_t num, size_t size, > - int (*cmp_func)(const void *, const void *), > - void (*swap_func)(void *, void *, int size)) > +void sort_r(void *base, size_t num, size_t size, > + int (*cmp_func)(const void *, const void *, const void *), > + void (*swap_func)(void *, void *, int size), > + const void *priv) > { > /* pre-scale counters for performance */ > size_t n = num * size, a = (num/2) * size; > @@ -238,12 +252,12 @@ void sort(void *base, size_t num, size_t size, > * average, 3/4 worst-case.) > */ > for (b = a; c = 2*b + size, (d = c + size) < n;) > - b = cmp_func(base + c, base + d) >= 0 ? c : d; > + b = do_cmp(base + c, base + d, cmp_func, priv) >= 0 ? c : d; > if (d == n) /* Special case last leaf with no sibling */ > b = c; > > /* Now backtrack from "b" to the correct location for "a" */ > - while (b != a && cmp_func(base + a, base + b) >= 0) > + while (b != a && do_cmp(base + a, base + b, cmp_func, priv) >= 0) > b = parent(b, lsbit, size); > c = b; /* Where "a" belongs */ > while (b != a) { /* Shift it into place */ > @@ -252,4 +266,12 @@ void sort(void *base, size_t num, size_t size, > } > } > } > +EXPORT_SYMBOL(sort_r); > + > +void sort(void *base, size_t num, size_t size, > + int (*cmp_func)(const void *, const void *), > + void (*swap_func)(void *, void *, int size)) > +{ > + return sort_r(base, num, size, _CMP_WRAPPER, swap_func, cmp_func); > +} > EXPORT_SYMBOL(sort);