lkml.org 
[lkml]   [2023]   [Jan]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
From
SubjectRe: [PATCH v2 1/4] sched/task: Add the put_task_struct_atomic_safe function
Date
On 23/01/23 14:24, Wander Lairson Costa wrote:
> On Mon, Jan 23, 2023 at 1:30 PM Oleg Nesterov <oleg@redhat.com> wrote:
>>
>> On 01/20, Wander Lairson Costa wrote:
>> >
>> > +static inline void put_task_struct_atomic_safe(struct task_struct *task)
>> > +{
>> > + if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
>> > + /*
>> > + * Decrement the refcount explicitly to avoid unnecessarily
>> > + * calling call_rcu.
>> > + */
>> > + if (refcount_dec_and_test(&task->usage))
>> > + /*
>> > + * under PREEMPT_RT, we can't call put_task_struct
>> > + * in atomic context because it will indirectly
>> > + * acquire sleeping locks.
>> > + */
>> > + call_rcu(&task->rcu, __delayed_put_task_struct);
>> ^^^^^^^^^
>> I am not sure the usage of task->rcu is safe...
>>
>> Suppose that, before __delayed_put_task_struct() is called by RCU, this task
>> does the last schedule and calls put_task_struct_rcu_user().
>>
>> And, can't we simply turn put_task_struct() into something like
>>
>> put_task_struct(struct task_struct *t)
>> {
>> if (refcount_dec_and_test(&t->usage)) {
>> if (IS_ENABLED(CONFIG_PREEMPT_RT)
>> && (in_atomic() || irqs_disabled()))
>> call_rcu(...);
>> else
>> __put_task_struct(t);
>> }
>> }
>>
>> ?
>
> Yeah, that was one approach I thought about. I chose to use an
> explicit function because I assumed calling __put_task_struct() from a
> non-preemptable context should be the exception, not the rule.

I'd tend to agree.

> Therefore (if I am correct in my assumption), it would make sense for
> only some call sites to pay the overhead price for it. But this is
> just a guess, and I have no evidence to support my claim.

My worry here is that it's easy to miss problematic callgraphs, and it's
potentially easy for new ones to creep in. Having a solution within
put_task_struct() itself would prevent that.

Another thing, if you look at release_task_stack(), it either caches the
outgoing stack for later use, or frees it via RCU (regardless of
PREEMPT_RT). Perhaps we could follow that and just always punt the freeing
of the task struct to RCU?

\
 
 \ /
  Last update: 2023-03-26 23:58    [W:0.107 / U:0.280 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site