Received: by 2002:a6b:500f:0:0:0:0:0 with SMTP id e15csp1774445iob; Fri, 29 Apr 2022 12:31:20 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzLYyY3/IBo7PYDbdesGwM1UDmQ0rOrK6VeydDVHrHCgKmob5wLh0kXy953+ysirO94pIDH X-Received: by 2002:a2e:9bc5:0:b0:24f:b2c:6dc0 with SMTP id w5-20020a2e9bc5000000b0024f0b2c6dc0mr445536ljj.280.1651260680454; Fri, 29 Apr 2022 12:31:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651260680; cv=none; d=google.com; s=arc-20160816; b=HJD8oFplbPEmNPn/1dOmuh+NfIsWr2G4R82nLminqfJSDOvqaHAPZ1S9AyzOoMaEJV wReA31ltc2BjSon0afHwXkcecW57iwxHHLAfCk23DzIWfI/4GIDefQyJsHeWKjgo0QsN GOQfVoaH8snyFb0tMa5qdQfwCe3v1BCsXSrd07RgUfbEHcle/Cpelh2X5/baqit6DiX5 fmpApWOPwzhjbYkVp7fjsmnrMAsilffmCu1Optv3rumg8Rj3ERLqqrxC1eTRrBiZh72a SEoLOn9xlYlibuDlnIu0M3xWULkCK0PeFngmQcf08KH4xDZEUyagezH6i7qa4KHaBUHD DArg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:user-agent:references:in-reply-to :subject:cc:to:from:message-id:date:dkim-signature; bh=RiUbpFSC+XrlFl2wlIuVV38HVgLzPWSNXAWxg0wz2FE=; b=PdJLyUe+H6D1GIo/SUG4lJHoTyHx/ghhkVsCmP/IXk5rEjm1cf7mbvnzqVqsvXbSXl h4i9ckV1Fe7YbWY+LTddH5jH7P97r3hhXciJZAqBO3Owa6ZVounB3FGKUoQIxlq+suea 15WQemb12gb3Ji3W5eM6BYVoa44e8kdN5n0/KTiuWJrnjZdiybNSYZcZCwqYu6JfoXRn B0C5d9iqXY9T0oX3Ctu1Oed3kYJzMXmDXGtyoQ7alREGvezYIUM+TMp7UMzgVQU2zNti 90g4tpmPC6SJIaACTWCMRhuXOPFuJNFa2AdoptdR5rMFqX+QNJ3ytMor2hxLCrm2dWSb zn5g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=WD6LVZDS; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id p27-20020a19f11b000000b004718d866ff0si7257582lfh.344.2022.04.29.12.30.48; Fri, 29 Apr 2022 12:31:20 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=WD6LVZDS; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1359454AbiD2QMQ (ORCPT + 99 others); Fri, 29 Apr 2022 12:12:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56666 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344906AbiD2QMQ (ORCPT ); Fri, 29 Apr 2022 12:12:16 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 27B24A6E28; Fri, 29 Apr 2022 09:08:57 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id D95ABB83645; Fri, 29 Apr 2022 16:08:55 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 905C0C385A4; Fri, 29 Apr 2022 16:08:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1651248534; bh=EzjHOli1jhhHNwga1qc/k/xK7Y/AYNU28aEQDIa5QaA=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=WD6LVZDS+PChJZPpxZt4lxvZKHt46bpDDdU3f5ImADZTPlKAU67CHJ28g47jR+6YG UVOnsXDTcVhyvW6wGDGDPYnXXM/ocYV4YFttgeWdvedJW8NP2O7pGohtZuPL1B3Csk 2az11Wn/XzNn/4W/90ReA1YD+6xi7iT7UILw/iG5KB6e7lPLwECOlBLzG5+YtdR+LD xdy2CKoTRWuIzjvV/FPNBANzS2Jvzq1bfPOiRbXypFKAc5dHznHTexbZ5jbXM9Lzwk 4HCi4GOYBwgIAjltYZ8VY1139Q1nKO+HeWYheDLNG9tCssBS3iS98ec2falSGw033n BMKYoKrqmYXJw== Received: from sofa.misterjones.org ([185.219.108.64] helo=why.misterjones.org) by disco-boy.misterjones.org with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1nkTAq-007z4M-3P; Fri, 29 Apr 2022 17:08:52 +0100 Date: Fri, 29 Apr 2022 17:08:51 +0100 Message-ID: <87sfpv98j0.wl-maz@kernel.org> From: Marc Zyngier To: Thomas Pfaff Cc: Thomas Gleixner , , , Hillf Danton Subject: Re: [PATCH v2] irq/core: synchronize irq_thread startup In-Reply-To: <1e3f96b7-9294-1534-e83b-efe3602f876f@pcs.com> References: <1e3f96b7-9294-1534-e83b-efe3602f876f@pcs.com> User-Agent: Wanderlust/2.15.9 (Almost Unreal) SEMI-EPG/1.14.7 (Harue) FLIM-LB/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL-LB/10.8 EasyPG/1.0.0 Emacs/27.1 (x86_64-pc-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") Content-Type: text/plain; charset=US-ASCII X-SA-Exim-Connect-IP: 185.219.108.64 X-SA-Exim-Rcpt-To: tpfaff@pcs.com, tglx@linutronix.de, linux-kernel@vger.kernel.org, linux-rt-users@vger.kernel.org, hdanton@sina.com X-SA-Exim-Mail-From: maz@kernel.org X-SA-Exim-Scanned: No (on disco-boy.misterjones.org); SAEximRunCond expanded to false X-Spam-Status: No, score=-7.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS 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: X-Mailing-List: linux-kernel@vger.kernel.org Hi Thomas, Thanks for this, a few comments below. On Fri, 29 Apr 2022 12:52:48 +0100, Thomas Pfaff wrote: > > From: Thomas Pfaff > > While running > "while /bin/true; do setserial /dev/ttyS0 uart none; > setserial /dev/ttyS0 uart 16550A; done" > on a kernel with threaded irqs, setserial is hung after some calls. > > setserial opens the device, this will install an irq handler if the uart is > not none, followed by TIOCGSERIAL and TIOCSSERIAL ioctls. > Then the device is closed. On close, synchronize_irq() is called by > serial_core. > > If the close comes too fast, the irq_thread does not really start, > it is terminated immediately without going into irq_thread(). > But an interrupt might already been handled by > irq_default_primary_handler(), going to __irq_wake_thread() and > incrementing threads_active. > If this happens, synchronize_irq() will hang forever, because the > irq_thread is already dead, and threads_active will never be decremented. > > The fix is to make sure that the irq_thread is really started > during __setup_irq(). > > Signed-off-by: Thomas Pfaff > --- > v1-v2: > - use already existing resources > diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h > index 99cbdf55a8bd..dca57bed0d96 100644 > --- a/kernel/irq/internals.h > +++ b/kernel/irq/internals.h > @@ -29,12 +29,14 @@ extern struct irqaction chained_action; > * IRQTF_WARNED - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed > * IRQTF_AFFINITY - irq thread is requested to adjust affinity > * IRQTF_FORCED_THREAD - irq action is force threaded > + * IRQTF_UP - signals that irq thread is ready nit: Why not call the flag IRQTF_READY then? I find it slightly more readable than 'UP'. > */ > enum { > IRQTF_RUNTHREAD, > IRQTF_WARNED, > IRQTF_AFFINITY, > IRQTF_FORCED_THREAD, > + IRQTF_UP, > }; > > /* > diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c > index f1d5a94c6c9f..7efa24629694 100644 > --- a/kernel/irq/manage.c > +++ b/kernel/irq/manage.c > @@ -1263,6 +1263,30 @@ static void irq_wake_secondary(struct irq_desc *desc, struct irqaction *action) > raw_spin_unlock_irq(&desc->lock); > } > > +/* > + * Internal function to notify that irq_thread is ready > + */ > +static void irq_thread_is_up(struct irq_desc *desc, > + struct irqaction *action) nit again: the name of this function makes it look like a predicate. The rest of the IRQ core uses the 'set' word to... set a bit. Something like irq_thread_set_ready() would have my preference. > +{ > + set_bit(IRQTF_UP, &action->thread_flags); > + wake_up(&desc->wait_for_threads); > +} > + > +/* > + * Internal function to wake up irq_thread > + * and wait until it is really up > + */ > +static void wait_for_irq_thread_startup(struct irq_desc *desc, > + struct irqaction *action) and this would be wait_for_irq_thread_ready(). > +{ > + if (action && action->thread) { > + wake_up_process(action->thread); > + wait_event(desc->wait_for_threads, > + test_bit(IRQTF_UP, &action->thread_flags)); > + } > +} > + > /* > * Interrupt handler thread > */ > @@ -1287,6 +1311,8 @@ static int irq_thread(void *data) > > irq_thread_check_affinity(desc, action); > > + irq_thread_is_up (desc, action); nit: extra space after the function. > + > while (!irq_wait_for_interrupt(action)) { > irqreturn_t action_ret; > > @@ -1522,6 +1548,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) > } > } > > + init_waitqueue_head(&desc->wait_for_threads); > + I'm trying to convince myself that this one is safe. It was so far only done when registering the first handler of a threaded interrupt, while it is now done on every call to __setup_irq(). However, this is now done outside of the protection of any of the locks, meaning that a concurrent __setup_irq() for a shared interrupt can now barge in and corrupt the wait queue. So I don't think this is right. You may be able to hoist the request_lock up, but I haven't checked what could break, if anything. > /* > * Create a handler thread when a thread function is supplied > * and the interrupt does not nest into another interrupt > @@ -1698,8 +1726,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) > } > > if (!shared) { > - init_waitqueue_head(&desc->wait_for_threads); > - > /* Setup the type (level, edge polarity) if configured: */ > if (new->flags & IRQF_TRIGGER_MASK) { > ret = __irq_set_trigger(desc, > @@ -1795,14 +1821,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) > > irq_setup_timings(desc, new); > > - /* > - * Strictly no need to wake it up, but hung_task complains > - * when no hard interrupt wakes the thread up. > - */ > - if (new->thread) > - wake_up_process(new->thread); > - if (new->secondary) > - wake_up_process(new->secondary->thread); > + wait_for_irq_thread_startup(desc, new); > + wait_for_irq_thread_startup(desc, new->secondary); > > register_irq_proc(irq, desc); > new->dir = NULL; Thanks, M. -- Without deviation from the norm, progress is not possible.