Messages in this thread | | | From | Andy Lutomirski <> | Date | Thu, 7 May 2015 05:22:40 -0700 | Subject | Re: [PATCH 3/3] context_tracking,x86: remove extraneous irq disable & enable from context tracking on syscall entry |
| |
On May 7, 2015 4:18 PM, "Ingo Molnar" <mingo@kernel.org> wrote: > > > * Rik van Riel <riel@redhat.com> wrote: > > > > If, on the other hand, you're just going to remotely sample the > > > in-memory context, that sounds good. > > > > It's the latter. > > > > If you look at /proc/<pid>/{stack,syscall,wchan} and other files, > > you will see we already have ways to determine, from in memory > > content, where a program is running at a certain point in time. > > > > In fact, the timer interrupt based accounting does a similar thing. > > It has a task examine its own in-memory state to figure out what it > > was doing before the timer interrupt happened. > > > > The kernel side stack pointer is probably enough to tell us whether > > a task is active in kernel space, on an irq stack, or (maybe) in > > user space. Not convinced about the latter, we may need to look at > > the same state the RCU code keeps track of to see what mode a task > > is in... > > > > I am looking at the code to see what locks we need to grab. > > > > I suspect the runqueue lock may be enough, to ensure that the task > > struct, and stack do not go away while we are looking at them. > > That will be enough, especially if you get to the task reference via > rq->curr. > > > We cannot take the lock_trace(task) from irq context, and we > > probably do not need to anyway, since we do not care about a precise > > stack trace for the task. > > So one worry with this and similar approaches of statistically > detecting user mode would be the fact that on the way out to > user-space we don't really destroy the previous call trace - we just > pop off the stack (non-destructively), restore RIPs and are gone. > > We'll need that percpu flag I suspect. > > And once we have the flag, we can get rid of the per syscall RCU > callback as well, relatively easily: with CMPXCHG (in > synchronize_rcu()!) we can reliably sample whether a CPU is in user > mode right now, while the syscall entry/exit path does not use any > atomics, we can just use a simple MOV. > > Once we observe 'user mode', then we have observed quiescent state and > synchronize_rcu() can continue. If we've observed kernel mode we can > frob the remote task's TIF_ flags to make it go into a quiescent state > publishing routine on syscall-return. >
How does that work?
If the exit code writes the per-cpu flag and then checks TIF_whatever, we need a barrier to avoid a race where we end up in user mode without seeing the flag.
I think the right solution is to accept that race and just have the RCU code send an IPI (or check again) if it sees too long of a period elapse in kernel mode.
I think the flag should be a counter, though. That way a workload that makes lots of syscalls will be quickly detected as going through quiescent states even if it's never actually observed in user mode.
> The only hard requirement of this scheme from the RCU synchronization > POV is that all kernel contexts that may touch RCU state need to flip > this flag reliably to 'kernel mode': i.e. all irq handlers, traps, > NMIs and all syscall variants need to do this. > > But once it's there, it's really neat. >
We already have to do this with the current code. I went through and checked all of the IST entries a couple versions ago.
I think we need to clean up the current garbage asm first, though. See:
https://git.kernel.org/cgit/linux/kernel/git/luto/linux.git/commit/?h=x86/entry&id=d22f1dca4c7c93fdd1ce754e38d71d1961c0f9ac
(Very much unfinished, and it should probably be split up, but AFAICT it works. Don't hold your breath for a real version.)
--Andy
> Thanks, > > Ingo
| |