tom fogal wrote:
> One thing I neglected to think about earlier is how one would do a
> `Can I still run?' check.  There is no notification to a user process
> when a context switch comes back.
> 
> Remember that valgrind instruments instructions.

You means a context switch occurred due to timeslice exhaustion whilst 
execution was in user-space.   So the scenario you describe is referring 
to resumption of user-space execution.

Why does it need to know ?  I can not see the problem, my strategy works 
just fine in the situation you describe.  Maybe you are confusing 
resumption of execution in user-space due to timeslice exhaustion with 
resumption of execution in user-space due to a syscall return.  The 
syscall return case I do have things to talk about (as previously written).


To add; as it is under emulation then it is true to say the user-space 
part of the thread spends most of its time executing valgrind code as 
opposed to simulated application/client code.  Since it is executing 
valgrind code then VG has control.

Thinking through your example above there would be an issue if valgrind 
allows a process to run an infinite loop of pure application/client 
code, i.e. a CPU bound application that never makes a 
syscall/libc/valgrind/etc function call.   If I understand correctly if 
everything is instrumented then this never happens there is always a 
point where valgrind has control.  If not then simply inject a 
checkpoint/safe-point during instrumentation.


My only concern so far has been syscalls.  When any thread makes a 
syscall you never know how long its going to take or if it will block, 
so you treat the situation as-if they always block, even when you know 
they don't.



> I had a long diatribe about how you essentially want the JVM's safe
> points and how ridiculously difficult it will be, as you'd have to
> write a parallel scheduler.  Which I still think is true, in your
> general case of the choosing which thread to run.

It depends what you mean by a scheduler.  Anything that manipulates what 
gets to run could be called a scheduler.  The points I've put forward 
propose to create artificial waits, artificial temporary suspension, 
artificial low priority.  Artificial meaning from the application/client 
code perspective the observable result is as-if.

I certainly wouldn't call whats proposed a parallel scheduler, it can't 
make something thats not runnable (due to being blocked in the kernel) 
runnable!  The kernel can.

But it can put something that is running to sleep, and thats a big 
enough wrench/spanner to achieve the goal.  I also think you 
misinterpted something as I wasn't providing any emphasis on difficulty 
levels; you're definitely adding that meaning yourself.

Your challenges have been great to hear and a good sounding board but 
there is nothing added that wasn't already thought about or seems a show 
stopper.



> You really don't need that functionality though.  All you want is to
> guarantee that <= 1 thread is running, at all times.
> 
> A solution to your issue -- introduce a new mutex, within valgrind.
> Wrap every function you possibly can.  Acquire the lock before the
> function, and release it after the function.

You're idea of adding a mutex lock around everything, that may work.  I 
wouldn't be wrapping anything I would be expecting valgrind to 
instrument the application/client in that way on my behalf.

It also won't be on a function call basis or a line of code basis as 
your example shows.  It would be one a unit (like your notes lean 
towards) of work basis that is only allowed to have a single load, store 
or load&store with memory within it or a single function call/jump.  So 
yes a single asm insn might need a lock around it.


So code actually becomes:

acquire(&vg_runnable_thread)
vg_scheduler_pre_client_hook();

// run some application/client code work
sys_call();

vg_scheduler_post_client_hook();
release(&vg_runnable_thread)


Note that you could then obtain/influence threading control with the 
vg_scheduler_pre_client_hook() and the vg_scheduler_post_client_hook().


You can obviously understand the major performance penalty for your 
scheme.  Now if you think about optimizing it for a moment...


I think you arrive at the solution I've been discussing, valgrind 
already does cool stuff at watching memory in a byte glandular way and 
hey its only syscalls that are a problem in having valgrind bend the 
scheduling rules of the kernel.

So why not intercept system calls in a not so different way to your 
example above, infact we can do away with the acquire() relead() stuff 
and roll in into the vg_scheduler_xxxx() stuff whilst wrapping all syscalls.

I agree with your approach but maybe I'm a little further down the road 
on it.



> In this scheme, you don't get to control which thread runs.  But I
> think Julian stressed, and I stress now, that you really don't want to
> do that.

Well you can control threads if you want as my version above explains.


But Yes I think I've concluded on that point.  It is not absolute 
control that is wanted it is the ability to bend the existing scheduling 
rules in the direction of exposing more bugs.

Add to this the want of an audit trail of memory access between point A 
and point B, the audit must match up 100% with the SMP/CPU/memory view 
of a real world system.



> It sounds like, if you wanted to do this, you *would* need to lock at
> every instruction, since you'd need some kind of global hash table or
> other data structure which would maintain this list.

Ah yes, now you see.  Yes a memory access would involve the questions 
being asked, are we interested in this extent ?  do we log this access ? 
  is this access an application error ?

Doesn't memcheck already do a lot of this stuff, this was the point of 
valgrind to leverage on this.  I'm just adding a threading twist to it.



> By the way, have you heard of software transactional memory? ``STM''.
> I'm not sure if there are any open-source systems which implement it.
> However, an STM system must keep exactly this, except they of course
> do it to provide better parallelism than the absurdity that is
> threads.

No thats a new one for me, I will research some as you suggest.  I 
disagree thread aren't absurd :)



> Thinking about those gives me the idea that you could probably avoid
> this wrapping in regions of code which could provably not r/w a shared
> variable, perhaps by knowing that the thread holds no locks.

Euh.  Just because a thread holds no locks doesn't mean that the thread 
(that holds no locks) won't violate the multi-threaded design by reading 
from or writing to memory it shouldn't.  The reason it shouldn't is 
because that location is guarded by a lock (which it didn't take before 
access).

A memory access audit will provide that info.



> If you only need a hint, not a hard guarantee, change your wrappers to
> set and restore the thread priority instead of grab a lock.  I imagine
> that'd be much cheaper.

There is no feedback / assurity from the kernel (or whatever scheduler) 
you as using of which threads have been given the opportunity to run.

We want to offer up a roll-call to all threads, some may run, some may 
not run, but they were offered the opportunity.



I disagree its hard to implement a timeout, there are many such 
mechanisms to do that.  Don't forget its the kernel that actually 
implements the timeout, a futex() would probably do the trick and 
provide a mechanism to be woken up to boot.


You misunderstand the point of system call interception, the point is to 
pass back control to valgrind, not to modify the "error return code of a 
system call" but to modify the "exit from system call and return to 
caller assembly code".  One is a code like a variable, the other is code 
as in a program.

A system call maybe implemented as a function call, jump point, call 
gate, software interrupt, whatever... but before that moment there is 
assembly code around it to setup the stack/data correctly and assembly 
code after it where execution resumes that might deal with storing 
errno.   We just want to "wrapper" that (aka intercept that).


Now if ALL code is instrumented under emulation then there may not be a 
need to intercept syscalls if we can ensure control is passed back to 
valgrind BEFORE application/client code.  This would then check a thread 
specific memory location to see if there is an outstanding inception 
event (a latching flag) for this thread and if there is it calls a 
function.  This function then works out what the nature of the 
interception is and deals with it.


You completely miss the point that GDB has no support for byte granular 
memory checking.   That is the main feature of valgrind looking to be 
leveraged.  The application/client program needs to communicate with the 
byte granular memory checker, whatever and wherever that is.  I think 
gdb watchpoints only work on natural sized memory locations (4/8 bytes) 
they don't seem suited to the goals.  Watchpoints can have the option of 
hardware assistance but in limited numbers.


STM-like may certainly be the way, I'll see what I can find on that avenue.



Darryl

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Valgrind-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/valgrind-users

Reply via email to