Re: sleep

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10/16/05, Jan Hudec <bulb@xxxxxx> wrote:
> On Mon, Sep 19, 2005 at 15:13:10 +0900, linux lover wrote:
> > You can use schedule_timeout like this
> > current->state = TASK_UNINTERRUPTIBLE;
> > schedule_timeout(X*HZ); /* Sleep for X seconds */
> > current->state = TASK_INTERRUPTIBLE;
>
> Um, no. Since preempt went in, this is exactly the one you _can't_ use.
> Because a schedule can occur from preempt just between setting the state
> to TASK_UNINTERRUPTIBLE and calling schedule_timeout. I don't know how
> to operate the necessary preempt stuff though.

Well, the code of:

set_current_state(TASK_{,UN}INTERRUPTIBLE);
schedule_timeout(x_secs*HZ);

does work in the kernel, under preempt. But you would not manually
keep the task in a sleeping state, that doesn't make sense (i.e. the
current->state = TASK_INTERRUPTIBLE assignment after
schedule_timeout), as schedule_timeout() guarantees to return in
TASK_RUNNING and you're not sleeping again immediately. I guess your
concern might be that we might sleep much longer than requested, since
we could preempt then sleep the x seconds? Not much you can do there.
Code should probably check that it should sleep before calling
schedule_timeout, generally. Not to say it can't happen, but I haven't
seen anyone report anything like that.

But we've changed that anyways now, and you have

schedule_timeout_{,un}interruptible(x_secs*HZ);

that sets the state for you.

You also have

msleep{,interruptible}(x_secs*1000);

and

ssleep();

Plus wait-queues (using wait_event() & co., which sleep).

When to use what?

If you want to sleep:

  and are on a waitqueue:

    and want to wake-up on signals and wait-queue events:
      schedule_timeout_interruptible();
    and want to wake-up on only wait-queue events:
      schedule_timeout_uninterruptible(); [notice, though, your loadavg is
                                                             pegged at
1 per each such task]
  and are not on a waitqueue:

    and want to wake-up on signals:
      msleep_interruptible();
    and don't want to sleep at least the requested time:
      msleep(); [again, loadavg gets upped by 1]

Now, all sleeps are "at least" the requested anyways, except any early
terminating events (the signals or wait-queue events mentioned above),
since there may be rounding going on you don't see, and there may be
high load when the corresponding kernel timer expires.

> Um, and current->state = TASK_<whatever> is not correct either -- there
> is a set_current_state macro, that must be used, because unlike the
> assignment it's quaranteed to be atomic and block undesired
> optimizations.

We also have

__set_current_state(), which is also atomic (I believe) but does not
have an mb, e.g. it should be identical to current->state =
TASK_{,UN}INTERRUPTIBLE.

You are right, though, if you are calling schedule_timeout()
immediately after, then you need the mb-version.

> >  On 9/19/05, raja <vnagaraju@xxxxxxxxxxxx> wrote:
> > >
> > > Hi,
> > > Would you please tell me how can i sleep in kernel space.
>
> Um, the above, with schedule_timeout, does not seem to be correct
> responese... In fact the correct response would be: In many ways (though
> all of them end up calling schedule() underneath). What do you want it
> for?
>
> By the way, TASK_INTERRUUPTIBLE is also sleep. When you
> set_current_state(TASK_INTERRUPTIBLE), preempt may call schedule on you
> and you won't wake up unless you get a signal.

Not entirely true, see above.

Thanks,
Nish

--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/



[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux