Received: by 10.213.65.68 with SMTP id h4csp222282imn; Fri, 16 Mar 2018 00:32:43 -0700 (PDT) X-Google-Smtp-Source: AG47ELvyW0FygnqKt/WSGR66kX6uVjZ5iCfD+JNurFu4x4mZJFtjyQHxL591u+hAPaY733isVDv1 X-Received: by 2002:a17:902:b903:: with SMTP id bf3-v6mr1029909plb.316.1521185563150; Fri, 16 Mar 2018 00:32:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521185563; cv=none; d=google.com; s=arc-20160816; b=pKxFgxgO97JMJrAOJxF/ekUzRGmK9oad6ja2fZdj3MukITaBzoUpviQ9lEoX+JdmKK dCXdBS+WQOxQGN4LXVnYRi8XNl1f82mKsm0SuwhRnKbWGQ79QNHUVc8yY7vmMchTllqt 50lIfSM1OrULFFxtDrEygRVVICO+0y9/bkK/gkLkYFEli4KN5NzSV8TZWWQlFig8mAAH g49jxCwmpzFA4oxDOYQINgNh4XO8Rkd28LGW+SzxhHr4gumwW4NXAJPVJnn6Ydcv6pOj UkdvdF0v+pPARAbNhQkn503jCQcZ1wl60ULQ9NbHgtheMYEyw2X5MBazzdDj1C9IpD9B 69Ww== 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 :content-language:in-reply-to:mime-version:user-agent:date :message-id:organization:from:references:cc:to:subject :dkim-signature:arc-authentication-results; bh=Zeo13r/nYGYZbsIT7FAsiPG2r1uCAth0c1rS0Q3VXXk=; b=Z8pefDayfebPmhqw6Katueum1gqQsK0yv3ZGKsTcJYvGHj9M8JEC6YGIut2ZBdaXEG +3BQ5BP3qbmaVNFYv8RJMAi1JetA2utedGAvkjOHeFzj3linu5yb9w7+FpyIvF8buhuf w33l1OdHWy6aJvpiujpHKdU7ruL9JofdoTbwZSDyxBcD/HqTIfvdlbzL+D//kiVzZSh5 z05+qnJPlPp44HNJ+fFmp27R2GXlLoBP9m64JmYC0iKRwTCEXun8luczJKGyBbV/33v0 cbbfKDOvvhPlR8HCzrOlTGgnOZi9zyLLWQ7R+oUmBnhEmCV6fuVTI7v0YickgTMl2UJF 8Ciw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=B5Rm1xff; 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 m10si4667515pgs.253.2018.03.16.00.32.28; Fri, 16 Mar 2018 00:32:43 -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; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=B5Rm1xff; 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 S1753131AbeCPHbb (ORCPT + 99 others); Fri, 16 Mar 2018 03:31:31 -0400 Received: from galahad.ideasonboard.com ([185.26.127.97]:54993 "EHLO galahad.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751599AbeCPHb3 (ORCPT ); Fri, 16 Mar 2018 03:31:29 -0400 Received: from [192.168.43.222] (unknown [149.254.234.209]) by galahad.ideasonboard.com (Postfix) with ESMTPSA id 7C81B20381; Fri, 16 Mar 2018 08:29:10 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1521185353; bh=FRyhDyKDquQhocKCS3OtNMY8UhLxfgLiB89gVPv2oU8=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From; b=B5Rm1xffSl5NSc8cWwFUzeuTT82LL+IcKfzUyaJF5ZbN4qrLeCOacRIgLj02SfuZV Y3qEyr4i08KBk/dfbCpjmNIba20fxdq6kzhdVvEUHOcK1Nu+uCOvrkBiEOyBvBEpzM m3ndWKQDs5N5C9mJydOPNhur10I7hAUmb+vPkFwE= Subject: Re: [PATCH][RFC] kernel.h: provide array iterator To: Julia Lawall , Kees Cook , Kieran Bingham Cc: LKML , Laurent Pinchart , linux-media@vger.kernel.org, Andrew Morton , Ingo Molnar , Thomas Gleixner , Herbert Xu , Masahiro Yamada , Greg Kroah-Hartman , Krzysztof Kozlowski , Randy Dunlap , Ian Abbott , cocci@systeme.lip6.fr, keescook@google.com References: <1521108052-26861-1-git-send-email-kieran.bingham@ideasonboard.com> <3d969683074366dfa32e2fbb83bf3b65@lip6.fr> From: Kieran Bingham Organization: Ideas on Board Message-ID: Date: Fri, 16 Mar 2018 08:31:21 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.0 MIME-Version: 1.0 In-Reply-To: <3d969683074366dfa32e2fbb83bf3b65@lip6.fr> Content-Type: text/plain; charset=utf-8 Content-Language: en-GB Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Kees, Julia, On 16/03/18 07:41, Julia Lawall wrote: > Le 16.03.2018 05:21, Kees Cook a écrit : >> On Thu, Mar 15, 2018 at 3:00 AM, Kieran Bingham >> wrote: >>> Simplify array iteration with a helper to iterate each entry in an array. >>> Utilise the existing ARRAY_SIZE macro to identify the length of the array >>> and pointer arithmetic to process each item as a for loop. >>> >>> Signed-off-by: Kieran Bingham >>> --- >>>  include/linux/kernel.h | 10 ++++++++++ >>>  1 file changed, 10 insertions(+) >>> >>> The use of static arrays to store data is a common use case throughout the >>> kernel. Along with that is the obvious need to iterate that data. >>> >>> In fact there are just shy of 5000 instances of iterating a static array: >>>         git grep "for .*ARRAY_SIZE" | wc -l >>>         4943 >> >> I suspect the main question is "Does this macro make the code easier to read?" >> >> I think it does, and we have other kinds of iterators like this in the Great :-D - I'm happy to read that response! >> kernel already. Would it be worth building a Coccinelle script to do >> the 5000 replacements? Perhaps - though I suspect each case may have its nuances. Looking around - I see some loops depend on their 'i' index variable in different ways, so it might not always be convenient to remove that automagically. Or perhaps I'd have to provide an alternative _indexed variant somehow which can include the current offset... (or just include a scoped index in this iterator some how) Is there any policy or precedent on creating variables inside the scope of the loop only through a macro like this? (I'm sure I recall something in the back of my memory so I'll dig, but if anyone has pointers...) > Coccinelle should be able to replace the for loop header. I think that would be the main focus. We would also need to add an iterator somewhere in the scope of the function... > Coccinelle > could create the local macro. I made the local macro for better readability of my use case ... Other places could use the core macro directly - or also create a local macro. That would be a per use case option I believe. But I guess it wouldn't be too hard to form a macro using coccinelle with the name of the array or type that it is iterating though. > Coccinelle might not put the definition in > exactly the right place.  Before the function of the first use would be > possible, or before any function. IMO - a macro to iterate the array specifically should come directly(ish) after the declaration of the array where possible. (but not inside any struct if the array is in there of course) > I don't think that Coccinelle could figure out how to split one loop into > two as done here, unless that specific pattern is very common.  I guess > that the split is to add the flush_workqueue, and is not the main goal? Yes, the split of this loop into two was very specific to this instance of adding the flush_workqueue in the middle. It was this process of splitting the loop in two which led me wanting to optimise the iterators, rather than just duplicating it. Regards Kieran Bingham > julia > > > > >> -Kees >> >>> >>> When working on the UVC driver - I found that I needed to split one such >>> iteration into two parts, and at the same time felt that this could be >>> refactored to be cleaner / easier to read. >>> >>> I do however worry that this simple short patch might not be desired or could >>> also be heavily bikeshedded due to it's potential wide spread use (though >>> perhaps that would be a good thing to have more users) ...  but here it is, >>> along with an example usage below which is part of a separate series. >>> >>> The aim is to simplify iteration on static arrays, in the same way that we have >>> iterators for lists. The use of the ARRAY_SIZE macro, provides all the >>> protections given by "__must_be_array(arr)" to this macro too. >>> >>> Regards >>> >>> Kieran >>> >>> ============================================================================= >>> Example Usage from a pending UVC development: >>> >>> +#define for_each_uvc_urb(uvc_urb, uvc_streaming) \ >>> +       for_each_array_element(uvc_urb, uvc_streaming->uvc_urb) >>> >>>  /* >>>   * Uninitialize isochronous/bulk URBs and free transfer buffers. >>>   */ >>>  static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) >>>  { >>> -       struct urb *urb; >>> -       unsigned int i; >>> +       struct uvc_urb *uvc_urb; >>> >>>         uvc_video_stats_stop(stream); >>> >>> -       for (i = 0; i < UVC_URBS; ++i) { >>> -               struct uvc_urb *uvc_urb = &stream->uvc_urb[i]; >>> +       for_each_uvc_urb(uvc_urb, stream) >>> +               usb_kill_urb(uvc_urb->urb); >>> >>> -               urb = uvc_urb->urb; >>> -               if (urb == NULL) >>> -                       continue; >>> +       flush_workqueue(stream->async_wq); >>> >>> -               usb_kill_urb(urb); >>> -               usb_free_urb(urb); >>> +       for_each_uvc_urb(uvc_urb, stream) { >>> +               usb_free_urb(uvc_urb->urb); >>>                 uvc_urb->urb = NULL; >>>         } >>> >>>         if (free_buffers) >>>                 uvc_free_urb_buffers(stream); >>>  } >>> ============================================================================= >>> >>> >>> >>> >>> diff --git a/include/linux/kernel.h b/include/linux/kernel.h >>> index ce51455e2adf..95d7dae248b7 100644 >>> --- a/include/linux/kernel.h >>> +++ b/include/linux/kernel.h >>> @@ -70,6 +70,16 @@ >>>   */ >>>  #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) >>> >>> +/** >>> + * for_each_array_element - Iterate all items in an array >>> + * @elem: pointer of array type for iteration cursor >>> + * @array: array to be iterated >>> + */ >>> +#define for_each_array_element(elem, array) \ >>> +       for (elem = &(array)[0]; \ >>> +            elem < &(array)[ARRAY_SIZE(array)]; \ >>> +            ++elem) >>> + >>>  #define u64_to_user_ptr(x) (           \ >>>  {                                      \ >>>         typecheck(u64, x);              \ >>> -- >>> 2.7.4 >>>