From: Oleg Nesterov <oleg@tv-sign.ru>
To: Roland McGrath <roland@redhat.com>
Cc: akpm@linux-foundation.org, torvalds@linux-foundation.org,
mingo@elte.hu, linux-kernel@vger.kernel.org,
Dmitry Adamushko <dmitry.adamushko@gmail.com>
Subject: Re: Q: wait_task_inactive() and !CONFIG_SMP && CONFIG_PREEMPT
Date: Fri, 1 Aug 2008 15:49:54 +0400 [thread overview]
Message-ID: <20080801114954.GA76@tv-sign.ru> (raw)
In-Reply-To: <20080801012747.7E17F15427E@magilla.localdomain>
On 07/31, Roland McGrath wrote:
>
> > I dont think this is right.
> >
> > Firstly, the above always fails if match_state == 0, this is not right.
>
> A call with 0 is the "legacy case", where the return value is 0 and nothing
> but the traditional wait_task_inactive behavior is expected. On UP, this
> was a nop before and still is.
>
> Anyway, this is moot since we are soon to have no callers that pass 0.
This means we can't use wait_task_inactive(p) unless we know p->state
is already != TASK_RUNNING. OK, the current callers assume exactly this.
But perhaps we should change the state checks from "==" to "&", note
that pfm_task_incompatible() checks task_is_stopped_or_traced().
> > But more importantly, we can't just check ->state == match_state. And
> > preempt_disable() buys nothing.
>
> It ensures that the samples of ->state and ->nvcsw both came while the
> target could never have run in between. Without it, a preemption after the
> ->state check could mean the ->nvcsw value we use is from a later block in
> a different state than the one intended.
I meant, it buys nothing because the task can set its state == TASK_RUNNING
right after preempt_enable(), because the task can be runnable despite
the fact its state is (say) TASK_UNINTERRUPTIBLE.
Please see below.
> > Let's look at task_current_syscall(). The "target" can set, say,
> > TASK_UNINTERRUPTIBLE many times, do a lot of syscalls, and not once
> > call schedule().
> >
> > And the task remains fully preemptible even if it runs in
> > TASK_UNINTERRUPTIBLE state.
>
> One of us is missing something basic. We are on the only CPU. If target
> does *anything*, it means we got preempted, then target switched in, did
> things, and then called schedule (including via preemption)--so that we
> could possibly be running again now afterwards. That schedule call bumped
> the counter after we sampled it. The second call done for "is it still
> blocked afterwards?" will see a different count and abort. Am I confused?
I think we misunderstood each other. I never said the _current_ callers have
problems (except the dummy version can't just return 1 of course).
I proposed to synchronize 2 implementations to avoid the possible problems,
and personally I still dislike the fact that !SMP version has the very
different behaviour.
But yes, if we only want to "fix" the current callers, we can make the !SMP
version
static inline unsigned long wait_task_inactive(struct task_struct *p,
long match_state)
{
int ret = 0;
preempt_disable();
if (!match_state || p->state == match_state)
ret = (p->nvcsw + p->nivcsw) | LONG_MIN;
preempt_enable();
return ret;
}
> Ah, I think it was me who was missing something when I let you talk me into
> checking only ->nvcsw. It really should be ->nivcsw + ->nvcsw as I had it
> originally (| LONG_MIN as you've done, a good trick). That makes what I
> just said true in the preemption case. This bit:
>
> if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
>
> will not hit, so switch_count = &prev->nivcsw; remains from before.
> This is why it was nivcsw + nvcsw to begin with.
This is fine on SMP, afaics.
More precisely, this is fine if wait_task_inactive(p) returns success only
when p->se.on_rq == 0, we shouldn't worry about preemption (nivcsw) at all.
Let's forget about the overflow, and suppose that 2 subsequent calls return
the same ->nvcsw. Every time the task leaves the runqueue (so that !.on_rq
becomes true), shedule() bumps its ->nvcsw. If the task was scheduled in
between we must notice this, because the second success means the task
was deactivate_task()'ed again.
We shouldn't look at nivcsw at all. While the task is deactivated, its
nivcsw/nvcsw can't be changed. If it is scheduled again, it must increment
->nvcsw before wait_task_inactive() can return success.
(Dmitry cc'ed to check my understanding).
Oleg.
next prev parent reply other threads:[~2008-08-01 11:46 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <200807260245.m6Q2jwB4012297@imap1.linux-foundation.org>
2008-07-27 11:37 ` [PATCH] wait_task_inactive: don't consider task->nivcsw Oleg Nesterov
2008-07-27 19:55 ` Roland McGrath
2008-07-27 12:15 ` Q: wait_task_inactive() and !CONFIG_SMP && CONFIG_PREEMPT Oleg Nesterov
2008-07-27 16:51 ` Linus Torvalds
2008-07-27 20:05 ` Roland McGrath
2008-07-28 12:57 ` Oleg Nesterov
2008-07-28 23:39 ` Roland McGrath
2008-07-29 12:21 ` Oleg Nesterov
2008-08-01 1:27 ` Roland McGrath
2008-08-01 11:49 ` Oleg Nesterov [this message]
2008-08-01 21:22 ` Roland McGrath
2008-07-27 12:42 ` [PATCH] kthread_bind: use wait_task_inactive(TASK_UNINTERRUPTIBLE) Oleg Nesterov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080801114954.GA76@tv-sign.ru \
--to=oleg@tv-sign.ru \
--cc=akpm@linux-foundation.org \
--cc=dmitry.adamushko@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=roland@redhat.com \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®