sched: Introduce task_struct::user_cpus_ptr to track requested affinity
In preparation for saving and restoring the user-requested CPU affinity mask of a task, add a new cpumask_t pointer to 'struct task_struct'. If the pointer is non-NULL, then the mask is copied across fork() and freed on task exit. Signed-off-by: Will Deacon <will@kernel.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Valentin Schneider <Valentin.Schneider@arm.com> Link: https://lore.kernel.org/r/20210730112443.23245-7-will@kernel.org
This commit is contained in:
parent
234a503e67
commit
b90ca8badb
|
@ -748,6 +748,7 @@ struct task_struct {
|
||||||
unsigned int policy;
|
unsigned int policy;
|
||||||
int nr_cpus_allowed;
|
int nr_cpus_allowed;
|
||||||
const cpumask_t *cpus_ptr;
|
const cpumask_t *cpus_ptr;
|
||||||
|
cpumask_t *user_cpus_ptr;
|
||||||
cpumask_t cpus_mask;
|
cpumask_t cpus_mask;
|
||||||
void *migration_pending;
|
void *migration_pending;
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
@ -1706,6 +1707,8 @@ extern int task_can_attach(struct task_struct *p, const struct cpumask *cs_cpus_
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
extern void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask);
|
extern void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask);
|
||||||
extern int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask);
|
extern int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask);
|
||||||
|
extern int dup_user_cpus_ptr(struct task_struct *dst, struct task_struct *src, int node);
|
||||||
|
extern void release_user_cpus_ptr(struct task_struct *p);
|
||||||
#else
|
#else
|
||||||
static inline void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
|
static inline void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
|
||||||
{
|
{
|
||||||
|
@ -1716,6 +1719,16 @@ static inline int set_cpus_allowed_ptr(struct task_struct *p, const struct cpuma
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
static inline int dup_user_cpus_ptr(struct task_struct *dst, struct task_struct *src, int node)
|
||||||
|
{
|
||||||
|
if (src->user_cpus_ptr)
|
||||||
|
return -EINVAL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline void release_user_cpus_ptr(struct task_struct *p)
|
||||||
|
{
|
||||||
|
WARN_ON(p->user_cpus_ptr);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int yield_to(struct task_struct *p, bool preempt);
|
extern int yield_to(struct task_struct *p, bool preempt);
|
||||||
|
|
|
@ -80,6 +80,7 @@ struct task_struct init_task
|
||||||
.normal_prio = MAX_PRIO - 20,
|
.normal_prio = MAX_PRIO - 20,
|
||||||
.policy = SCHED_NORMAL,
|
.policy = SCHED_NORMAL,
|
||||||
.cpus_ptr = &init_task.cpus_mask,
|
.cpus_ptr = &init_task.cpus_mask,
|
||||||
|
.user_cpus_ptr = NULL,
|
||||||
.cpus_mask = CPU_MASK_ALL,
|
.cpus_mask = CPU_MASK_ALL,
|
||||||
.nr_cpus_allowed= NR_CPUS,
|
.nr_cpus_allowed= NR_CPUS,
|
||||||
.mm = NULL,
|
.mm = NULL,
|
||||||
|
|
|
@ -446,6 +446,7 @@ void put_task_stack(struct task_struct *tsk)
|
||||||
|
|
||||||
void free_task(struct task_struct *tsk)
|
void free_task(struct task_struct *tsk)
|
||||||
{
|
{
|
||||||
|
release_user_cpus_ptr(tsk);
|
||||||
scs_release(tsk);
|
scs_release(tsk);
|
||||||
|
|
||||||
#ifndef CONFIG_THREAD_INFO_IN_TASK
|
#ifndef CONFIG_THREAD_INFO_IN_TASK
|
||||||
|
@ -919,6 +920,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
|
||||||
#endif
|
#endif
|
||||||
if (orig->cpus_ptr == &orig->cpus_mask)
|
if (orig->cpus_ptr == &orig->cpus_mask)
|
||||||
tsk->cpus_ptr = &tsk->cpus_mask;
|
tsk->cpus_ptr = &tsk->cpus_mask;
|
||||||
|
dup_user_cpus_ptr(tsk, orig, node);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* One for the user space visible state that goes away when reaped.
|
* One for the user space visible state that goes away when reaped.
|
||||||
|
|
|
@ -2480,6 +2480,26 @@ void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
|
||||||
__do_set_cpus_allowed(p, new_mask, 0);
|
__do_set_cpus_allowed(p, new_mask, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dup_user_cpus_ptr(struct task_struct *dst, struct task_struct *src,
|
||||||
|
int node)
|
||||||
|
{
|
||||||
|
if (!src->user_cpus_ptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
dst->user_cpus_ptr = kmalloc_node(cpumask_size(), GFP_KERNEL, node);
|
||||||
|
if (!dst->user_cpus_ptr)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
cpumask_copy(dst->user_cpus_ptr, src->user_cpus_ptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release_user_cpus_ptr(struct task_struct *p)
|
||||||
|
{
|
||||||
|
kfree(p->user_cpus_ptr);
|
||||||
|
p->user_cpus_ptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is wildly self concurrent; here be dragons.
|
* This function is wildly self concurrent; here be dragons.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue