Message ID | 20231204180603.470421-2-gnstark@salutedevices.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:bcd1:0:b0:403:3b70:6f57 with SMTP id r17csp2940278vqy; Mon, 4 Dec 2023 10:07:34 -0800 (PST) X-Google-Smtp-Source: AGHT+IHwQx8lfI/3X7OuPK5OkBlZ4zgiy0SZwsSUTqDwpoZnUrDfUBWXfD6hvXgiz+JsOKKyswpp X-Received: by 2002:a05:6a00:2d11:b0:6ce:689d:e002 with SMTP id fa17-20020a056a002d1100b006ce689de002mr143797pfb.42.1701713253856; Mon, 04 Dec 2023 10:07:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701713253; cv=none; d=google.com; s=arc-20160816; b=oyf8Kso9eFf/n/uU2ZdTEVlsvZX7n6tAKM7ye+VgVWgjyKV7unNE02oKJIzmPY8XEb jeEr8XZZFewQjegIV/NPsxzY63W/e5HaTnjULsoqFNKXQd8R6EHwypgg6to1nb706rTR fIgZr23kArAH/MGE+24zAaWt0gHG3eFuIdHKLvIlI5dnlHUzmdcvgypAOj6420XLd2+Q DFLreFO5VIdpu9cB77yA/XjFx3teoWqSixZm5PsfkiBDpEuCIDeqUiRgOpjFqBgadRx/ /0f+ZbOBLlR2dOpI0qJPwWZeA2ByLiXkYUDxSRn20zuInxpKgFFoCOHQ+kjQHoHfyfwj xMxw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature:dkim-filter; bh=C1kd2llJNcGGgAraxX7oH4BfSAuepfS4aqwkW0KOQ7M=; fh=pRi79UjbBxWuX+YtUUQtxvW+xSh0P2pNtOkO2EuISps=; b=kdcWVHURjSkAEpBEb/ERvZbRGjve+JvcRVOLM6d9xp6WJ5WUXK7RgoeCnviw4onPam hBONYfl88gOLNchbggObb6x+itkk+Ba+2qOEeWXcnyy4s45GhBQwB6lJvWm0eQLkvCtn f3ycsPQ+OZST2cXisIv7HxQDWs3W4bzWg5mSI1vzwaIw/h1lZDnnqyEFRwXTX1yAPHS+ KnojM2jXzfrxoH5BvfPTuCdNINxCnfONCPnJEXXHls26MRZ6lj6vnbvlSctkGd1ILPmL 9lFCWdKjDHotrwOiVejrBieMojrj7eRjqVEfG5QXOUu2ebxVPm5abdvZj0aL7NBR1LeB wYPg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@salutedevices.com header.s=mail header.b=JMFIIEw+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=salutedevices.com Received: from snail.vger.email (snail.vger.email. [2620:137:e000::3:7]) by mx.google.com with ESMTPS id cm3-20020a056a020a0300b0057755b2f032si1902441pgb.542.2023.12.04.10.07.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Dec 2023 10:07:33 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) client-ip=2620:137:e000::3:7; Authentication-Results: mx.google.com; dkim=pass header.i=@salutedevices.com header.s=mail header.b=JMFIIEw+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=salutedevices.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by snail.vger.email (Postfix) with ESMTP id 0C36480AC5A8; Mon, 4 Dec 2023 10:07:33 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at snail.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231803AbjLDSHW (ORCPT <rfc822;chrisfriedt@gmail.com> + 99 others); Mon, 4 Dec 2023 13:07:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35212 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231783AbjLDSHM (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Mon, 4 Dec 2023 13:07:12 -0500 Received: from mx1.sberdevices.ru (mx1.sberdevices.ru [37.18.73.165]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 68886FA; Mon, 4 Dec 2023 10:07:16 -0800 (PST) Received: from p-infra-ksmg-sc-msk01 (localhost [127.0.0.1]) by mx1.sberdevices.ru (Postfix) with ESMTP id B7D4610000A; Mon, 4 Dec 2023 21:07:14 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.sberdevices.ru B7D4610000A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=salutedevices.com; s=mail; t=1701713234; bh=C1kd2llJNcGGgAraxX7oH4BfSAuepfS4aqwkW0KOQ7M=; h=From:To:Subject:Date:Message-ID:MIME-Version:Content-Type:From; b=JMFIIEw+TJjmTZaUN2hwxIHFsYUAKZELyeJ7UiXtfsZsEkB9YNKyGrv8u/3IuFsZ9 bZrWfC857T2TXB2I0K/DzVOWPR7BRbDwfryP1rrll4TFBsXiwNcP+lADCmDOWittk/ L+cWaFO7Nl4L8x2di8RLkOv+n3yybtqNQgv/gqmcv7LreFSu8i2Bp/LTuKuMxO0KaI WGRNqhOCwXFAGujYvFY3nyP5pzCcBga70Org1s2OtNXM2wbXqIDtT8CjKUrYhFuhCD ZEopm8HY/eWEi9hELx5HgO/SW+s2CPEwIC84ryMu5wrcO3sBXH+m6xG6o5AxSlj84p zLb3c0DjmwJdg== Received: from p-i-exch-sc-m01.sberdevices.ru (p-i-exch-sc-m01.sberdevices.ru [172.16.192.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.sberdevices.ru (Postfix) with ESMTPS; Mon, 4 Dec 2023 21:07:14 +0300 (MSK) Received: from localhost.localdomain (100.64.160.123) by p-i-exch-sc-m01.sberdevices.ru (172.16.192.107) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.40; Mon, 4 Dec 2023 21:07:14 +0300 From: George Stark <gnstark@salutedevices.com> To: <pavel@ucw.cz>, <lee@kernel.org>, <vadimp@nvidia.com>, <mpe@ellerman.id.au>, <npiggin@gmail.com>, <christophe.leroy@csgroup.eu>, <hdegoede@redhat.com>, <mazziesaccount@gmail.com>, <andy.shevchenko@gmail.com>, <jic23@kernel.org> CC: <linux-leds@vger.kernel.org>, <linux-kernel@vger.kernel.org>, <linuxppc-dev@lists.ozlabs.org>, <kernel@salutedevices.com>, George Stark <gnstark@salutedevices.com> Subject: [PATCH v2 01/10] devm-helpers: introduce devm_mutex_init Date: Mon, 4 Dec 2023 21:05:54 +0300 Message-ID: <20231204180603.470421-2-gnstark@salutedevices.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231204180603.470421-1-gnstark@salutedevices.com> References: <20231204180603.470421-1-gnstark@salutedevices.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Originating-IP: [100.64.160.123] X-ClientProxiedBy: p-i-exch-sc-m01.sberdevices.ru (172.16.192.107) To p-i-exch-sc-m01.sberdevices.ru (172.16.192.107) X-KSMG-Rule-ID: 10 X-KSMG-Message-Action: clean X-KSMG-AntiSpam-Lua-Profiles: 181831 [Dec 04 2023] X-KSMG-AntiSpam-Version: 6.0.0.2 X-KSMG-AntiSpam-Envelope-From: gnstark@salutedevices.com X-KSMG-AntiSpam-Rate: 0 X-KSMG-AntiSpam-Status: not_detected X-KSMG-AntiSpam-Method: none X-KSMG-AntiSpam-Auth: dkim=none X-KSMG-AntiSpam-Info: LuaCore: 5 0.3.5 98d108ddd984cca1d7e65e595eac546a62b0144b, {Tracking_from_domain_doesnt_match_to}, salutedevices.com:7.1.1;100.64.160.123:7.1.2;d41d8cd98f00b204e9800998ecf8427e.com:7.1.1;127.0.0.199:7.1.2;p-i-exch-sc-m01.sberdevices.ru:7.1.1,5.0.1, FromAlignment: s, ApMailHostAddress: 100.64.160.123 X-MS-Exchange-Organization-SCL: -1 X-KSMG-AntiSpam-Interceptor-Info: scan successful X-KSMG-AntiPhishing: Clean X-KSMG-LinksScanning: Clean X-KSMG-AntiVirus: Kaspersky Secure Mail Gateway, version 2.0.1.6960, bases: 2023/12/04 11:06:00 #22624476 X-KSMG-AntiVirus-Status: Clean, skipped X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_NONE,SPF_NONE,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (snail.vger.email [0.0.0.0]); Mon, 04 Dec 2023 10:07:33 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1784375676703290860 X-GMAIL-MSGID: 1784375676703290860 |
Series |
devm_led_classdev_register() usage problem
|
|
Commit Message
George Stark
Dec. 4, 2023, 6:05 p.m. UTC
Using of devm API leads to certain order of releasing resources.
So all dependent resources which are not devm-wrapped should be deleted
with respect to devm-release order. Mutex is one of such objects that
often is bound to other resources and has no own devm wrapping.
Since mutex_destroy() actually does nothing in non-debug builds
frequently calling mutex_destroy() is just ignored which is safe for now
but wrong formally and can lead to a problem if mutex_destroy() is
extended so introduce devm_mutex_init().
Signed-off-by: George Stark <gnstark@salutedevices.com>
---
include/linux/devm-helpers.h | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
Comments
On Mon, Dec 4, 2023 at 8:07 PM George Stark <gnstark@salutedevices.com> wrote: > > Using of devm API leads to certain order of releasing resources. > So all dependent resources which are not devm-wrapped should be deleted > with respect to devm-release order. Mutex is one of such objects that > often is bound to other resources and has no own devm wrapping. > Since mutex_destroy() actually does nothing in non-debug builds > frequently calling mutex_destroy() is just ignored which is safe for now > but wrong formally and can lead to a problem if mutex_destroy() is > extended so introduce devm_mutex_init(). ... Do you need to include mutex.h? ... > +/** > + * devm_mutex_init - Resource-managed mutex initialization > + * @dev: Device which lifetime work is bound to > + * @lock: Pointer to a mutex > + * > + * Initialize mutex which is automatically destroyed when driver is detached. the driver Have you run scripts/kernel-doc -v -Wall -none ... against this file? I'm pretty sure it will complain. > + */
Le 04/12/2023 à 19:05, George Stark a écrit : > Using of devm API leads to certain order of releasing resources. > So all dependent resources which are not devm-wrapped should be deleted > with respect to devm-release order. Mutex is one of such objects that > often is bound to other resources and has no own devm wrapping. > Since mutex_destroy() actually does nothing in non-debug builds > frequently calling mutex_destroy() is just ignored which is safe for now > but wrong formally and can lead to a problem if mutex_destroy() is > extended so introduce devm_mutex_init(). This is not needed for patch 2. Should patch 2 go first ? > > Signed-off-by: George Stark <gnstark@salutedevices.com> > --- > include/linux/devm-helpers.h | 18 ++++++++++++++++++ > 1 file changed, 18 insertions(+) > > diff --git a/include/linux/devm-helpers.h b/include/linux/devm-helpers.h > index 74891802200d..2f56e476776f 100644 > --- a/include/linux/devm-helpers.h > +++ b/include/linux/devm-helpers.h > @@ -76,4 +76,22 @@ static inline int devm_work_autocancel(struct device *dev, > return devm_add_action(dev, devm_work_drop, w); > } > > +static inline void devm_mutex_release(void *res) > +{ > + mutex_destroy(res); > +} > + > +/** > + * devm_mutex_init - Resource-managed mutex initialization > + * @dev: Device which lifetime work is bound to > + * @lock: Pointer to a mutex > + * > + * Initialize mutex which is automatically destroyed when driver is detached. > + */ > +static inline int devm_mutex_init(struct device *dev, struct mutex *lock) > +{ > + mutex_init(lock); > + return devm_add_action_or_reset(dev, devm_mutex_release, lock); > +} > + > #endif
On 12/4/23 20:05, George Stark wrote: > Using of devm API leads to certain order of releasing resources. > So all dependent resources which are not devm-wrapped should be deleted > with respect to devm-release order. Mutex is one of such objects that > often is bound to other resources and has no own devm wrapping. > Since mutex_destroy() actually does nothing in non-debug builds > frequently calling mutex_destroy() is just ignored which is safe for now > but wrong formally and can lead to a problem if mutex_destroy() is > extended so introduce devm_mutex_init(). > > Signed-off-by: George Stark <gnstark@salutedevices.com> > --- > include/linux/devm-helpers.h | 18 ++++++++++++++++++ > 1 file changed, 18 insertions(+) > > diff --git a/include/linux/devm-helpers.h b/include/linux/devm-helpers.h > index 74891802200d..2f56e476776f 100644 > --- a/include/linux/devm-helpers.h > +++ b/include/linux/devm-helpers.h > @@ -76,4 +76,22 @@ static inline int devm_work_autocancel(struct device *dev, > return devm_add_action(dev, devm_work_drop, w); > } > > +static inline void devm_mutex_release(void *res) > +{ > + mutex_destroy(res); > +} > + > +/** > + * devm_mutex_init - Resource-managed mutex initialization > + * @dev: Device which lifetime work is bound to Work? Copy-paste error? > + * @lock: Pointer to a mutex > + * > + * Initialize mutex which is automatically destroyed when driver is detached. > + */ > +static inline int devm_mutex_init(struct device *dev, struct mutex *lock) > +{ > + mutex_init(lock); > + return devm_add_action_or_reset(dev, devm_mutex_release, lock); > +} > + > #endif Doesn't the mutex stuff need a header inclusion? Yours, -- Matti
Hello Andy Thanks for the review. On 12/4/23 21:11, Andy Shevchenko wrote: > On Mon, Dec 4, 2023 at 8:07 PM George Stark <gnstark@salutedevices.com> wrote: >> >> Using of devm API leads to certain order of releasing resources. >> So all dependent resources which are not devm-wrapped should be deleted >> with respect to devm-release order. Mutex is one of such objects that >> often is bound to other resources and has no own devm wrapping. >> Since mutex_destroy() actually does nothing in non-debug builds >> frequently calling mutex_destroy() is just ignored which is safe for now >> but wrong formally and can lead to a problem if mutex_destroy() is >> extended so introduce devm_mutex_init(). > > ... > > Do you need to include mutex.h? It's already included in linux/device.h which is included in devm-helpers. Should I include mutex.h explicitly? > > ... > >> +/** >> + * devm_mutex_init - Resource-managed mutex initialization >> + * @dev: Device which lifetime work is bound to >> + * @lock: Pointer to a mutex >> + * >> + * Initialize mutex which is automatically destroyed when driver is detached. > > the driver > > Have you run scripts/kernel-doc -v -Wall -none ... against this file? > I'm pretty sure it will complain. It does with warning "No description found for return value". Fixed > >> + */ > >
Hi, On 12/6/23 08:56, George Stark wrote: > Hello Andy > > Thanks for the review. > > On 12/4/23 21:11, Andy Shevchenko wrote: >> On Mon, Dec 4, 2023 at 8:07 PM George Stark <gnstark@salutedevices.com> wrote: >>> >>> Using of devm API leads to certain order of releasing resources. >>> So all dependent resources which are not devm-wrapped should be deleted >>> with respect to devm-release order. Mutex is one of such objects that >>> often is bound to other resources and has no own devm wrapping. >>> Since mutex_destroy() actually does nothing in non-debug builds >>> frequently calling mutex_destroy() is just ignored which is safe for now >>> but wrong formally and can lead to a problem if mutex_destroy() is >>> extended so introduce devm_mutex_init(). >> >> ... >> >> Do you need to include mutex.h? > It's already included in linux/device.h which is included in devm-helpers. Should I include mutex.h explicitly? Yes you must explicitly include all headers you use definitions from. Relying on other headers to do this for you is error prone. Regards, Hans
Hi George, On 12/4/23 19:05, George Stark wrote: > Using of devm API leads to certain order of releasing resources. > So all dependent resources which are not devm-wrapped should be deleted > with respect to devm-release order. Mutex is one of such objects that > often is bound to other resources and has no own devm wrapping. > Since mutex_destroy() actually does nothing in non-debug builds > frequently calling mutex_destroy() is just ignored which is safe for now > but wrong formally and can lead to a problem if mutex_destroy() is > extended so introduce devm_mutex_init(). > > Signed-off-by: George Stark <gnstark@salutedevices.com> > --- > include/linux/devm-helpers.h | 18 ++++++++++++++++++ > 1 file changed, 18 insertions(+) > > diff --git a/include/linux/devm-helpers.h b/include/linux/devm-helpers.h > index 74891802200d..2f56e476776f 100644 > --- a/include/linux/devm-helpers.h > +++ b/include/linux/devm-helpers.h > @@ -76,4 +76,22 @@ static inline int devm_work_autocancel(struct device *dev, > return devm_add_action(dev, devm_work_drop, w); > } > > +static inline void devm_mutex_release(void *res) > +{ > + mutex_destroy(res); > +} > + > +/** > + * devm_mutex_init - Resource-managed mutex initialization > + * @dev: Device which lifetime work is bound to > + * @lock: Pointer to a mutex > + * > + * Initialize mutex which is automatically destroyed when driver is detached. > + */ > +static inline int devm_mutex_init(struct device *dev, struct mutex *lock) > +{ > + mutex_init(lock); > + return devm_add_action_or_reset(dev, devm_mutex_release, lock); > +} > + > #endif mutex_destroy() only actually does anything if CONFIG_DEBUG_MUTEXES is set, otherwise it is an empty inline-stub. Adding a devres resource to the device just to call an empty inline stub which is a no-op seems like a waste of resources. IMHO it would be better to change this to: static inline int devm_mutex_init(struct device *dev, struct mutex *lock) { mutex_init(lock); #ifdef CONFIG_DEBUG_MUTEXES return devm_add_action_or_reset(dev, devm_mutex_release, lock); #else return 0; #endif } To avoid the unnecessary devres allocation when CONFIG_DEBUG_MUTEXES is not set. Regards, Hans
Hello Hans Thanks for the review. On 12/6/23 18:01, Hans de Goede wrote: > Hi George, > > On 12/4/23 19:05, George Stark wrote: >> Using of devm API leads to certain order of releasing resources. >> So all dependent resources which are not devm-wrapped should be deleted >> with respect to devm-release order. Mutex is one of such objects that >> often is bound to other resources and has no own devm wrapping. >> Since mutex_destroy() actually does nothing in non-debug builds >> frequently calling mutex_destroy() is just ignored which is safe for now >> but wrong formally and can lead to a problem if mutex_destroy() is >> extended so introduce devm_mutex_init(). >> >> Signed-off-by: George Stark <gnstark@salutedevices.com> >> --- >> include/linux/devm-helpers.h | 18 ++++++++++++++++++ >> 1 file changed, 18 insertions(+) >> >> diff --git a/include/linux/devm-helpers.h b/include/linux/devm-helpers.h >> index 74891802200d..2f56e476776f 100644 >> --- a/include/linux/devm-helpers.h >> +++ b/include/linux/devm-helpers.h >> @@ -76,4 +76,22 @@ static inline int devm_work_autocancel(struct device *dev, >> return devm_add_action(dev, devm_work_drop, w); >> } >> >> +static inline void devm_mutex_release(void *res) >> +{ >> + mutex_destroy(res); >> +} >> + >> +/** >> + * devm_mutex_init - Resource-managed mutex initialization >> + * @dev: Device which lifetime work is bound to >> + * @lock: Pointer to a mutex >> + * >> + * Initialize mutex which is automatically destroyed when driver is detached. >> + */ >> +static inline int devm_mutex_init(struct device *dev, struct mutex *lock) >> +{ >> + mutex_init(lock); >> + return devm_add_action_or_reset(dev, devm_mutex_release, lock); >> +} >> + >> #endif > > mutex_destroy() only actually does anything if CONFIG_DEBUG_MUTEXES > is set, otherwise it is an empty inline-stub. > > Adding a devres resource to the device just to call an empty inline > stub which is a no-op seems like a waste of resources. IMHO it > would be better to change this to: > > static inline int devm_mutex_init(struct device *dev, struct mutex *lock) > { > mutex_init(lock); > #ifdef CONFIG_DEBUG_MUTEXES > return devm_add_action_or_reset(dev, devm_mutex_release, lock); > #else > return 0; > #endif > } > > To avoid the unnecessary devres allocation when > CONFIG_DEBUG_MUTEXES is not set. Honestly saying I don't like unnecessary devres allocation either but the proposed approach has its own price: 1) we'll have more than one place with branching if mutex_destroy is empty or not using indirect condition. If suddenly mutex_destroy is extended for non-debug code (in upstream branch or e.g. by someone for local debug) than there'll be a problem. 2) If mutex_destroy is empty or not depends on CONFIG_PREEMPT_RT option too. When CONFIG_PREEMPT_RT is on mutex_destroy is always empty. As I see it only the mutex interface (mutex.h) has to say definitely if mutex_destroy must be called. Probably we could add some define to include/linux/mutex.h,like IS_MUTEX_DESTROY_REQUIRED and declare it near mutex_destroy definition itself. I tried to put devm_mutex_init itself in mutex.h and it could've helped too but it's not the place for devm API. > > Regards, > > Hans > > > >
Hi, On 12/6/23 19:58, George Stark wrote: > > Hello Hans > > Thanks for the review. > > On 12/6/23 18:01, Hans de Goede wrote: >> Hi George, >> >> On 12/4/23 19:05, George Stark wrote: >>> Using of devm API leads to certain order of releasing resources. >>> So all dependent resources which are not devm-wrapped should be deleted >>> with respect to devm-release order. Mutex is one of such objects that >>> often is bound to other resources and has no own devm wrapping. >>> Since mutex_destroy() actually does nothing in non-debug builds >>> frequently calling mutex_destroy() is just ignored which is safe for now >>> but wrong formally and can lead to a problem if mutex_destroy() is >>> extended so introduce devm_mutex_init(). >>> >>> Signed-off-by: George Stark <gnstark@salutedevices.com> >>> --- >>> include/linux/devm-helpers.h | 18 ++++++++++++++++++ >>> 1 file changed, 18 insertions(+) >>> >>> diff --git a/include/linux/devm-helpers.h b/include/linux/devm-helpers.h >>> index 74891802200d..2f56e476776f 100644 >>> --- a/include/linux/devm-helpers.h >>> +++ b/include/linux/devm-helpers.h >>> @@ -76,4 +76,22 @@ static inline int devm_work_autocancel(struct device *dev, >>> return devm_add_action(dev, devm_work_drop, w); >>> } >>> +static inline void devm_mutex_release(void *res) >>> +{ >>> + mutex_destroy(res); >>> +} >>> + >>> +/** >>> + * devm_mutex_init - Resource-managed mutex initialization >>> + * @dev: Device which lifetime work is bound to >>> + * @lock: Pointer to a mutex >>> + * >>> + * Initialize mutex which is automatically destroyed when driver is detached. >>> + */ >>> +static inline int devm_mutex_init(struct device *dev, struct mutex *lock) >>> +{ >>> + mutex_init(lock); >>> + return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>> +} >>> + >>> #endif >> >> mutex_destroy() only actually does anything if CONFIG_DEBUG_MUTEXES >> is set, otherwise it is an empty inline-stub. >> >> Adding a devres resource to the device just to call an empty inline >> stub which is a no-op seems like a waste of resources. IMHO it >> would be better to change this to: >> >> static inline int devm_mutex_init(struct device *dev, struct mutex *lock) >> { >> mutex_init(lock); >> #ifdef CONFIG_DEBUG_MUTEXES >> return devm_add_action_or_reset(dev, devm_mutex_release, lock); >> #else >> return 0; >> #endif >> } >> >> To avoid the unnecessary devres allocation when >> CONFIG_DEBUG_MUTEXES is not set. > > Honestly saying I don't like unnecessary devres allocation either but the proposed approach has its own price: > > 1) we'll have more than one place with branching if mutex_destroy is empty or not using indirect condition. If suddenly mutex_destroy is extended for non-debug code (in upstream branch or e.g. by someone for local debug) than there'll be a problem. > > 2) If mutex_destroy is empty or not depends on CONFIG_PREEMPT_RT option too. When CONFIG_PREEMPT_RT is on mutex_destroy is always empty. > > As I see it only the mutex interface (mutex.h) has to say definitely if mutex_destroy must be called. Probably we could add some define to include/linux/mutex.h,like IS_MUTEX_DESTROY_REQUIRED and declare it near mutex_destroy definition itself. That (a IS_MUTEX_DESTROY_REQUIRED define) is an interesting idea. Lets see for v3 if the mutex maintainers will accept that and if not then I guess we will just need to live with the unnecessary devres allocation. Regards, Hans
On 12/6/23 14:55, Hans de Goede wrote: > Hi, > > On 12/6/23 19:58, George Stark wrote: >> Hello Hans >> >> Thanks for the review. >> >> On 12/6/23 18:01, Hans de Goede wrote: >>> Hi George, >>> >>> On 12/4/23 19:05, George Stark wrote: >>>> Using of devm API leads to certain order of releasing resources. >>>> So all dependent resources which are not devm-wrapped should be deleted >>>> with respect to devm-release order. Mutex is one of such objects that >>>> often is bound to other resources and has no own devm wrapping. >>>> Since mutex_destroy() actually does nothing in non-debug builds >>>> frequently calling mutex_destroy() is just ignored which is safe for now >>>> but wrong formally and can lead to a problem if mutex_destroy() is >>>> extended so introduce devm_mutex_init(). >>>> >>>> Signed-off-by: George Stark <gnstark@salutedevices.com> >>>> --- >>>> include/linux/devm-helpers.h | 18 ++++++++++++++++++ >>>> 1 file changed, 18 insertions(+) >>>> >>>> diff --git a/include/linux/devm-helpers.h b/include/linux/devm-helpers.h >>>> index 74891802200d..2f56e476776f 100644 >>>> --- a/include/linux/devm-helpers.h >>>> +++ b/include/linux/devm-helpers.h >>>> @@ -76,4 +76,22 @@ static inline int devm_work_autocancel(struct device *dev, >>>> return devm_add_action(dev, devm_work_drop, w); >>>> } >>>> +static inline void devm_mutex_release(void *res) >>>> +{ >>>> + mutex_destroy(res); >>>> +} >>>> + >>>> +/** >>>> + * devm_mutex_init - Resource-managed mutex initialization >>>> + * @dev: Device which lifetime work is bound to >>>> + * @lock: Pointer to a mutex >>>> + * >>>> + * Initialize mutex which is automatically destroyed when driver is detached. >>>> + */ >>>> +static inline int devm_mutex_init(struct device *dev, struct mutex *lock) >>>> +{ >>>> + mutex_init(lock); >>>> + return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>>> +} >>>> + >>>> #endif >>> mutex_destroy() only actually does anything if CONFIG_DEBUG_MUTEXES >>> is set, otherwise it is an empty inline-stub. >>> >>> Adding a devres resource to the device just to call an empty inline >>> stub which is a no-op seems like a waste of resources. IMHO it >>> would be better to change this to: >>> >>> static inline int devm_mutex_init(struct device *dev, struct mutex *lock) >>> { >>> mutex_init(lock); >>> #ifdef CONFIG_DEBUG_MUTEXES >>> return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>> #else >>> return 0; >>> #endif >>> } >>> >>> To avoid the unnecessary devres allocation when >>> CONFIG_DEBUG_MUTEXES is not set. >> Honestly saying I don't like unnecessary devres allocation either but the proposed approach has its own price: >> >> 1) we'll have more than one place with branching if mutex_destroy is empty or not using indirect condition. If suddenly mutex_destroy is extended for non-debug code (in upstream branch or e.g. by someone for local debug) than there'll be a problem. >> >> 2) If mutex_destroy is empty or not depends on CONFIG_PREEMPT_RT option too. When CONFIG_PREEMPT_RT is on mutex_destroy is always empty. >> >> As I see it only the mutex interface (mutex.h) has to say definitely if mutex_destroy must be called. Probably we could add some define to include/linux/mutex.h,like IS_MUTEX_DESTROY_REQUIRED and declare it near mutex_destroy definition itself. > That (a IS_MUTEX_DESTROY_REQUIRED define) is an interesting idea. Lets see for v3 if the mutex maintainers will accept that and if not then I guess we will just need to live with the unnecessary devres allocation. The purpose of calling mutex_destroy() is to mark a mutex as being destroyed so that any subsequent call to mutex_lock/unlock will cause a warning to be printed when CONFIG_DEBUG_MUTEXES is defined. I would not say that mutex_destroy() is required. Rather it is a nice to have for catching programming error. Cheers, Longman
Le 06/12/2023 à 19:58, George Stark a écrit : > [Vous ne recevez pas souvent de courriers de gnstark@salutedevices.com. > Découvrez pourquoi ceci est important à > https://aka.ms/LearnAboutSenderIdentification ] > > Hello Hans > > Thanks for the review. > > On 12/6/23 18:01, Hans de Goede wrote: >> Hi George, >> >> On 12/4/23 19:05, George Stark wrote: >>> Using of devm API leads to certain order of releasing resources. >>> So all dependent resources which are not devm-wrapped should be deleted >>> with respect to devm-release order. Mutex is one of such objects that >>> often is bound to other resources and has no own devm wrapping. >>> Since mutex_destroy() actually does nothing in non-debug builds >>> frequently calling mutex_destroy() is just ignored which is safe for now >>> but wrong formally and can lead to a problem if mutex_destroy() is >>> extended so introduce devm_mutex_init(). >>> >>> Signed-off-by: George Stark <gnstark@salutedevices.com> >>> --- >>> include/linux/devm-helpers.h | 18 ++++++++++++++++++ >>> 1 file changed, 18 insertions(+) >>> >>> diff --git a/include/linux/devm-helpers.h b/include/linux/devm-helpers.h >>> index 74891802200d..2f56e476776f 100644 >>> --- a/include/linux/devm-helpers.h >>> +++ b/include/linux/devm-helpers.h >>> @@ -76,4 +76,22 @@ static inline int devm_work_autocancel(struct >>> device *dev, >>> return devm_add_action(dev, devm_work_drop, w); >>> } >>> >>> +static inline void devm_mutex_release(void *res) >>> +{ >>> + mutex_destroy(res); >>> +} >>> + >>> +/** >>> + * devm_mutex_init - Resource-managed mutex initialization >>> + * @dev: Device which lifetime work is bound to >>> + * @lock: Pointer to a mutex >>> + * >>> + * Initialize mutex which is automatically destroyed when driver is >>> detached. >>> + */ >>> +static inline int devm_mutex_init(struct device *dev, struct mutex >>> *lock) >>> +{ >>> + mutex_init(lock); >>> + return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>> +} >>> + >>> #endif >> >> mutex_destroy() only actually does anything if CONFIG_DEBUG_MUTEXES >> is set, otherwise it is an empty inline-stub. >> >> Adding a devres resource to the device just to call an empty inline >> stub which is a no-op seems like a waste of resources. IMHO it >> would be better to change this to: >> >> static inline int devm_mutex_init(struct device *dev, struct mutex *lock) >> { >> mutex_init(lock); >> #ifdef CONFIG_DEBUG_MUTEXES >> return devm_add_action_or_reset(dev, devm_mutex_release, lock); >> #else >> return 0; >> #endif >> } >> >> To avoid the unnecessary devres allocation when >> CONFIG_DEBUG_MUTEXES is not set. > > Honestly saying I don't like unnecessary devres allocation either but > the proposed approach has its own price: > > 1) we'll have more than one place with branching if mutex_destroy is > empty or not using indirect condition. If suddenly mutex_destroy is > extended for non-debug code (in upstream branch or e.g. by someone for > local debug) than there'll be a problem. > > 2) If mutex_destroy is empty or not depends on CONFIG_PREEMPT_RT option > too. When CONFIG_PREEMPT_RT is on mutex_destroy is always empty. > > As I see it only the mutex interface (mutex.h) has to say definitely if > mutex_destroy must be called. Probably we could add some define to > include/linux/mutex.h,like IS_MUTEX_DESTROY_REQUIRED and declare it near > mutex_destroy definition itself. > > I tried to put devm_mutex_init itself in mutex.h and it could've helped > too but it's not the place for devm API. > What do you mean by "it's not the place for devm API" ? If you do a 'grep devm_ include/linux/' you'll find devm_ functions in almost 100 .h files. Why wouldn't mutex.h be the place for devm_mutex_init() ? Christophe
Le 06/12/2023 à 23:14, Christophe Leroy a écrit : > > > Le 06/12/2023 à 19:58, George Stark a écrit : >> [Vous ne recevez pas souvent de courriers de >> gnstark@salutedevices.com. Découvrez pourquoi ceci est important à >> https://aka.ms/LearnAboutSenderIdentification ] >> >> Hello Hans >> >> Thanks for the review. >> >> On 12/6/23 18:01, Hans de Goede wrote: >>> Hi George, >>> >>> On 12/4/23 19:05, George Stark wrote: >>>> Using of devm API leads to certain order of releasing resources. >>>> So all dependent resources which are not devm-wrapped should be deleted >>>> with respect to devm-release order. Mutex is one of such objects that >>>> often is bound to other resources and has no own devm wrapping. >>>> Since mutex_destroy() actually does nothing in non-debug builds >>>> frequently calling mutex_destroy() is just ignored which is safe for >>>> now >>>> but wrong formally and can lead to a problem if mutex_destroy() is >>>> extended so introduce devm_mutex_init(). >>>> >>>> Signed-off-by: George Stark <gnstark@salutedevices.com> >>>> --- >>>> include/linux/devm-helpers.h | 18 ++++++++++++++++++ >>>> 1 file changed, 18 insertions(+) >>>> >>>> diff --git a/include/linux/devm-helpers.h >>>> b/include/linux/devm-helpers.h >>>> index 74891802200d..2f56e476776f 100644 >>>> --- a/include/linux/devm-helpers.h >>>> +++ b/include/linux/devm-helpers.h >>>> @@ -76,4 +76,22 @@ static inline int devm_work_autocancel(struct >>>> device *dev, >>>> return devm_add_action(dev, devm_work_drop, w); >>>> } >>>> >>>> +static inline void devm_mutex_release(void *res) >>>> +{ >>>> + mutex_destroy(res); >>>> +} >>>> + >>>> +/** >>>> + * devm_mutex_init - Resource-managed mutex initialization >>>> + * @dev: Device which lifetime work is bound to >>>> + * @lock: Pointer to a mutex >>>> + * >>>> + * Initialize mutex which is automatically destroyed when driver is >>>> detached. >>>> + */ >>>> +static inline int devm_mutex_init(struct device *dev, struct mutex >>>> *lock) >>>> +{ >>>> + mutex_init(lock); >>>> + return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>>> +} >>>> + >>>> #endif >>> >>> mutex_destroy() only actually does anything if CONFIG_DEBUG_MUTEXES >>> is set, otherwise it is an empty inline-stub. >>> >>> Adding a devres resource to the device just to call an empty inline >>> stub which is a no-op seems like a waste of resources. IMHO it >>> would be better to change this to: >>> >>> static inline int devm_mutex_init(struct device *dev, struct mutex >>> *lock) >>> { >>> mutex_init(lock); >>> #ifdef CONFIG_DEBUG_MUTEXES >>> return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>> #else >>> return 0; >>> #endif >>> } >>> >>> To avoid the unnecessary devres allocation when >>> CONFIG_DEBUG_MUTEXES is not set. >> >> Honestly saying I don't like unnecessary devres allocation either but >> the proposed approach has its own price: >> >> 1) we'll have more than one place with branching if mutex_destroy is >> empty or not using indirect condition. If suddenly mutex_destroy is >> extended for non-debug code (in upstream branch or e.g. by someone for >> local debug) than there'll be a problem. >> >> 2) If mutex_destroy is empty or not depends on CONFIG_PREEMPT_RT option >> too. When CONFIG_PREEMPT_RT is on mutex_destroy is always empty. >> >> As I see it only the mutex interface (mutex.h) has to say definitely if >> mutex_destroy must be called. Probably we could add some define to >> include/linux/mutex.h,like IS_MUTEX_DESTROY_REQUIRED and declare it near >> mutex_destroy definition itself. >> >> I tried to put devm_mutex_init itself in mutex.h and it could've helped >> too but it's not the place for devm API. >> > > What do you mean by "it's not the place for devm API" ? > > If you do a 'grep devm_ include/linux/' you'll find devm_ functions in > almost 100 .h files. Why wouldn't mutex.h be the place for > devm_mutex_init() ? Looking at it closer, I have the feeling that you want to do similar to devm_gpio_request() in linux/gpio.h : In linux/mutex.h, add a prototype for devm_mutex_init() when CONFIG_DEBUG_MUTEXES is defined and an empty static inline otherwise. Then define devm_mutex_init() in kernel/locking/mutex-debug.c Wouldn't that work ? Christophe
Hello Christophe On 12/7/23 01:37, Christophe Leroy wrote: > > > Le 06/12/2023 à 23:14, Christophe Leroy a écrit : >> >> >> Le 06/12/2023 à 19:58, George Stark a écrit : >>> [Vous ne recevez pas souvent de courriers de >>> gnstark@salutedevices.com. Découvrez pourquoi ceci est important à >>> https://aka.ms/LearnAboutSenderIdentification ] >>> >>> Hello Hans >>> >>> Thanks for the review. >>> >>> On 12/6/23 18:01, Hans de Goede wrote: >>>> Hi George, >>>> >>>> On 12/4/23 19:05, George Stark wrote: >>>>> Using of devm API leads to certain order of releasing resources. >>>>> So all dependent resources which are not devm-wrapped should be deleted >>>>> with respect to devm-release order. Mutex is one of such objects that >>>>> often is bound to other resources and has no own devm wrapping. >>>>> Since mutex_destroy() actually does nothing in non-debug builds >>>>> frequently calling mutex_destroy() is just ignored which is safe for >>>>> now >>>>> but wrong formally and can lead to a problem if mutex_destroy() is >>>>> extended so introduce devm_mutex_init(). >>>>> >>>>> Signed-off-by: George Stark <gnstark@salutedevices.com> >>>>> --- >>>>> include/linux/devm-helpers.h | 18 ++++++++++++++++++ >>>>> 1 file changed, 18 insertions(+) >>>>> >>>>> diff --git a/include/linux/devm-helpers.h >>>>> b/include/linux/devm-helpers.h >>>>> index 74891802200d..2f56e476776f 100644 >>>>> --- a/include/linux/devm-helpers.h >>>>> +++ b/include/linux/devm-helpers.h >>>>> @@ -76,4 +76,22 @@ static inline int devm_work_autocancel(struct >>>>> device *dev, >>>>> return devm_add_action(dev, devm_work_drop, w); >>>>> } >>>>> >>>>> +static inline void devm_mutex_release(void *res) >>>>> +{ >>>>> + mutex_destroy(res); >>>>> +} >>>>> + >>>>> +/** >>>>> + * devm_mutex_init - Resource-managed mutex initialization >>>>> + * @dev: Device which lifetime work is bound to >>>>> + * @lock: Pointer to a mutex >>>>> + * >>>>> + * Initialize mutex which is automatically destroyed when driver is >>>>> detached. >>>>> + */ >>>>> +static inline int devm_mutex_init(struct device *dev, struct mutex >>>>> *lock) >>>>> +{ >>>>> + mutex_init(lock); >>>>> + return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>>>> +} >>>>> + >>>>> #endif >>>> >>>> mutex_destroy() only actually does anything if CONFIG_DEBUG_MUTEXES >>>> is set, otherwise it is an empty inline-stub. >>>> >>>> Adding a devres resource to the device just to call an empty inline >>>> stub which is a no-op seems like a waste of resources. IMHO it >>>> would be better to change this to: >>>> >>>> static inline int devm_mutex_init(struct device *dev, struct mutex >>>> *lock) >>>> { >>>> mutex_init(lock); >>>> #ifdef CONFIG_DEBUG_MUTEXES >>>> return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>>> #else >>>> return 0; >>>> #endif >>>> } >>>> >>>> To avoid the unnecessary devres allocation when >>>> CONFIG_DEBUG_MUTEXES is not set. >>> >>> Honestly saying I don't like unnecessary devres allocation either but >>> the proposed approach has its own price: >>> >>> 1) we'll have more than one place with branching if mutex_destroy is >>> empty or not using indirect condition. If suddenly mutex_destroy is >>> extended for non-debug code (in upstream branch or e.g. by someone for >>> local debug) than there'll be a problem. >>> >>> 2) If mutex_destroy is empty or not depends on CONFIG_PREEMPT_RT option >>> too. When CONFIG_PREEMPT_RT is on mutex_destroy is always empty. >>> >>> As I see it only the mutex interface (mutex.h) has to say definitely if >>> mutex_destroy must be called. Probably we could add some define to >>> include/linux/mutex.h,like IS_MUTEX_DESTROY_REQUIRED and declare it near >>> mutex_destroy definition itself. >>> >>> I tried to put devm_mutex_init itself in mutex.h and it could've helped >>> too but it's not the place for devm API. >>> >> >> What do you mean by "it's not the place for devm API" ? >> >> If you do a 'grep devm_ include/linux/' you'll find devm_ functions in >> almost 100 .h files. Why wouldn't mutex.h be the place for >> devm_mutex_init() ? mutex.h's maintainers believe so. https://lore.kernel.org/lkml/070c174c-057a-46de-ae8e-836e9e20eceb@salutedevices.com/T/#mb42e1d7760816b0cedd3130e08f29690496b5ac2 > > Looking at it closer, I have the feeling that you want to do similar to > devm_gpio_request() in linux/gpio.h : > > In linux/mutex.h, add a prototype for devm_mutex_init() when > CONFIG_DEBUG_MUTEXES is defined and an empty static inline otherwise. > Then define devm_mutex_init() in kernel/locking/mutex-debug.c Yes, this would be almost perfect decision. BTW just as in linux/gpio.h we wouldn't have to include whole "linux/device.h" into mutex.h, only add forward declaration of struct device; > > Wouldn't that work ? > > Christophe
Hello Waiman Thanks for the review. On 12/7/23 00:02, Waiman Long wrote: > On 12/6/23 14:55, Hans de Goede wrote: >> Hi, >> >> On 12/6/23 19:58, George Stark wrote: >>> Hello Hans >>> >>> Thanks for the review. >>> >>> On 12/6/23 18:01, Hans de Goede wrote: >>>> Hi George, >>>> ... >>>> mutex_destroy() only actually does anything if CONFIG_DEBUG_MUTEXES >>>> is set, otherwise it is an empty inline-stub. >>>> >>>> Adding a devres resource to the device just to call an empty inline >>>> stub which is a no-op seems like a waste of resources. IMHO it >>>> would be better to change this to: >>>> >>>> static inline int devm_mutex_init(struct device *dev, struct mutex >>>> *lock) >>>> { >>>> mutex_init(lock); >>>> #ifdef CONFIG_DEBUG_MUTEXES >>>> return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>>> #else >>>> return 0; >>>> #endif >>>> } >>>> >>>> To avoid the unnecessary devres allocation when >>>> CONFIG_DEBUG_MUTEXES is not set. >>> Honestly saying I don't like unnecessary devres allocation either but >>> the proposed approach has its own price: >>> >>> 1) we'll have more than one place with branching if mutex_destroy is >>> empty or not using indirect condition. If suddenly mutex_destroy is >>> extended for non-debug code (in upstream branch or e.g. by someone >>> for local debug) than there'll be a problem. >>> >>> 2) If mutex_destroy is empty or not depends on CONFIG_PREEMPT_RT >>> option too. When CONFIG_PREEMPT_RT is on mutex_destroy is always empty. >>> >>> As I see it only the mutex interface (mutex.h) has to say definitely >>> if mutex_destroy must be called. Probably we could add some define to >>> include/linux/mutex.h,like IS_MUTEX_DESTROY_REQUIRED and declare it >>> near mutex_destroy definition itself. >> That (a IS_MUTEX_DESTROY_REQUIRED define) is an interesting idea. >> Lets s> >>>> Adding a devres resource to the device just to call an empty inline >>>> stub which is a no-op seems like a waste of resources. IMHO it >>>> would be better to change this to: >>>> >>>> static inline int devm_mutex_init(struct device *dev, struct mutex >>>> *lock) >>>> { >>>> mutex_init(lock); >>>> #ifdef CONFIG_DEBUG_MUTEXES >>>> return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>>> #else >>>> return 0; >>>> #endif >>>> } >>>>ee for v3 if the mutex maintainers will accept that and if not >> then I guess we will just need to live with the unnecessary devres >> allocation. > > The purpose of calling mutex_destroy() is to mark a mutex as being > destroyed so that any subsequent call to mutex_lock/unlock will cause a > warning to be printed when CONFIG_DEBUG_MUTEXES is defined. I would not > say that mutex_destroy() is required. Rather it is a nice to have for > catching programming error. This is quite understandable but probably mutex_destroy() is not the best name for an optional API. Questions are asked over and over again if it can be safely ignored taking into account that it could be extended in the future. Every maintainer makes decision on that question in his own way and it leads to inconsistency. devm_mutex_init could take responsibility for calling/dropping mutex_destroy() on its own. > Cheers, > Longman >
On 12/6/23 19:37, George Stark wrote: > Hello Waiman > > Thanks for the review. > > On 12/7/23 00:02, Waiman Long wrote: >> On 12/6/23 14:55, Hans de Goede wrote: >>> Hi, >>> >>> On 12/6/23 19:58, George Stark wrote: >>>> Hello Hans >>>> >>>> Thanks for the review. >>>> >>>> On 12/6/23 18:01, Hans de Goede wrote: >>>>> Hi George, >>>>> > ... >>>>> mutex_destroy() only actually does anything if CONFIG_DEBUG_MUTEXES >>>>> is set, otherwise it is an empty inline-stub. >>>>> >>>>> Adding a devres resource to the device just to call an empty inline >>>>> stub which is a no-op seems like a waste of resources. IMHO it >>>>> would be better to change this to: >>>>> >>>>> static inline int devm_mutex_init(struct device *dev, struct mutex >>>>> *lock) >>>>> { >>>>> mutex_init(lock); >>>>> #ifdef CONFIG_DEBUG_MUTEXES >>>>> return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>>>> #else >>>>> return 0; >>>>> #endif >>>>> } >>>>> >>>>> To avoid the unnecessary devres allocation when >>>>> CONFIG_DEBUG_MUTEXES is not set. >>>> Honestly saying I don't like unnecessary devres allocation either >>>> but the proposed approach has its own price: >>>> >>>> 1) we'll have more than one place with branching if mutex_destroy >>>> is empty or not using indirect condition. If suddenly >>>> mutex_destroy is extended for non-debug code (in upstream branch or >>>> e.g. by someone for local debug) than there'll be a problem. >>>> >>>> 2) If mutex_destroy is empty or not depends on CONFIG_PREEMPT_RT >>>> option too. When CONFIG_PREEMPT_RT is on mutex_destroy is always >>>> empty. >>>> >>>> As I see it only the mutex interface (mutex.h) has to say >>>> definitely if mutex_destroy must be called. Probably we could add >>>> some define to include/linux/mutex.h,like IS_MUTEX_DESTROY_REQUIRED >>>> and declare it near mutex_destroy definition itself. >>> That (a IS_MUTEX_DESTROY_REQUIRED define) is an interesting idea. >>> Lets s> >>>>> Adding a devres resource to the device just to call an empty inline >>>>> stub which is a no-op seems like a waste of resources. IMHO it >>>>> would be better to change this to: >>>>> >>>>> static inline int devm_mutex_init(struct device *dev, struct mutex >>>>> *lock) >>>>> { >>>>> mutex_init(lock); >>>>> #ifdef CONFIG_DEBUG_MUTEXES >>>>> return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>>>> #else >>>>> return 0; >>>>> #endif >>>>> } >>>>> ee for v3 if the mutex maintainers will accept that and if not >>> then I guess we will just need to live with the unnecessary devres >>> allocation. >> >> The purpose of calling mutex_destroy() is to mark a mutex as being >> destroyed so that any subsequent call to mutex_lock/unlock will cause >> a warning to be printed when CONFIG_DEBUG_MUTEXES is defined. I would >> not say that mutex_destroy() is required. Rather it is a nice to have >> for catching programming error. > > This is quite understandable but probably mutex_destroy() is not the > best name for an optional API. Questions are asked over and over again > if it can be safely ignored taking into account that it could be > extended in the future. Every maintainer makes decision on that question > in his own way and it leads to inconsistency. > > devm_mutex_init could take responsibility for calling/dropping > mutex_destroy() on its own. The DEBUG_MUTEXES code is relatively old and there was no major change to it for a number of years. I don't see we will make major change to it in the near future. Of course, thing may change if there are new requirement that may affect the DEBUG_MUTEXES code. Cheers, Longman > >> Cheers, >> Longman >> >
On Thu, Dec 7, 2023 at 1:23 AM George Stark <gnstark@salutedevices.com> wrote: > On 12/7/23 01:37, Christophe Leroy wrote: > > Le 06/12/2023 à 23:14, Christophe Leroy a écrit : > >> Le 06/12/2023 à 19:58, George Stark a écrit : > >>> On 12/6/23 18:01, Hans de Goede wrote: > >>>> On 12/4/23 19:05, George Stark wrote: ... > >>>> mutex_destroy() only actually does anything if CONFIG_DEBUG_MUTEXES > >>>> is set, otherwise it is an empty inline-stub. > >>>> > >>>> Adding a devres resource to the device just to call an empty inline > >>>> stub which is a no-op seems like a waste of resources. IMHO it > >>>> would be better to change this to: > >>>> > >>>> static inline int devm_mutex_init(struct device *dev, struct mutex > >>>> *lock) > >>>> { > >>>> mutex_init(lock); > >>>> #ifdef CONFIG_DEBUG_MUTEXES > >>>> return devm_add_action_or_reset(dev, devm_mutex_release, lock); > >>>> #else > >>>> return 0; > >>>> #endif > >>>> } > >>>> > >>>> To avoid the unnecessary devres allocation when > >>>> CONFIG_DEBUG_MUTEXES is not set. > >>> > >>> Honestly saying I don't like unnecessary devres allocation either but > >>> the proposed approach has its own price: > >>> > >>> 1) we'll have more than one place with branching if mutex_destroy is > >>> empty or not using indirect condition. If suddenly mutex_destroy is > >>> extended for non-debug code (in upstream branch or e.g. by someone for > >>> local debug) than there'll be a problem. > >>> > >>> 2) If mutex_destroy is empty or not depends on CONFIG_PREEMPT_RT option > >>> too. When CONFIG_PREEMPT_RT is on mutex_destroy is always empty. > >>> > >>> As I see it only the mutex interface (mutex.h) has to say definitely if > >>> mutex_destroy must be called. Probably we could add some define to > >>> include/linux/mutex.h,like IS_MUTEX_DESTROY_REQUIRED and declare it near > >>> mutex_destroy definition itself. > >>> > >>> I tried to put devm_mutex_init itself in mutex.h and it could've helped > >>> too but it's not the place for devm API. > >>> > >> > >> What do you mean by "it's not the place for devm API" ? > >> > >> If you do a 'grep devm_ include/linux/' you'll find devm_ functions in > >> almost 100 .h files. Why wouldn't mutex.h be the place for > >> devm_mutex_init() ? > mutex.h's maintainers believe so. > > https://lore.kernel.org/lkml/070c174c-057a-46de-ae8e-836e9e20eceb@salutedevices.com/T/#mb42e1d7760816b0cedd3130e08f29690496b5ac2 > > > > Looking at it closer, I have the feeling that you want to do similar to > > devm_gpio_request() in linux/gpio.h : > > > > In linux/mutex.h, add a prototype for devm_mutex_init() when > > CONFIG_DEBUG_MUTEXES is defined and an empty static inline otherwise. > > Then define devm_mutex_init() in kernel/locking/mutex-debug.c > > Yes, this would be almost perfect decision. BTW just as in linux/gpio.h > we wouldn't have to include whole "linux/device.h" into mutex.h, only > add forward declaration of struct device; > > > Wouldn't that work ? No. It will require inclusion of device.h (which is a twisted hell from the header perspective) into mutex.h. Completely unappreciated move.
On Thu, Dec 7, 2023 at 1:23 AM George Stark <gnstark@salutedevices.com> wrote: > On 12/7/23 01:37, Christophe Leroy wrote: > > Le 06/12/2023 à 23:14, Christophe Leroy a écrit : ... > > Looking at it closer, I have the feeling that you want to do similar to > > devm_gpio_request() in linux/gpio.h : > > > > In linux/mutex.h, add a prototype for devm_mutex_init() when > > CONFIG_DEBUG_MUTEXES is defined and an empty static inline otherwise. > > Then define devm_mutex_init() in kernel/locking/mutex-debug.c > > Yes, this would be almost perfect decision. BTW just as in linux/gpio.h > we wouldn't have to include whole "linux/device.h" into mutex.h, only > add forward declaration of struct device; In case you place it into a C-file. Otherwise you need a header for the API and that is not acceptable for mutex.h.
Le 07/12/2023 à 13:02, Andy Shevchenko a écrit : > On Thu, Dec 7, 2023 at 1:23 AM George Stark <gnstark@salutedevices.com> wrote: >> On 12/7/23 01:37, Christophe Leroy wrote: >>> Le 06/12/2023 à 23:14, Christophe Leroy a écrit : > > ... > >>> Looking at it closer, I have the feeling that you want to do similar to >>> devm_gpio_request() in linux/gpio.h : >>> >>> In linux/mutex.h, add a prototype for devm_mutex_init() when >>> CONFIG_DEBUG_MUTEXES is defined and an empty static inline otherwise. >>> Then define devm_mutex_init() in kernel/locking/mutex-debug.c >> >> Yes, this would be almost perfect decision. BTW just as in linux/gpio.h >> we wouldn't have to include whole "linux/device.h" into mutex.h, only >> add forward declaration of struct device; > > In case you place it into a C-file. Otherwise you need a header for > the API and that is not acceptable for mutex.h. > Right, that's the reason why I'm suggesting to define devm_mutex_init() in kernel/locking/mutex-debug.c. In linux/mutex.h, you define a stub for when CONFIG_DEBUG_MUTEXES is not set, and the prototype of devm_mutex_init() when CONFIG_DEBUG_MUTEXES is set.
Le 07/12/2023 à 12:59, Andy Shevchenko a écrit : > On Thu, Dec 7, 2023 at 1:23 AM George Stark <gnstark@salutedevices.com> wrote: >> On 12/7/23 01:37, Christophe Leroy wrote: >>> Le 06/12/2023 à 23:14, Christophe Leroy a écrit : >>>> Le 06/12/2023 à 19:58, George Stark a écrit : >>>>> On 12/6/23 18:01, Hans de Goede wrote: >>>>>> On 12/4/23 19:05, George Stark wrote: > > ... > >>>>>> mutex_destroy() only actually does anything if CONFIG_DEBUG_MUTEXES >>>>>> is set, otherwise it is an empty inline-stub. >>>>>> >>>>>> Adding a devres resource to the device just to call an empty inline >>>>>> stub which is a no-op seems like a waste of resources. IMHO it >>>>>> would be better to change this to: >>>>>> >>>>>> static inline int devm_mutex_init(struct device *dev, struct mutex >>>>>> *lock) >>>>>> { >>>>>> mutex_init(lock); >>>>>> #ifdef CONFIG_DEBUG_MUTEXES >>>>>> return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>>>>> #else >>>>>> return 0; >>>>>> #endif >>>>>> } >>>>>> >>>>>> To avoid the unnecessary devres allocation when >>>>>> CONFIG_DEBUG_MUTEXES is not set. >>>>> >>>>> Honestly saying I don't like unnecessary devres allocation either but >>>>> the proposed approach has its own price: >>>>> >>>>> 1) we'll have more than one place with branching if mutex_destroy is >>>>> empty or not using indirect condition. If suddenly mutex_destroy is >>>>> extended for non-debug code (in upstream branch or e.g. by someone for >>>>> local debug) than there'll be a problem. >>>>> >>>>> 2) If mutex_destroy is empty or not depends on CONFIG_PREEMPT_RT option >>>>> too. When CONFIG_PREEMPT_RT is on mutex_destroy is always empty. >>>>> >>>>> As I see it only the mutex interface (mutex.h) has to say definitely if >>>>> mutex_destroy must be called. Probably we could add some define to >>>>> include/linux/mutex.h,like IS_MUTEX_DESTROY_REQUIRED and declare it near >>>>> mutex_destroy definition itself. >>>>> >>>>> I tried to put devm_mutex_init itself in mutex.h and it could've helped >>>>> too but it's not the place for devm API. >>>>> >>>> >>>> What do you mean by "it's not the place for devm API" ? >>>> >>>> If you do a 'grep devm_ include/linux/' you'll find devm_ functions in >>>> almost 100 .h files. Why wouldn't mutex.h be the place for >>>> devm_mutex_init() ? >> mutex.h's maintainers believe so. >> >> https://lore.kernel.org/lkml/070c174c-057a-46de-ae8e-836e9e20eceb@salutedevices.com/T/#mb42e1d7760816b0cedd3130e08f29690496b5ac2 >>> >>> Looking at it closer, I have the feeling that you want to do similar to >>> devm_gpio_request() in linux/gpio.h : >>> >>> In linux/mutex.h, add a prototype for devm_mutex_init() when >>> CONFIG_DEBUG_MUTEXES is defined and an empty static inline otherwise. >>> Then define devm_mutex_init() in kernel/locking/mutex-debug.c >> >> Yes, this would be almost perfect decision. BTW just as in linux/gpio.h >> we wouldn't have to include whole "linux/device.h" into mutex.h, only >> add forward declaration of struct device; >> >>> Wouldn't that work ? > > No. It will require inclusion of device.h (which is a twisted hell > from the header perspective) into mutex.h. Completely unappreciated > move. > I see no reason for including device.h, I think a forward declaration of struct device would be enough, as done in linux/gpio.h Am I missing something ?
On Thu, Dec 7, 2023 at 2:31 PM Christophe Leroy <christophe.leroy@csgroup.eu> wrote: > Le 07/12/2023 à 12:59, Andy Shevchenko a écrit : > > On Thu, Dec 7, 2023 at 1:23 AM George Stark <gnstark@salutedevices.com> wrote: > >> On 12/7/23 01:37, Christophe Leroy wrote: > >>> Le 06/12/2023 à 23:14, Christophe Leroy a écrit : > >>>> Le 06/12/2023 à 19:58, George Stark a écrit : > >>>>> On 12/6/23 18:01, Hans de Goede wrote: > >>>>>> On 12/4/23 19:05, George Stark wrote: ... > >>>>>> mutex_destroy() only actually does anything if CONFIG_DEBUG_MUTEXES > >>>>>> is set, otherwise it is an empty inline-stub. > >>>>>> > >>>>>> Adding a devres resource to the device just to call an empty inline > >>>>>> stub which is a no-op seems like a waste of resources. IMHO it > >>>>>> would be better to change this to: > >>>>>> > >>>>>> static inline int devm_mutex_init(struct device *dev, struct mutex > >>>>>> *lock) > >>>>>> { > >>>>>> mutex_init(lock); > >>>>>> #ifdef CONFIG_DEBUG_MUTEXES > >>>>>> return devm_add_action_or_reset(dev, devm_mutex_release, lock); ^^^^ (1) > >>>>>> #else > >>>>>> return 0; > >>>>>> #endif > >>>>>> } > >>>>>> > >>>>>> To avoid the unnecessary devres allocation when > >>>>>> CONFIG_DEBUG_MUTEXES is not set. > >>>>> > >>>>> Honestly saying I don't like unnecessary devres allocation either but > >>>>> the proposed approach has its own price: > >>>>> > >>>>> 1) we'll have more than one place with branching if mutex_destroy is > >>>>> empty or not using indirect condition. If suddenly mutex_destroy is > >>>>> extended for non-debug code (in upstream branch or e.g. by someone for > >>>>> local debug) than there'll be a problem. > >>>>> > >>>>> 2) If mutex_destroy is empty or not depends on CONFIG_PREEMPT_RT option > >>>>> too. When CONFIG_PREEMPT_RT is on mutex_destroy is always empty. > >>>>> > >>>>> As I see it only the mutex interface (mutex.h) has to say definitely if > >>>>> mutex_destroy must be called. Probably we could add some define to > >>>>> include/linux/mutex.h,like IS_MUTEX_DESTROY_REQUIRED and declare it near > >>>>> mutex_destroy definition itself. > >>>>> > >>>>> I tried to put devm_mutex_init itself in mutex.h and it could've helped > >>>>> too but it's not the place for devm API. > >>>>> > >>>> > >>>> What do you mean by "it's not the place for devm API" ? > >>>> > >>>> If you do a 'grep devm_ include/linux/' you'll find devm_ functions in > >>>> almost 100 .h files. Why wouldn't mutex.h be the place for > >>>> devm_mutex_init() ? > >> mutex.h's maintainers believe so. > >> > >> https://lore.kernel.org/lkml/070c174c-057a-46de-ae8e-836e9e20eceb@salutedevices.com/T/#mb42e1d7760816b0cedd3130e08f29690496b5ac2 > >>> > >>> Looking at it closer, I have the feeling that you want to do similar to > >>> devm_gpio_request() in linux/gpio.h : > >>> > >>> In linux/mutex.h, add a prototype for devm_mutex_init() when > >>> CONFIG_DEBUG_MUTEXES is defined and an empty static inline otherwise. > >>> Then define devm_mutex_init() in kernel/locking/mutex-debug.c > >> > >> Yes, this would be almost perfect decision. BTW just as in linux/gpio.h > >> we wouldn't have to include whole "linux/device.h" into mutex.h, only > >> add forward declaration of struct device; > >> > >>> Wouldn't that work ? > > > > No. It will require inclusion of device.h (which is a twisted hell > > from the header perspective) into mutex.h. Completely unappreciated > > move. > > I see no reason for including device.h, I think a forward declaration of > struct device would be enough, as done in linux/gpio.h > > Am I missing something ? Yes, see (1) above. If you want to have it in the header, you must provide an API, which is located in device.h. The idea about mutex-debug.c is interesting, but the file naming and the devm_*() API for _initing_ the mutex seems confusing.
On 12/7/23 15:28, Christophe Leroy wrote: > > > Le 07/12/2023 à 13:02, Andy Shevchenko a écrit : >> On Thu, Dec 7, 2023 at 1:23 AM George Stark <gnstark@salutedevices.com> wrote: >>> On 12/7/23 01:37, Christophe Leroy wrote: >>>> Le 06/12/2023 à 23:14, Christophe Leroy a écrit : >> >> ... >> >>>> Looking at it closer, I have the feeling that you want to do similar to >>>> devm_gpio_request() in linux/gpio.h : >>>> >>>> In linux/mutex.h, add a prototype for devm_mutex_init() when >>>> CONFIG_DEBUG_MUTEXES is defined and an empty static inline otherwise. >>>> Then define devm_mutex_init() in kernel/locking/mutex-debug.c >>> >>> Yes, this would be almost perfect decision. BTW just as in linux/gpio.h >>> we wouldn't have to include whole "linux/device.h" into mutex.h, only >>> add forward declaration of struct device; >> >> In case you place it into a C-file. Otherwise you need a header for >> the API and that is not acceptable for mutex.h. >> > > Right, that's the reason why I'm suggesting to define devm_mutex_init() > in kernel/locking/mutex-debug.c. > > In linux/mutex.h, you define a stub for when CONFIG_DEBUG_MUTEXES is not > set, and the prototype of devm_mutex_init() when CONFIG_DEBUG_MUTEXES is > set. Something like this: diff --git a/include/linux/mutex.h b/include/linux/mutex.h index a33aa9eb9fc3..4a6041a7fd44 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -21,6 +21,8 @@ #include <linux/debug_locks.h> #include <linux/cleanup.h> +struct device; + #ifdef CONFIG_DEBUG_LOCK_ALLOC # define __DEP_MAP_MUTEX_INITIALIZER(lockname) \ , .dep_map = { \ @@ -127,6 +129,20 @@ extern void __mutex_init(struct mutex *lock, const char *name, */ extern bool mutex_is_locked(struct mutex *lock); +#ifdef CONFIG_DEBUG_MUTEXES + +extern int devm_mutex_init(struct device *dev, struct mutex *lock); + +#else + +static inline int devm_mutex_init(struct device *dev, struct mutex *lock) +{ + mutex_init(lock); + return 0; +} + +#endif + #else /* !CONFIG_PREEMPT_RT */ /* * Preempt-RT variant based on rtmutexes. @@ -169,6 +185,13 @@ do { \ \ __mutex_init((mutex), #mutex, &__key); \ } while (0) + +static inline int devm_mutex_init(struct device *dev, struct mutex *lock) +{ + mutex_init(lock); + return 0; +} + #endif /* CONFIG_PREEMPT_RT */ /* diff --git a/kernel/locking/mutex-debug.c b/kernel/locking/mutex-debug.c index bc8abb8549d2..d50dfa06e82c 100644 --- a/kernel/locking/mutex-debug.c +++ b/kernel/locking/mutex-debug.c @@ -19,6 +19,7 @@ #include <linux/kallsyms.h> #include <linux/interrupt.h> #include <linux/debug_locks.h> +#include <linux/device.h> #include "mutex.h" @@ -104,3 +105,25 @@ void mutex_destroy(struct mutex *lock) } EXPORT_SYMBOL_GPL(mutex_destroy); + +static void devm_mutex_release(void *res) +{ + mutex_destroy(res); +} + +/** + * devm_mutex_init - Resource-managed mutex initialization + * @dev: Device which lifetime mutex is bound to + * @lock: Pointer to a mutex + * + * Initialize mutex which is automatically destroyed when the driver is detached. + * + * Returns: 0 on success or a negative error code on failure. + */ +int devm_mutex_init(struct device *dev, struct mutex *lock) +{ + mutex_init(lock); + return devm_add_action_or_reset(dev, devm_mutex_release, lock); +} + +EXPORT_SYMBOL_GPL(devm_mutex_init); \ No newline at end of file
Le 07/12/2023 à 13:51, George Stark a écrit : > > > On 12/7/23 15:28, Christophe Leroy wrote: >> >> >> Le 07/12/2023 à 13:02, Andy Shevchenko a écrit : >>> On Thu, Dec 7, 2023 at 1:23 AM George Stark >>> <gnstark@salutedevices.com> wrote: >>>> On 12/7/23 01:37, Christophe Leroy wrote: >>>>> Le 06/12/2023 à 23:14, Christophe Leroy a écrit : >>> >>> ... >>> >>>>> Looking at it closer, I have the feeling that you want to do >>>>> similar to >>>>> devm_gpio_request() in linux/gpio.h : >>>>> >>>>> In linux/mutex.h, add a prototype for devm_mutex_init() when >>>>> CONFIG_DEBUG_MUTEXES is defined and an empty static inline otherwise. >>>>> Then define devm_mutex_init() in kernel/locking/mutex-debug.c >>>> >>>> Yes, this would be almost perfect decision. BTW just as in linux/gpio.h >>>> we wouldn't have to include whole "linux/device.h" into mutex.h, only >>>> add forward declaration of struct device; >>> >>> In case you place it into a C-file. Otherwise you need a header for >>> the API and that is not acceptable for mutex.h. >>> >> >> Right, that's the reason why I'm suggesting to define devm_mutex_init() >> in kernel/locking/mutex-debug.c. >> >> In linux/mutex.h, you define a stub for when CONFIG_DEBUG_MUTEXES is not >> set, and the prototype of devm_mutex_init() when CONFIG_DEBUG_MUTEXES is >> set. > > Something like this: > > diff --git a/include/linux/mutex.h b/include/linux/mutex.h > index a33aa9eb9fc3..4a6041a7fd44 100644 > --- a/include/linux/mutex.h > +++ b/include/linux/mutex.h > @@ -21,6 +21,8 @@ > #include <linux/debug_locks.h> > #include <linux/cleanup.h> > > +struct device; > + > #ifdef CONFIG_DEBUG_LOCK_ALLOC > # define __DEP_MAP_MUTEX_INITIALIZER(lockname) \ > , .dep_map = { \ > @@ -127,6 +129,20 @@ extern void __mutex_init(struct mutex *lock, const > char *name, > */ > extern bool mutex_is_locked(struct mutex *lock); > > +#ifdef CONFIG_DEBUG_MUTEXES There is already a CONFIG_DEBUG_MUTEXES block, can you re-use it ? > + > +extern int devm_mutex_init(struct device *dev, struct mutex *lock); 'extern' is pointless and deprecated for function prototypes. I know the kernel is full of them, but it is not a good reason to add new ones. > + > +#else > + > +static inline int devm_mutex_init(struct device *dev, struct mutex *lock) > +{ > + mutex_init(lock); > + return 0; > +} > + > +#endif > + > #else /* !CONFIG_PREEMPT_RT */ > /* > * Preempt-RT variant based on rtmutexes. > @@ -169,6 +185,13 @@ do { \ > \ > __mutex_init((mutex), #mutex, &__key); \ > } while (0) > + > +static inline int devm_mutex_init(struct device *dev, struct mutex *lock) > +{ > + mutex_init(lock); > + return 0; > +} > + > #endif /* CONFIG_PREEMPT_RT */ > > /* > diff --git a/kernel/locking/mutex-debug.c b/kernel/locking/mutex-debug.c > index bc8abb8549d2..d50dfa06e82c 100644 > --- a/kernel/locking/mutex-debug.c > +++ b/kernel/locking/mutex-debug.c > @@ -19,6 +19,7 @@ > #include <linux/kallsyms.h> > #include <linux/interrupt.h> > #include <linux/debug_locks.h> > +#include <linux/device.h> > > #include "mutex.h" > > @@ -104,3 +105,25 @@ void mutex_destroy(struct mutex *lock) > } > > EXPORT_SYMBOL_GPL(mutex_destroy); > + > +static void devm_mutex_release(void *res) > +{ > + mutex_destroy(res); > +} > + > +/** > + * devm_mutex_init - Resource-managed mutex initialization > + * @dev: Device which lifetime mutex is bound to > + * @lock: Pointer to a mutex > + * > + * Initialize mutex which is automatically destroyed when the driver is > detached. > + * > + * Returns: 0 on success or a negative error code on failure. > + */ > +int devm_mutex_init(struct device *dev, struct mutex *lock) > +{ > + mutex_init(lock); > + return devm_add_action_or_reset(dev, devm_mutex_release, lock); > +} > + > +EXPORT_SYMBOL_GPL(devm_mutex_init); > \ No newline at end of file > >
On 12/7/23 16:01, Christophe Leroy wrote: > > > Le 07/12/2023 à 13:51, George Stark a écrit : >> >> >> On 12/7/23 15:28, Christophe Leroy wrote: >>> >>> >>> Le 07/12/2023 à 13:02, Andy Shevchenko a écrit : >>>> On Thu, Dec 7, 2023 at 1:23 AM George Stark >>>> <gnstark@salutedevices.com> wrote: >>>>> On 12/7/23 01:37, Christophe Leroy wrote: >>>>>> Le 06/12/2023 à 23:14, Christophe Leroy a écrit : >>>> >>>> ... >>>> >>>>>> Looking at it closer, I have the feeling that you want to do >>>>>> similar to >>>>>> devm_gpio_request() in linux/gpio.h : >>>>>> >>>>>> In linux/mutex.h, add a prototype for devm_mutex_init() when >>>>>> CONFIG_DEBUG_MUTEXES is defined and an empty static inline otherwise. >>>>>> Then define devm_mutex_init() in kernel/locking/mutex-debug.c >>>>> >>>>> Yes, this would be almost perfect decision. BTW just as in linux/gpio.h >>>>> we wouldn't have to include whole "linux/device.h" into mutex.h, only >>>>> add forward declaration of struct device; >>>> >>>> In case you place it into a C-file. Otherwise you need a header for >>>> the API and that is not acceptable for mutex.h. >>>> >>> >>> Right, that's the reason why I'm suggesting to define devm_mutex_init() >>> in kernel/locking/mutex-debug.c. >>> >>> In linux/mutex.h, you define a stub for when CONFIG_DEBUG_MUTEXES is not >>> set, and the prototype of devm_mutex_init() when CONFIG_DEBUG_MUTEXES is >>> set. >> >> Something like this: >> >> diff --git a/include/linux/mutex.h b/include/linux/mutex.h >> index a33aa9eb9fc3..4a6041a7fd44 100644 >> --- a/include/linux/mutex.h >> +++ b/include/linux/mutex.h >> @@ -21,6 +21,8 @@ >> #include <linux/debug_locks.h> >> #include <linux/cleanup.h> >> >> +struct device; >> + >> #ifdef CONFIG_DEBUG_LOCK_ALLOC >> # define __DEP_MAP_MUTEX_INITIALIZER(lockname) \ >> , .dep_map = { \ >> @@ -127,6 +129,20 @@ extern void __mutex_init(struct mutex *lock, const >> char *name, >> */ >> extern bool mutex_is_locked(struct mutex *lock); >> >> +#ifdef CONFIG_DEBUG_MUTEXES > > There is already a CONFIG_DEBUG_MUTEXES block, can you re-use it ? those CONFIG_DEBUG_MUTEXES blockd are declared before mutex_init macro :( > >> + >> +extern int devm_mutex_init(struct device *dev, struct mutex *lock); > > 'extern' is pointless and deprecated for function prototypes. > I know the kernel is full of them, but it is not a good reason to add > new ones. Ok Sure I will send this patch in the right way and then we could have proper review but firstly I'd like to hear from Andy and mutex.h's maintainers is it acceptable at all? > >> + >> +#else >> + >> +static inline int devm_mutex_init(struct device *dev, struct mutex *lock) >> +{ >> + mutex_init(lock); >> + return 0; >> +} >> + >> +#endif >> + >> #else /* !CONFIG_PREEMPT_RT */ >> /* >> * Preempt-RT variant based on rtmutexes. >> @@ -169,6 +185,13 @@ do { \ >> \ >> __mutex_init((mutex), #mutex, &__key); \ >> } while (0) >> + >> +static inline int devm_mutex_init(struct device *dev, struct mutex *lock) >> +{ >> + mutex_init(lock); >> + return 0; >> +} >> + >> #endif /* CONFIG_PREEMPT_RT */ >> >> /* >> diff --git a/kernel/locking/mutex-debug.c b/kernel/locking/mutex-debug.c >> index bc8abb8549d2..d50dfa06e82c 100644 >> --- a/kernel/locking/mutex-debug.c >> +++ b/kernel/locking/mutex-debug.c >> @@ -19,6 +19,7 @@ >> #include <linux/kallsyms.h> >> #include <linux/interrupt.h> >> #include <linux/debug_locks.h> >> +#include <linux/device.h> >> >> #include "mutex.h" >> >> @@ -104,3 +105,25 @@ void mutex_destroy(struct mutex *lock) >> } >> >> EXPORT_SYMBOL_GPL(mutex_destroy); >> + >> +static void devm_mutex_release(void *res) >> +{ >> + mutex_destroy(res); >> +} >> + >> +/** >> + * devm_mutex_init - Resource-managed mutex initialization >> + * @dev: Device which lifetime mutex is bound to >> + * @lock: Pointer to a mutex >> + * >> + * Initialize mutex which is automatically destroyed when the driver is >> detached. >> + * >> + * Returns: 0 on success or a negative error code on failure. >> + */ >> +int devm_mutex_init(struct device *dev, struct mutex *lock) >> +{ >> + mutex_init(lock); >> + return devm_add_action_or_reset(dev, devm_mutex_release, lock); >> +} >> + >> +EXPORT_SYMBOL_GPL(devm_mutex_init); >> \ No newline at end of file >> >>
On 12/6/23 16:02, Waiman Long wrote: > On 12/6/23 14:55, Hans de Goede wrote: >> Hi, >> >> On 12/6/23 19:58, George Stark wrote: >>> Hello Hans >>> >>> Thanks for the review. >>> >>> On 12/6/23 18:01, Hans de Goede wrote: >>>> Hi George, >>>> >>>> On 12/4/23 19:05, George Stark wrote: >>>>> Using of devm API leads to certain order of releasing resources. >>>>> So all dependent resources which are not devm-wrapped should be >>>>> deleted >>>>> with respect to devm-release order. Mutex is one of such objects that >>>>> often is bound to other resources and has no own devm wrapping. >>>>> Since mutex_destroy() actually does nothing in non-debug builds >>>>> frequently calling mutex_destroy() is just ignored which is safe >>>>> for now >>>>> but wrong formally and can lead to a problem if mutex_destroy() is >>>>> extended so introduce devm_mutex_init(). >>>>> >>>>> Signed-off-by: George Stark <gnstark@salutedevices.com> >>>>> --- >>>>> include/linux/devm-helpers.h | 18 ++++++++++++++++++ >>>>> 1 file changed, 18 insertions(+) >>>>> >>>>> diff --git a/include/linux/devm-helpers.h >>>>> b/include/linux/devm-helpers.h >>>>> index 74891802200d..2f56e476776f 100644 >>>>> --- a/include/linux/devm-helpers.h >>>>> +++ b/include/linux/devm-helpers.h >>>>> @@ -76,4 +76,22 @@ static inline int devm_work_autocancel(struct >>>>> device *dev, >>>>> return devm_add_action(dev, devm_work_drop, w); >>>>> } >>>>> +static inline void devm_mutex_release(void *res) >>>>> +{ >>>>> + mutex_destroy(res); >>>>> +} >>>>> + >>>>> +/** >>>>> + * devm_mutex_init - Resource-managed mutex initialization >>>>> + * @dev: Device which lifetime work is bound to >>>>> + * @lock: Pointer to a mutex >>>>> + * >>>>> + * Initialize mutex which is automatically destroyed when driver >>>>> is detached. >>>>> + */ >>>>> +static inline int devm_mutex_init(struct device *dev, struct >>>>> mutex *lock) >>>>> +{ >>>>> + mutex_init(lock); >>>>> + return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>>>> +} >>>>> + >>>>> #endif >>>> mutex_destroy() only actually does anything if CONFIG_DEBUG_MUTEXES >>>> is set, otherwise it is an empty inline-stub. >>>> >>>> Adding a devres resource to the device just to call an empty inline >>>> stub which is a no-op seems like a waste of resources. IMHO it >>>> would be better to change this to: >>>> >>>> static inline int devm_mutex_init(struct device *dev, struct mutex >>>> *lock) >>>> { >>>> mutex_init(lock); >>>> #ifdef CONFIG_DEBUG_MUTEXES >>>> return devm_add_action_or_reset(dev, devm_mutex_release, lock); >>>> #else >>>> return 0; >>>> #endif >>>> } >>>> >>>> To avoid the unnecessary devres allocation when >>>> CONFIG_DEBUG_MUTEXES is not set. >>> Honestly saying I don't like unnecessary devres allocation either >>> but the proposed approach has its own price: >>> >>> 1) we'll have more than one place with branching if mutex_destroy is >>> empty or not using indirect condition. If suddenly mutex_destroy is >>> extended for non-debug code (in upstream branch or e.g. by someone >>> for local debug) than there'll be a problem. >>> >>> 2) If mutex_destroy is empty or not depends on CONFIG_PREEMPT_RT >>> option too. When CONFIG_PREEMPT_RT is on mutex_destroy is always empty. >>> >>> As I see it only the mutex interface (mutex.h) has to say definitely >>> if mutex_destroy must be called. Probably we could add some define >>> to include/linux/mutex.h,like IS_MUTEX_DESTROY_REQUIRED and declare >>> it near mutex_destroy definition itself. >> That (a IS_MUTEX_DESTROY_REQUIRED define) is an interesting idea. >> Lets see for v3 if the mutex maintainers will accept that and if not >> then I guess we will just need to live with the unnecessary devres >> allocation. > > The purpose of calling mutex_destroy() is to mark a mutex as being > destroyed so that any subsequent call to mutex_lock/unlock will cause > a warning to be printed when CONFIG_DEBUG_MUTEXES is defined. I would > not say that mutex_destroy() is required. Rather it is a nice to have > for catching programming error. OTOH, one thing that we can probably do in mutex.h is something like diff --git a/include/linux/mutex.h b/include/linux/mutex.h index a33aa9eb9fc3..7db7862de3f1 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -83,6 +83,9 @@ struct mutex { extern void mutex_destroy(struct mutex *lock); +/* mutex_destroy() is a real function, not a NOP */ +#define mutex_destroy mutex_destroy + #else ---------------------------------------- Now in some devm files, you can use the absense/presence of mutex_destroy macro to decide on what to do. Cheers, Longman
diff --git a/include/linux/devm-helpers.h b/include/linux/devm-helpers.h index 74891802200d..2f56e476776f 100644 --- a/include/linux/devm-helpers.h +++ b/include/linux/devm-helpers.h @@ -76,4 +76,22 @@ static inline int devm_work_autocancel(struct device *dev, return devm_add_action(dev, devm_work_drop, w); } +static inline void devm_mutex_release(void *res) +{ + mutex_destroy(res); +} + +/** + * devm_mutex_init - Resource-managed mutex initialization + * @dev: Device which lifetime work is bound to + * @lock: Pointer to a mutex + * + * Initialize mutex which is automatically destroyed when driver is detached. + */ +static inline int devm_mutex_init(struct device *dev, struct mutex *lock) +{ + mutex_init(lock); + return devm_add_action_or_reset(dev, devm_mutex_release, lock); +} + #endif