Permit changing cpu mask for cpu set 1 in presence of drivers
binding their threads to particular CPU. Changing ithread cpu mask is now performed by special cpuset_setithread(). It creates additional cpuset root group on first bind invocation. No objection: jhb Tested by: hiren MFC after: 2 weeks Sponsored by: Yandex LLC
This commit is contained in:
parent
fe156048d8
commit
3f08add0c8
@ -106,7 +106,7 @@ static uma_zone_t cpuset_zone;
|
||||
static struct mtx cpuset_lock;
|
||||
static struct setlist cpuset_ids;
|
||||
static struct unrhdr *cpuset_unr;
|
||||
static struct cpuset *cpuset_zero;
|
||||
static struct cpuset *cpuset_zero, *cpuset_default;
|
||||
|
||||
/* Return the size of cpuset_t at the kernel level */
|
||||
SYSCTL_INT(_kern_sched, OID_AUTO, cpusetsize, CTLFLAG_RD,
|
||||
@ -715,6 +715,89 @@ cpuset_setthread(lwpid_t id, cpuset_t *mask)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply new cpumask to the ithread.
|
||||
*/
|
||||
int
|
||||
cpuset_setithread(lwpid_t id, u_char cpu)
|
||||
{
|
||||
struct cpuset *nset, *rset;
|
||||
struct cpuset *parent, *old_set;
|
||||
struct thread *td;
|
||||
struct proc *p;
|
||||
cpusetid_t cs_id;
|
||||
cpuset_t mask;
|
||||
int error;
|
||||
|
||||
nset = uma_zalloc(cpuset_zone, M_WAITOK);
|
||||
rset = uma_zalloc(cpuset_zone, M_WAITOK);
|
||||
|
||||
CPU_ZERO(&mask);
|
||||
if (cpu == NOCPU)
|
||||
CPU_COPY(cpuset_root, &mask);
|
||||
else
|
||||
CPU_SET(cpu, &mask);
|
||||
|
||||
error = cpuset_which(CPU_WHICH_TID, id, &p, &td, &old_set);
|
||||
if (((cs_id = alloc_unr(cpuset_unr)) == CPUSET_INVALID) || error != 0)
|
||||
goto out;
|
||||
|
||||
thread_lock(td);
|
||||
old_set = td->td_cpuset;
|
||||
|
||||
if (cpu == NOCPU) {
|
||||
/*
|
||||
* roll back to default set. We're not using cpuset_shadow()
|
||||
* here because we can fail CPU_SUBSET() check. This can happen
|
||||
* if default set does not contain all CPUs.
|
||||
*/
|
||||
error = _cpuset_create(nset, cpuset_default, &mask,
|
||||
CPUSET_INVALID);
|
||||
|
||||
goto applyset;
|
||||
}
|
||||
|
||||
if (old_set->cs_id == 1 || (old_set->cs_id == CPUSET_INVALID &&
|
||||
old_set->cs_parent->cs_id == 1)) {
|
||||
/* Default mask, we need to use new root set */
|
||||
error = _cpuset_create(rset, cpuset_zero,
|
||||
&cpuset_zero->cs_mask, cs_id);
|
||||
if (error != 0) {
|
||||
PROC_UNLOCK(p);
|
||||
goto out;
|
||||
}
|
||||
rset->cs_flags |= CPU_SET_ROOT;
|
||||
parent = rset;
|
||||
rset = NULL;
|
||||
cs_id = CPUSET_INVALID;
|
||||
} else {
|
||||
/* Assume existing set was already allocated by previous call */
|
||||
parent = td->td_cpuset;
|
||||
old_set = NULL;
|
||||
}
|
||||
|
||||
error = cpuset_shadow(parent, nset, &mask);
|
||||
applyset:
|
||||
if (error == 0) {
|
||||
td->td_cpuset = nset;
|
||||
sched_affinity(td);
|
||||
nset = NULL;
|
||||
}
|
||||
thread_unlock(td);
|
||||
PROC_UNLOCK(p);
|
||||
if (old_set != NULL)
|
||||
cpuset_rel(old_set);
|
||||
out:
|
||||
if (nset != NULL)
|
||||
uma_zfree(cpuset_zone, nset);
|
||||
if (rset != NULL)
|
||||
uma_zfree(cpuset_zone, rset);
|
||||
if (cs_id != CPUSET_INVALID)
|
||||
free_unr(cpuset_unr, cs_id);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Creates the cpuset for thread0. We make two sets:
|
||||
*
|
||||
@ -735,6 +818,7 @@ cpuset_thread0(void)
|
||||
cpuset_zone = uma_zcreate("cpuset", sizeof(struct cpuset), NULL, NULL,
|
||||
NULL, NULL, UMA_ALIGN_PTR, 0);
|
||||
mtx_init(&cpuset_lock, "cpuset", NULL, MTX_SPIN | MTX_RECURSE);
|
||||
|
||||
/*
|
||||
* Create the root system set for the whole machine. Doesn't use
|
||||
* cpuset_create() due to NULL parent.
|
||||
@ -747,12 +831,15 @@ cpuset_thread0(void)
|
||||
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.
|
||||
*/
|
||||
set = uma_zalloc(cpuset_zone, M_WAITOK);
|
||||
error = _cpuset_create(set, cpuset_zero, &cpuset_zero->cs_mask, 1);
|
||||
KASSERT(error == 0, ("Error creating default set: %d\n", error));
|
||||
cpuset_default = set;
|
||||
|
||||
/*
|
||||
* Initialize the unit allocator. 0 and 1 are allocated above.
|
||||
*/
|
||||
|
@ -295,7 +295,6 @@ intr_event_create(struct intr_event **event, void *source, int flags, int irq,
|
||||
int
|
||||
intr_event_bind(struct intr_event *ie, u_char cpu)
|
||||
{
|
||||
cpuset_t mask;
|
||||
lwpid_t id;
|
||||
int error;
|
||||
|
||||
@ -316,14 +315,9 @@ intr_event_bind(struct intr_event *ie, u_char cpu)
|
||||
*/
|
||||
mtx_lock(&ie->ie_lock);
|
||||
if (ie->ie_thread != NULL) {
|
||||
CPU_ZERO(&mask);
|
||||
if (cpu == NOCPU)
|
||||
CPU_COPY(cpuset_root, &mask);
|
||||
else
|
||||
CPU_SET(cpu, &mask);
|
||||
id = ie->ie_thread->it_thread->td_tid;
|
||||
mtx_unlock(&ie->ie_lock);
|
||||
error = cpuset_setthread(id, &mask);
|
||||
error = cpuset_setithread(id, cpu);
|
||||
if (error)
|
||||
return (error);
|
||||
} else
|
||||
@ -332,14 +326,10 @@ intr_event_bind(struct intr_event *ie, u_char cpu)
|
||||
if (error) {
|
||||
mtx_lock(&ie->ie_lock);
|
||||
if (ie->ie_thread != NULL) {
|
||||
CPU_ZERO(&mask);
|
||||
if (ie->ie_cpu == NOCPU)
|
||||
CPU_COPY(cpuset_root, &mask);
|
||||
else
|
||||
CPU_SET(ie->ie_cpu, &mask);
|
||||
cpu = ie->ie_cpu;
|
||||
id = ie->ie_thread->it_thread->td_tid;
|
||||
mtx_unlock(&ie->ie_lock);
|
||||
(void)cpuset_setthread(id, &mask);
|
||||
(void)cpuset_setithread(id, cpu);
|
||||
} else
|
||||
mtx_unlock(&ie->ie_lock);
|
||||
return (error);
|
||||
|
@ -118,6 +118,7 @@ struct cpuset *cpuset_thread0(void);
|
||||
struct cpuset *cpuset_ref(struct cpuset *);
|
||||
void cpuset_rel(struct cpuset *);
|
||||
int cpuset_setthread(lwpid_t id, cpuset_t *);
|
||||
int cpuset_setithread(lwpid_t id, u_char cpu);
|
||||
int cpuset_create_root(struct prison *, struct cpuset **);
|
||||
int cpuset_setproc_update_set(struct proc *, struct cpuset *);
|
||||
char *cpusetobj_strprint(char *, const cpuset_t *);
|
||||
|
Loading…
Reference in New Issue
Block a user