Thread (9 messages) 9 messages, 3 authors, 2014-02-10

Re: allow preemption in check_task_state

From: Steven Rostedt <rostedt@goodmis.org>
Date: 2014-02-10 16:11:17
Also in: lkml

Subject is missing patch number.


On Mon, 10 Feb 2014 16:38:56 +0100
Nicholas Mc Guire [off-list ref] wrote:
A lockfree approach to check_task_state

This treates the state as an indicator variable and use it to probe 
saved_state lock free. There is actually no consistency demand on 
state/saved_state but rather a consistency demand on the transitions 
of the two variables but those transition, based on path inspection,
are not independent.

Its probably not faster than the lock/unlock case if uncontended - atleast
it does not show up in benchmark results, but it would never be hit by a 
full pi-boost cycle as there is no contention.

This also was tested against the test-case from Sebastian as well as 
rnning a few scripted gdb breakpoint debugging/single-stepping loops
to trigger this.
To trigger what?
quoted hunk ↗ jump to hunk
Tested-by: Andreas Platschek <redacted>
Tested-by: Carsten Emde <redacted>
Signed-off-by: Nicholas Mc Guire <redacted>
---
 kernel/sched/core.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index bf93f63..5690ba3 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1074,11 +1074,17 @@ static int migration_cpu_stop(void *data);
 static bool check_task_state(struct task_struct *p, long match_state)
 {
 	bool match = false;
+	long state, saved_state;
+
+	/* catch restored state */
+	do {
+		state = p->state;
+		saved_state = p->saved_state;
+		rmb();  /* make sure we actually catch updates */
The problem I have with this is that there's no matching wmb(). Also,
shouldn't that be a smp_rmb(), I don't think we can race with devices
here.
+	} while (state != p->state);
 
-	raw_spin_lock_irq(&p->pi_lock);
 	if (p->state == match_state || p->saved_state == match_state)
 		match = true;
-	raw_spin_unlock_irq(&p->pi_lock);
 
 	return match;
 }

In rtmutex.c we have:

	pi_lock(&self->pi_lock);
	__set_current_state(self->saved_state);
	self->saved_state = TASK_RUNNING;
	pi_unlock(&self->pi_lock);

As there is no wmb() here, it can be very possible that another CPU
will see saved_state as TASK_RUNNING, and current state as
TASK_RUNNING, and miss the update completely.

I would not want to add a wmb() unless there is a real bug with the
check state, as the above is in a very fast path and the check state is
in a slower path.

-- Steve
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help