lkml.org 
[lkml]   [1999]   [Dec]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: sleep_on, wake_up question
    Okay, I checked Rubini's book, and he has a solution which seems elegant
    enough (Alan suggested it in a previous post, but here's the full
    expansion).
    Here's the code:

    struct wait_queue wait = {current, NULL};

    add_wait_queue(&my_q, &wait);
    current->state = TASK_INTERRUPTIBLE;
    play_with_my_hardware_which_will_eventually_generate_an_interrupt();
    schedule();
    remove_wait_queue(&my_q, &wait);

    my_isr()
    {
    ...
    wake_up_interruptible(&my_q);
    ...
    }

    The story is that if the interrupt beats the schedule(), then the task
    will be set to state TASK_RUNNING via the wake_up_interruptible call, and
    the process removes itself from the wait queue. This should work well
    enough, but I still think that having a bulletproof version of sleep_on is
    far more elegant, and may prevent some painful mistakes for driver
    writers.
    Just one more question (I'm new to linux drivers, was in NT driverland
    till recently, glad to get the needle out of my vein :)
    In the code above, is there any possibility of the process' state being
    changed prior to the schedule() call (i.e. can nonblocking kernel code be
    context-switched out?)

    thanks,
    -Mark

    >
    > Mark,
    > I checked a later kernel and it can get stuck. However, you can
    > use sleep_on_timeout() to make sure you do get awakened. A
    > check of something the interrupt should have written will let you
    > know what happened, i.e,...
    >
    > spin_lock_irqsave(&device_lock, flags);
    > if(irq_flag)
    > {
    > spin_unlock_irqrestore(&device_lock, flags);
    > //// You already got interrupted, fix this first!
    >
    > spin_lock_irqsave(&device_lock, flags);
    > }
    > irq_flag = 0;
    > tickle_hardware(); /* Interrupts are off */
    > spin_unlock_irqrestore(&device_lock, flags);
    >
    >
    > interruptible_sleep_on_timeout(&wait, time * HZ);
    > spin_lock_irqsave(&device_lock, flags);
    > if(irq_flag)
    > /// Was interrupted
    > else
    > /// Was not
    > spin_unlock_irqrestore(&device_lock, flags);
    >
    >
    > isr()
    > {
    > irq_flag = 1;
    > wake_up_interruptible(&wait);
    > }
    >
    > Just check program flow under a spin-lock and it should be safe
    > in SMP. Keep the code under the locks short. I have a GPIB driver
    > which will have to be modifed once a new kernel is released. It
    > does about 100,000 interrupts per second without losing data, but
    > it won't even compile with a new kernel because some types have
    > changed. So I haven't done anything with it recently.
    >
    > Cheers,
    > Dick Johnson
    >
    > Penguin : Linux version 2.3.13 on an i686 machine (400.59 BogoMips).
    > Warning : The end of the world as we know it requires a new calendar.
    > Seconds : 125933 (until Y2K)
    >
    >
    > -
    > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    > the body of a message to majordomo@vger.rutgers.edu
    > Please read the FAQ at http://www.tux.org/lkml/
    >



    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.rutgers.edu
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 13:55    [W:2.210 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site