From mboxrd@z Thu Jan 1 00:00:00 1970 From: OGAWA Hirofumi Subject: Re: [Bug #14388] keyboard under X with 2.6.31 Date: Fri, 16 Oct 2009 02:38:38 +0900 Message-ID: <87aazsh80x.fsf@devron.myhome.or.jp> References: <56acieJJ2fF.A.nEB.Hzl0KB@chimera> <87ljjgfcbu.fsf@spindle.srvr.nix> <4AD3F769.5080405@gmail.com> <4AD437F9.9020708@yahoo.co.uk> <4AD4DE4C.4010402@yahoo.co.uk> <4AD4F548.2030506@microgate.com> <1255478932.19056.24.camel@localhost.localdomain> <4AD51D6B.7010509@microgate.com> <20091014125846.1a3c8d40@lxorguk.ukuu.org.uk> Mime-Version: 1.0 Return-path: In-Reply-To: (Linus Torvalds's message of "Wed, 14 Oct 2009 09:38:43 -0700 (PDT)") Sender: linux-kernel-owner@vger.kernel.org List-ID: Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: Linus Torvalds Cc: Alan Cox , Oleg Nesterov , Paul Fulghum , Boyan , "Rafael J. Wysocki" , Linux Kernel Mailing List , Kernel Testers List , Dmitry Torokhov , Ed Tomlinson Hi, Linus Torvalds writes: > diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c > index 0296612..66fa4e1 100644 > --- a/drivers/char/tty_buffer.c > +++ b/drivers/char/tty_buffer.c > @@ -468,7 +468,7 @@ static void flush_to_ldisc(struct work_struct *work) > */ > void tty_flush_to_ldisc(struct tty_struct *tty) > { > - flush_to_ldisc(&tty->buf.work.work); > + flush_delayed_work(&tty->buf.work); > } This might wait unnecessary scheduled-work on input_available_p(). This is nitpick though, we can call tty_flush_to_ldisc() only when data is unavailable. I.e. the following or something, static inline int input_available_p(struct tty_struct *tty, int amt) { int try = 0; retry: if (tty->icanon) { if (tty->canon_data) return 1; } else if (tty->read_cnt >= (amt ? amt : 1)) return 1; if (!checked) { tty_flush_to_ldisc(tty); try = 1; goto retry; } return 0; } > +void flush_delayed_work(struct delayed_work *dwork) > +{ > + if (del_timer(&dwork->timer)) { > + struct cpu_workqueue_struct *cwq; > + cwq = wq_per_cpu(keventd_wq, get_cpu()); > + __queue_work(cwq, &dwork->work); > + put_cpu(); > + } > + flush_work(&dwork->work); > +} > +EXPORT_SYMBOL(flush_delayed_work); > + > +/** Sorry if I'm missing the point. Doesn't this have (possible) race with schedule_delayed_work() (i.e. by tty writer)? cpu0 cpu1 if (del_timer(&dwork->timer)) { // cpu0 doesn't set _PENDING schedule_delayed_work() cwq = wq_per_cpu(); __queue_work(cwq, &dwork->work); put_cpu(); } // run timer delayed_work_timer_fn() __queue_work() list_add_tail() // re-add without list_del(), // so this will break the list? flush_work(&dwork->work); Thanks. -- OGAWA Hirofumi