rmn
rmn

Reputation: 2426

Sleeping in the kernel using set_current_state

I've been reading http://www.linuxjournal.com/article/8144 and thinking about the following situation:

4253  /* Wait for kthread_stop */
4254  set_current_state(TASK_INTERRUPTIBLE);
4255  while (!kthread_should_stop()) {
4256          schedule();
4257          set_current_state(TASK_INTERRUPTIBLE);
4258  }
4259  set_current_state(TASK_RUNNING);
4260 return 0;

Now, what happens if kthread_stop was called right before line 4254 where we set the process to sleep, and right after that line we actually get preempted/scheduled and the process is also really sent to sleep?

In this case, the wake up call is received right before changing the state (so it does not affect us), and the normal operation of the operating system puts us to sleep before we actually check anything.

I imagine I'm missing something, probably one of the following two options: (1) The actual change of the state only happens when we call schedule(), or (2) There is no way for us to get scheduled out (either by preemption, interrupts, anything) after the set_current_state call and before the schedule() call.

Thanks for any assistance!

Upvotes: 4

Views: 3831

Answers (3)

Sudheer Divakaran
Sudheer Divakaran

Reputation: 11

Here is a similar question & answer

http://fixunix.com/linux/7425-schedule_timeout-doubt-possible-infinite-sleep.html

quoting from the link,

[quote-]

If I understand it correctly, when a preemption occurs, the PREEMPT_ACTIVE bit gets added to the thread's preempt_count; this happens in preempt_schedule / preempt_schedule_irq. These then call schedule(), which checks for PREEMPT_ACTIVE being set in the count and if it's set, it doesn't call deactivate_task(), which leaves the thread on the active list. [-quote]

So if an interrupt or preemption happens, the thread will not be moved out of the run queue.

Upvotes: 1

Hasturkun
Hasturkun

Reputation: 36402

If kthread_stop gets called before line 4254, kthread_should_stop() will return true, and schedule() will not be called. In this specific case, the migration_thread is scheduled with high priority with the SCHED_FIFO policy (which has no time slices), and can only be preempted by another SCHED_FIFO task with higher priority (see sched_setscheduler).

Upvotes: 1

Mats Petersson
Mats Petersson

Reputation: 129364

schedule() is the ONLY way that the Linux kernel will change context between threads.

As the code comments, this is for migrating between processors, so presumably isn't run very often (relatively speaking).

Upvotes: -1

Related Questions