Skip to content

Commit 5eacb68

Browse files
author
Frederic Weisbecker
committed
kthread: Make sure kthread hasn't started while binding it
Make sure the kthread is sleeping in the schedule_preempt_disabled() call before calling its handler when kthread_bind[_mask]() is called on it. This provides a sanity check verifying that the task is not randomly blocked later at some point within its function handler, in which case it could be just concurrently awaken, leaving the call to do_set_cpus_allowed() without any effect until the next voluntary sleep. Rely on the wake-up ordering to ensure that the newly introduced "started" field returns the expected value: TASK A TASK B ------ ------ READ kthread->started wake_up_process(B) rq_lock() ... rq_unlock() // RELEASE schedule() rq_lock() // ACQUIRE // schedule task B rq_unlock() WRITE kthread->started Similarly, writing kthread->started before subsequent voluntary sleeps will be visible after calling wait_task_inactive() in __kthread_bind_mask(), reporting potential misuse of the API. Upcoming patches will make further use of this facility. Acked-by: Vlastimil Babka <[email protected]> Signed-off-by: Frederic Weisbecker <[email protected]>
1 parent 3a54466 commit 5eacb68

File tree

1 file changed

+7
-0
lines changed

1 file changed

+7
-0
lines changed

kernel/kthread.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ struct kthread_create_info
5353
struct kthread {
5454
unsigned long flags;
5555
unsigned int cpu;
56+
int started;
5657
int result;
5758
int (*threadfn)(void *);
5859
void *data;
@@ -382,6 +383,8 @@ static int kthread(void *_create)
382383
schedule_preempt_disabled();
383384
preempt_enable();
384385

386+
self->started = 1;
387+
385388
ret = -EINTR;
386389
if (!test_bit(KTHREAD_SHOULD_STOP, &self->flags)) {
387390
cgroup_kthread_ready();
@@ -540,7 +543,9 @@ static void __kthread_bind(struct task_struct *p, unsigned int cpu, unsigned int
540543

541544
void kthread_bind_mask(struct task_struct *p, const struct cpumask *mask)
542545
{
546+
struct kthread *kthread = to_kthread(p);
543547
__kthread_bind_mask(p, mask, TASK_UNINTERRUPTIBLE);
548+
WARN_ON_ONCE(kthread->started);
544549
}
545550

546551
/**
@@ -554,7 +559,9 @@ void kthread_bind_mask(struct task_struct *p, const struct cpumask *mask)
554559
*/
555560
void kthread_bind(struct task_struct *p, unsigned int cpu)
556561
{
562+
struct kthread *kthread = to_kthread(p);
557563
__kthread_bind(p, cpu, TASK_UNINTERRUPTIBLE);
564+
WARN_ON_ONCE(kthread->started);
558565
}
559566
EXPORT_SYMBOL(kthread_bind);
560567

0 commit comments

Comments
 (0)