From nobody Tue Apr 14 15:37:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BEB4CECAAD1 for ; Sat, 27 Aug 2022 17:58:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229984AbiH0R6i (ORCPT ); Sat, 27 Aug 2022 13:58:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33048 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230215AbiH0R61 (ORCPT ); Sat, 27 Aug 2022 13:58:27 -0400 Received: from mail-qv1-xf2f.google.com (mail-qv1-xf2f.google.com [IPv6:2607:f8b0:4864:20::f2f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6553BF3262 for ; Sat, 27 Aug 2022 10:58:12 -0700 (PDT) Received: by mail-qv1-xf2f.google.com with SMTP id cv7so932172qvb.3 for ; Sat, 27 Aug 2022 10:58:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=lkk0aNtBdprK6/w6JDryUnYgq5tZfZLWxr5bNxCaRTc=; b=cUOpGrFUBGR9Oh8Uy8dOhTXuMqO7GQro/NIk/L2wTn/SFNLHyqY7tYM/U4U0pF4y3V /bSWlSe5YdkELLX8uy0kOAQeJus+ouMVDbavQPpQmypwnt9IQW7hWj3iOcQWWva4Dajh EGFDSCwk1AGfW2TvfDTBe4LYt7DSlznylUd5/y7KIU0xH/en7v31yCdp1ZbFC6JRg/+d F0PWA3wHwPih02wYhc2Z9VuSy2Hd3RBDFogoQ9qfzLoNBSJGv9eo7ukueKzxhZRMFRji +xbWy1uD0fWw8sVrN8F2SBPc/TAwltDs6jzd3RYhEIKLyiA3otxH9laugaEt0+rW1tJ+ jnEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=lkk0aNtBdprK6/w6JDryUnYgq5tZfZLWxr5bNxCaRTc=; b=maLsXKO2dMsC+1NafOed0uLO74eWBkirZt6gomsQ58wmtN4IGU4XJrhVKZRnG6RpDJ WUPSFU03vk8nx/xNIMLMEiDNdaa0o4zfU/92Pa82fPS/NL6LA4B5L3FMJh0B8QAfvoDR 2s0rXVqfZAZmey/NX4FoP4zwqkhMrni27SZpS0Kmq7AkrqTyNEPYY+KOv+Pzrkxd8YjR a8gr4gE6R/VWApL+sIgrvXiVThuQrvLPv333pxvpjsulanhEO1JF2TvjaLTdr5HWR1EK hrzszMtY3al939PfHiRiwdGgu9ZoPTgg1Efi3k4uCWDhz2/15T67GmhuLhg071J6OAYP S5fg== X-Gm-Message-State: ACgBeo3HXz5AUDShwHRsi7AQTLJ246n6tQ+aSlVtzzlLkU/X4EqPchFR EyDXdZagCQhDIXpUeoI69CM= X-Google-Smtp-Source: AA6agR7slLkZEQvL0YLebJFYcI/RfCWbweYpS1bnNyfegL53J7FIMntAv+UkUyP2stCiCr/bpIrBsA== X-Received: by 2002:a05:6214:2301:b0:498:9f6f:28d with SMTP id gc1-20020a056214230100b004989f6f028dmr4457995qvb.5.1661623090442; Sat, 27 Aug 2022 10:58:10 -0700 (PDT) Received: from localhost ([2601:4c1:c100:2270:2454:ae5e:5655:e298]) by smtp.gmail.com with ESMTPSA id z23-20020ac81017000000b00338ae1f5421sm2053827qti.0.2022.08.27.10.58.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 27 Aug 2022 10:58:10 -0700 (PDT) From: Yury Norov To: Linus Torvalds , linux-kernel@vger.kernel.org Cc: Yury Norov , Alexey Klimov , Andy Shevchenko , Andy Whitcroft , Catalin Marinas , David Laight , Dennis Zhou , Guenter Roeck , Kees Cook , Rasmus Villemoes , Russell King Subject: [PATCH v3 1/4] lib/find_bit: introduce FIND_FIRST_BIT() macro Date: Sat, 27 Aug 2022 10:58:04 -0700 Message-Id: <20220827175807.4017673-2-yury.norov@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220827175807.4017673-1-yury.norov@gmail.com> References: <20220827175807.4017673-1-yury.norov@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Now that we have many flavors of find_first_bit(), and expect even more, it's better to have one macro that generates optimal code for all and makes maintaining of slightly different functions simpler. The logic common to all versions is moved to the new macro, and all the flavors are generated by providing an FETCH macro-parameter, like in this example: #define FIND_FIRST_BIT(FETCH, MUNGE, size) ... find_first_ornot_and_bit(addr1, addr2, addr3, size) { return FIND_NEXT_BIT(addr1[idx] | ~addr2[idx] & addr3[idx], /* nop = */, size); } The FETCH may be of any complexity, as soon as it only refers the bitmap(s) and an iterator idx. MUNGE is here to support _le code generation for BE builds. May be empty. Suggested-by: Linus Torvalds Signed-off-by: Yury Norov Reviewed-by: Valentin Schneider --- lib/find_bit.c | 49 ++++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/lib/find_bit.c b/lib/find_bit.c index 1b8e4b2a9cba..894b656f6836 100644 --- a/lib/find_bit.c +++ b/lib/find_bit.c @@ -19,6 +19,27 @@ #include #include =20 +/* + * Common helper for find_bit() function family + * @FETCH: The expression that fetches and pre-processes each word of bitm= ap(s) + * @MUNGE: The expression that post-processes a word containing found bit = (may be empty) + * @size: The bitmap size in bits + */ +#define FIND_FIRST_BIT(FETCH, MUNGE, size) \ +({ \ + unsigned long idx, val, sz =3D (size); \ + \ + for (idx =3D 0; idx * BITS_PER_LONG < sz; idx++) { \ + val =3D (FETCH); \ + if (val) { \ + sz =3D min(idx * BITS_PER_LONG + __ffs(MUNGE(val)), sz); \ + break; \ + } \ + } \ + \ + sz; \ +}) + #if !defined(find_next_bit) || !defined(find_next_zero_bit) || \ !defined(find_next_bit_le) || !defined(find_next_zero_bit_le) || \ !defined(find_next_and_bit) @@ -77,14 +98,7 @@ EXPORT_SYMBOL(_find_next_bit); */ unsigned long _find_first_bit(const unsigned long *addr, unsigned long siz= e) { - unsigned long idx; - - for (idx =3D 0; idx * BITS_PER_LONG < size; idx++) { - if (addr[idx]) - return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size); - } - - return size; + return FIND_FIRST_BIT(addr[idx], /* nop */, size); } EXPORT_SYMBOL(_find_first_bit); #endif @@ -97,15 +111,7 @@ unsigned long _find_first_and_bit(const unsigned long *= addr1, const unsigned long *addr2, unsigned long size) { - unsigned long idx, val; - - for (idx =3D 0; idx * BITS_PER_LONG < size; idx++) { - val =3D addr1[idx] & addr2[idx]; - if (val) - return min(idx * BITS_PER_LONG + __ffs(val), size); - } - - return size; + return FIND_FIRST_BIT(addr1[idx] & addr2[idx], /* nop */, size); } EXPORT_SYMBOL(_find_first_and_bit); #endif @@ -116,14 +122,7 @@ EXPORT_SYMBOL(_find_first_and_bit); */ unsigned long _find_first_zero_bit(const unsigned long *addr, unsigned lon= g size) { - unsigned long idx; - - for (idx =3D 0; idx * BITS_PER_LONG < size; idx++) { - if (addr[idx] !=3D ~0UL) - return min(idx * BITS_PER_LONG + ffz(addr[idx]), size); - } - - return size; + return FIND_FIRST_BIT(~addr[idx], /* nop */, size); } EXPORT_SYMBOL(_find_first_zero_bit); #endif --=20 2.34.1 From nobody Tue Apr 14 15:37:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8EF9FECAAD1 for ; Sat, 27 Aug 2022 17:58:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229497AbiH0R6b (ORCPT ); Sat, 27 Aug 2022 13:58:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32774 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229976AbiH0R6T (ORCPT ); Sat, 27 Aug 2022 13:58:19 -0400 Received: from mail-qk1-x729.google.com (mail-qk1-x729.google.com [IPv6:2607:f8b0:4864:20::729]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B091CF327E for ; Sat, 27 Aug 2022 10:58:13 -0700 (PDT) Received: by mail-qk1-x729.google.com with SMTP id f14so3462971qkm.0 for ; Sat, 27 Aug 2022 10:58:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=+ROIhR+DUlx4fpKW5KLbgmJzC5ncENSa5comAdZ246Q=; b=D3Tl/vpiPHu8H8igqykqECr+3dgVEyZ8XzOb2zB6Sk8qIE9+t5FABGPMeqSP+E5P0t sZPQq92HA9mqw/yG4N8vnUsA0qG2qdiEv1k0gWo8LMtCzKuspZ54U1Zsl4qNi/TEx0QE kj8n2pSGjQxdKFx0IB/FU3Xlyoosyj05lScctNb9fLjsSIlL4/nbYKB4aeMrIg4l+tl7 cx3GMt4DK/gU86KO9R64gIHzcGxcpWAkNye6vx50hOJ86dLo91nrJBAenPMONtnEGIFY TphM0ShCXXJLcQIQasJJ5FlVYI0M5acW9OL1EdRhYENTvajdoSy0C4EQtCoZsYQeVxv+ fpeA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=+ROIhR+DUlx4fpKW5KLbgmJzC5ncENSa5comAdZ246Q=; b=EMMSb2BErCmxLsCdN8JM3uR25kzPGDf7LNR2joOyuKnv4HGTTIQyDpO1EqFHo9uViN WAo/8xfnV8X0+W4W/0/Yb1KBiZEbHUmFprMNIwkF+RI0N3TrSYYpHiQpQWmPzDEZ+/bY 4mRp/ve1X6BytXgCOE2zpzWwNeG87F52/maU8fpcFzBmIzq236DJhu7w/yd2PqjP93eo 9jClmM5/Bce2qwSOwNPjLchjlz52395L05EIkSxuLSPTUfkfnarJKTMIzTHN7QGlPm+L KQ3cU7q9YTUHt9Lon+yw5ap4HIl1rpjTTOURxFI6XK89yH67FtV91gYMkcnjhnOBkJ0d GAdQ== X-Gm-Message-State: ACgBeo2Dm/8Z3lgNWy6RvXtd/QdjYdlIX2SYS8oco0MtfzETNvw7RFAw NErx1BTkYNcQV4ptls8ldXU= X-Google-Smtp-Source: AA6agR5DtVTedUb0fJmhOAdeqfwA395d9c01AeYRUFpxmgQLem/pnzYzeWylEI2VfDWT7iVEeilDbg== X-Received: by 2002:a37:9ad4:0:b0:6b9:c5d1:74e2 with SMTP id c203-20020a379ad4000000b006b9c5d174e2mr3546613qke.319.1661623091470; Sat, 27 Aug 2022 10:58:11 -0700 (PDT) Received: from localhost ([2601:4c1:c100:2270:2454:ae5e:5655:e298]) by smtp.gmail.com with ESMTPSA id az20-20020a05620a171400b006bb41ac3b6bsm2250194qkb.113.2022.08.27.10.58.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 27 Aug 2022 10:58:11 -0700 (PDT) From: Yury Norov To: Linus Torvalds , linux-kernel@vger.kernel.org Cc: Yury Norov , Alexey Klimov , Andy Shevchenko , Andy Whitcroft , Catalin Marinas , David Laight , Dennis Zhou , Guenter Roeck , Kees Cook , Rasmus Villemoes , Russell King Subject: [PATCH v3 2/4] lib/find_bit: create find_first_zero_bit_le() Date: Sat, 27 Aug 2022 10:58:05 -0700 Message-Id: <20220827175807.4017673-3-yury.norov@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220827175807.4017673-1-yury.norov@gmail.com> References: <20220827175807.4017673-1-yury.norov@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" find_first_zero_bit_le() is an alias to find_next_zero_bit_le(), despite that 'next' is known to be slower than 'first' version. Now that we have common FIND_FIRST_BIT() macro helper, it's trivial to implement find_first_zero_bit_le() as a real function. Signed-off-by: Yury Norov Reviewed-by: Valentin Schneider --- include/linux/find.h | 23 ++++++++++++++++++----- lib/find_bit.c | 14 ++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/include/linux/find.h b/include/linux/find.h index 424ef67d4a42..a1861d0ba533 100644 --- a/include/linux/find.h +++ b/include/linux/find.h @@ -17,6 +17,10 @@ extern unsigned long _find_first_and_bit(const unsigned = long *addr1, extern unsigned long _find_first_zero_bit(const unsigned long *addr, unsig= ned long size); extern unsigned long _find_last_bit(const unsigned long *addr, unsigned lo= ng size); =20 +#ifdef __BIG_ENDIAN +unsigned long _find_first_zero_bit_le(const unsigned long *addr, unsigned = long size); +#endif + #ifndef find_next_bit /** * find_next_bit - find the next set bit in a memory region @@ -251,6 +255,20 @@ unsigned long find_next_zero_bit_le(const void *addr, = unsigned } #endif =20 +#ifndef find_first_zero_bit_le +static inline +unsigned long find_first_zero_bit_le(const unsigned long *addr, unsigned l= ong size) +{ + if (small_const_nbits(size)) { + unsigned long val =3D swab(*addr) | ~GENMASK(size - 1, 0); + + return val =3D=3D ~0UL ? size : ffz(val); + } + + return _find_first_zero_bit_le(addr, size); +} +#endif + #ifndef find_next_bit_le static inline unsigned long find_next_bit_le(const void *addr, unsigned @@ -270,11 +288,6 @@ unsigned long find_next_bit_le(const void *addr, unsig= ned } #endif =20 -#ifndef find_first_zero_bit_le -#define find_first_zero_bit_le(addr, size) \ - find_next_zero_bit_le((addr), (size), 0) -#endif - #else #error "Please fix " #endif diff --git a/lib/find_bit.c b/lib/find_bit.c index 894b656f6836..f4d9b9684811 100644 --- a/lib/find_bit.c +++ b/lib/find_bit.c @@ -160,3 +160,17 @@ unsigned long find_next_clump8(unsigned long *clump, c= onst unsigned long *addr, return offset; } EXPORT_SYMBOL(find_next_clump8); + +#ifdef __BIG_ENDIAN +#ifndef find_first_zero_bit_le +/* + * Find the first cleared bit in an LE memory region. + */ +unsigned long _find_first_zero_bit_le(const unsigned long *addr, unsigned = long size) +{ + return FIND_FIRST_BIT(~addr[idx], swab, size); +} +EXPORT_SYMBOL(_find_first_zero_bit_le); +#endif + +#endif /* __BIG_ENDIAN */ --=20 2.34.1 From nobody Tue Apr 14 15:37:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 014FBECAAD5 for ; Sat, 27 Aug 2022 17:58:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230024AbiH0R6U (ORCPT ); Sat, 27 Aug 2022 13:58:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60924 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229486AbiH0R6Q (ORCPT ); Sat, 27 Aug 2022 13:58:16 -0400 Received: from mail-qv1-xf2b.google.com (mail-qv1-xf2b.google.com [IPv6:2607:f8b0:4864:20::f2b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CF02AF327F for ; Sat, 27 Aug 2022 10:58:13 -0700 (PDT) Received: by mail-qv1-xf2b.google.com with SMTP id kh8so3480264qvb.1 for ; Sat, 27 Aug 2022 10:58:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=ZEsSYrJvIW9CblQ4yml8Kvt67y6IrxJVfEY8E/20bB0=; b=gkAe713/vxeRJyussElZ2qGv68tGjwamhaPfgGOk1ML/UgIqP0GxairADaxFuC5jo7 zFPQHzbfUKVjiuWsbD1pcudFMVXZ9QgW7Qi/ul1M0yo+MR+MVI5aXjh8ACwAb9caPs3V i2rWJu2T4ujoDSrYvTqzGuOddd+vdh3W8AmDgCgK8A/t4IioqlhnZWUzobiWUQfm3QO/ FQjxdSyuHXDPMvmAtbkY4Himac5afTdlZQKcvieBnsMgCCzcP21cnjkRUadKfMZte6Um 6mmmdKxnCE0SmQleBzdhA10wYXcR/PbqBKHPRmJrFrT/Z4Ae5vdUJkkqIsy4JPxG0RAM qavQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=ZEsSYrJvIW9CblQ4yml8Kvt67y6IrxJVfEY8E/20bB0=; b=AI24zz8muRNe0DxHue6Ui4S72XklN5fhRrraZ/Jt4dFRH/a5msM7n416t7avl+vCVe 4P2WmgduSACjxHrY0y5OLs5rk9RZhxkFoor9yVP5htEEDRKSphle5U+cTW5gex1GAP+3 x+WaybME9KXorkEOx7SdXs5J65SkgZJAV3IA/Pm9KTUEt6CRvnAM181Rqa10/CMMnquw 4lQPHaClxk2+PmNIVF3vjW/OapS0qsrXqb7nz9FtV0iqkYSFQycI5wGLvbkjWOVt4TYt N3lBuwH3uBLJDDm45qYhpolv65x06MQ3FHA4QAnUbrVuWG5SoUGpDrqkkEtDej05NbLj E2Rw== X-Gm-Message-State: ACgBeo0eCmX1JYP1bxxnfSnRZKXNEb+TkXKzGQdrcOzylNjeBP/CLqnt ix2FRr0C7SD21uiXE+LM1is= X-Google-Smtp-Source: AA6agR7YsAWRQye40+utTHKRooGzb6wddYdixmYNANvq+sf6QfpjDRlz5trEp/a3OAeMy1TzPLjPCA== X-Received: by 2002:ad4:5aec:0:b0:498:f40a:dcc4 with SMTP id c12-20020ad45aec000000b00498f40adcc4mr3391970qvh.115.1661623092446; Sat, 27 Aug 2022 10:58:12 -0700 (PDT) Received: from localhost ([2601:4c1:c100:2270:2454:ae5e:5655:e298]) by smtp.gmail.com with ESMTPSA id v13-20020a05620a440d00b006bb29d932e1sm2347739qkp.105.2022.08.27.10.58.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 27 Aug 2022 10:58:12 -0700 (PDT) From: Yury Norov To: Linus Torvalds , linux-kernel@vger.kernel.org Cc: Yury Norov , Alexey Klimov , Andy Shevchenko , Andy Whitcroft , Catalin Marinas , David Laight , Dennis Zhou , Guenter Roeck , Kees Cook , Rasmus Villemoes , Russell King Subject: [PATCH v3 3/4] lib/find_bit: optimize find_next_bit() functions Date: Sat, 27 Aug 2022 10:58:06 -0700 Message-Id: <20220827175807.4017673-4-yury.norov@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220827175807.4017673-1-yury.norov@gmail.com> References: <20220827175807.4017673-1-yury.norov@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Over the past couple years, the function _find_next_bit() was extended with parameters that modify its behavior to implement and- zero- and le- flavors. The parameters are passed at compile time, but current design prevents a compiler from optimizing out the conditionals. As find_next_bit() API grows, I expect that more parameterss will be added. Current design would require more conditional code in _find_next_bit(), which would bloat the helper even more and make it barely readable. This patch replaces _find_next_bit() with a macro FIND_NEXT_BIT, and adds a set of wrappers, so that the compile-time optimizations become possible. The common logic is moved to the new macro, and all flavors may be generated by providing a FETCH macro parameter, like in this example: #define FIND_NEXT_BIT(FETCH, MUNGE, size, start) ... find_next_xornot_and_bit(addr1, addr2, addr3, size, start) { return FIND_NEXT_BIT(addr1[idx] ^ ~addr2[idx] & addr3[idx], /* nop */, size, start); } The FETCH may be of any complexity, as soon as it only refers the bitmap(s) and an iterator idx. MUNGE is here to support _le code generation for BE builds. May be empty. I ran find_bit_benchmark 16 times on top of 6.0-rc2 and 16 times on top of this series. The results for kvm/x86_64 are: v6.0-rc2 Optimized Difference Z-score Random dense bitmap ns ns ns % find_next_bit: 787735 670546 117189 14.9 3.97 find_next_zero_bit: 777492 664208 113284 14.6 10.51 find_last_bit: 830925 687573 143352 17.3 2.35 find_first_bit: 3874366 3306635 567731 14.7 1.84 find_first_and_bit: 40677125 37739887 2937238 7.2 1.36 find_next_and_bit: 347865 304456 43409 12.5 1.35 Random sparse bitmap find_next_bit: 19816 14021 5795 29.2 6.10 find_next_zero_bit: 1318901 1223794 95107 7.2 1.41 find_last_bit: 14573 13514 1059 7.3 6.92 find_first_bit: 1313321 1249024 64297 4.9 1.53 find_first_and_bit: 8921 8098 823 9.2 4.56 find_next_and_bit: 9796 7176 2620 26.7 5.39 Where the statistics is significant (z-score > 3), the improvement is ~15%. According to bloat-o-meter, the Image size is 10-11K less: x86_64/defconfig: add/remove: 32/14 grow/shrink: 61/782 up/down: 6344/-16521 (-10177) arm64/defconfig: add/remove: 3/2 grow/shrink: 50/714 up/down: 608/-11556 (-10948) Suggested-by: Linus Torvalds Signed-off-by: Yury Norov --- include/linux/find.h | 23 ++++++--- lib/find_bit.c | 119 +++++++++++++++++++++++++------------------ 2 files changed, 85 insertions(+), 57 deletions(-) diff --git a/include/linux/find.h b/include/linux/find.h index a1861d0ba533..d3b360ba428f 100644 --- a/include/linux/find.h +++ b/include/linux/find.h @@ -8,9 +8,12 @@ =20 #include =20 -extern unsigned long _find_next_bit(const unsigned long *addr1, - const unsigned long *addr2, unsigned long nbits, - unsigned long start, unsigned long invert, unsigned long le); +unsigned long _find_next_bit(const unsigned long *addr1, unsigned long nbi= ts, + unsigned long start); +unsigned long _find_next_and_bit(const unsigned long *addr1, const unsigne= d long *addr2, + unsigned long nbits, unsigned long start); +unsigned long _find_next_zero_bit(const unsigned long *addr, unsigned long= nbits, + unsigned long start); extern unsigned long _find_first_bit(const unsigned long *addr, unsigned l= ong size); extern unsigned long _find_first_and_bit(const unsigned long *addr1, const unsigned long *addr2, unsigned long size); @@ -19,6 +22,10 @@ extern unsigned long _find_last_bit(const unsigned long = *addr, unsigned long siz =20 #ifdef __BIG_ENDIAN unsigned long _find_first_zero_bit_le(const unsigned long *addr, unsigned = long size); +unsigned long _find_next_zero_bit_le(const unsigned long *addr, unsigned + long size, unsigned long offset); +unsigned long _find_next_bit_le(const unsigned long *addr, unsigned + long size, unsigned long offset); #endif =20 #ifndef find_next_bit @@ -45,7 +52,7 @@ unsigned long find_next_bit(const unsigned long *addr, un= signed long size, return val ? __ffs(val) : size; } =20 - return _find_next_bit(addr, NULL, size, offset, 0UL, 0); + return _find_next_bit(addr, size, offset); } #endif =20 @@ -75,7 +82,7 @@ unsigned long find_next_and_bit(const unsigned long *addr= 1, return val ? __ffs(val) : size; } =20 - return _find_next_bit(addr1, addr2, size, offset, 0UL, 0); + return _find_next_and_bit(addr1, addr2, size, offset); } #endif =20 @@ -103,7 +110,7 @@ unsigned long find_next_zero_bit(const unsigned long *a= ddr, unsigned long size, return val =3D=3D ~0UL ? size : ffz(val); } =20 - return _find_next_bit(addr, NULL, size, offset, ~0UL, 0); + return _find_next_zero_bit(addr, size, offset); } #endif =20 @@ -251,7 +258,7 @@ unsigned long find_next_zero_bit_le(const void *addr, u= nsigned return val =3D=3D ~0UL ? size : ffz(val); } =20 - return _find_next_bit(addr, NULL, size, offset, ~0UL, 1); + return _find_next_zero_bit_le(addr, size, offset); } #endif =20 @@ -284,7 +291,7 @@ unsigned long find_next_bit_le(const void *addr, unsign= ed return val ? __ffs(val) : size; } =20 - return _find_next_bit(addr, NULL, size, offset, 0UL, 1); + return _find_next_bit_le(addr, size, offset); } #endif =20 diff --git a/lib/find_bit.c b/lib/find_bit.c index f4d9b9684811..ba119f69f5ff 100644 --- a/lib/find_bit.c +++ b/lib/find_bit.c @@ -40,57 +40,33 @@ sz; \ }) =20 -#if !defined(find_next_bit) || !defined(find_next_zero_bit) || \ - !defined(find_next_bit_le) || !defined(find_next_zero_bit_le) || \ - !defined(find_next_and_bit) /* - * This is a common helper function for find_next_bit, find_next_zero_bit,= and - * find_next_and_bit. The differences are: - * - The "invert" argument, which is XORed with each fetched word before - * searching it for one bits. - * - The optional "addr2", which is anded with "addr1" if present. + * Common helper for find_next_bit() function family + * @FETCH: The expression that fetches and pre-processes each word of bitm= ap(s) + * @MUNGE: The expression that post-processes a word containing found bit = (may be empty) + * @size: The bitmap size in bits + * @start: The bitnumber to start searching at */ -unsigned long _find_next_bit(const unsigned long *addr1, - const unsigned long *addr2, unsigned long nbits, - unsigned long start, unsigned long invert, unsigned long le) -{ - unsigned long tmp, mask; - - if (unlikely(start >=3D nbits)) - return nbits; - - tmp =3D addr1[start / BITS_PER_LONG]; - if (addr2) - tmp &=3D addr2[start / BITS_PER_LONG]; - tmp ^=3D invert; - - /* Handle 1st word. */ - mask =3D BITMAP_FIRST_WORD_MASK(start); - if (le) - mask =3D swab(mask); - - tmp &=3D mask; - - start =3D round_down(start, BITS_PER_LONG); - - while (!tmp) { - start +=3D BITS_PER_LONG; - if (start >=3D nbits) - return nbits; - - tmp =3D addr1[start / BITS_PER_LONG]; - if (addr2) - tmp &=3D addr2[start / BITS_PER_LONG]; - tmp ^=3D invert; - } - - if (le) - tmp =3D swab(tmp); - - return min(start + __ffs(tmp), nbits); -} -EXPORT_SYMBOL(_find_next_bit); -#endif +#define FIND_NEXT_BIT(FETCH, MUNGE, size, start) \ +({ \ + unsigned long mask, idx, tmp, sz =3D (size), __start =3D (start); \ + \ + if (unlikely(__start >=3D sz)) \ + goto out; \ + \ + mask =3D MUNGE(BITMAP_FIRST_WORD_MASK(__start)); \ + idx =3D __start / BITS_PER_LONG; \ + \ + for (tmp =3D (FETCH) & mask; !tmp; tmp =3D (FETCH)) { \ + if (idx > sz / BITS_PER_LONG) \ + goto out; \ + idx++; \ + } \ + \ + sz =3D min(idx * BITS_PER_LONG + __ffs(MUNGE(tmp)), sz); \ +out: \ + sz; \ +}) =20 #ifndef find_first_bit /* @@ -127,6 +103,32 @@ unsigned long _find_first_zero_bit(const unsigned long= *addr, unsigned long size EXPORT_SYMBOL(_find_first_zero_bit); #endif =20 +#ifndef find_next_bit +unsigned long _find_next_bit(const unsigned long *addr, unsigned long nbit= s, unsigned long start) +{ + return FIND_NEXT_BIT(addr[idx], /* nop */, nbits, start); +} +EXPORT_SYMBOL(_find_next_bit); +#endif + +#ifndef find_next_and_bit +unsigned long _find_next_and_bit(const unsigned long *addr1, const unsigne= d long *addr2, + unsigned long nbits, unsigned long start) +{ + return FIND_NEXT_BIT(addr1[idx] & addr2[idx], /* nop */, nbits, start); +} +EXPORT_SYMBOL(_find_next_and_bit); +#endif + +#ifndef find_next_zero_bit +unsigned long _find_next_zero_bit(const unsigned long *addr, unsigned long= nbits, + unsigned long start) +{ + return FIND_NEXT_BIT(~addr[idx], /* nop */, nbits, start); +} +EXPORT_SYMBOL(_find_next_zero_bit); +#endif + #ifndef find_last_bit unsigned long _find_last_bit(const unsigned long *addr, unsigned long size) { @@ -173,4 +175,23 @@ unsigned long _find_first_zero_bit_le(const unsigned l= ong *addr, unsigned long s EXPORT_SYMBOL(_find_first_zero_bit_le); #endif =20 +#ifndef find_next_zero_bit_le +unsigned long _find_next_zero_bit_le(const unsigned long *addr, unsigned + long size, unsigned long offset) +{ + return FIND_NEXT_BIT(~addr[idx], swab, size, offset); +} +EXPORT_SYMBOL(_find_next_zero_bit_le); +#endif + +#ifndef find_next_bit_le +unsigned long _find_next_bit_le(const unsigned long *addr, unsigned + long size, unsigned long offset) +{ + return FIND_NEXT_BIT(addr[idx], swab, size, offset); +} +EXPORT_SYMBOL(_find_next_bit_le); + +#endif + #endif /* __BIG_ENDIAN */ --=20 2.34.1 From nobody Tue Apr 14 15:37:42 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 77E39ECAAD5 for ; Sat, 27 Aug 2022 17:58:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230141AbiH0R6Y (ORCPT ); Sat, 27 Aug 2022 13:58:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60924 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229650AbiH0R6R (ORCPT ); Sat, 27 Aug 2022 13:58:17 -0400 Received: from mail-qv1-xf2d.google.com (mail-qv1-xf2d.google.com [IPv6:2607:f8b0:4864:20::f2d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7F654F32CF for ; Sat, 27 Aug 2022 10:58:14 -0700 (PDT) Received: by mail-qv1-xf2d.google.com with SMTP id y15so163970qvn.2 for ; Sat, 27 Aug 2022 10:58:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=RHParwCR4cn2lNrRo0cT6xejtHubyBfMuzBqgRMrU1Q=; b=cN41ZCrUUkZBZsNunK77moSkD0r8wnOZSuV8R+gKUJNDSLDp1AGHLNZaVj2Rt6siyw wFw6vDBeLZHv4aBSYnGTo7D1ttN12d4KwTLrKUE0mwEVb7lkccJxmeSsOO5jmhDJaRra GOlONchvLOiGsOolwm+/QzxpVGIookkg//lcqZ/Z3GYNV2pW4KMVipAb4/FPeQm3OpMB 81nhwBNrS9hHJ71GY2FHp+V+87TFcdigaqUGilZ4+txvCPBwuTdil4NLtkVIHymglDta HtdJty8zi+1zTiYj/nPOEJo9F9danv7NN7EONmRS2LawEcFp/3ymQibTgM0kzfSCk20+ eK4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=RHParwCR4cn2lNrRo0cT6xejtHubyBfMuzBqgRMrU1Q=; b=eYSiZWHFP7a7MZg4C+BttATvahWWCnA6U13wbPhAa0gsUy8x8zBeReFbLxLOpRPjjq +fVlNjLtrEKQEwkvMsRExfc06Jw5hU1L4e0UYyNWNMCfMEdrw1dwU3MsOdatLf/zkPG2 83rMKcaGY9dJ5BhZwRlZ6IVcBpEgl05p+sBcmnp8i1YgpEBihg8yx2peFpz+xKCgxZRn sBHyLwfx1x9i0AACgSaI/w9+Dp/ZR34C0rQv1Np4ocFgniPw1DvakEOWdHGL70s6S5W7 6q2QfXVTKRRoxw+jp7DK8leHl5gfykzUF0+V9taF59nMHULbfxxMBsy/KJSTWlqAmZfT EoVA== X-Gm-Message-State: ACgBeo2tXdLlIz7QSYiCFlsa+yMSlNENrvcHHx/AT3/KgsdGp2PUCh9/ 9ztXGbHpUhJWKwF0/l/ReYI= X-Google-Smtp-Source: AA6agR59pQuOxMwKknXn0UqCatol5YBwGGUuDH5FplMfc09rpUXWlrNGv9qI5HyWDsHOJU5YSddITA== X-Received: by 2002:a05:6214:4005:b0:472:be5a:810d with SMTP id kd5-20020a056214400500b00472be5a810dmr4399283qvb.36.1661623093380; Sat, 27 Aug 2022 10:58:13 -0700 (PDT) Received: from localhost ([2601:4c1:c100:2270:2454:ae5e:5655:e298]) by smtp.gmail.com with ESMTPSA id k17-20020a05620a143100b006bb83e2e65fsm2190807qkj.42.2022.08.27.10.58.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 27 Aug 2022 10:58:13 -0700 (PDT) From: Yury Norov To: Linus Torvalds , linux-kernel@vger.kernel.org Cc: Yury Norov , Alexey Klimov , Andy Shevchenko , Andy Whitcroft , Catalin Marinas , David Laight , Dennis Zhou , Guenter Roeck , Kees Cook , Rasmus Villemoes , Russell King Subject: [PATCH v3 4/4] tools: sync find_bit() implementation Date: Sat, 27 Aug 2022 10:58:07 -0700 Message-Id: <20220827175807.4017673-5-yury.norov@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220827175807.4017673-1-yury.norov@gmail.com> References: <20220827175807.4017673-1-yury.norov@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Sync find_first_bit() and find_next_bit() implementation with the mother kernel. Also, drop unused find_last_bit() and find_next_clump8(). Signed-off-by: Yury Norov --- tools/include/linux/find.h | 61 +++------------ tools/lib/find_bit.c | 149 +++++++++++++++++-------------------- 2 files changed, 81 insertions(+), 129 deletions(-) diff --git a/tools/include/linux/find.h b/tools/include/linux/find.h index 47e2bd6c5174..38c0a542b0e2 100644 --- a/tools/include/linux/find.h +++ b/tools/include/linux/find.h @@ -8,21 +8,23 @@ =20 #include =20 -extern unsigned long _find_next_bit(const unsigned long *addr1, - const unsigned long *addr2, unsigned long nbits, - unsigned long start, unsigned long invert, unsigned long le); +unsigned long _find_next_bit(const unsigned long *addr1, unsigned long nbi= ts, + unsigned long start); +unsigned long _find_next_and_bit(const unsigned long *addr1, const unsigne= d long *addr2, + unsigned long nbits, unsigned long start); +unsigned long _find_next_zero_bit(const unsigned long *addr, unsigned long= nbits, + unsigned long start); extern unsigned long _find_first_bit(const unsigned long *addr, unsigned l= ong size); extern unsigned long _find_first_and_bit(const unsigned long *addr1, const unsigned long *addr2, unsigned long size); extern unsigned long _find_first_zero_bit(const unsigned long *addr, unsig= ned long size); -extern unsigned long _find_last_bit(const unsigned long *addr, unsigned lo= ng size); =20 #ifndef find_next_bit /** * find_next_bit - find the next set bit in a memory region * @addr: The address to base the search on - * @offset: The bitnumber to start searching at * @size: The bitmap size in bits + * @offset: The bitnumber to start searching at * * Returns the bit number for the next set bit * If no bits are set, returns @size. @@ -41,7 +43,7 @@ unsigned long find_next_bit(const unsigned long *addr, un= signed long size, return val ? __ffs(val) : size; } =20 - return _find_next_bit(addr, NULL, size, offset, 0UL, 0); + return _find_next_bit(addr, size, offset); } #endif =20 @@ -50,8 +52,8 @@ unsigned long find_next_bit(const unsigned long *addr, un= signed long size, * find_next_and_bit - find the next set bit in both memory regions * @addr1: The first address to base the search on * @addr2: The second address to base the search on - * @offset: The bitnumber to start searching at * @size: The bitmap size in bits + * @offset: The bitnumber to start searching at * * Returns the bit number for the next set bit * If no bits are set, returns @size. @@ -71,7 +73,7 @@ unsigned long find_next_and_bit(const unsigned long *addr= 1, return val ? __ffs(val) : size; } =20 - return _find_next_bit(addr1, addr2, size, offset, 0UL, 0); + return _find_next_and_bit(addr1, addr2, size, offset); } #endif =20 @@ -79,8 +81,8 @@ unsigned long find_next_and_bit(const unsigned long *addr= 1, /** * find_next_zero_bit - find the next cleared bit in a memory region * @addr: The address to base the search on - * @offset: The bitnumber to start searching at * @size: The bitmap size in bits + * @offset: The bitnumber to start searching at * * Returns the bit number of the next zero bit * If no bits are zero, returns @size. @@ -99,7 +101,7 @@ unsigned long find_next_zero_bit(const unsigned long *ad= dr, unsigned long size, return val =3D=3D ~0UL ? size : ffz(val); } =20 - return _find_next_bit(addr, NULL, size, offset, ~0UL, 0); + return _find_next_zero_bit(addr, size, offset); } #endif =20 @@ -172,43 +174,4 @@ unsigned long find_first_zero_bit(const unsigned long = *addr, unsigned long size) } #endif =20 -#ifndef find_last_bit -/** - * find_last_bit - find the last set bit in a memory region - * @addr: The address to start the search at - * @size: The number of bits to search - * - * Returns the bit number of the last set bit, or size. - */ -static inline -unsigned long find_last_bit(const unsigned long *addr, unsigned long size) -{ - if (small_const_nbits(size)) { - unsigned long val =3D *addr & GENMASK(size - 1, 0); - - return val ? __fls(val) : size; - } - - return _find_last_bit(addr, size); -} -#endif - -/** - * find_next_clump8 - find next 8-bit clump with set bits in a memory regi= on - * @clump: location to store copy of found clump - * @addr: address to base the search on - * @size: bitmap size in number of bits - * @offset: bit offset at which to start searching - * - * Returns the bit offset for the next set clump; the found clump value is - * copied to the location pointed by @clump. If no bits are set, returns @= size. - */ -extern unsigned long find_next_clump8(unsigned long *clump, - const unsigned long *addr, - unsigned long size, unsigned long offset); - -#define find_first_clump8(clump, bits, size) \ - find_next_clump8((clump), (bits), (size), 0) - - #endif /*__LINUX_FIND_H_ */ diff --git a/tools/lib/find_bit.c b/tools/lib/find_bit.c index ba4b8d94e004..709d312a94ca 100644 --- a/tools/lib/find_bit.c +++ b/tools/lib/find_bit.c @@ -18,66 +18,54 @@ #include #include =20 -#if !defined(find_next_bit) || !defined(find_next_zero_bit) || \ - !defined(find_next_and_bit) - /* - * This is a common helper function for find_next_bit, find_next_zero_bit,= and - * find_next_and_bit. The differences are: - * - The "invert" argument, which is XORed with each fetched word before - * searching it for one bits. - * - The optional "addr2", which is anded with "addr1" if present. + * Common helper for find_bit() function family + * @FETCH: The expression that fetches and pre-processes each word of bitm= ap(s) + * @MUNGE: The expression that post-processes a word containing found bit = (may be empty) + * @size: The bitmap size in bits */ -unsigned long _find_next_bit(const unsigned long *addr1, - const unsigned long *addr2, unsigned long nbits, - unsigned long start, unsigned long invert, unsigned long le) -{ - unsigned long tmp, mask; - (void) le; - - if (unlikely(start >=3D nbits)) - return nbits; - - tmp =3D addr1[start / BITS_PER_LONG]; - if (addr2) - tmp &=3D addr2[start / BITS_PER_LONG]; - tmp ^=3D invert; - - /* Handle 1st word. */ - mask =3D BITMAP_FIRST_WORD_MASK(start); - - /* - * Due to the lack of swab() in tools, and the fact that it doesn't - * need little-endian support, just comment it out - */ -#if (0) - if (le) - mask =3D swab(mask); -#endif - - tmp &=3D mask; +#define FIND_FIRST_BIT(FETCH, MUNGE, size) \ +({ \ + unsigned long idx, val, sz =3D (size); \ + \ + for (idx =3D 0; idx * BITS_PER_LONG < sz; idx++) { \ + val =3D (FETCH); \ + if (val) { \ + sz =3D min(idx * BITS_PER_LONG + __ffs(MUNGE(val)), sz); \ + break; \ + } \ + } \ + \ + sz; \ +}) =20 - start =3D round_down(start, BITS_PER_LONG); - - while (!tmp) { - start +=3D BITS_PER_LONG; - if (start >=3D nbits) - return nbits; - - tmp =3D addr1[start / BITS_PER_LONG]; - if (addr2) - tmp &=3D addr2[start / BITS_PER_LONG]; - tmp ^=3D invert; - } - -#if (0) - if (le) - tmp =3D swab(tmp); -#endif - - return min(start + __ffs(tmp), nbits); -} -#endif +/* + * Common helper for find_next_bit() function family + * @FETCH: The expression that fetches and pre-processes each word of bitm= ap(s) + * @MUNGE: The expression that post-processes a word containing found bit = (may be empty) + * @size: The bitmap size in bits + * @start: The bitnumber to start searching at + */ +#define FIND_NEXT_BIT(FETCH, MUNGE, size, start) \ +({ \ + unsigned long mask, idx, tmp, sz =3D (size), __start =3D (start); \ + \ + if (unlikely(__start >=3D sz)) \ + goto out; \ + \ + mask =3D MUNGE(BITMAP_FIRST_WORD_MASK(__start)); \ + idx =3D __start / BITS_PER_LONG; \ + \ + for (tmp =3D (FETCH) & mask; !tmp; tmp =3D (FETCH)) { \ + if (idx > sz / BITS_PER_LONG) \ + goto out; \ + idx++; \ + } \ + \ + sz =3D min(idx * BITS_PER_LONG + __ffs(MUNGE(tmp)), sz); \ +out: \ + sz; \ +}) =20 #ifndef find_first_bit /* @@ -85,14 +73,7 @@ unsigned long _find_next_bit(const unsigned long *addr1, */ unsigned long _find_first_bit(const unsigned long *addr, unsigned long siz= e) { - unsigned long idx; - - for (idx =3D 0; idx * BITS_PER_LONG < size; idx++) { - if (addr[idx]) - return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size); - } - - return size; + return FIND_FIRST_BIT(addr[idx], /* nop */, size); } #endif =20 @@ -104,15 +85,7 @@ unsigned long _find_first_and_bit(const unsigned long *= addr1, const unsigned long *addr2, unsigned long size) { - unsigned long idx, val; - - for (idx =3D 0; idx * BITS_PER_LONG < size; idx++) { - val =3D addr1[idx] & addr2[idx]; - if (val) - return min(idx * BITS_PER_LONG + __ffs(val), size); - } - - return size; + return FIND_FIRST_BIT(addr1[idx] & addr2[idx], /* nop */, size); } #endif =20 @@ -122,13 +95,29 @@ unsigned long _find_first_and_bit(const unsigned long = *addr1, */ unsigned long _find_first_zero_bit(const unsigned long *addr, unsigned lon= g size) { - unsigned long idx; + return FIND_FIRST_BIT(~addr[idx], /* nop */, size); +} +#endif =20 - for (idx =3D 0; idx * BITS_PER_LONG < size; idx++) { - if (addr[idx] !=3D ~0UL) - return min(idx * BITS_PER_LONG + ffz(addr[idx]), size); - } +#ifndef find_next_bit +unsigned long _find_next_bit(const unsigned long *addr, unsigned long nbit= s, unsigned long start) +{ + return FIND_NEXT_BIT(addr[idx], /* nop */, nbits, start); +} +#endif =20 - return size; +#ifndef find_next_and_bit +unsigned long _find_next_and_bit(const unsigned long *addr1, const unsigne= d long *addr2, + unsigned long nbits, unsigned long start) +{ + return FIND_NEXT_BIT(addr1[idx] & addr2[idx], /* nop */, nbits, start); +} +#endif + +#ifndef find_next_zero_bit +unsigned long _find_next_zero_bit(const unsigned long *addr, unsigned long= nbits, + unsigned long start) +{ + return FIND_NEXT_BIT(~addr[idx], /* nop */, nbits, start); } #endif --=20 2.34.1