diff options
author | Paul Menage <menage@google.com> | 2007-10-19 02:40:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-19 14:53:41 -0400 |
commit | 8707d8b8c0cbdf4441507f8dded194167da896c7 (patch) | |
tree | 1e9ac6b15027bd55263378e551c1595a937d66d6 /kernel/sched.c | |
parent | 020958b6272882c1a8bfbe5f3e0927f3845c2698 (diff) |
Fix cpusets update_cpumask
Cause writes to cpuset "cpus" file to update cpus_allowed for member tasks:
- collect batches of tasks under tasklist_lock and then call
set_cpus_allowed() on them outside the lock (since this can sleep).
- add a simple generic priority heap type to allow efficient collection
of batches of tasks to be processed without duplicating or missing any
tasks in subsequent batches.
- make "cpus" file update a no-op if the mask hasn't changed
- fix race between update_cpumask() and sched_setaffinity() by making
sched_setaffinity() post-check that it's not running on any cpus outside
cpuset_cpus_allowed().
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Paul Menage <menage@google.com>
Cc: Paul Jackson <pj@sgi.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Balbir Singh <balbir@in.ibm.com>
Cc: Cedric Le Goater <clg@fr.ibm.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 39d6354af489..72a809a54d5b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -4471,8 +4471,21 @@ long sched_setaffinity(pid_t pid, cpumask_t new_mask) | |||
4471 | 4471 | ||
4472 | cpus_allowed = cpuset_cpus_allowed(p); | 4472 | cpus_allowed = cpuset_cpus_allowed(p); |
4473 | cpus_and(new_mask, new_mask, cpus_allowed); | 4473 | cpus_and(new_mask, new_mask, cpus_allowed); |
4474 | again: | ||
4474 | retval = set_cpus_allowed(p, new_mask); | 4475 | retval = set_cpus_allowed(p, new_mask); |
4475 | 4476 | ||
4477 | if (!retval) { | ||
4478 | cpus_allowed = cpuset_cpus_allowed(p); | ||
4479 | if (!cpus_subset(new_mask, cpus_allowed)) { | ||
4480 | /* | ||
4481 | * We must have raced with a concurrent cpuset | ||
4482 | * update. Just reset the cpus_allowed to the | ||
4483 | * cpuset's cpus_allowed | ||
4484 | */ | ||
4485 | new_mask = cpus_allowed; | ||
4486 | goto again; | ||
4487 | } | ||
4488 | } | ||
4476 | out_unlock: | 4489 | out_unlock: |
4477 | put_task_struct(p); | 4490 | put_task_struct(p); |
4478 | mutex_unlock(&sched_hotcpu_mutex); | 4491 | mutex_unlock(&sched_hotcpu_mutex); |