Received: by 2002:ac0:946b:0:0:0:0:0 with SMTP id j40csp4021361imj; Tue, 19 Feb 2019 13:48:36 -0800 (PST) X-Google-Smtp-Source: AHgI3IZ9/g8qKtm16CutiBajAv7y6lDg2W/0uoMQa9X4cW/oGicS26aSvPWtAV9Wshwq6jDTLGV1 X-Received: by 2002:a63:ae0e:: with SMTP id q14mr30256517pgf.151.1550612916888; Tue, 19 Feb 2019 13:48:36 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1550612916; cv=none; d=google.com; s=arc-20160816; b=G2WWIcy6O2QJVWyXNWu6+1AqtajOkHMeQxHmfAqFeQLMDpX8p9cZxmGqi2zM0EkzfU TAXxkYVsAquqHAR664Whl1ZCRjg014qlntf9VeJ/B2omWPT+b4Cv6Pt1/1vIMQoGne0U 3y8PgzwY0iRYmW+nNMsgvrRLYeKbUgu5Bu8JOC1DKhx79qwpzI1Q8scvjzEScViYEcaZ 1SdgHJL4kC+L2qftiCoe38UdlzhQCfg5zrYt1OBsg0G54C0CMXaNxSVgGVKXsiBKbKNI gkHlIFiUZnQkGfwzn/4Ww4JIkviBYGdJwn//6C72tEqKZvSBnuuJRxfZ0Sizs/1N2l9B XFcg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:message-id :in-reply-to:date:references:subject:cc:to:from; bh=8QEaoSXBdpvIsjta5UU22/KgooJCloMudSdSaJCY/Xs=; b=J0YROJ3izgFYIhfbpmUEuBuOJFhVUshINu9ThLIV87ZtqONiKE0kY02VFNiFumkAEB +L8BR0hRoAzgPF+2ysxwxAWHywrfDGb8Ib6Vgm64Uiwu8LXFElRVhgKobjlgXJk4h65c /do84Gipp0sJckY90CsshBblK5YKlrUevcK6wIHZkvRCPdXxgbXHHzmhSwb4is5dBgPN TyuNrx2+69u+fqdNH92r7UXeQtTkBLYguV+OE2ovKE9GQARFC5aF3VeUS82ZjxjnlPZx ZETpicMB6EfCegWKSLlsdoRV0MDRrFBe2pdDB0SANGmGOgXs894Ke5bsgdCNHXtiHz2m SpCw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e67si18633052plb.107.2019.02.19.13.48.21; Tue, 19 Feb 2019 13:48:36 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729588AbfBSVry (ORCPT + 99 others); Tue, 19 Feb 2019 16:47:54 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:36160 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725994AbfBSVry (ORCPT ); Tue, 19 Feb 2019 16:47:54 -0500 Received: from localhost ([127.0.0.1] helo=vostro.local) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1gwDEw-0000yh-PT; Tue, 19 Feb 2019 22:47:46 +0100 From: John Ogness To: Petr Mladek Cc: linux-kernel@vger.kernel.org, Peter Zijlstra , Sergey Senozhatsky , Steven Rostedt , Daniel Wang , Andrew Morton , Linus Torvalds , Greg Kroah-Hartman , Alan Cox , Jiri Slaby , Peter Feiner , linux-serial@vger.kernel.org, Sergey Senozhatsky Subject: Re: [RFC PATCH v1 06/25] printk-rb: add blocking reader support References: <20190212143003.48446-1-john.ogness@linutronix.de> <20190212143003.48446-7-john.ogness@linutronix.de> <20190218140538.5sug36qiji2rurxx@pathway.suse.cz> Date: Tue, 19 Feb 2019 22:47:45 +0100 In-Reply-To: <20190218140538.5sug36qiji2rurxx@pathway.suse.cz> (Petr Mladek's message of "Mon, 18 Feb 2019 15:05:38 +0100") Message-ID: <87k1hvv4am.fsf@linutronix.de> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.4 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 2019-02-18, Petr Mladek wrote: >> Add a blocking read function for readers. An irq_work function is >> used to signal the wait queue so that write notification can >> be triggered from any context. > > I would be more precise what exacly is problematic in which context. > Something like: > > An irq_work function is used because wake_up() cannot be called safely > from NMI and scheduler context. OK. >> Signed-off-by: John Ogness >> --- >> include/linux/printk_ringbuffer.h | 20 ++++++++++++++++ >> lib/printk_ringbuffer.c | 49 +++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 69 insertions(+) >> >> diff --git a/include/linux/printk_ringbuffer.h b/include/linux/printk_ringbuffer.h >> index 5fdaf632c111..106f20ef8b4d 100644 >> --- a/include/linux/printk_ringbuffer.h >> +++ b/include/linux/printk_ringbuffer.h >> @@ -2,8 +2,10 @@ >> #ifndef _LINUX_PRINTK_RINGBUFFER_H >> #define _LINUX_PRINTK_RINGBUFFER_H >> >> +#include >> #include >> #include >> +#include >> >> struct prb_cpulock { >> atomic_t owner; >> @@ -22,6 +24,10 @@ struct printk_ringbuffer { >> >> struct prb_cpulock *cpulock; >> atomic_t ctx; >> + >> + struct wait_queue_head *wq; >> + atomic_long_t wq_counter; >> + struct irq_work *wq_work; >> }; >> >> struct prb_entry { >> @@ -59,6 +65,15 @@ struct prb_iterator { >> #define DECLARE_STATIC_PRINTKRB(name, szbits, cpulockptr) \ >> static char _##name##_buffer[1 << (szbits)] \ >> __aligned(__alignof__(long)); \ >> +static DECLARE_WAIT_QUEUE_HEAD(_##name##_wait); \ >> +static void _##name##_wake_work_func(struct irq_work *irq_work) \ >> +{ \ >> + wake_up_interruptible_all(&_##name##_wait); \ >> +} \ > > All ring buffers might share the same generic function, something like: > > void prb_wake_readers_work_func(struct irq_work *irq_work) > { > struct printk_ringbuffer *rb; > > rb = container_of(irq_work, struct printk_ring_buffer, wq_work); > wake_up_interruptible_all(rb->wq); \ > } Agreed. >> +static struct irq_work _##name##_wake_work = { \ >> + .func = _##name##_wake_work_func, \ >> + .flags = IRQ_WORK_LAZY, \ >> +}; \ >> static struct printk_ringbuffer name = { \ >> .buffer = &_##name##_buffer[0], \ >> .size_bits = szbits, \ >> diff --git a/lib/printk_ringbuffer.c b/lib/printk_ringbuffer.c >> index 1d1e886a0966..c2ddf4cb9f92 100644 >> --- a/lib/printk_ringbuffer.c >> +++ b/lib/printk_ringbuffer.c >> @@ -185,6 +188,12 @@ void prb_commit(struct prb_handle *h) >> } >> >> prb_unlock(rb->cpulock, h->cpu); >> + >> + if (changed) { >> + atomic_long_inc(&rb->wq_counter); >> + if (wq_has_sleeper(rb->wq)) >> + irq_work_queue(rb->wq_work); >> + } >> } >> >> /* >> @@ -437,3 +446,43 @@ int prb_iter_next(struct prb_iterator *iter, char *buf, int size, u64 *seq) >> >> return 1; >> } >> + >> +/* >> + * prb_iter_wait_next: Advance to the next record, blocking if none available. >> + * @iter: Iterator tracking the current position. >> + * @buf: A buffer to store the data of the next record. May be NULL. >> + * @size: The size of @buf. (Ignored if @buf is NULL.) >> + * @seq: The sequence number of the next record. May be NULL. >> + * >> + * If a next record is already available, this function works like >> + * prb_iter_next(). Otherwise block interruptible until a next record is >> + * available. >> + * >> + * When a next record is available, @iter is advanced and (if specified) >> + * the data and/or sequence number of that record are provided. >> + * >> + * This function might sleep. >> + * >> + * Returns 1 if @iter was advanced, -EINVAL if @iter is now invalid, or >> + * -ERESTARTSYS if interrupted by a signal. >> + */ >> +int prb_iter_wait_next(struct prb_iterator *iter, char *buf, int size, u64 *seq) >> +{ >> + unsigned long last_seen; >> + int ret; >> + >> + for (;;) { >> + last_seen = atomic_long_read(&iter->rb->wq_counter); >> + >> + ret = prb_iter_next(iter, buf, size, seq); >> + if (ret != 0) >> + break; >> + >> + ret = wait_event_interruptible(*iter->rb->wq, >> + last_seen != atomic_long_read(&iter->rb->wq_counter)); > > Do we really need yet another counter here? > > I think that rb->seq might do the same job. Or if there is problem > with atomicity then rb->head might work as well. Or do I miss > anything? You are correct. rb->head would be appropriate. John Ogness