|
From: <sv...@va...> - 2006-05-01 00:56:04
|
Author: weidendo
Date: 2006-05-01 01:55:54 +0100 (Mon, 01 May 2006)
New Revision: 5869
Log:
Callgrind: Improve self-hosting with outer callgrind tool
This adds an option to change the default handling of jumps
between functions. Usually, a jump between functions is
interpreted as call, because such jumps are typically
generated by compilers on tail recursion optimization, and
we want to present this as call to the user. Thus, such
a jump pushes a call onto callgrinds shadow stack.
The option "--pop-on-jump" changes this to pop+push the
shadow callstack: then, a jump between functions is seen
as a return to the caller and a new call.
The default behaviour is _bad_ for using callgrind with
self-hosting. Valgrinds inner loop VG_(run_innerloop)
jumps to generated code, and this code jumps back to
the inner loop. Thus, every executed BB adds 2 calls
to an ever increasing shadow call stack, leading to
memory consumption increasing with runtime :-(
So: For self-hosting valgrind with an outer callgrind,
always use option "--pop-on-jump" for the outer callgrind.=20
Modified:
trunk/callgrind/clo.c
trunk/callgrind/fn.c
trunk/callgrind/global.h
Modified: trunk/callgrind/clo.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/callgrind/clo.c 2006-04-29 18:03:14 UTC (rev 5868)
+++ trunk/callgrind/clo.c 2006-05-01 00:55:54 UTC (rev 5869)
@@ -527,7 +527,10 @@
else if (0 =3D=3D VG_(strncmp)(arg, "--separate-recs=3D", 16))
CLG_(clo).separate_recursions =3D (Int)VG_(atoll)(&arg[16]);
=20
- /* workaround to find runtime_resolve (needs special handling) */
+ /* change handling of a jump between functions to ret+call */
+ else if (0 =3D=3D VG_(strcmp)(arg, "--pop-on-jump")) {
+ CLG_(clo).pop_on_jump =3D True;
+ }
else if (0 =3D=3D VG_(strncmp)(arg, "--pop-on-jump=3D", 14)) {
fn_config* fnc =3D get_fnc(arg+14);
fnc->pop_on_jump =3D CONFIG_TRUE;
@@ -758,6 +761,9 @@
CLG_(clo).instrument_atstart =3D True;
CLG_(clo).simulate_cache =3D False;
=20
+ /* Call graph */
+ CLG_(clo).pop_on_jump =3D False;
+
#if CLG_ENABLE_DEBUG
CLG_(clo).verbose =3D 0;
CLG_(clo).verbose_start =3D 0;
Modified: trunk/callgrind/fn.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/callgrind/fn.c 2006-04-29 18:03:14 UTC (rev 5868)
+++ trunk/callgrind/fn.c 2006-05-01 00:55:54 UTC (rev 5869)
@@ -295,7 +295,7 @@
new->zero_before =3D False;
new->toggle_collect =3D False;
new->skip =3D False;
- new->pop_on_jump =3D False;
+ new->pop_on_jump =3D CLG_(clo).pop_on_jump;
new->is_malloc =3D False;
new->is_realloc =3D False;
new->is_free =3D False;
Modified: trunk/callgrind/global.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/callgrind/global.h 2006-04-29 18:03:14 UTC (rev 5868)
+++ trunk/callgrind/global.h 2006-05-01 00:55:54 UTC (rev 5869)
@@ -89,6 +89,9 @@
Bool instrument_atstart; /* Instrument at start? */
Bool simulate_cache; /* Call into cache simulator ? */
=20
+ /* Call graph generation */
+ Bool pop_on_jump; /* Handle a jump between functions as ret+call=
*/
+
#if CLG_ENABLE_DEBUG
Int verbose;
ULong verbose_start;
|
|
From: Josef W. <Jos...@gm...> - 2006-05-01 01:17:14
|
On Monday 01 May 2006 02:55, sv...@va... wrote:
> Callgrind: Improve self-hosting with outer callgrind tool
> ...
> The default behaviour is _bad_ for using callgrind with
> self-hosting. Valgrinds inner loop VG_(run_innerloop)
> jumps to generated code, and this code jumps back to
> the inner loop. Thus, every executed BB adds 2 calls
> to an ever increasing shadow call stack, leading to
> memory consumption increasing with runtime :-(
This explains the huge memory requirements of self-hosting
with outer callgrind. Using the new option should get rid of this.
Should I add a tip to use "--pop-on-jump" with callgrind in the
self-hosting section of README_DEVELOPERS?
I will not document it otherwise, because it makes callgrind quite
unstable (something to investigate).
Note that this does not change the embarrasing slow loading time
of resulting profile data files with KCachegrind, which currently
has time complexity quadratic to the maximum number of callers and
callees of a function (to be fixed with KCachegrind in KDE 3.5.3).
"run_thread_for_a_while" will have the same number of callees as
there are instrumented BBs. However, such call graphs are quite
unusual...
I noted that a lot of Valgrinds assembler functions like
VG_(run_innerloop) do not show up as function symbols with
self-hosting. This is because of missing ".type ..., @function" and
.size directives. I think this should be fixed. Attached
is such a fix for the x86 version of VG_(run_innerloop).
Josef
--- m_dispatch/dispatch-x86-linux.S (Revision 5868)
+++ m_dispatch/dispatch-x86-linux.S (Arbeitskopie)
@@ -51,6 +51,7 @@
*/
.text
.globl VG_(run_innerloop)
+.type VG_(run_innerloop), @function
VG_(run_innerloop):
/* 4(%esp) holds guest_state */
/* 8(%esp) holds do_profiling */
@@ -251,8 +252,8 @@
popl %ecx
popl %ebx
ret
+.size VG_(run_innerloop), .-VG_(run_innerloop)
|
|
From: Nicholas N. <nj...@cs...> - 2006-05-01 01:29:36
|
On Mon, 1 May 2006, Josef Weidendorfer wrote: > Should I add a tip to use "--pop-on-jump" with callgrind in the > self-hosting section of README_DEVELOPERS? Yes! Thanks. Nick |
|
From: Julian S. <js...@ac...> - 2006-05-01 01:42:59
|
> This explains the huge memory requirements of self-hosting > with outer callgrind. Using the new option should get rid of this. Excellent. > Should I add a tip to use "--pop-on-jump" with callgrind in the > self-hosting section of README_DEVELOPERS? Yes. > I will not document it otherwise, because it makes callgrind quite > unstable (something to investigate). Ok. If --pop-on-jump is not used, then callgrind's stability is unchanged, right? > --- m_dispatch/dispatch-x86-linux.S (Revision 5868) > +++ m_dispatch/dispatch-x86-linux.S (Arbeitskopie) > @@ -51,6 +51,7 @@ > */ > .text > .globl VG_(run_innerloop) > +.type VG_(run_innerloop), @function > VG_(run_innerloop): > /* 4(%esp) holds guest_state */ > /* 8(%esp) holds do_profiling */ > @@ -251,8 +252,8 @@ > popl %ecx > popl %ebx > ret > +.size VG_(run_innerloop), .-VG_(run_innerloop) Sounds good. Please commit it. J |
|
From: Nicholas N. <nj...@cs...> - 2006-05-01 02:18:20
|
On Mon, 1 May 2006, Julian Seward wrote: >> --- m_dispatch/dispatch-x86-linux.S (Revision 5868) >> +++ m_dispatch/dispatch-x86-linux.S (Arbeitskopie) >> @@ -51,6 +51,7 @@ >> */ >> .text >> .globl VG_(run_innerloop) >> +.type VG_(run_innerloop), @function >> VG_(run_innerloop): >> /* 4(%esp) holds guest_state */ >> /* 8(%esp) holds do_profiling */ >> @@ -251,8 +252,8 @@ >> popl %ecx >> popl %ebx >> ret >> +.size VG_(run_innerloop), .-VG_(run_innerloop) > > Sounds good. Please commit it. Is the same thing required for the dispatchers of the other platforms? Nick |
|
From: Julian S. <js...@ac...> - 2006-05-01 02:20:58
|
> >> +.size VG_(run_innerloop), .-VG_(run_innerloop) > > > > Sounds good. Please commit it. > > Is the same thing required for the dispatchers of the other platforms? Probably, if anyone can be bothered to do so. Fixing at least amd64-linux would be good. J |
|
From: Josef W. <Jos...@gm...> - 2006-05-01 02:01:12
|
On Monday 01 May 2006 03:42, Julian Seward wrote: > > I will not document it otherwise, because it makes callgrind quite > > unstable (something to investigate). > > Ok. If --pop-on-jump is not used, then callgrind's stability is > unchanged, right? Yes. Nothing is changed when the option is not used. When using it, it probably leads to some underruns of the shadow call stack. This should be handled quite fine, but obviously can have problems. "callgrind --pop-on-jump /bin/true" runs fine, but: ================================================ weidendo@linux:~/tmp/vgself/run4> callgrind --pop-on-jump ls ==23939== Callgrind, a call-graph generating cache profiler. ==23939== Copyright (C) 2002-2006, and GNU GPL'd, by Josef Weidendorfer et al. ==23939== Using LibVEX rev 1604, a library for dynamic binary translation. ==23939== Copyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP. ==23939== Using valgrind-3.2.0.SVN, a dynamic binary instrumentation framework. ==23939== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al. ==23939== For more details, rerun with: -v ==23939== ==23939== For interactive control, run 'callgrind_control -h'. ==23939== ==23939== Process terminating with default action of signal 11 (SIGSEGV) ==23939== Access not within mapped region at address 0xF1CCDC58 ==23939== at 0x4179E065: _IO_file_read (in /lib/tls/libc-2.3.5.so) ==23939== by 0x4179CDFD: _IO_file_underflow@@GLIBC_2.1 (in /lib/tls/libc-2.3.5.so) ==23939== by 0x4179F2EA: _IO_default_uflow (in /lib/tls/libc-2.3.5.so) ==23939== by 0x4179F0CB: __uflow (in /lib/tls/libc-2.3.5.so) ==23939== by 0x41794227: _IO_getline_info (in /lib/tls/libc-2.3.5.so) ==23939== by 0x4179414E: _IO_getline (in /lib/tls/libc-2.3.5.so) ==23939== by 0x4179C119: fgets_unlocked (in /lib/tls/libc-2.3.5.so) ==23939== by 0x404146A: (within /lib/libselinux.so.1) ==23939== by 0x4044365: (within /lib/libselinux.so.1) ==23939== by 0x403A0B4: (within /lib/libselinux.so.1) ==23939== by 0x4100B9A3: call_init (in /lib/ld-2.3.5.so) ==23939== by 0x4100BAE0: _dl_init (in /lib/ld-2.3.5.so) ==23939== --23939-- VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting --23939-- si_code=1; Faulting address: 0x10; sp: 0x626D27A8 valgrind: m_signals.c:1772 (sync_signalhandler): Assertion 'tid != 0' failed. ==23939== at 0xB00170B6: report_and_quit (m_libcassert.c:136) =========================================== As this is reproducable, it should be fixable... > > --- m_dispatch/dispatch-x86-linux.S (Revision 5868) > > +++ m_dispatch/dispatch-x86-linux.S (Arbeitskopie) > > @@ -51,6 +51,7 @@ > > */ > > .text > > .globl VG_(run_innerloop) > > +.type VG_(run_innerloop), @function > > VG_(run_innerloop): > > /* 4(%esp) holds guest_state */ > > /* 8(%esp) holds do_profiling */ > > @@ -251,8 +252,8 @@ > > popl %ecx > > popl %ebx > > ret > > +.size VG_(run_innerloop), .-VG_(run_innerloop) > > Sounds good. Please commit it. Will do. Josef |
|
From: Dave N. <dc...@us...> - 2006-12-06 17:09:38
|
I am trying to find out what became of Yao Qi's patch to lackey to support instruction tracing? Searching the archives I see that it was recommended that he put itrace functionality into lackey rather than as a separate tool. It looks like his patches titled: *Re: Re: [RFC]contribute a new tool to valgrind, Instruction Trace *submitted on Mar 6, 2006 moved itrace into the lackey tool. Yao Qi is no longer working on this project so I'm trying to determine where we stand with this patch. Did it fall through the cracks? Is there a problem with it? Unresolved issues? |
|
From: Josef W. <Jos...@gm...> - 2006-12-06 17:35:42
|
On Wednesday 06 December 2006 18:11, Dave Nomura wrote: > Yao Qi is no longer working on this project so I'm trying to determine > where we stand with this patch. Did it fall through the cracks? Is > there a problem with it? Unresolved issues? I saw the overlap with lackey and made some comments for easier integration, but I do not feel responsible to decide what to put into lackey and what not. Lackey is meant to be a tool writing tutorial for newcomers, and merging to many things, it probably actually distracts potential new developers. It probably would be better to put more really small example tools into valgrind. What about the memtrace tool from the IISWC-2006 tutorial? However, there was some discussion to make it easier for independently developed valgrind tools to show up in a more prominent place for better visibility. I am not sure about the outcome of this discussion. Josef |
|
From: Nicholas N. <nj...@cs...> - 2006-12-06 22:04:50
|
On Wed, 6 Dec 2006, Josef Weidendorfer wrote: > On Wednesday 06 December 2006 18:11, Dave Nomura wrote: >> Yao Qi is no longer working on this project so I'm trying to determine >> where we stand with this patch. Did it fall through the cracks? Is >> there a problem with it? Unresolved issues? > > I saw the overlap with lackey and made some comments for easier integration, > but I do not feel responsible to decide what to put into lackey and what not. > Lackey is meant to be a tool writing tutorial for newcomers, and merging to > many things, it probably actually distracts potential new developers. > > It probably would be better to put more really small example tools into valgrind. > What about the memtrace tool from the IISWC-2006 tutorial? > > However, there was some discussion to make it easier for independently > developed valgrind tools to show up in a more prominent place for better > visibility. I am not sure about the outcome of this discussion. Yes, Lackey already has enough stuff in it. I don't think that code ever got merged. Memtrace is subsumed by Lackey's --trace-mem option. (Nb: I don't think that's the same as the --trace-mem option mentioned in the subject line of this email.) Julian and I have been discussing the idea of having an area for experimental tools in the Valgrind distribution. It'll probably get introduced in release 3.3.0. Nick |
|
From: Bart V. A. <bar...@gm...> - 2006-12-07 07:33:51
|
On 12/6/06, Nicholas Nethercote <nj...@cs...> wrote: > > Julian and I have been discussing the idea of having an area for > experimental tools in the Valgrind distribution. It'll probably get > introduced in release 3.3.0. > > Nick Will it be possible for experimental tools to branch Valgrind's core ? Bart. |
|
From: Nicholas N. <nj...@cs...> - 2006-12-07 10:41:05
|
On Thu, 7 Dec 2006, Bart Van Assche wrote: >> Julian and I have been discussing the idea of having an area for >> experimental tools in the Valgrind distribution. It'll probably get >> introduced in release 3.3.0. > > Will it be possible for experimental tools to branch Valgrind's core ? We hadn't thought of that... I'm not sure how it would be possible. Better would probably be to try to add whatever features the tool needs to the the standard core, so long as they're not too dramatic. IIRC we've already made some core changes for DRD, are there more required? (Sorry if you've mentioned them before and I've forgotten.) Nick |
|
From: Bart V. A. <bar...@gm...> - 2006-12-07 11:03:01
|
On 12/7/06, Nicholas Nethercote <nj...@cs...> wrote: > On Thu, 7 Dec 2006, Bart Van Assche wrote: > > > Will it be possible for experimental tools to branch Valgrind's core ? > > We hadn't thought of that... I'm not sure how it would be possible. Better > would probably be to try to add whatever features the tool needs to the the > standard core, so long as they're not too dramatic. IIRC we've already > made some core changes for DRD, are there more required? (Sorry if you've > mentioned them before and I've forgotten.) > > Nick The core changes required for drd are substantial -- this is the last published version of the core changes: http://home.euphonynet.be/bvassche/valgrind/valgrind-6361-core-2006-11-20.patch Note: I'm currently reworking these core changes such that detached threads can be supported. Bart. |
|
From: Julian S. <js...@ac...> - 2006-12-07 12:10:50
|
On Thursday 07 December 2006 10:55, Bart Van Assche wrote: > On 12/7/06, Nicholas Nethercote <nj...@cs...> wrote: > > On Thu, 7 Dec 2006, Bart Van Assche wrote: > > > Will it be possible for experimental tools to branch Valgrind's core ? > > > > We hadn't thought of that... I'm not sure how it would be possible. Doesn't sound desirable to me .. will increase the long term maintenance overhead. > http://home.euphonynet.be/bvassche/valgrind/valgrind-6361-core-2006-11-20.p >atch Note: I'm currently reworking these core changes such that detached > threads can be supported. On a quick look at that, I notice(d before now) your pthread_* function wrappers are in coregrind/vg_preloaded.c. I would prefer that those wrappers be placed in a drd-specific its own preload .so, in the same way that memcheck has its malloc wrappers placed in its own .so, vgpreload_memcheck-<platform>.so. This has two advantages: (1) it avoids forcing all tools to use the pthread wrappers when they don't need to, which avoids a potentially large performance loss, and (2) it reduces the amount of drd-specific stuff that the core needs to know about. In particularly, it ought to be possible to engineer this so that the core does not have to know anything about the drd-specific client requests either. J |
|
From: Bart V. A. <bar...@gm...> - 2006-12-07 13:35:04
|
On 12/7/06, Julian Seward <js...@ac...> wrote: > On Thursday 07 December 2006 10:55, Bart Van Assche wrote: > > http://home.euphonynet.be/bvassche/valgrind/valgrind-6361-core-2006-11-20.p > >atch Note: I'm currently reworking these core changes such that detached > > threads can be supported. > > On a quick look at that, I notice(d before now) your pthread_* function > wrappers are in coregrind/vg_preloaded.c. I would prefer that those > wrappers be placed in a drd-specific its own preload .so, in the same > way that memcheck has its malloc wrappers placed in its own .so, > vgpreload_memcheck-<platform>.so. > > This has two advantages: (1) it avoids forcing all tools to use the pthread > wrappers when they don't need to, which avoids a potentially large performance > loss, and (2) it reduces the amount of drd-specific stuff that the core needs > to know about. In particularly, it ought to be possible to engineer this so > that the core does not have to know anything about the drd-specific client > requests either. Moving the pthread_* function wrappers to a drd-specific preload is no problem. But did you consider the following: - every tool that needs information about thread events (e.g. helgrind or a tool that tracks stack usage of threads) will have to be informed about thread creation and thread termination. - The overhead of having wrappers in vg_preloaded.c for pthread_create() and pthread_join() is relatively small, the impact is only significant for software that creates and stops threads very quickly. The largest performance penalty is for none/tests/manythreads: with --tool=none and without my patch, it completes in 1.60s. With my patch and --tool=none it completes in about 1.63s, or a slowdown of 2%. Maybe I can keep the wrappers for pthread_create()/pthread_join() in vg_preloaded.c, and move the other wrappers to a drd/... file ? Bart. |
|
From: Josef W. <Jos...@gm...> - 2006-12-07 17:24:45
|
On Thursday 07 December 2006 14:05, Bart Van Assche wrote: > > On a quick look at that, I notice(d before now) your pthread_* function > > wrappers are in coregrind/vg_preloaded.c. I would prefer that those > > wrappers be placed in a drd-specific its own preload .so, in the same > > way that memcheck has its malloc wrappers placed in its own .so, > > vgpreload_memcheck-<platform>.so. > > This has two advantages: (1) it avoids forcing all tools to use the pthread > > wrappers when they don't need to, which avoids a potentially large performance > > loss I think the one reason for not making wrappers tool-global is, that e.g. for cachegrind or callgrind, these wrappers actually can appear quite high on the cost list of functions, depending on application behavior. Especially for the malloc wrappers and for malloc-intensive C++ applications, you originally saw valgrinds own malloc replacements on top of your profile. And that can not be correct: you want to see the behavior of the malloc versions in your C runtime library. However, I thought it should be possible to optionally provide wrappers in coregrind, and the tool can specify if it want it enabled or not. Or is this not possible? Josef |
|
From: Nicholas N. <nj...@cs...> - 2006-12-07 21:41:19
|
On Thu, 7 Dec 2006, Josef Weidendorfer wrote: > However, I thought it should be possible to optionally provide wrappers > in coregrind, and the tool can specify if it want it enabled or not. > Or is this not possible? That's basically what Julian's suggestion achieves. The tool-writer has to write the wrappers separately for each tool, so it's not as convenient as ticking a box, but it's not that much code and we so far only have one tool that needs pthread_* wrapprs. Nick |
|
From: Julian S. <js...@ac...> - 2006-12-08 12:10:39
|
> Maybe I can keep the wrappers for pthread_create()/pthread_join() in > vg_preloaded.c, and move the other wrappers to a drd/... file ? I see what you're saying, but I still prefer all the wrappers to be drd-specific. The real reason is that there is already an overwhelming level of complexity in coregrind/, and I am reluctant to add more, especially considering that at the moment we do not have any other tools which require to see thread create/exit events. I even hope to reduce the amount of code in the core if we can. Specifically, are m_threadmodel.c and m_pthreadmodel.c really necessary? I don't think they are used at present and if not we should delete them and/or move drd-required parts into drd/. J |
|
From: Bart V. A. <bar...@gm...> - 2006-12-08 13:00:34
|
On 12/8/06, Julian Seward <js...@ac...> wrote: > > > Maybe I can keep the wrappers for pthread_create()/pthread_join() in > > vg_preloaded.c, and move the other wrappers to a drd/... file ? > > I see what you're saying, but I still prefer all the wrappers to be > drd-specific. The real reason is that there is already an overwhelming > level of complexity in coregrind/, and I am reluctant to add more, > especially considering that at the moment we do not have any other > tools which require to see thread create/exit events. > > I even hope to reduce the amount of code in the core if we can. > Specifically, are m_threadmodel.c and m_pthreadmodel.c really necessary? > I don't think they are used at present and if not we should delete > them and/or move drd-required parts into drd/. Regarding the core changes I proposed, I'll move them as much as possible to the drd tool. And about m_threadmodel.c and m_pthreadmodel.c: as far as I know the code in these files is not used by any tool. The presence of this code was confusing for me when I tried to understand how Valgrind handles threads, since I was searching through the code with grep. I propose to remove these two source files from the Valgrind source tree. Bart. |
|
From: Julian S. <js...@ac...> - 2006-12-08 13:16:37
|
> > I even hope to reduce the amount of code in the core if we can. > > Specifically, are m_threadmodel.c and m_pthreadmodel.c really necessary? > > I don't think they are used at present and if not we should delete > > them and/or move drd-required parts into drd/. > > Regarding the core changes I proposed, I'll move them as much as > possible to the drd tool. Great. You should understand that I'm not unsympathetic to the split you proposed. But a permanent background problem is the complexity and maintainability of the core -- in the past we have gotten into some serious difficulties with that. > And about m_threadmodel.c and > m_pthreadmodel.c: as far as I know the code in these files is not used > by any tool. Ok, these should then be removed. They can of course be brought back (or parts of them) from source control if we need them later. > The presence of this code was confusing for me when I > tried to understand how Valgrind handles threads, since I was > searching through the code with grep. Yes. I think this is a historical artefact left over from development of Helgrind. J |