From a03ee0000e93386df03128e4c38870fcede169a0 Mon Sep 17 00:00:00 2001 From: Jeff Roberson Date: Sun, 30 Mar 2008 11:31:14 +0000 Subject: [PATCH] - Consistently return EDEADLK when presented with a new set that is incompatible with existing bindings. - Try to copyout the setid in cpuset() before migrating the proc to the setid in case the user has supplied a bad buffer. - Rename cpuset_root() and cpuset_base() to cpuset_ref{root,base} to be more descriptive and free cpuset_root to be used as a different type of symbol. - Make cpuset_root the cpuset_t set of all cpus in the system. This should contain the same bitmask as all_cpus presently. - Add a CPU_CMP() macro to compare two sets. --- sys/kern/kern_cpuset.c | 47 ++++++++++++++++++++++++------------------ sys/sys/cpuset.h | 16 +++++++++++++- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/sys/kern/kern_cpuset.c b/sys/kern/kern_cpuset.c index fe9bcb76cdd6..9c962a59091c 100644 --- a/sys/kern/kern_cpuset.c +++ b/sys/kern/kern_cpuset.c @@ -46,6 +46,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include @@ -93,8 +95,10 @@ __FBSDID("$FreeBSD$"); static uma_zone_t cpuset_zone; static struct mtx cpuset_lock; static struct setlist cpuset_ids; -struct cpuset *cpuset_zero; static struct unrhdr *cpuset_unr; +static struct cpuset *cpuset_zero; + +cpuset_t *cpuset_root; /* * Acquire a reference to a cpuset, all pointers must be tracked with refs. @@ -312,7 +316,7 @@ out: * referenced. */ static struct cpuset * -cpuset_root(struct cpuset *set) +cpuset_refroot(struct cpuset *set) { for (; set->cs_parent != NULL; set = set->cs_parent) @@ -329,7 +333,7 @@ cpuset_root(struct cpuset *set) * not anonymous. */ static struct cpuset * -cpuset_base(struct cpuset *set) +cpuset_refbase(struct cpuset *set) { if (set->cs_id == CPUSET_INVALID) @@ -396,7 +400,7 @@ cpuset_which(cpuwhich_t which, id_t id, struct proc **pp, struct thread **tdp, case CPU_WHICH_CPUSET: if (id == -1) { thread_lock(curthread); - set = cpuset_base(curthread->td_cpuset); + set = cpuset_refbase(curthread->td_cpuset); thread_unlock(curthread); } else set = cpuset_lookup(id); @@ -435,7 +439,7 @@ cpuset_shadow(struct cpuset *set, struct cpuset *fset, cpuset_t *mask) else parent = set; if (!CPU_SUBSET(&parent->cs_mask, mask)) - return (EINVAL); + return (EDEADLK); return (_cpuset_create(fset, parent, mask, CPUSET_INVALID)); } @@ -505,7 +509,7 @@ cpuset_setproc(pid_t pid, struct cpuset *set, cpuset_t *mask) if (tdset->cs_id == CPUSET_INVALID) tdset = tdset->cs_parent; if (!CPU_SUBSET(&tdset->cs_mask, mask)) - error = EINVAL; + error = EDEADLK; /* * Verify that a new set won't leave an existing thread * mask without a cpu to run on. It can, however, restrict @@ -513,7 +517,7 @@ cpuset_setproc(pid_t pid, struct cpuset *set, cpuset_t *mask) */ } else if (tdset->cs_id == CPUSET_INVALID) { if (!CPU_OVERLAP(&set->cs_mask, &tdset->cs_mask)) - error = EINVAL; + error = EDEADLK; } thread_unlock(td); if (error) @@ -570,7 +574,7 @@ out: /* * Apply an anonymous mask to a single thread. */ -static int +int cpuset_setthread(lwpid_t id, cpuset_t *mask) { struct cpuset *nset; @@ -583,17 +587,19 @@ cpuset_setthread(lwpid_t id, cpuset_t *mask) error = cpuset_which(CPU_WHICH_TID, id, &p, &td, &set); if (error) goto out; + set = NULL; thread_lock(td); - set = td->td_cpuset; - error = cpuset_shadow(set, nset, mask); + error = cpuset_shadow(td->td_cpuset, nset, mask); if (error == 0) { - cpuset_rel(td->td_cpuset); + set = td->td_cpuset; td->td_cpuset = nset; sched_affinity(td); nset = NULL; } thread_unlock(td); PROC_UNLOCK(p); + if (set) + cpuset_rel(set); out: if (nset) uma_zfree(cpuset_zone, nset); @@ -631,6 +637,7 @@ cpuset_thread0(void) set->cs_ref = 1; set->cs_flags = CPU_SET_ROOT; cpuset_zero = set; + cpuset_root = &set->cs_mask; /* * Now derive a default, modifiable set from that to give out. */ @@ -679,15 +686,15 @@ cpuset(struct thread *td, struct cpuset_args *uap) int error; thread_lock(td); - root = cpuset_root(td->td_cpuset); + root = cpuset_refroot(td->td_cpuset); thread_unlock(td); error = cpuset_create(&set, root, &root->cs_mask); cpuset_rel(root); if (error) return (error); - error = cpuset_setproc(-1, set, NULL); + error = copyout(&set->cs_id, uap->setid, sizeof(set->cs_id)); if (error == 0) - error = copyout(&set->cs_id, uap->setid, sizeof(set->cs_id)); + error = cpuset_setproc(-1, set, NULL); cpuset_rel(set); return (error); } @@ -744,7 +751,7 @@ cpuset_getid(struct thread *td, struct cpuset_getid_args *uap) case CPU_WHICH_TID: case CPU_WHICH_PID: thread_lock(ttd); - set = cpuset_base(ttd->td_cpuset); + set = cpuset_refbase(ttd->td_cpuset); thread_unlock(ttd); PROC_UNLOCK(p); break; @@ -753,7 +760,7 @@ cpuset_getid(struct thread *td, struct cpuset_getid_args *uap) } switch (uap->level) { case CPU_LEVEL_ROOT: - nset = cpuset_root(set); + nset = cpuset_refroot(set); cpuset_rel(set); set = nset; break; @@ -812,9 +819,9 @@ cpuset_getaffinity(struct thread *td, struct cpuset_getaffinity_args *uap) break; } if (uap->level == CPU_LEVEL_ROOT) - nset = cpuset_root(set); + nset = cpuset_refroot(set); else - nset = cpuset_base(set); + nset = cpuset_refbase(set); CPU_COPY(&nset->cs_mask, mask); cpuset_rel(nset); break; @@ -913,9 +920,9 @@ cpuset_setaffinity(struct thread *td, struct cpuset_setaffinity_args *uap) break; } if (uap->level == CPU_LEVEL_ROOT) - nset = cpuset_root(set); + nset = cpuset_refroot(set); else - nset = cpuset_base(set); + nset = cpuset_refbase(set); error = cpuset_modify(nset, mask); cpuset_rel(nset); cpuset_rel(set); diff --git a/sys/sys/cpuset.h b/sys/sys/cpuset.h index d4634f0c1884..35b12adaa3d6 100644 --- a/sys/sys/cpuset.h +++ b/sys/sys/cpuset.h @@ -87,6 +87,16 @@ typedef struct _cpuset { __i != _NCPUWORDS; \ }) +/* Compare two sets, returns 0 if equal 1 otherwise. */ +#define CPU_CMP(p, c) __extension__ ({ \ + __size_t __i; \ + for (__i = 0; __i < _NCPUWORDS; __i++) \ + if (((c)->__bits[__i] != \ + (p)->__bits[__i])) \ + break; \ + __i != _NCPUWORDS; \ +}) + #define CPU_OR(d, s) do { \ __size_t __i; \ for (__i = 0; __i < _NCPUWORDS; __i++) \ @@ -153,9 +163,13 @@ struct cpuset { #define CPU_SET_ROOT 0x0001 /* Set is a root set. */ #define CPU_SET_RDONLY 0x0002 /* No modification allowed. */ +extern cpuset_t *cpuset_root; + struct cpuset *cpuset_thread0(void); struct cpuset *cpuset_ref(struct cpuset *); -void cpuset_rel(struct cpuset *); +void cpuset_rel(struct cpuset *); +int cpuset_setthread(lwpid_t id, cpuset_t *); + #else __BEGIN_DECLS int cpuset(cpusetid_t *);