lkml.org 
[lkml]   [2009]   [Oct]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [Bug #14388] keyboard under X with 2.6.31
    On 10/14, Linus Torvalds wrote:
    >
    > Of course, keventd itself is multi-threaded, so I'm not entirely sure even
    > -that- guarantees that one 'flush_to_ldisc()' couldn't be pending on one
    > CPU while it is then scheduled and then run on another CPU concurrently
    > too. The WORK_STRUCT_PENDING bit guarantees exclusion from the lists and
    > from being pending, but the work might be both pending and _running_ at
    > the same time, afaik.

    Yes.

    > void tty_flush_to_ldisc(struct tty_struct *tty)
    > {
    > - flush_to_ldisc(&tty->buf.work.work);
    > + flush_delayed_work(&tty->buf.work);
    > }

    Can't comment this change because I don't understand the problem.

    > + * flush_delayed_work - block until a dwork_struct's callback has terminated
    > + * @dwork: the delayed work which is to be flushed
    > + *
    > + * Any timeout is cancelled, and any pending work is run immediately.
    > + */
    > +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);
    > +}

    I think this is correct. If del_timer() succeeds, we "own" _PENDING bit and
    dwork->work must not be queued. But afaics this helper needs del_timer_sync(),
    otherwise I am not sure about the "flush" part.

    Let's suppose this dwork was pending and del_timer() returns 0. Since we use
    del_timer, not del_timer_sync, it is possible that delayed_work_timer_fn() is
    running in parallel, and the queueing is in progress. In this case flush_work()
    can just return, before delayed_work_timer_fn() actually queues this dwork.

    And just in case... Of course, if dwork was pending and running on another CPU,
    then flush_delayed_work(dwork) can return before the running callback terminates.
    But I guess this is what we want.


    As for tty_flush_to_ldisc(), what if tty->buf.work.work was not scheduled?
    In this case flush_delayed_work() does nothing. Is it OK?

    Oleg.



    \
     
     \ /
      Last update: 2009-10-14 20:37    [W:4.085 / U:0.080 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site