Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp624703ybi; Wed, 19 Jun 2019 05:17:07 -0700 (PDT) X-Google-Smtp-Source: APXvYqx7312Rxxc5YpJ95+mAFyii18PneMkyOqYXyi/roSh72PH3e3LaxBgUZrBemJd9XUfnFqba X-Received: by 2002:aa7:8102:: with SMTP id b2mr9861452pfi.105.1560946627004; Wed, 19 Jun 2019 05:17:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1560946626; cv=none; d=google.com; s=arc-20160816; b=QxNwtywj5HQDjRPwKbEEE/Qt4pFN48uL2AsLJyFbqSlOFgUsRsJ+zkLNvirZakqC9a Jj9yVFJDGIyI/KztpnSr4AKxuTZwziJbusOjYt3pP88KsDIOOj5ae7nhbsv2FJutW9BR 31fVbIV180pFDifFf7d6a0AjpyIm7ylREDP8JqfNZiUg+O2laNVMY1v81/Pic5tUMDNX VNLHDA9tn6+Rt52oh/kXXB3SEMG+O1xwhcahWxFKVOPzaUzYSRWnux4lHFAF8DcedbxL jaROyfM1AGPOOAg0eyYzMzEGsoOgsS9ECX0GwWOqzoO2Wbi82kGTJL3kaKBs3JQDfva0 N7yA== 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 :references:in-reply-to:message-id:date:subject:cc:to:from; bh=icTqbJUyFvxF5F2Hz7jj8UCZIBIA0/+WWkGl7JxstkQ=; b=xKY9N+LOyyjdh9JV8UTv9DsCL8YJhuJiCV6QNTy9TALDltbbhK0TqBZPqr2Per37BN XGaaeQrovegi3tpJoPpjjGuBU1KKqz8q2FwBAZ5sqKcymxtj9xYVxvBFPgRkbJm3hsPP wJFy63xiyzi15VwBXmuexKDc+kO51Sk8BKERkaabYipVdhz6WKZU/rWlgjMejc9YmTC7 ASWLG4XVVnAATQA/g6wgsW2xnyQVJDncGl3eNvZeWiU3wWnyOmXhpvc5gT0xBNAB2o1V /iJ23Q57JKMP3KiJHVelovdAFm8Hfq/WVjQq4/UjzcoQvQDAtRpF63wr5gNAKTy+3Jbv RP2A== 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 o61si17908359plb.0.2019.06.19.05.16.51; Wed, 19 Jun 2019 05:17:06 -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 S1731742AbfFSMPs (ORCPT + 99 others); Wed, 19 Jun 2019 08:15:48 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:40472 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727314AbfFSMPr (ORCPT ); Wed, 19 Jun 2019 08:15:47 -0400 Received: from localhost.localdomain (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 173A12606DF; Wed, 19 Jun 2019 13:15:45 +0100 (BST) From: Boris Brezillon To: Mauro Carvalho Chehab , Hans Verkuil , Laurent Pinchart , Sakari Ailus , linux-media@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Tomasz Figa , Nicolas Dufresne , kernel@collabora.com, Paul Kocialkowski , Ezequiel Garcia , Jonas Karlman , linux-rockchip@lists.infradead.org, Heiko Stuebner , Andrew Morton , Rasmus Villemoes , Philipp Zabel , Boris Brezillon Subject: [PATCH 1/9] lib/sort.c: implement sort() variant taking context argument Date: Wed, 19 Jun 2019 14:15:32 +0200 Message-Id: <20190619121540.29320-2-boris.brezillon@collabora.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190619121540.29320-1-boris.brezillon@collabora.com> References: <20190619121540.29320-1-boris.brezillon@collabora.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Rasmus Villemoes 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 Signed-off-by: Boris Brezillon Cc: Andrew Morton --- Hi all, Andrew, you acked the first version of this patch, but Rasmus proposed a better solution and posted a v2. Can you review/ack this version. Hans, Mauro, Andrew suggested to have this patch applied along with its first user (the H264 backend of the hantro codec), so here it is. Note that, if possible, I'd like to have this patch queued for the next release even if the H264 bits don't get accepted as is. The rationale here being that Rasmus told me he was planning to further improve the sort() logic after the next -rc1 is out, and I fear his changes will conflict with this patch, which might involve some kind synchronisation (a topic branch) between the media maintainers and Andrew. Let me know how you want to proceed with that. Regards, 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..d54cf97e9548 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); -- 2.20.1