On Fri, Jan 22, 2021 at 08:17:01PM -0500, Joel Fernandes (Google) wrote: > --- a/kernel/fork.c > +++ b/kernel/fork.c > @@ -736,6 +736,7 @@ void __put_task_struct(struct task_struct *tsk) > exit_creds(tsk); > delayacct_tsk_free(tsk); > put_signal_struct(tsk->signal); > + sched_tsk_free(tsk); > > if (!profile_handoff_task(tsk)) > free_task(tsk);
> +struct sched_core_task_cookie { > + refcount_t refcnt; > + struct work_struct work; /* to free in WQ context. */; > +}; > +static void sched_core_put_cookie_work(struct work_struct *ws); > + > +/* Caller has to call sched_core_get() if non-zero value is returned. */ > +static unsigned long sched_core_alloc_task_cookie(void) > +{ > + struct sched_core_task_cookie *ck = > + kmalloc(sizeof(struct sched_core_task_cookie), GFP_KERNEL); > + > + if (!ck) > + return 0; > + refcount_set(&ck->refcnt, 1); > + INIT_WORK(&ck->work, sched_core_put_cookie_work); > + > + return (unsigned long)ck; > +} > +static void sched_core_put_task_cookie(unsigned long cookie) > +{ > + struct sched_core_task_cookie *ptr = > + (struct sched_core_task_cookie *)cookie; > + > + if (refcount_dec_and_test(&ptr->refcnt)) > + kfree(ptr); > +} > +static void sched_core_put_cookie_work(struct work_struct *ws) > +{ > + struct sched_core_task_cookie *ck = > + container_of(ws, struct sched_core_task_cookie, work); > + > + sched_core_put_task_cookie((unsigned long)ck); > + sched_core_put(); > +} > +void sched_tsk_free(struct task_struct *tsk) > +{ > + struct sched_core_task_cookie *ck; > + > + sched_core_put_cookie((struct sched_core_cookie *)tsk->core_cookie); > + > + if (!tsk->core_task_cookie) > + return; > + > + ck = (struct sched_core_task_cookie *)tsk->core_task_cookie; > + queue_work(system_wq, &ck->work); > +} *groan*.. so the purpose of that work is to be able to disable core-scheduling after the last such task dies. Maybe add sched_core_put_async() instead?