Putting a thread to sleep using schedule() is foolproof?
Yes, there are other ways, but I have a doubt on one of the basic method of sleeping - set_current_state (TASK_INTERRUPTIBLE); schedule (); Is this a sure-shot way of putting a thread to sleep, or are there conditions when this may not put the calling thread into sleep? Almost always I see that the thread goes to sleep, until explicitly woken up by another thread. But, once it a blue moon, I find that thread executes the above instructions and does not go to sleep! -- Joshi
On Wed, 11 Jun 2014 23:09:05 +0530, Joshi said:
set_current_state (TASK_INTERRUPTIBLE); schedule ();
Is this a sure-shot way of putting a thread to sleep, or are there conditions when this may not put the calling thread into sleep?
This will only succeed in guaranteeing the thread sleep if the thread has done something *else* to render it not schedulable. schedule() will return right back to that thread if it's the highest-priority thing that's runnable. What problem are you trying to solve? Usually, you do that sort of schedule() when you're doing something that will take a relatively long chunk of time, and want other things to have a *chance* of running. But usually, you're perfectly happy with continuing to run if nobody else wants to run. Why did you want a guaranteed sleep? If it's because you've started an I/O and you *know* it will be 125 milliseconds before you can make further progress, there's mdelay() and similar APIs... and so on for other reasons for wanting to sleep (for instance, blocking on a lock has an API, etc)
Is not changing the state to TASK_INTERRUPTIBLE before calling schedule() renders it not-schedulable? I thought task would be removed off run-queue by schedule() because it is in TASK_INTERRUPTIBLE state. I was making a sort of task queue. Threads puts themselves into this queue when a resource(say memory-space) is not available. And other thread, post releasing the memory space, will wake the first thread in queue. There are other means to achieve that, but I wondered why the above mentioned method did not succeed in making thread sleep. On Wed, Jun 11, 2014 at 11:21 PM, <Valdis.Kletnieks@vt.edu> wrote:
On Wed, 11 Jun 2014 23:09:05 +0530, Joshi said:
set_current_state (TASK_INTERRUPTIBLE); schedule ();
Is this a sure-shot way of putting a thread to sleep, or are there conditions when this may not put the calling thread into sleep?
This will only succeed in guaranteeing the thread sleep if the thread has done something *else* to render it not schedulable. schedule() will return right back to that thread if it's the highest-priority thing that's runnable.
What problem are you trying to solve? Usually, you do that sort of schedule() when you're doing something that will take a relatively long chunk of time, and want other things to have a *chance* of running. But usually, you're perfectly happy with continuing to run if nobody else wants to run.
Why did you want a guaranteed sleep? If it's because you've started an I/O and you *know* it will be 125 milliseconds before you can make further progress, there's mdelay() and similar APIs... and so on for other reasons for wanting to sleep (for instance, blocking on a lock has an API, etc)
-- Joshi
From: kernelnewbies-bounces@kernelnewbies.org [mailto:kernelnewbies-bounces@kernelnewbies.org] On Behalf Of Joshi Sent: Wednesday, June 11, 2014 11:33 AM To: Valdis.Kletnieks@vt.edu Cc: kernelnewbies@kernelnewbies.org Subject: Re: Putting a thread to sleep using schedule() is foolproof? Is not changing the state to TASK_INTERRUPTIBLE before calling schedule() renders it not-schedulable? I thought task would be removed off run-queue by schedule() because it is in TASK_INTERRUPTIBLE state. I was making a sort of task queue. Threads puts themselves into this queue when a resource(say memory-space) is not available. And other thread, post releasing the memory space, will wake the first thread in queue. There are other means to achieve that, but I wondered why the above mentioned method did not succeed in making thread sleep. I think TASK_INTERRUPTIBLE has to do with whether or not a task can be “interrupted” by a signal, as in wait_event_interruptible(). Jeff Haran
But if the state is anything other than TASK_RUNNING, schedule() is attempts to remove the task off run queue. Please see below (implementation of __schedule, called by schedule()) - 2671 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2671> */**2672 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2672> * * Make sure that signal_pending_state()->signal_pending() below*2673 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2673> * * can't be reordered with __set_current_state(TASK_INTERRUPTIBLE)*2674 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2674> * * done by the caller to avoid the race with signal_wake_up().*2675 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2675> * */*2676 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2676> smp_mb__before_spinlock <http://lxr.free-electrons.com/ident?v=3.14;i=smp_mb__before_spinlock>();2677 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2677> raw_spin_lock_irq <http://lxr.free-electrons.com/ident?v=3.14;i=raw_spin_lock_irq>(&rq <http://lxr.free-electrons.com/ident?v=3.14;i=rq>->lock <http://lxr.free-electrons.com/ident?v=3.14;i=lock>);2678 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2678> 2679 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2679> switch_count = &prev->nivcsw;2680 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2680> if (prev->state <http://lxr.free-electrons.com/ident?v=3.14;i=state> && !(preempt_count <http://lxr.free-electrons.com/ident?v=3.14;i=preempt_count>() & PREEMPT_ACTIVE <http://lxr.free-electrons.com/ident?v=3.14;i=PREEMPT_ACTIVE>)) {2681 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2681> if (unlikely <http://lxr.free-electrons.com/ident?v=3.14;i=unlikely>(signal_pending_state <http://lxr.free-electrons.com/ident?v=3.14;i=signal_pending_state>(prev->state <http://lxr.free-electrons.com/ident?v=3.14;i=state>, prev))) {2682 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2682> prev->state <http://lxr.free-electrons.com/ident?v=3.14;i=state> = TASK_RUNNING <http://lxr.free-electrons.com/ident?v=3.14;i=TASK_RUNNING>;2683 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2683> } else {2684 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2684> deactivate_task <http://lxr.free-electrons.com/ident?v=3.14;i=deactivate_task>(rq <http://lxr.free-electrons.com/ident?v=3.14;i=rq>, prev, DEQUEUE_SLEEP <http://lxr.free-electrons.com/ident?v=3.14;i=DEQUEUE_SLEEP>);2685 <http://lxr.free-electrons.com/source/kernel/sched/core.c?v=3.14#L2685> prev->on_rq = 0; At line 2684 task is removed. So it will be suspended. However,as per line 2681, there seems to be a case when it may not put a task to sleep. But I am not sure when that can happen. Also comment at line 2672 talks about preventing a race-condition in the caller. I did not understand that. In the code-snippet(in my first post) I did not do anything special in caller to avoid any race condition! On Thu, Jun 12, 2014 at 12:15 AM, Jeff Haran <Jeff.Haran@citrix.com> wrote:
*From:* kernelnewbies-bounces@kernelnewbies.org [mailto: kernelnewbies-bounces@kernelnewbies.org] *On Behalf Of *Joshi *Sent:* Wednesday, June 11, 2014 11:33 AM *To:* Valdis.Kletnieks@vt.edu *Cc:* kernelnewbies@kernelnewbies.org *Subject:* Re: Putting a thread to sleep using schedule() is foolproof?
Is not changing the state to TASK_INTERRUPTIBLE before calling schedule() renders it not-schedulable? I thought task would be removed off run-queue by schedule() because it is in TASK_INTERRUPTIBLE state.
I was making a sort of task queue. Threads puts themselves into this queue when a resource(say memory-space) is not available. And other thread, post releasing the memory space, will wake the first thread in queue.
There are other means to achieve that, but I wondered why the above mentioned method did not succeed in making thread sleep.
I think TASK_INTERRUPTIBLE has to do with whether or not a task can be “interrupted” by a signal, as in wait_event_interruptible().
Jeff Haran
-- Joshi
participants (3)
-
Jeff Haran -
Joshi -
Valdis.Kletnieks@vt.edu