Skip to content

Commit 974acae

Browse files
art049claude
andcommitted
test(tracegrind): add multi-thread interleaved callstack regression test
Spawns 3 threads with distinct noinline call chains at different depths (work_a->depth_a1->depth_a2, work_b->depth_b1, work_c->depth_c1->depth_c2) to verify tracegrind correctly tracks per-thread ENTER_FN/EXIT_FN stacks. Output is sorted by tid for deterministic comparison. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ef5bcde commit 974acae

5 files changed

Lines changed: 102 additions & 0 deletions

File tree

tracegrind/tests/Makefile.am

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ check_PROGRAMS = \
2121
test_tailcall.bin \
2222
test_recursion.bin \
2323
test_thread_create.bin \
24+
test_thread_interleave.bin \
2425
test_syscall.bin
2526

2627
AM_CPPFLAGS += -I$(top_srcdir)/tracegrind
@@ -46,6 +47,8 @@ test_tailcall_bin_CFLAGS = $(AM_CFLAGS) -O2 -g
4647
test_recursion_bin_SOURCES = test_recursion.c
4748
test_thread_create_bin_SOURCES = test_thread_create.c
4849
test_thread_create_bin_LDADD = -lpthread
50+
test_thread_interleave_bin_SOURCES = test_thread_interleave.c
51+
test_thread_interleave_bin_LDADD = -lpthread
4952
test_syscall_bin_SOURCES = test_syscall.c
5053

5154
EXTRA_DIST = \
@@ -63,5 +66,6 @@ EXTRA_DIST = \
6366
test_tailcall.vgtest test_tailcall.stderr.exp test_tailcall.post.exp \
6467
test_recursion.vgtest test_recursion.stderr.exp test_recursion.post.exp \
6568
test_thread_create.vgtest test_thread_create.stderr.exp test_thread_create.post.exp \
69+
test_thread_interleave.vgtest test_thread_interleave.stderr.exp test_thread_interleave.post.exp \
6670
test_syscall.vgtest test_syscall.stderr.exp test_syscall.post.exp \
6771
test_schema.vgtest test_schema.stderr.exp test_schema.post.exp
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include "tracegrind.h"
2+
#include <pthread.h>
3+
4+
__attribute__((noinline)) static void depth_a2(void) { }
5+
6+
__attribute__((noinline)) static void depth_a1(void) {
7+
depth_a2();
8+
}
9+
10+
__attribute__((noinline)) static void *work_a(void *arg) {
11+
(void)arg;
12+
depth_a1();
13+
return NULL;
14+
}
15+
16+
__attribute__((noinline)) static void depth_b1(void) { }
17+
18+
__attribute__((noinline)) static void *work_b(void *arg) {
19+
(void)arg;
20+
depth_b1();
21+
return NULL;
22+
}
23+
24+
__attribute__((noinline)) static void depth_c2(void) { }
25+
26+
__attribute__((noinline)) static void depth_c1(void) {
27+
depth_c2();
28+
}
29+
30+
__attribute__((noinline)) static void *work_c(void *arg) {
31+
(void)arg;
32+
depth_c1();
33+
return NULL;
34+
}
35+
36+
int main(void) {
37+
pthread_t t1, t2, t3;
38+
39+
TRACEGRIND_ADD_MARKER("start");
40+
TRACEGRIND_START_INSTRUMENTATION;
41+
42+
pthread_create(&t1, NULL, work_a, NULL);
43+
pthread_create(&t2, NULL, work_b, NULL);
44+
pthread_create(&t3, NULL, work_c, NULL);
45+
46+
pthread_join(t1, NULL);
47+
pthread_join(t2, NULL);
48+
pthread_join(t3, NULL);
49+
50+
TRACEGRIND_STOP_INSTRUMENTATION;
51+
TRACEGRIND_ADD_MARKER("end");
52+
53+
return 0;
54+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
Format Version: N
2+
Format Name: tracegrind-msgpack
3+
Schema Version: N
4+
Event Schemas (discriminated union):
5+
0 (MARKER): ['seq', 'tid', 'event', 'marker']
6+
1 (ENTER_FN): ['seq', 'tid', 'event', 'fn', 'obj', 'file', 'line', 'Ir']
7+
2 (EXIT_FN): ['seq', 'tid', 'event', 'fn', 'obj', 'file', 'line', 'Ir']
8+
3 (ENTER_INLINED_FN): ['seq', 'tid', 'event', 'fn', 'obj', 'file', 'line', 'Ir']
9+
4 (EXIT_INLINED_FN): ['seq', 'tid', 'event', 'fn', 'obj', 'file', 'line', 'Ir']
10+
5 (FORK): ['seq', 'tid', 'event', 'child_pid']
11+
6 (THREAD_CREATE): ['seq', 'tid', 'event', 'child_tid']
12+
Showing N of N rows
13+
seq=N | tid=1 | event=MARKER | marker=start
14+
seq=N | tid=1 | event=THREAD_CREATE | child_tid=2
15+
seq=N | tid=1 | event=THREAD_CREATE | child_tid=3
16+
seq=N | tid=1 | event=THREAD_CREATE | child_tid=4
17+
seq=N | tid=1 | event=MARKER | marker=end
18+
seq=N | tid=2 | event=ENTER_FN | fn=work_a | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
19+
seq=N | tid=2 | event=ENTER_FN | fn=depth_a1 | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
20+
seq=N | tid=2 | event=ENTER_FN | fn=depth_a2 | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
21+
seq=N | tid=2 | event=EXIT_FN | fn=depth_a2 | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
22+
seq=N | tid=2 | event=EXIT_FN | fn=depth_a1 | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
23+
seq=N | tid=2 | event=EXIT_FN | fn=work_a | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
24+
seq=N | tid=3 | event=ENTER_FN | fn=work_b | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
25+
seq=N | tid=3 | event=ENTER_FN | fn=depth_b1 | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
26+
seq=N | tid=3 | event=EXIT_FN | fn=depth_b1 | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
27+
seq=N | tid=3 | event=EXIT_FN | fn=work_b | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
28+
seq=N | tid=4 | event=ENTER_FN | fn=work_c | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
29+
seq=N | tid=4 | event=ENTER_FN | fn=depth_c1 | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
30+
seq=N | tid=4 | event=ENTER_FN | fn=depth_c2 | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
31+
seq=N | tid=4 | event=EXIT_FN | fn=depth_c2 | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
32+
seq=N | tid=4 | event=EXIT_FN | fn=depth_c1 | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
33+
seq=N | tid=4 | event=EXIT_FN | fn=work_c | obj=test_thread_interleave.bin | file=test_thread_interleave.c | line=0 | Ir=N
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
3+
Events : Ir
4+
Collected :
5+
6+
I refs:
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
prereq: ../../tracegrind/scripts/tracegrind-analyzer --help 2>/dev/null
2+
prog: test_thread_interleave.bin
3+
vgopts: --tracegrind-out-file=tracegrind.out.test_thread_interleave --instr-atstart=no
4+
post: ../../tracegrind/scripts/tracegrind-analyzer tracegrind.out.test_thread_interleave.msgpack.lz4 | ./filter_trace | grep -E '(Format |Schema |Event Schemas|Showing |\(|MARKER|THREAD_CREATE|fn=work_a |fn=work_b |fn=work_c |fn=depth_a1 |fn=depth_a2 |fn=depth_b1 |fn=depth_c1 |fn=depth_c2 )' | sort -t'|' -k2,2 -s
5+
cleanup: rm -f tracegrind.out.test_thread_interleave.msgpack.lz4

0 commit comments

Comments
 (0)