Helgrindのサンプルを試す
はじめに
マルチスレッドでプログラムを動かすことが多くある。性能向上のために。Helgrindは、マルチスレッドでのバグを発見するために使用するツールである。今回は、このツールを動かす。簡単なサンプルを使用して。
今回使用したサンプルはこちら。
なお、valgrindのバージョンは3.8.1である。
サンプルソース
下のサンプルソースは、本家からコピーしたもの。
通常、複数のスレッドが同一リソースを使用する場合、排他ロックするべきだが、していない。
したがって、不具合を生む可能性がある。
andre@andre-VirtualBox:~/work/helgrind$ cat main.c #include <pthread.h> int var = 0; void* child_fn ( void* arg ) { var++; /* Unprotected relative to parent */ /* this is line 6 */ ★リソースvarが競合している。 return NULL; } int main ( void ) { pthread_t child; pthread_create(&child, NULL, child_fn, NULL); var++; /* Unprotected relative to child */ /* this is line 13 */ ★リソースvarが競合している。 pthread_join(child, NULL); return 0; }
Helgrindを動かす。
Helgrindを動かした結果を下記に示す。
andre@andre-VirtualBox:~/work/helgrind$ valgrind --tool=helgrind ./test_main > no_history.txt 2>&1 andre@andre-VirtualBox:~/work/helgrind$ cat no_history.txt ==11250== Helgrind, a thread error detector ==11250== Copyright (C) 2007-2012, and GNU GPL'd, by OpenWorks LLP et al. ==11250== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==11250== Command: ./test_main ==11250== ==11250== ---Thread-Announcement------------------------------------------ ==11250== ==11250== Thread #1 is the program's root thread ★#1 はmainスレッド ==11250== ==11250== ---Thread-Announcement------------------------------------------ ==11250== ==11250== Thread #2 was created ==11250== at 0x41340B8: clone (clone.S:111) ★#2 はchild_fnスレッド(生成されたスレッドである) ==11250== ==11250== ---------------------------------------------------------------- ==11250== ==11250== Possible data race during read of size 4 at 0x804A020 by thread #1 ★#1 は4バイトの競合リソースを読み込んだ。 ==11250== Locks held: none ★ ロック状態:ロックなし ==11250== at 0x8048419: main (main.c:13) ==11250== ==11250== This conflicts with a previous write of size 4 by thread #2 ★#2 は4バイトの競合リソースを読み込んだ。 ==11250== Locks held: none ★ ロック状態:ロックなし ==11250== at 0x80484E0: child_fn (main.c:6) ==11250== by 0x404CD30: start_thread (pthread_create.c:304) ==11250== by 0x41340CD: clone (clone.S:130) ==11250== ==11250== ---------------------------------------------------------------- ==11250== ==11250== Possible data race during write of size 4 at 0x804A020 by thread #1 ★#1 は4バイトの競合リソースに書き込んだ。 ==11250== Locks held: none ★ ロック状態:ロックなし ==11250== at 0x8048419: main (main.c:13) ★ 13行目が競合している ==11250== ==11250== This conflicts with a previous write of size 4 by thread #2 ★#2 は4バイトの競合リソースに書き込んだ。 ==11250== Locks held: none ★ ロック状態:ロックなし ==11250== at 0x80484E0: child_fn (main.c:6) ★ 6行目が競合している ==11250== by 0x404CD30: start_thread (pthread_create.c:304) ==11250== by 0x41340CD: clone (clone.S:130) ==11250== ==11250== ==11250== For counts of detected and suppressed errors, rerun with: -v ==11250== Use --history-level=approx or =none to gain increased speed, at ==11250== the cost of reduced accuracy of conflicting-access information ==11250== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
その他のオプションを試す。
上記Helgrind実行結果の最後4行にあるオプションを試す。
==11250== For counts of detected and suppressed errors, rerun with: ★-v★ ==11250== Use ★--history-level=approx or =none★ to gain increased speed, at ==11250== the cost of reduced accuracy of conflicting-access information ==11250== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
--history-level=approx を試す。
approx は、approximateの略語みたいだ。下記の実行結果を見ると、もう少し詳細な動き(リソースを触った順番)がわかるようだ。
approximate:おおよその,ほぼ正確な
andre@andre-VirtualBox:~/work/helgrind$ valgrind --tool=helgrind --history-level=approx ./test_main >history_approx.txt 2>&1 andre@andre-VirtualBox:~/work/helgrind$ cat history_approx.txt ==11283== Helgrind, a thread error detector ==11283== Copyright (C) 2007-2012, and GNU GPL'd, by OpenWorks LLP et al. ==11283== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==11283== Command: ./test_main ==11283== ==11283== ---Thread-Announcement------------------------------------------ ==11283== ==11283== Thread #1 is the program's root thread ★#1 はmainスレッド ==11283== ==11283== ---Thread-Announcement------------------------------------------ ==11283== ==11283== Thread #2 was created ==11283== at 0x41340B8: clone (clone.S:111) ★#2 はchild_fnスレッド ==11283== ==11283== ---------------------------------------------------------------- ==11283== ==11283== Possible data race during read of size 4 at 0x804A020 by thread #1 ==11283== Locks held: none ==11283== at 0x8048419: main (main.c:13) ==11283== This conflicts with a previous access by thread #2, after ★リソースを触った順番(#2 -> #1)が書かれているようだ。 ==11283== (the start of the thread) ==11283== but before ==11283== at 0x4130779: madvise (syscall-template.S:82) ==11283== by 0x41340CD: clone (clone.S:130) ==11283== ==11283== ---------------------------------------------------------------- ==11283== ==11283== Possible data race during write of size 4 at 0x804A020 by thread #1 ==11283== Locks held: none ==11283== at 0x8048419: main (main.c:13) ==11283== This conflicts with a previous access by thread #2, after ★リソースを触った順番(#2 -> #1)が書かれているようだ。 ==11283== (the start of the thread) ==11283== but before ==11283== at 0x4130779: madvise (syscall-template.S:82) ==11283== by 0x41340CD: clone (clone.S:130) ==11283== ==11283== ==11283== For counts of detected and suppressed errors, rerun with: -v ==11283== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
--history-level=none
よくわからない。
andre@andre-VirtualBox:~/work/helgrind$ valgrind --tool=helgrind --history-level=none ./test_main >history_none.txt 2>&1 andre@andre-VirtualBox:~/work/helgrind$ cat history_none.txt ==11299== Helgrind, a thread error detector ==11299== Copyright (C) 2007-2012, and GNU GPL'd, by OpenWorks LLP et al. ==11299== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==11299== Command: ./test_main ==11299== ==11299== ---Thread-Announcement------------------------------------------ ==11299== ==11299== Thread #1 is the program's root thread ==11299== ==11299== ---------------------------------------------------------------- ==11299== ==11299== Possible data race during read of size 4 at 0x804A020 by thread #1 ==11299== Locks held: none ==11299== at 0x8048419: main (main.c:13) ==11299== ==11299== ---------------------------------------------------------------- ==11299== ==11299== Possible data race during write of size 4 at 0x804A020 by thread #1 ==11299== Locks held: none ==11299== at 0x8048419: main (main.c:13) ==11299== ==11299== ==11299== For counts of detected and suppressed errors, rerun with: -v ==11299== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
-v を試す。
いろいろな情報が盛り込まれたようだ。OSやgcc のバージョンまで表示されている。
andre@andre-VirtualBox:~/work/helgrind$ valgrind --tool=helgrind -v ./test_main >v.txt 2>&1 andre@andre-VirtualBox:~/work/helgrind$ cat v.txt ==11313== Helgrind, a thread error detector ==11313== Copyright (C) 2007-2012, and GNU GPL'd, by OpenWorks LLP et al. ==11313== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==11313== Command: ./test_main ==11313== --11313-- Valgrind options: --11313-- --tool=helgrind --11313-- -v --11313-- Contents of /proc/version: --11313-- Linux version 3.0.0-24-generic (buildd@akateko) (gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3) ) #40-Ubuntu SMP Tue Jul 24 15:36:59 UTC 2012 --11313-- Arch and hwcaps: X86, x86-sse1-sse2 --11313-- Page sizes: currently 4096, max supported 4096 --11313-- Valgrind library directory: /usr/local/lib/valgrind --11313-- Reading syms from /lib/i386-linux-gnu/ld-2.13.so --11313-- Considering /lib/i386-linux-gnu/ld-2.13.so .. --11313-- .. CRC mismatch (computed 1a2ed160 wanted fece6135) --11313-- Considering /usr/lib/debug/lib/i386-linux-gnu/ld-2.13.so .. --11313-- .. CRC is valid --11313-- Reading syms from /home/andre/work/helgrind/test_main --11313-- Reading syms from /usr/local/lib/valgrind/helgrind-x86-linux --11313-- object doesn't have a dynamic symbol table --11313-- Scheduler: using generic scheduler lock implementation. --11313-- Reading suppressions file: /usr/local/lib/valgrind/default.supp ==11313== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-11313-by-andre-on-??? ==11313== embedded gdbserver: writing to /tmp/vgdb-pipe-to-vgdb-from-11313-by-andre-on-??? ==11313== embedded gdbserver: shared mem /tmp/vgdb-pipe-shared-mem-vgdb-11313-by-andre-on-??? ==11313== ==11313== TO CONTROL THIS PROCESS USING vgdb (which you probably ==11313== don't want to do, unless you know exactly what you're doing, ==11313== or are doing some strange experiment): ==11313== /usr/local/lib/valgrind/../../bin/vgdb --pid=11313 ...command... ==11313== ==11313== TO DEBUG THIS PROCESS USING GDB: start GDB like this ==11313== /path/to/gdb ./test_main ==11313== and then give GDB the following command ==11313== target remote | /usr/local/lib/valgrind/../../bin/vgdb --pid=11313 ==11313== --pid is optional if only one valgrind process is running ==11313== --11313-- Reading syms from /usr/local/lib/valgrind/vgpreload_core-x86-linux.so --11313-- Reading syms from /usr/local/lib/valgrind/vgpreload_helgrind-x86-linux.so ==11313== WARNING: new redirection conflicts with existing -- ignoring it --11313-- old: 0x04016b80 (index ) R-> (0000.0) 0x0402d2dd index --11313-- new: 0x04016b80 (index ) R-> (0000.0) 0x0402d2a0 strchr --11313-- REDIR: 0x4016b80 (index) redirected to 0x402d2dd (index) --11313-- REDIR: 0x4016d40 (strlen) redirected to 0x402d3af (strlen) --11313-- Reading syms from /lib/i386-linux-gnu/libpthread-2.13.so --11313-- Considering /lib/i386-linux-gnu/libpthread-2.13.so .. --11313-- .. CRC mismatch (computed 0b26b884 wanted 21b4acb3) --11313-- Considering /usr/lib/debug/lib/i386-linux-gnu/libpthread-2.13.so .. --11313-- .. CRC is valid ==11313== WARNING: new redirection conflicts with existing -- ignoring it --11313-- old: 0x04051660 (pthread_spin_init ) W-> (0000.0) 0x0402c64a pthread_spin_init --11313-- new: 0x04051660 (pthread_spin_init ) W-> (0000.0) 0x0402c65a pthread_spin_unlock ==11313== WARNING: new redirection conflicts with existing -- ignoring it --11313-- old: 0x04052cf0 (sem_wait@@GLIBC_2.1 ) W-> (0000.0) 0x0402ca8a sem_wait@* --11313-- new: 0x04052cf0 (sem_wait@@GLIBC_2.1 ) W-> (0000.0) 0x0402ca7d sem_wait ==11313== WARNING: new redirection conflicts with existing -- ignoring it --11313-- old: 0x04052d90 (sem_wait@GLIBC_2.0 ) W-> (0000.0) 0x0402ca8a sem_wait@* --11313-- new: 0x04052d90 (sem_wait@GLIBC_2.0 ) W-> (0000.0) 0x0402ca7d sem_wait ==11313== WARNING: new redirection conflicts with existing -- ignoring it --11313-- old: 0x04052f50 (sem_post@@GLIBC_2.1 ) W-> (0000.0) 0x0402caa4 sem_post@* --11313-- new: 0x04052f50 (sem_post@@GLIBC_2.1 ) W-> (0000.0) 0x0402ca97 sem_post ==11313== WARNING: new redirection conflicts with existing -- ignoring it --11313-- old: 0x04052fd4 (sem_post@GLIBC_2.0 ) W-> (0000.0) 0x0402caa4 sem_post@* --11313-- new: 0x04052fd4 (sem_post@GLIBC_2.0 ) W-> (0000.0) 0x0402ca97 sem_post --11313-- Reading syms from /lib/i386-linux-gnu/libc-2.13.so --11313-- Considering /lib/i386-linux-gnu/libc-2.13.so .. --11313-- .. CRC mismatch (computed 365f96ac wanted ff3422fe) --11313-- Considering /usr/lib/debug/lib/i386-linux-gnu/libc-2.13.so .. --11313-- .. CRC is valid ==11313== WARNING: new redirection conflicts with existing -- ignoring it --11313-- old: 0x040d7b40 (index ) R-> (0000.0) 0x0402d263 index --11313-- new: 0x040d7b40 (index ) R-> (0000.0) 0x0402d226 strchr --11313-- REDIR: 0x40d7b40 (index) redirected to 0x402d263 (index) --11313-- REDIR: 0x404cfd0 (pthread_create@@GLIBC_2.1) redirected to 0x402bb75 (pthread_create@*) --11313-- REDIR: 0x40d5420 (calloc) redirected to 0x40281f7 (calloc) --11313-- REDIR: 0x40d48e0 (free) redirected to 0x4028e78 (free) ==11313== ---Thread-Announcement------------------------------------------ ==11313== ==11313== Thread #1 is the program's root thread ==11313== ==11313== ---Thread-Announcement------------------------------------------ ==11313== ==11313== Thread #2 was created ==11313== at 0x41340B8: clone (clone.S:111) ==11313== ==11313== ---------------------------------------------------------------- ==11313== ==11313== Possible data race during read of size 4 at 0x804A020 by thread #1 ==11313== Locks held: none ==11313== at 0x8048419: main (main.c:13) ==11313== ==11313== This conflicts with a previous write of size 4 by thread #2 ==11313== Locks held: none ==11313== at 0x80484E0: child_fn (main.c:6) ==11313== by 0x404CD30: start_thread (pthread_create.c:304) ==11313== by 0x41340CD: clone (clone.S:130) ==11313== ==11313== ---------------------------------------------------------------- ==11313== ==11313== Possible data race during write of size 4 at 0x804A020 by thread #1 ==11313== Locks held: none ==11313== at 0x8048419: main (main.c:13) ==11313== ==11313== This conflicts with a previous write of size 4 by thread #2 ==11313== Locks held: none ==11313== at 0x80484E0: child_fn (main.c:6) ==11313== by 0x404CD30: start_thread (pthread_create.c:304) ==11313== by 0x41340CD: clone (clone.S:130) ==11313== --11313-- REDIR: 0x404dd70 (pthread_join) redirected to 0x402bb95 (pthread_join) --11313-- REDIR: 0x404ed70 (pthread_mutex_lock) redirected to 0x402bdd4 (pthread_mutex_lock) --11313-- REDIR: 0x404fdf0 (pthread_mutex_unlock) redirected to 0x402c1ae (pthread_mutex_unlock) ==11313== ==11313== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) ==11313== ==11313== 1 errors in context 1 of 2: ==11313== ---------------------------------------------------------------- ==11313== ==11313== Possible data race during write of size 4 at 0x804A020 by thread #1 ==11313== Locks held: none ==11313== at 0x8048419: main (main.c:13) ==11313== ==11313== This conflicts with a previous write of size 4 by thread #2 ==11313== Locks held: none ==11313== at 0x80484E0: child_fn (main.c:6) ==11313== by 0x404CD30: start_thread (pthread_create.c:304) ==11313== by 0x41340CD: clone (clone.S:130) ==11313== ==11313== ==11313== 1 errors in context 2 of 2: ==11313== ---------------------------------------------------------------- ==11313== ==11313== Possible data race during read of size 4 at 0x804A020 by thread #1 ==11313== Locks held: none ==11313== at 0x8048419: main (main.c:13) ==11313== ==11313== This conflicts with a previous write of size 4 by thread #2 ==11313== Locks held: none ==11313== at 0x80484E0: child_fn (main.c:6) ==11313== by 0x404CD30: start_thread (pthread_create.c:304) ==11313== by 0x41340CD: clone (clone.S:130) ==11313== ==11313== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)