You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
|
|
|
|
1
(12) |
|
2
(6) |
3
(13) |
4
(9) |
5
(6) |
6
(8) |
7
(5) |
8
(5) |
|
9
(15) |
10
(18) |
11
(18) |
12
(18) |
13
(7) |
14
(11) |
15
(6) |
|
16
(12) |
17
(28) |
18
(15) |
19
(12) |
20
(17) |
21
(23) |
22
(10) |
|
23
(9) |
24
(11) |
25
(7) |
26
(21) |
27
(12) |
28
(6) |
29
(6) |
|
30
(8) |
|
|
|
|
|
|
|
From: <sv...@va...> - 2007-09-17 23:15:33
|
Author: njn
Date: 2007-09-18 00:15:35 +0100 (Tue, 18 Sep 2007)
New Revision: 6857
Log:
Add a warning about --log-file-exactly.
Modified:
trunk/docs/xml/manual-core.xml
Modified: trunk/docs/xml/manual-core.xml
===================================================================
--- trunk/docs/xml/manual-core.xml 2007-09-17 22:50:46 UTC (rev 6856)
+++ trunk/docs/xml/manual-core.xml 2007-09-17 23:15:35 UTC (rev 6857)
@@ -710,7 +710,11 @@
</term>
<listitem>
<para>Just like <option>--log-file</option>, but the suffix
- <computeroutput>".pid"</computeroutput> is not added.</para>
+ <computeroutput>".pid"</computeroutput> is not added. WARNING: If you
+ use this option with <option>--trace-children=yes</option> and your
+ program invokes multiple processes, the Valgrind output from all those
+ processes will go into this one file, possibly jumbled up, and
+ possibly incomplete.</para>
</listitem>
</varlistentry>
|
|
From: <sv...@va...> - 2007-09-17 22:50:45
|
Author: njn
Date: 2007-09-17 23:50:46 +0100 (Mon, 17 Sep 2007)
New Revision: 6856
Log:
update
Modified:
trunk/docs/internals/3_2_BUGSTATUS.txt
Modified: trunk/docs/internals/3_2_BUGSTATUS.txt
===================================================================
--- trunk/docs/internals/3_2_BUGSTATUS.txt 2007-09-17 22:46:45 UTC (rev 6855)
+++ trunk/docs/internals/3_2_BUGSTATUS.txt 2007-09-17 22:50:46 UTC (rev 6856)
@@ -30,7 +30,7 @@
145609 valgrind aborts all runs with 'repeated section!'
147825 r6793 crash on amd64-linux with gcc 4.2 and glibc 2.6 (CFI)
148096 VALGRIND_MALLOCLIKE_BLOCK not working correctly?
-148174 Incorrect type of freed_list_volume causes
+148174 r6855 Incorrect type of freed_list_volume causes
assertion with large memory allocations
148254 crash writing global var on ppc64 from instrumentation fn
148363 amd64->IR: 0x65 0x4C 0x8B 0x1C (mov %gs:0x10,%r11)
|
|
From: <sv...@va...> - 2007-09-17 22:46:44
|
Author: njn
Date: 2007-09-17 23:46:45 +0100 (Mon, 17 Sep 2007)
New Revision: 6855
Log:
Change an Int to a SSizeT to avoid overflows. Fixed bug 148174.
Modified:
trunk/memcheck/mc_include.h
trunk/memcheck/mc_main.c
trunk/memcheck/mc_malloc_wrappers.c
Modified: trunk/memcheck/mc_include.h
===================================================================
--- trunk/memcheck/mc_include.h 2007-09-17 22:35:57 UTC (rev 6854)
+++ trunk/memcheck/mc_include.h 2007-09-17 22:46:45 UTC (rev 6855)
@@ -255,7 +255,7 @@
extern Bool MC_(clo_partial_loads_ok);
/* Max volume of the freed blocks queue. */
-extern Int MC_(clo_freelist_vol);
+extern SSizeT MC_(clo_freelist_vol);
/* Do leak check at exit? default: NO */
extern LeakCheckMode MC_(clo_leak_check);
Modified: trunk/memcheck/mc_main.c
===================================================================
--- trunk/memcheck/mc_main.c 2007-09-17 22:35:57 UTC (rev 6854)
+++ trunk/memcheck/mc_main.c 2007-09-17 22:46:45 UTC (rev 6855)
@@ -4367,7 +4367,7 @@
/*------------------------------------------------------------*/
Bool MC_(clo_partial_loads_ok) = False;
-Int MC_(clo_freelist_vol) = 5000000;
+SSizeT MC_(clo_freelist_vol) = 5000000;
LeakCheckMode MC_(clo_leak_check) = LC_Summary;
VgRes MC_(clo_leak_resolution) = Vg_LowRes;
Bool MC_(clo_show_reachable) = False;
Modified: trunk/memcheck/mc_malloc_wrappers.c
===================================================================
--- trunk/memcheck/mc_malloc_wrappers.c 2007-09-17 22:35:57 UTC (rev 6854)
+++ trunk/memcheck/mc_malloc_wrappers.c 2007-09-17 22:46:45 UTC (rev 6855)
@@ -71,7 +71,7 @@
/* Records blocks after freeing. */
static MC_Chunk* freed_list_start = NULL;
static MC_Chunk* freed_list_end = NULL;
-static Int freed_list_volume = 0;
+static SSizeT freed_list_volume = 0;
/* Put a shadow chunk on the freed blocks queue, possibly freeing up
some of the oldest blocks in the queue at the same time. */
|
|
From: Nicholas N. <nj...@cs...> - 2007-09-17 22:36:25
|
On Tue, 28 Aug 2007, John Reiser wrote: > I found these hints to be helpful. The patch is against valgrind-3.2.3 , > also svn 6788 with just a 2-line offset. I just committed a change based on this patch. Thanks. Nick > --- ./README_DEVELOPERS.orig 2007-01-02 06:52:30.000000000 -0800 > +++ ./README_DEVELOPERS 2007-08-28 12:45:45.000000000 -0700 > @@ -69,15 +69,32 @@ > > export VALGRIND_LAUNCHER=/usr/local/bin/valgrind > > + [Or, to specify a newly-built but uninstalled version: > + > + export VALGRIND_LAUNCHER=$dir/coregrind/valgrind > + ] > + > (2) Run "gdb <prefix>/lib/valgrind/<platform>/<tool>": > > gdb /usr/local/lib/valgrind/ppc32-linux/lackey > > + [Or, to debug a newly-built but uninstalled version: > + > + gdb $dir/.in_place/x86-linux/memcheck > + ] > + > (3) Do "handle SIGSEGV SIGILL nostop noprint" in GDB to prevent GDB from > stopping on a SIGSEGV or SIGILL: > > (gdb) handle SIGILL SIGSEGV nostop noprint > > + [Steps 1-3 may be combined in a .gdbinit file: > + set env VALGRIND_LAUNCHER=$dir/coregrind/valgrind > + file $dir/.in_place/x86-linux/memcheck > + handle SIGILL SIGSEGV nostop noprint > + However, .gdbinit requires that $dir be expanded to a literal string. > + ] > + > (4) Set any breakpoints you want and proceed as normal for gdb. The > macro VG_(FUNC) is expanded to vgPlain_FUNC, so If you want to set > a breakpoint VG_(do_exec), you could do like this in GDB: > > -- > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Splunk Inc. > Still grepping through log files to find problems? Stop. > Now Search log events and configuration files using AJAX and a browser. > Download your FREE copy of Splunk now >> http://get.splunk.com/ > _______________________________________________ > Valgrind-developers mailing list > Val...@li... > https://lists.sourceforge.net/lists/listinfo/valgrind-developers > |
|
From: <sv...@va...> - 2007-09-17 22:35:56
|
Author: njn
Date: 2007-09-17 23:35:57 +0100 (Mon, 17 Sep 2007)
New Revision: 6854
Log:
Extra info about debugging with GDB
Modified:
trunk/README_DEVELOPERS
Modified: trunk/README_DEVELOPERS
===================================================================
--- trunk/README_DEVELOPERS 2007-09-17 22:28:21 UTC (rev 6853)
+++ trunk/README_DEVELOPERS 2007-09-17 22:35:57 UTC (rev 6854)
@@ -67,14 +67,22 @@
a particular tool) requires a bit more trickery but can be achieved
without too much problem by following these steps:
-(1) Set VALGRIND_LAUNCHER to <prefix>/bin/valgrind:
+(1) Set VALGRIND_LAUNCHER to point to the valgrind executable. Eg:
- export VALGRIND_LAUNCHER=/usr/local/bin/valgrind
+ export VALGRIND_LAUNCHER=/usr/local/bin/valgrind
-(2) Run "gdb <prefix>/lib/valgrind/<platform>/<tool>":
+ or for an uninstalled version in a source directory $DIR:
- gdb /usr/local/lib/valgrind/ppc32-linux/lackey
+ export VALGRIND_LAUNCHER=$DIR/coregrind/valgrind
+(2) Run gdb on the tool executable. Eg:
+
+ gdb /usr/local/lib/valgrind/ppc32-linux/lackey
+
+ or
+
+ gdb $DIR/.in_place/x86-linux/memcheck
+
(3) Do "handle SIGSEGV SIGILL nostop noprint" in GDB to prevent GDB from
stopping on a SIGSEGV or SIGILL:
@@ -90,6 +98,8 @@
(gdb) run pwd
+Steps (1)--(3) can be put in a .gdbinit file, but any directory names must
+be fully expanded (ie. not an environment variable).
Self-hosting
~~~~~~~~~~~~
|
|
From: <sv...@va...> - 2007-09-17 22:28:19
|
Author: njn Date: 2007-09-17 23:28:21 +0100 (Mon, 17 Sep 2007) New Revision: 6853 Log: Add a section to the cachegrind manual suggesting how to act on the results. Modified: trunk/cachegrind/docs/cg-manual.xml Modified: trunk/cachegrind/docs/cg-manual.xml =================================================================== --- trunk/cachegrind/docs/cg-manual.xml 2007-09-17 22:19:01 UTC (rev 6852) +++ trunk/cachegrind/docs/cg-manual.xml 2007-09-17 22:28:21 UTC (rev 6853) @@ -1226,28 +1226,31 @@ <para> So, you've managed to profile your program with Cachegrind. Now what? What's the best way to actually act on the information it provides to speed -up your program?</para> +up your program? Here are some rules of thumb that we have found to be +useful.</para> <para> First of all, the global hit/miss rate numbers are not that useful. If you have multiple programs or multiple runs of a program, comparing the numbers -might identify if any are outliers. Otherwise, they're not enough to act -on.</para> +might identify if any are outliers and worthy of closer investigation. +Otherwise, they're not enough to act on.</para> <para> -The source code annotations are much more useful. In our experience, the -best place to start is by looking at the <computeroutput>Ir</computeroutput> -numbers. They simply measure how many instructions were executed for each -line, and don't include any cache information, but they can still be very -useful for identifying bottlenecks.</para> +The line-by-line source code annotations are much more useful. In our +experience, the best place to start is by looking at the +<computeroutput>Ir</computeroutput> numbers. They simply measure how many +instructions were executed for each line, and don't include any cache +information, but they can still be very useful for identifying +bottlenecks.</para> <para> After that, we have found that L2 misses are typically a much bigger source of slow-downs than L1 misses. So it's worth looking for any snippets of -code that cause a lot of L2 misses. If you find any, it's still not always -easy to work out how to improve things. You need to have a reasonable -understanding of how caches work, the principles of locality, and your -program's data access patterns. </para> +code that cause a high proportion of the L2 misses. If you find any, it's +still not always easy to work out how to improve things. You need to have a +reasonable understanding of how caches work, the principles of locality, and +your program's data access patterns. Improving things may require +redesigning a data structure, for example.</para> <para> In short, Cachegrind can tell you where some of the bottlenecks in your code |
|
From: <sv...@va...> - 2007-09-17 22:19:00
|
Author: njn Date: 2007-09-17 23:19:01 +0100 (Mon, 17 Sep 2007) New Revision: 6852 Log: Add section on how to use Cachegrind's results. Modified: trunk/cachegrind/docs/cg-manual.xml Modified: trunk/cachegrind/docs/cg-manual.xml =================================================================== --- trunk/cachegrind/docs/cg-manual.xml 2007-09-17 22:01:14 UTC (rev 6851) +++ trunk/cachegrind/docs/cg-manual.xml 2007-09-17 22:19:01 UTC (rev 6852) @@ -1221,11 +1221,48 @@ </sect1> +<sect1> +<title>Acting on Cachegrind's information</title> +<para> +So, you've managed to profile your program with Cachegrind. Now what? +What's the best way to actually act on the information it provides to speed +up your program?</para> +<para> +First of all, the global hit/miss rate numbers are not that useful. If you +have multiple programs or multiple runs of a program, comparing the numbers +might identify if any are outliers. Otherwise, they're not enough to act +on.</para> + +<para> +The source code annotations are much more useful. In our experience, the +best place to start is by looking at the <computeroutput>Ir</computeroutput> +numbers. They simply measure how many instructions were executed for each +line, and don't include any cache information, but they can still be very +useful for identifying bottlenecks.</para> + +<para> +After that, we have found that L2 misses are typically a much bigger source +of slow-downs than L1 misses. So it's worth looking for any snippets of +code that cause a lot of L2 misses. If you find any, it's still not always +easy to work out how to improve things. You need to have a reasonable +understanding of how caches work, the principles of locality, and your +program's data access patterns. </para> + +<para> +In short, Cachegrind can tell you where some of the bottlenecks in your code +are, but it can't tell you how to fix them. You have to work that out for +yourself. But at least you have the information! +</para> + +</sect1> + <sect1> <title>Implementation details</title> +<para> This section talks about details you don't need to know about in order to use Cachegrind, but may be of interest to some people. +</para> <sect2> <title>How Cachegrind works</title> @@ -1294,8 +1331,8 @@ <para>More than one line of info can be presented for each file/fn/line number. In such cases, the counts for the named events will be accumulated.</para> -<para>Counts can be "." to represent zero. This makes the files easier to -read.</para> +<para>Counts can be "." to represent zero. This makes the files easier for +humans to read.</para> <para>The number of counts in each <computeroutput>line</computeroutput> and the @@ -1303,7 +1340,8 @@ the number of events in the <computeroutput>event_line</computeroutput>. If the number in each <computeroutput>line</computeroutput> is less, cg_annotate -treats those missing as though they were a "." entry.</para> +treats those missing as though they were a "." entry. This saves space. +</para> <para>A <computeroutput>file_line</computeroutput> changes the current file name. A <computeroutput>fn_line</computeroutput> |
|
From: <sv...@va...> - 2007-09-17 22:01:18
|
Author: njn
Date: 2007-09-17 23:01:14 +0100 (Mon, 17 Sep 2007)
New Revision: 6851
Log:
minor tweak
Modified:
trunk/cachegrind/cg_annotate.in
Modified: trunk/cachegrind/cg_annotate.in
===================================================================
--- trunk/cachegrind/cg_annotate.in 2007-09-17 12:52:10 UTC (rev 6850)
+++ trunk/cachegrind/cg_annotate.in 2007-09-17 22:01:14 UTC (rev 6851)
@@ -747,9 +747,9 @@
my $opened_file = "";
my $full_file_name = "";
- # We first try it with the empty include_dir, in case the filename has
- # the full path.
- foreach my $include_dir ("", @include_dirs) {
+ # Nb: include_dirs already includes "", so it works in the case
+ # where the filename has the full path.
+ foreach my $include_dir (@include_dirs) {
my $try_name = $include_dir . $src_file;
if (open(INPUTFILE, "< $try_name")) {
$opened_file = $try_name;
|
|
From: <js...@ac...> - 2007-09-17 12:58:48
|
Nightly build on minnie ( SuSE 10.0, ppc32 ) started at 2007-09-17 09:00:01 BST Results differ from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 220 tests, 10 stderr failures, 6 stdout failures, 0 posttest failures == memcheck/tests/leak-tree (stderr) memcheck/tests/leakotron (stdout) memcheck/tests/pointer-trace (stderr) memcheck/tests/stack_changes (stderr) memcheck/tests/xml1 (stderr) none/tests/faultstatus (stderr) none/tests/fdleak_cmsg (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) none/tests/ppc32/jm-fp (stdout) none/tests/ppc32/jm-fp (stderr) none/tests/ppc32/round (stdout) none/tests/ppc32/round (stderr) none/tests/ppc32/test_fx (stdout) none/tests/ppc32/test_fx (stderr) none/tests/ppc32/test_gx (stdout) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 220 tests, 10 stderr failures, 7 stdout failures, 0 posttest failures == memcheck/tests/leak-tree (stderr) memcheck/tests/leakotron (stdout) memcheck/tests/pointer-trace (stderr) memcheck/tests/stack_changes (stderr) memcheck/tests/xml1 (stderr) none/tests/faultstatus (stderr) none/tests/fdleak_cmsg (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) none/tests/ppc32/jm-fp (stdout) none/tests/ppc32/jm-fp (stderr) none/tests/ppc32/round (stdout) none/tests/ppc32/round (stderr) none/tests/ppc32/test_fx (stdout) none/tests/ppc32/test_fx (stderr) none/tests/ppc32/test_gx (stdout) none/tests/pth_detached (stdout) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Mon Sep 17 09:12:16 2007 --- new.short Mon Sep 17 09:25:05 2007 *************** *** 8,10 **** ! == 220 tests, 10 stderr failures, 7 stdout failures, 0 posttest failures == memcheck/tests/leak-tree (stderr) --- 8,10 ---- ! == 220 tests, 10 stderr failures, 6 stdout failures, 0 posttest failures == memcheck/tests/leak-tree (stderr) *************** *** 25,27 **** none/tests/ppc32/test_gx (stdout) - none/tests/pth_detached (stdout) --- 25,26 ---- |
|
From: <sv...@va...> - 2007-09-17 12:52:11
|
Author: weidendo
Date: 2007-09-17 13:52:10 +0100 (Mon, 17 Sep 2007)
New Revision: 6850
Log:
callgrind: Use directory in debug info when available
Prepend the file name of a source file with the directory
if that is available. This not only gets rid of problems with the
same file name used in different paths of a project, but lets
the annotation work out of the box without having to specify any
source directory.
Works both with callgrind_annotate and KCachegrind without any
changes there.
Inspired by Nick's change to cachegrind doing the same thing
in r6839 (and gets rid of a FIXME in the source)
Modified:
trunk/NEWS
trunk/callgrind/dump.c
trunk/callgrind/fn.c
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2007-09-17 09:54:57 UTC (rev 6849)
+++ trunk/NEWS 2007-09-17 12:52:10 UTC (rev 6850)
@@ -30,6 +30,9 @@
This means that the -I option to 'cg_annotate' should not be needed in
most cases. It also means it can correctly handle the case where two
source files in different directories have the same name.
+ The same is true for Callgrind and callgrind_annotate, respectively.
+ The benefits also apply to KCachegrind, without any further change
+ (ie. in most cases there is no configuration of source directories needed).
Developer-visible changes:
Modified: trunk/callgrind/dump.c
===================================================================
--- trunk/callgrind/dump.c 2007-09-17 09:54:57 UTC (rev 6849)
+++ trunk/callgrind/dump.c 2007-09-17 12:52:10 UTC (rev 6850)
@@ -438,27 +438,36 @@
Bool get_debug_pos(BBCC* bbcc, Addr addr, AddrPos* p)
{
Char file[FILENAME_LEN];
- Bool res;
+ Char dir[FILENAME_LEN];
+ Bool found_file_line, found_dirname;
int cachepos = addr % DEBUG_CACHE_SIZE;
if (debug_cache_addr[cachepos] == addr) {
p->line = debug_cache_line[cachepos];
p->file = debug_cache_file[cachepos];
- res = debug_cache_info[cachepos];
+ found_file_line = debug_cache_info[cachepos];
}
else {
- res = VG_(get_filename_linenum)(addr,
- file, FILENAME_LEN,
- NULL, 0, NULL, //FIXME
- &(p->line));
- if (!res) {
+ found_file_line = VG_(get_filename_linenum)(addr,
+ file, FILENAME_LEN,
+ dir, FILENAME_LEN,
+ &found_dirname,
+ &(p->line));
+ if (!found_file_line) {
VG_(strcpy)(file, "???");
p->line = 0;
}
+ if (found_dirname) {
+ // +1 for the '/'.
+ CLG_ASSERT(VG_(strlen)(dir) + VG_(strlen)(file) + 1 < FILENAME_LEN);
+ VG_(strcat)(dir, "/"); // Append '/'
+ VG_(strcat)(dir, file); // Append file to dir
+ VG_(strcpy)(file, dir); // Move dir+file to file
+ }
p->file = CLG_(get_file_node)(bbcc->bb->obj, file);
- debug_cache_info[cachepos] = res;
+ debug_cache_info[cachepos] = found_file_line;
debug_cache_addr[cachepos] = addr;
debug_cache_line[cachepos] = p->line;
debug_cache_file[cachepos] = p->file;
@@ -472,7 +481,7 @@
addr, bb_addr(bbcc->bb), bbcc->cxt->fn[0]->name,
p->file->name, p->line);
- return res;
+ return found_file_line;
}
Modified: trunk/callgrind/fn.c
===================================================================
--- trunk/callgrind/fn.c 2007-09-17 09:54:57 UTC (rev 6849)
+++ trunk/callgrind/fn.c 2007-09-17 12:52:10 UTC (rev 6850)
@@ -364,11 +364,12 @@
Bool CLG_(get_debug_info)(Addr instr_addr,
- Char filename[FILENAME_LEN],
+ Char file[FILENAME_LEN],
Char fn_name[FN_NAME_LEN], UInt* line_num,
SegInfo** pSegInfo)
{
- Bool found1, found2, result = True;
+ Bool found_file_line, found_fn, found_dirname, result = True;
+ Char dir[FILENAME_LEN];
UInt line;
CLG_DEBUG(6, " + get_debug_info(%p)\n", instr_addr);
@@ -379,32 +380,41 @@
// for generated code in anonymous space, pSegInfo is 0
}
- found1 = VG_(get_filename_linenum)(instr_addr,
- filename, FILENAME_LEN,
- NULL, 0, NULL, // FIXME: add dirnames!
- &line);
- found2 = VG_(get_fnname)(instr_addr,
- fn_name, FN_NAME_LEN);
+ found_file_line = VG_(get_filename_linenum)(instr_addr,
+ file, FILENAME_LEN,
+ dir, FILENAME_LEN,
+ &found_dirname,
+ &line);
+ found_fn = VG_(get_fnname)(instr_addr,
+ fn_name, FN_NAME_LEN);
- if (!found1 && !found2) {
+ if (found_dirname) {
+ // +1 for the '/'.
+ CLG_ASSERT(VG_(strlen)(dir) + VG_(strlen)(file) + 1 < FILENAME_LEN);
+ VG_(strcat)(dir, "/"); // Append '/'
+ VG_(strcat)(dir, file); // Append file to dir
+ VG_(strcpy)(file, dir); // Move dir+file to file
+ }
+
+ if (!found_file_line && !found_fn) {
CLG_(stat).no_debug_BBs++;
- VG_(strcpy)(filename, "???");
+ VG_(strcpy)(file, "???");
VG_(strcpy)(fn_name, "???");
if (line_num) *line_num=0;
result = False;
- } else if ( found1 && found2) {
+ } else if ( found_file_line && found_fn) {
CLG_(stat).full_debug_BBs++;
if (line_num) *line_num=line;
- } else if ( found1 && !found2) {
+ } else if ( found_file_line && !found_fn) {
CLG_(stat).file_line_debug_BBs++;
VG_(strcpy)(fn_name, "???");
if (line_num) *line_num=line;
- } else /*(!found1 && found2)*/ {
+ } else /*(!found_file_line && found_fn)*/ {
CLG_(stat).fn_name_debug_BBs++;
- VG_(strcpy)(filename, "???");
+ VG_(strcpy)(file, "???");
if (line_num) *line_num=0;
}
|
|
From: Josef W. <Jos...@gm...> - 2007-09-17 12:29:00
|
On Monday 17 September 2007, sv...@va... wrote:
> Author: njn
> Date: 2007-09-17 01:41:07 +0100 (Mon, 17 Sep 2007)
> New Revision: 6839
>
> Log:
> Add directory-reading of debug info to cachegrind.
Hi Nick,
thanks for doing this. Exactly the same change works perfectly also
in callgrind.
When testing it, source annotation worked out of the box
with KCachegrind, but also with the callgrind_annotate script.
Therefore I wondered about your change...
> Modified: trunk/cachegrind/cg_annotate.in
> ===================================================================
> --- trunk/cachegrind/cg_annotate.in 2007-09-17 00:33:52 UTC (rev 6838)
> +++ trunk/cachegrind/cg_annotate.in 2007-09-17 00:41:07 UTC (rev 6839)
> @@ -747,7 +747,9 @@
>
> my $opened_file = "";
> my $full_file_name = "";
> - foreach my $include_dir (@include_dirs) {
> + # We first try it with the empty include_dir, in case the filename has
> + # the full path.
> + foreach my $include_dir ("", @include_dirs) {
This seems to not be needed, as @include_dir is initialized as
...
my @include_dirs = ("");
...
Ie. the emty entry is already there.
Josef
|
|
From: <sv...@va...> - 2007-09-17 09:55:00
|
Author: sewardj
Date: 2007-09-17 10:54:57 +0100 (Mon, 17 Sep 2007)
New Revision: 6849
Log:
Minimal glibc-2.3 support.
Modified:
branches/THRCHECK/glibc-2.3.supp
branches/THRCHECK/thrcheck/tests/tc10_rec_lock.c
Modified: branches/THRCHECK/glibc-2.3.supp
===================================================================
--- branches/THRCHECK/glibc-2.3.supp 2007-09-17 07:42:15 UTC (rev 6848)
+++ branches/THRCHECK/glibc-2.3.supp 2007-09-17 09:54:57 UTC (rev 6849)
@@ -610,3 +610,39 @@
obj:/lib/libpthread-0.10.so
fun:pthread_create
}
+
+##----------------------------------------------------------------------##
+# Suppressions for the Thrcheck tool
+
+###--- ld.so stuff ---###
+{
+ thrcheck-glibc23-ldso-1
+ Thrcheck:Race
+ fun:_dl_lookup_symbol_x
+ fun:fixup
+ fun:_dl_runtime_resolve
+}
+
+###--- pthread_join ---###
+{
+ thrcheck-glibc23-pthjoin-1
+ Thrcheck:Race
+ fun:pthread_join
+ fun:pthread_join
+}
+
+###--- pthread_mutex_lock ---###
+{
+ thrcheck-glibc23-pthmxlock-1
+ Thrcheck:Race
+ fun:pthread_mutex_lock
+ fun:pthread_mutex_lock
+}
+
+###--- pthread_create ---###
+{
+ thrcheck-glibc23-pthcreate-1
+ Thrcheck:Race
+ fun:pthread_create@@GLIBC_*
+ fun:pthread_create@*
+}
Modified: branches/THRCHECK/thrcheck/tests/tc10_rec_lock.c
===================================================================
--- branches/THRCHECK/thrcheck/tests/tc10_rec_lock.c 2007-09-17 07:42:15 UTC (rev 6848)
+++ branches/THRCHECK/thrcheck/tests/tc10_rec_lock.c 2007-09-17 09:54:57 UTC (rev 6849)
@@ -5,6 +5,20 @@
#include <stdlib.h>
#include <assert.h>
+
+
+/* glibc 2.3 doesn't appear to supply PTHREAD_MUTEX_RECURSIVE.
+ We have to give up. */
+#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)
+int main ( void ) {
+ printf("This program does not compile on systems "
+ "using glibc 2.3 or earlier.\n");
+ return 0;
+}
+#else
+
+
+
#define __USE_UNIX98 1
#include <pthread.h>
@@ -44,3 +58,6 @@
nearly_main();
return 0;
}
+
+
+#endif /* !(glibc 2.3 or earlier) */
|
|
From: <sv...@va...> - 2007-09-17 07:42:14
|
Author: njn
Date: 2007-09-17 08:42:15 +0100 (Mon, 17 Sep 2007)
New Revision: 6848
Log:
Remove the --<pid> and --massif-out-file options. Just specify the file
name as a normal argument.
Modified:
branches/MASSIF2/massif/ms_print
Modified: branches/MASSIF2/massif/ms_print
===================================================================
--- branches/MASSIF2/massif/ms_print 2007-09-17 07:29:34 UTC (rev 6847)
+++ branches/MASSIF2/massif/ms_print 2007-09-17 07:42:15 UTC (rev 6848)
@@ -126,17 +126,15 @@
# Usage message.
my $usage = <<END
-usage: ms_print [options]
+usage: ms_print [options] <file>
options for the user, with defaults in [ ], are:
-h --help show this message
-v --version show version
- --<pid> read profile data from massif.<pid>
- --massif-out-file=<file> read profile data from <file>
--threshold=<n> significance threshold, in percent [$threshold]
- You must use either --<pid> or --massif-out-file exactly once
- in order that ms_print knows what file to read profile data from.
+ You must use either --<pid> or specify exactly one profile file
+ so that ms_print knows what file to read profile data from.
ms_print is Copyright (C) 2007-2007 Nicholas Nethercote.
and licensed under the GNU General Public License, version 2.
@@ -153,6 +151,7 @@
#-----------------------------------------------------------------------------
sub process_cmd_line()
{
+ my @files;
for my $arg (@ARGV) {
# Option handling
@@ -167,33 +166,19 @@
$threshold = $1;
($1 >= 0 && $1 <= 100) or die($usage);
- # --massif-out-file=<filename>
- } elsif ($arg =~ /^--massif-out-file=(.*)$/) {
- if (not defined $input_file) {
- $input_file = $1;
- } else {
- die("You may only specify one input file\n" .
- "using the --<pid> and --massif-out-file options.\n");
- }
-
- # --<pid>
- } elsif ($arg =~ /^--(\d+)$/) {
- my $pid = $1;
- if (not defined $input_file) {
- $input_file = "massif.$pid";
- } else {
- die("You may only specify one input file\n" .
- "using the --<pid> and --massif-out-file options.\n");
- }
-
} else { # -h and --help fall under this case
die($usage);
}
+ } else {
+ # Not an option. Remember it as a filename.
+ push(@files, $arg);
}
}
- # Must have chosen an input file
- if (not defined $input_file) {
+ # Must have chosen exactly one input file.
+ if (scalar @files) {
+ $input_file = $files[0];
+ } else {
die($usage);
}
}
|
|
From: <sv...@va...> - 2007-09-17 07:29:33
|
Author: njn
Date: 2007-09-17 08:29:34 +0100 (Mon, 17 Sep 2007)
New Revision: 6847
Log:
Remove remaining assumptions that time is measured in milliseconds.
Modified:
branches/MASSIF2/massif/ms_main.c
branches/MASSIF2/massif/ms_print
Modified: branches/MASSIF2/massif/ms_main.c
===================================================================
--- branches/MASSIF2/massif/ms_main.c 2007-09-17 07:15:15 UTC (rev 6846)
+++ branches/MASSIF2/massif/ms_main.c 2007-09-17 07:29:34 UTC (rev 6847)
@@ -1492,8 +1492,7 @@
P("#--------------------------------\n");
P("snapshot=%d\n", snapshot_n);
P("#--------------------------------\n");
- // XXX: shouldn't print 'time_ms' now that time can be measured in bytes.
- P("time_ms=%lu\n", snapshot->time);
+ P("time=%lu\n", snapshot->time);
P("mem_total_B=%lu\n", snapshot->total_szB);
P("mem_heap_B=%lu\n", snapshot->heap_szB);
P("mem_heap_admin_B=%lu\n", snapshot->heap_admin_szB);
@@ -1540,6 +1539,10 @@
}
P("\n");
+ P("time_unit: ");
+ if (clo_time_unit == TimeMS) P("ms\n");
+ else if (clo_time_unit == TimeB) P("B\n");
+ else tl_assert2(0, "bad --time-unit value");
for (i = 0; i < next_snapshot; i++) {
Snapshot* snapshot = & snapshots[i];
Modified: branches/MASSIF2/massif/ms_print
===================================================================
--- branches/MASSIF2/massif/ms_print 2007-09-17 07:15:15 UTC (rev 6846)
+++ branches/MASSIF2/massif/ms_print 2007-09-17 07:29:34 UTC (rev 6847)
@@ -111,6 +111,9 @@
# Command line of profiled program.
my $cmd;
+# Time unit used in profile.
+my $time_unit;
+
# Threshold dictating what percentage an entry must represent for us to
# bother showing it.
my $threshold = 1.0;
@@ -308,7 +311,7 @@
{
my $desc = ""; # Concatenated description lines.
my @snapshot_nums = ();
- my @time_mss = ();
+ my @times = ();
my @mem_total_Bs = ();
my @is_detaileds = ();
my $peak_mem_total_szB = 0;
@@ -327,15 +330,22 @@
}
# Read "cmd:" line (Nb: will already be in $line from "desc:" loop above).
- ($line =~ /^cmd:\s*(.*)$/) or die("Line $.: missing command line\n");
+ ($line =~ /^cmd:\s*(.*)$/) or
+ die("Line $.: missing 'cmd' line\n");
$cmd = $1;
+ # Read "time_unit:" line.
+ $line = get_line();
+ ($line =~ /^time_unit:\s*(.*)$/) or
+ die("Line $.: missing 'time_unit' line\n");
+ $time_unit = $1;
+
# Read body of input file.
$line = get_line();
while (defined $line) {
# XXX: equals_num_line vs get_equals_num_line is ugly
my $snapshot_num = equals_num_line($line, "snapshot");
- my $time_ms = get_equals_num_line("time_ms");
+ my $time = get_equals_num_line("time");
my $mem_total_B = get_equals_num_line("mem_total_B");
my $mem_heap_B = get_equals_num_line("mem_heap_B");
my $mem_heap_admin_B = get_equals_num_line("mem_heap_admin_B");
@@ -354,7 +364,7 @@
# Remember the pertinent information
push(@snapshot_nums, $snapshot_num);
- push(@time_mss, $time_ms);
+ push(@times, $time);
push(@mem_total_Bs, $mem_total_B);
push(@is_detaileds, ( $heap_tree eq "empty" ? 0 : 1 ));
$peak_mem_total_szB = $mem_total_B
@@ -391,8 +401,8 @@
# before it, and doesn't spill over into the final column.
my $n_snapshots = scalar(@snapshot_nums);
($n_snapshots > 0) or die;
- my $end_time_ms = $time_mss[$n_snapshots-1] + 1;
- ($end_time_ms > 0) or die;
+ my $end_time = $times[$n_snapshots-1] + 1;
+ ($end_time > 0) or die;
# Setup graph[][].
$graph[0][0] = '+'; # axes join point
@@ -415,7 +425,7 @@
my $per_row_half_thresh_szB = $per_row_full_thresh_szB / 2;
# Work out which column this snapshot belongs to.
- my $x_pos_frac = ($time_mss[$i] / $end_time_ms) * $GRAPH_X;
+ my $x_pos_frac = ($times[$i] / $end_time) * $GRAPH_X;
$x = int($x_pos_frac) + 1; # +1 due to y-axis
# Draw the column only if it's a detailed snapshot, or we don't already
@@ -489,9 +499,8 @@
print("\n");
for (my $i = 0; $i < $n_snapshots; $i++) {
# XXX: adjust the column widths dynamically
- # XXX: assuming ms as the time-unit
- printf(" snapshot %3d: t = %12s ms, size = %12s bytes\n",
- $snapshot_nums[$i], commify($time_mss[$i]),
+ printf(" snapshot %3d: t = %12s $time_unit, size = %12s bytes\n",
+ $snapshot_nums[$i], commify($times[$i]),
commify($mem_total_Bs[$i]));
}
print("\n");
@@ -520,12 +529,17 @@
# Read "cmd:" line (Nb: will already be in $line from "desc:" loop above).
($line =~ /^cmd:\s*(.*)$/) or die("Line $.: missing command line\n");
+ # Read "time_unit:" line.
+ $line = get_line();
+ ($line =~ /^time_unit:\s*(.*)$/) or
+ die("Line $.: missing 'time_unit' line\n");
+
# Read body of input file.
$line = get_line();
while (defined $line) {
# XXX: equals_num_line vs get_equals_num_line is ugly
my $snapshot_num = equals_num_line($line, "snapshot");
- my $time_ms = get_equals_num_line("time_ms");
+ my $time = get_equals_num_line("time");
my $mem_total_B = get_equals_num_line("mem_total_B");
my $mem_heap_B = get_equals_num_line("mem_heap_B");
my $mem_heap_admin_B = get_equals_num_line("mem_heap_admin_B");
@@ -534,8 +548,8 @@
# Print snapshot header.
printf("=================================\n");
- # XXX: assuming ms as the time-unit
- printf("== snapshot $snapshot_num (%s ms)\n", commify($time_ms));
+ printf("== snapshot $snapshot_num (%s $time_unit)\n",
+ commify($time));
printf("=================================\n");
printf("Total memory usage: %12s bytes\n", commify($mem_total_B));
printf("Useful heap usage : %12s bytes\n", commify($mem_heap_B));
|
|
From: <sv...@va...> - 2007-09-17 07:15:16
|
Author: njn
Date: 2007-09-17 08:15:15 +0100 (Mon, 17 Sep 2007)
New Revision: 6846
Log:
Allow time to be measured either in milliseconds or bytes
allocated/deallocated on the heap. The latter will be very useful for
testing as it allows deterministic runs. There are still some places that
talk about 'ms' that should be parameterised.
Modified:
branches/MASSIF2/massif/ms_main.c
branches/MASSIF2/massif/ms_print
Modified: branches/MASSIF2/massif/ms_main.c
===================================================================
--- branches/MASSIF2/massif/ms_main.c 2007-09-17 06:43:58 UTC (rev 6845)
+++ branches/MASSIF2/massif/ms_main.c 2007-09-17 07:15:15 UTC (rev 6846)
@@ -266,7 +266,10 @@
typedef
struct {
- Int time_ms; // Int: must allow -1.
+ // Time is measured either in ms or bytes, depending on the
+ // --time-unit option. It's a Long because it can get very big with
+ // --time-unit=ms.
+ Long time; // Long: must allow -1.
SizeT total_szB; // Size of all allocations at that snapshot time.
SizeT heap_admin_szB;
SizeT heap_szB;
@@ -331,6 +334,11 @@
static SSizeT peak_heap_szB = 0; // XXX: currently unused
static SSizeT peak_snapshot_total_szB = 0;
+// Incremented every time memory is allocated/deallocated, by the
+// allocated/deallocated amount. An alternative unit of program progress to
+// time.
+static ULong total_allocs_deallocs_szB = 0;
+
static VgHashTable malloc_list = NULL; // HP_Chunks
static UInt n_heap_blocks = 0;
@@ -395,11 +403,14 @@
#define MAX_DEPTH 50
+typedef enum { TimeMS, TimeB } TimeUnit;
+
static Bool clo_heap = True;
static UInt clo_heap_admin = 8;
static Bool clo_stacks = True;
static Bool clo_depth = 8;
static UInt clo_threshold = 100; // 100 == 1%
+static UInt clo_time_unit = TimeMS;
static Bool ms_process_cmd_line_option(Char* arg)
{
@@ -411,6 +422,9 @@
else VG_NUM_CLO(arg, "--threshold", clo_threshold)
+ else if (VG_CLO_STREQ(arg, "--time-unit=ms")) clo_time_unit = TimeMS;
+ else if (VG_CLO_STREQ(arg, "--time-unit=B")) clo_time_unit = TimeB;
+
else if (VG_CLO_STREQN(11, arg, "--alloc-fn=")) {
VG_(OSetWord_Insert)(alloc_fns, (Word) & arg[11]);
}
@@ -432,6 +446,8 @@
" --threshold=<n> significance threshold, in 100ths of a percent\n"
" (eg. <n>=100 shows nodes covering >= 1%% of\n"
" total size, <n>=0 shows all nodes) [100]\n"
+" --time-unit=ms|B time unit, milliseconds or bytes\n"
+" alloc'd/dealloc'd on the heap [ms]\n"
);
VG_(replacement_malloc_print_usage)();
}
@@ -650,7 +666,7 @@
Bool should_hide_below_main = /*!VG_(clo_show_below_main)*/True;
// We ask for a few more IPs than clo_depth suggests we need. Then we
- // remove every entry that is an alloc-fns or above an alloc-fn, and
+ // remove every entry that is an alloc-fn or above an alloc-fn, and
// remove anything below main-or-below-main functions. Depending on the
// circumstances, we may need to redo it all, asking for more IPs.
// Details:
@@ -710,7 +726,8 @@
}
n_alloc_fns_removed = i+1;
- for (j = 0; j < n_ips; j++) { // Shuffle the rest down.
+ // Shuffle the rest down.
+ for (j = 0; j < n_ips; j++) {
ips[j] = ips[j + n_alloc_fns_removed];
}
n_ips -= n_alloc_fns_removed;
@@ -719,7 +736,7 @@
}
}
- // Must be at least one alloc function, unless client used
+ // There must be at least one alloc function, unless client used
// MALLOCLIKE_BLOCK.
if (!is_custom_malloc)
tl_assert2(n_alloc_fns_removed > 0,
@@ -736,7 +753,6 @@
enough_IPs_after_filtering)
{
return n_ips;
-
} else {
n_getXCon_redo++;
}
@@ -811,8 +827,8 @@
static Bool is_snapshot_in_use(Snapshot* snapshot)
{
- if (-1 == snapshot->time_ms) {
- // If .time_ms looks unused, check everything else is.
+ if (-1 == snapshot->time) {
+ // If .time looks unused, check everything else is.
tl_assert(snapshot->total_szB == 0);
tl_assert(snapshot->heap_admin_szB == 0);
tl_assert(snapshot->heap_szB == 0);
@@ -855,7 +871,7 @@
static void clear_snapshot(Snapshot* snapshot)
{
sanity_check_snapshot(snapshot);
- snapshot->time_ms = -1;
+ snapshot->time = -1;
snapshot->total_szB = 0;
snapshot->heap_admin_szB = 0;
snapshot->heap_szB = 0;
@@ -915,7 +931,7 @@
FIND_SNAPSHOT(1, j);
FIND_SNAPSHOT(j+1, jn);
while (jn < MAX_N_SNAPSHOTS) {
- Int timespan = snapshots[jn].time_ms - snapshots[jp].time_ms;
+ Int timespan = snapshots[jn].time - snapshots[jp].time;
tl_assert(timespan >= 0);
if (timespan < min_span) {
min_span = timespan;
@@ -957,18 +973,25 @@
// [XXX: is that still true?]
static void take_snapshot(void)
{
- static UInt interval_ms = 5;
- static UInt ms_prev_snapshot = 0;
- static UInt ms_next_snapshot = 0; // zero allows startup snapshot
+ static UInt time_interval = 5;
+ static UInt time_of_prev_snapshot = 0;
+ static UInt time_of_next_snapshot = 0; // zero allows startup snapshot
static Int n_snapshots_since_last_detailed = 0;
- Int time_ms, time_ms_since_prev;
+ Int time, time_since_prev, time_ms;
Snapshot* snapshot;
+ // For measuring how long the snapshot took (used with -v).
+ time_ms = VG_(read_millisecond_timer)();
+
+ // Get current time, in whatever time unit we're using.
+ if (clo_time_unit == TimeMS) time = VG_(read_millisecond_timer)();
+ else if (clo_time_unit == TimeB) time = total_allocs_deallocs_szB;
+ else tl_assert2(0, "bad --time-unit value");
+
// Only do a snapshot if it's time.
- time_ms = VG_(read_millisecond_timer)();
- time_ms_since_prev = time_ms - ms_prev_snapshot;
- if (time_ms < ms_next_snapshot) {
+ time_since_prev = time - time_of_prev_snapshot;
+ if (time < time_of_next_snapshot) {
n_fake_snapshots++;
return;
}
@@ -1009,7 +1032,7 @@
}
// Finish writing snapshot ------------------------------------------
- snapshot->time_ms = time_ms;
+ snapshot->time = time;
snapshot->total_szB =
snapshot->heap_szB + snapshot->heap_admin_szB + snapshot->stacks_szB;
@@ -1031,7 +1054,7 @@
// Halve the entries, if our snapshot table is full
if (MAX_N_SNAPSHOTS == next_snapshot) {
halve_snapshots();
- interval_ms *= 2;
+ time_interval *= 2;
}
// Take time for next snapshot from now, rather than when this snapshot
@@ -1039,11 +1062,11 @@
// operation, there's no point doing catch-up snapshots every allocation
// for a while -- that would just give N snapshots at almost the same time.
if (VG_(clo_verbosity) > 1) {
- VG_(message)(Vg_DebugMsg, "snapshot: %d ms (took %d ms)", time_ms,
+ VG_(message)(Vg_DebugMsg, "snapshot: %d %s (took %d ms)", time_ms,
VG_(read_millisecond_timer)() - time_ms );
}
- ms_prev_snapshot = time_ms;
- ms_next_snapshot = time_ms + interval_ms;
+ time_of_prev_snapshot = time;
+ time_of_next_snapshot = time + time_interval;
}
@@ -1078,6 +1101,9 @@
if (heap_szB > peak_heap_szB) {
peak_heap_szB = heap_szB;
}
+
+ if (heap_szB_delta < 0) total_allocs_deallocs_szB -= heap_szB_delta;
+ if (heap_szB_delta > 0) total_allocs_deallocs_szB += heap_szB_delta;
}
static
@@ -1466,7 +1492,8 @@
P("#--------------------------------\n");
P("snapshot=%d\n", snapshot_n);
P("#--------------------------------\n");
- P("time_ms=%lu\n", snapshot->time_ms);
+ // XXX: shouldn't print 'time_ms' now that time can be measured in bytes.
+ P("time_ms=%lu\n", snapshot->time);
P("mem_total_B=%lu\n", snapshot->total_szB);
P("mem_heap_B=%lu\n", snapshot->heap_szB);
P("mem_heap_admin_B=%lu\n", snapshot->heap_admin_szB);
Modified: branches/MASSIF2/massif/ms_print
===================================================================
--- branches/MASSIF2/massif/ms_print 2007-09-17 06:43:58 UTC (rev 6845)
+++ branches/MASSIF2/massif/ms_print 2007-09-17 07:15:15 UTC (rev 6846)
@@ -257,7 +257,7 @@
# We precede this node's line with "$this_prefix.$arrow". We precede
# any children of this node with "$this_prefix$child_midfix$arrow".
if ($print && $is_significant) {
- printf("$this_prefix$arrow%05.2f%% $is_significant(${bytes}B)$details\n", $perc);
+ printf("$this_prefix$arrow%05.2f%% (${bytes}B)$details\n", $perc);
}
# Now read all the children.
@@ -488,7 +488,8 @@
#-------------------------------------------------------------------------
print("\n");
for (my $i = 0; $i < $n_snapshots; $i++) {
- # XXX adjust the column widths dynamically
+ # XXX: adjust the column widths dynamically
+ # XXX: assuming ms as the time-unit
printf(" snapshot %3d: t = %12s ms, size = %12s bytes\n",
$snapshot_nums[$i], commify($time_mss[$i]),
commify($mem_total_Bs[$i]));
@@ -533,6 +534,7 @@
# Print snapshot header.
printf("=================================\n");
+ # XXX: assuming ms as the time-unit
printf("== snapshot $snapshot_num (%s ms)\n", commify($time_ms));
printf("=================================\n");
printf("Total memory usage: %12s bytes\n", commify($mem_total_B));
|
|
From: <sv...@va...> - 2007-09-17 06:43:57
|
Author: njn
Date: 2007-09-17 07:43:58 +0100 (Mon, 17 Sep 2007)
New Revision: 6845
Log:
When drawing the graph, don't overwrite the bars of detailed snapshots with
those of non-detailed snapshots.
Modified:
branches/MASSIF2/massif/ms_print
Modified: branches/MASSIF2/massif/ms_print
===================================================================
--- branches/MASSIF2/massif/ms_print 2007-09-17 06:01:55 UTC (rev 6844)
+++ branches/MASSIF2/massif/ms_print 2007-09-17 06:43:58 UTC (rev 6845)
@@ -371,7 +371,7 @@
print($fancy);
print("Command: $cmd\n");
print("Data file: $input_file\n");
- print($desc);
+ print("Description: $desc\n");
print("\n");
#-------------------------------------------------------------------------
@@ -395,18 +395,19 @@
($end_time_ms > 0) or die;
# Setup graph[][].
- $graph[0][0] = '+'; # axes join point
- for ($x = 1; $x <= $GRAPH_X; $x++) { $graph[$x][0] = '-'; } # x-axis
- for ($y = 1; $y <= $GRAPH_Y; $y++) { $graph[0][$y] = '|'; } # y-axis
- for ($x = 1; $x <= $GRAPH_X; $x++) { # usable area
+ $graph[0][0] = '+'; # axes join point
+ for ($x = 1; $x <= $GRAPH_X; $x++) { $graph[$x][0] = '-'; } # x-axis
+ for ($y = 1; $y <= $GRAPH_Y; $y++) { $graph[0][$y] = '|'; } # y-axis
+ for ($x = 1; $x <= $GRAPH_X; $x++) { # usable area
for ($y = 1; $y <= $GRAPH_Y; $y++) {
$graph[$x][$y] = ' ';
}
}
+ my $detailed_char = '@';
+ my $normal_char = ':';
+
# Write snapshot bars into graph[][].
- # XXX: many detailed snapshot bars are being overwritten by non-detailed
- # bars
for (my $i = 0; $i < $n_snapshots; $i++) {
# Work out how many bytes each row represents.
@@ -417,24 +418,32 @@
my $x_pos_frac = ($time_mss[$i] / $end_time_ms) * $GRAPH_X;
$x = int($x_pos_frac) + 1; # +1 due to y-axis
- # Grow this snapshot bar from bottom to top.
- for ($y = 1; $y <= $GRAPH_Y; $y++) {
- my $this_row_full_thresh_szB = $y * $per_row_full_thresh_szB;
- my $this_row_half_thresh_szB =
- $this_row_full_thresh_szB - $per_row_half_thresh_szB;
-
- $graph[$x][$y] = ' ';
- if ($mem_total_Bs[$i] >= $this_row_half_thresh_szB) {
- $graph[$x][$y] = '.';
+ # Draw the column only if it's a detailed snapshot, or we don't already
+ # have a detailed snapshot's bar in this column -- we don't want to
+ # overwrite detailed snapshot's bars with non-detailed snapshot's bars.
+ my $should_draw_column =
+ ($is_detaileds[$i] or $graph[$x][0] ne $detailed_char
+ ? 1 : 0);
+ if ($should_draw_column == 1) {
+ # If it's detailed, mark the x-axis
+ if ($is_detaileds[$i]) {
+ $graph[$x][0] = $detailed_char;
}
- if ($mem_total_Bs[$i] >= $this_row_full_thresh_szB) {
- $graph[$x][$y] = ( $is_detaileds[$i] ? '|' : ':' );
+ # Grow this snapshot bar from bottom to top.
+ for ($y = 1; $y <= $GRAPH_Y; $y++) {
+ my $this_row_full_thresh_szB = $y * $per_row_full_thresh_szB;
+ my $this_row_half_thresh_szB =
+ $this_row_full_thresh_szB - $per_row_half_thresh_szB;
+
+ if ($mem_total_Bs[$i] >= $this_row_half_thresh_szB) {
+ $graph[$x][$y] = '.';
+ }
+ if ($mem_total_Bs[$i] >= $this_row_full_thresh_szB) {
+ $graph[$x][$y] = ( $is_detaileds[$i]
+ ? $detailed_char : $normal_char );
+ }
}
}
- # If it's detailed, mark the x-axis
- if ($is_detaileds[$i]) {
- $graph[$x][0] = '|';
- }
}
# Work out the units for the $y-axis.
|
|
From: <sv...@va...> - 2007-09-17 06:01:53
|
Author: njn
Date: 2007-09-17 07:01:55 +0100 (Mon, 17 Sep 2007)
New Revision: 6844
Log:
- Tweak some comments.
- Use an OSet for the alloc-fns, so as to avoid a limit in their number.
Modified:
branches/MASSIF2/massif/ms_main.c
Modified: branches/MASSIF2/massif/ms_main.c
===================================================================
--- branches/MASSIF2/massif/ms_main.c 2007-09-17 05:45:40 UTC (rev 6843)
+++ branches/MASSIF2/massif/ms_main.c 2007-09-17 06:01:55 UTC (rev 6844)
@@ -77,7 +77,7 @@
// 142197 nor massif tool ignores --massif:alloc-fn parameters in .valg...
// - fixed in trunk
// 142491 nor Maximise use of alloc_fns array
-// - addressed, using the patch (with minor changes) from the bug report
+// - addressed, it's now an OSet and thus unlimited in size
// 89061 cra Massif: ms_main.c:485 (get_XCon): Assertion `xpt->max_chi...
// - relevant code now gone
//
@@ -148,6 +148,7 @@
#include "pub_tool_machine.h"
#include "pub_tool_mallocfree.h"
#include "pub_tool_options.h"
+#include "pub_tool_oset.h"
#include "pub_tool_replacemalloc.h"
#include "pub_tool_stacktrace.h"
#include "pub_tool_tooliface.h"
@@ -204,13 +205,13 @@
// It's a bit of a fake XPt (ie. its 'ip' is zero), and is only used because
// it makes the code simpler.
//
-// Any child of 'alloc_xpt' is called a "top-XPt". The XPts are the bottom
-// of an XTree (leaf nodes) are "bottom-XPTs". The number of XCons in an
-// XTree is equal to the number of bottom-XPTs in that XTree.
+// Any child of 'alloc_xpt' is called a "top-XPt". The XPts at the bottom
+// of an XTree (leaf nodes) are "bottom-XPTs".
//
// Each path from a top-XPt to a bottom-XPt through an XTree gives an
// execution context ("XCon"), ie. a stack trace. (And sub-paths represent
-// stack sub-traces.)
+// stack sub-traces.) The number of XCons in an XTree is equal to the
+// number of bottom-XPTs in that XTree.
//
// alloc_xpt XTrees are bi-directional.
// | ^
@@ -222,7 +223,7 @@
// child1 child2
//
// Sanity checking: we check snapshot XTrees when they are taken, deleted
-// and printed. We periodically check the main heap XTree periodically via
+// and printed. We periodically check the main heap XTree with
// ms_expensive_sanity_check.
typedef struct _XPt XPt;
@@ -238,9 +239,9 @@
XPt* parent; // pointer to parent XPt
// Children.
- // n_children and max_children are 32-bit integers, not 16-bit, because
- // a very big program might have more than 65536 allocation points (ie.
- // top-XPts) -- Konqueror starting up has 1800.
+ // n_children and max_children are 32-bit integers. 16-bit integers
+ // are too small -- a very big program might have more than 65536
+ // allocation points (ie. top-XPts) -- Konqueror starting up has 1800.
UInt n_children; // number of children
UInt max_children; // capacity of children array
XPt** children; // pointers to children XPts
@@ -279,8 +280,7 @@
// HP_Chunks, XPt 'space' fields are incremented (at allocation) and
// decremented (at deallocation).
//
-// Nb: first two fields must match core's VgHashNode. [XXX: is that still
-// true?]
+// Nb: first two fields must match core's VgHashNode.
typedef
struct _HP_Chunk {
struct _HP_Chunk* next;
@@ -340,7 +340,10 @@
#define MAX_ALLOC_FNS 128 // includes the builtin ones
-// First few filled in, rest should be zeroed. Zero-terminated vector.
+//------------------------------------------------------------//
+//--- Alloc fns ---//
+//------------------------------------------------------------//
+
// Nb: I used to have the following four C++ global overloadable allocators
// in alloc_fns:
// operator new(unsigned)
@@ -355,17 +358,37 @@
// ]
// But someone might be interested in seeing them. If they're not, they can
// specify them with --alloc-fn.
-static UInt n_alloc_fns = 6;
-static Char* alloc_fns[MAX_ALLOC_FNS] = {
- "malloc",
- "__builtin_new",
- "__builtin_vec_new",
- "calloc",
- "realloc",
- "memalign",
-};
+OSet* alloc_fns;
+static void init_alloc_fns(void)
+{
+ // Create the OSet, and add the default elements.
+ alloc_fns = VG_(OSetWord_Create)(VG_(malloc), VG_(free));
+ #define DO(x) VG_(OSetWord_Insert)(alloc_fns, (Word)x);
+ DO("malloc" );
+ DO("calloc" );
+ DO("realloc" );
+ DO("memalign" );
+ DO("__builtin_new" );
+ DO("__builtin_vec_new");
+}
+
+static Bool is_alloc_fn(Char* fnname)
+{
+ Word alloc_fn_word;
+
+ // Nb: It's a linear search through the list, because we're comparing
+ // strings rather than pointers to strings.
+ VG_(OSetWord_ResetIter)(alloc_fns);
+ while ( VG_(OSetWord_Next)(alloc_fns, &alloc_fn_word) ) {
+ if (VG_STREQ(fnname, (Char*)alloc_fn_word))
+ return True;
+ }
+ return False;
+}
+
+
//------------------------------------------------------------//
//--- Command line args ---//
//------------------------------------------------------------//
@@ -389,21 +412,7 @@
else VG_NUM_CLO(arg, "--threshold", clo_threshold)
else if (VG_CLO_STREQN(11, arg, "--alloc-fn=")) {
- int i;
-
- // Check first if the function is already present.
- for (i = 0; i < n_alloc_fns; i++) {
- if ( VG_STREQ(alloc_fns[i], & arg[11]) )
- return True;
- }
- // Abort if we reached the limit.
- if (n_alloc_fns >= MAX_ALLOC_FNS) {
- VG_(printf)("Too many alloc functions specified, sorry");
- VG_(err_bad_option)(arg);
- }
- // Ok, add the function.
- alloc_fns[n_alloc_fns] = & arg[11];
- n_alloc_fns++;
+ VG_(OSetWord_Insert)(alloc_fns, (Word) & arg[11]);
}
else
@@ -613,27 +622,13 @@
#define MAX_OVERESTIMATE 50
#define MAX_IPS (MAX_DEPTH + MAX_OVERESTIMATE)
-static Bool is_alloc_fn(Char* fnname)
-{
- Int i;
- for (i = 0; i < n_alloc_fns; i++) {
- if (VG_STREQ(fnname, alloc_fns[i]))
- return True;
- }
- return False;
-}
-
// XXX: look at the "(below main)"/"__libc_start_main" mess (m_stacktrace.c
// and m_demangle.c). Don't hard-code "(below main)" in here.
// [Nb: Josef wants --show-below-main to work for his fn entry/exit tracing]
static Bool is_main_or_below_main(Char* fnname)
{
- Int i;
-
- for (i = 0; i < n_alloc_fns; i++) {
- if (VG_STREQ(fnname, "main")) return True;
- if (VG_STREQ(fnname, "(below main)")) return True;
- }
+ if (VG_STREQ(fnname, "main")) return True;
+ if (VG_STREQ(fnname, "(below main)")) return True;
return False;
}
@@ -726,7 +721,9 @@
// Must be at least one alloc function, unless client used
// MALLOCLIKE_BLOCK.
- if (!is_custom_malloc) tl_assert(n_alloc_fns_removed > 0);
+ if (!is_custom_malloc)
+ tl_assert2(n_alloc_fns_removed > 0,
+ "n_alloc_fns_removed = %s\n", n_alloc_fns_removed);
// Did we get enough IPs after filtering? If so, redo=False.
if (n_ips >= clo_depth) {
@@ -1565,11 +1562,15 @@
static void ms_post_clo_init(void)
{
- Int i;
+ Int i = 1;
+ Word alloc_fn_word;
+
if (VG_(clo_verbosity) > 1) {
VG_(message)(Vg_DebugMsg, "alloc-fns:");
- for (i = 0; i < n_alloc_fns; i++) {
- VG_(message)(Vg_DebugMsg, " %d: %s", i, alloc_fns[i]);
+ VG_(OSetWord_ResetIter)(alloc_fns);
+ while ( VG_(OSetWord_Next)(alloc_fns, &alloc_fn_word) ) {
+ VG_(message)(Vg_DebugMsg, " %d: %s", i, (Char*)alloc_fn_word);
+ i++;
}
}
@@ -1629,6 +1630,9 @@
}
sanity_check_snapshots_array();
+ // Initialise alloc_fns.
+ init_alloc_fns();
+
tl_assert( VG_(getcwd)(base_dir, VKI_PATH_MAX) );
}
|
|
From: <sv...@va...> - 2007-09-17 05:45:43
|
Author: njn
Date: 2007-09-17 06:45:40 +0100 (Mon, 17 Sep 2007)
New Revision: 6843
Log:
Merge r6841 (split OSet interface in two) from trunk.
Modified:
branches/MASSIF2/cachegrind/cg_main.c
branches/MASSIF2/coregrind/m_debuginfo/readelf.c
branches/MASSIF2/coregrind/m_oset.c
branches/MASSIF2/coregrind/m_redir.c
branches/MASSIF2/include/pub_tool_oset.h
branches/MASSIF2/memcheck/mc_main.c
branches/MASSIF2/memcheck/tests/oset_test.c
branches/MASSIF2/memcheck/tests/oset_test.stdout.exp
Modified: branches/MASSIF2/cachegrind/cg_main.c
===================================================================
--- branches/MASSIF2/cachegrind/cg_main.c 2007-09-17 05:35:10 UTC (rev 6842)
+++ branches/MASSIF2/cachegrind/cg_main.c 2007-09-17 05:45:40 UTC (rev 6843)
@@ -173,13 +173,13 @@
// been encountered before, or dup it and put it into the string table.
static Char* get_perm_string(Char* s)
{
- Char** s_ptr = VG_(OSet_Lookup)(stringTable, &s);
+ Char** s_ptr = VG_(OSetGen_Lookup)(stringTable, &s);
if (s_ptr) {
return *s_ptr;
} else {
- Char** s_node = VG_(OSet_AllocNode)(stringTable, sizeof(Char*));
+ Char** s_node = VG_(OSetGen_AllocNode)(stringTable, sizeof(Char*));
*s_node = VG_(strdup)(s);
- VG_(OSet_Insert)(stringTable, s_node);
+ VG_(OSetGen_Insert)(stringTable, s_node);
return *s_node;
}
}
@@ -230,14 +230,14 @@
loc.fn = fn;
loc.line = line;
- lineCC = VG_(OSet_Lookup)(CC_table, &loc);
+ lineCC = VG_(OSetGen_Lookup)(CC_table, &loc);
if (!lineCC) {
// Allocate and zero a new node.
- lineCC = VG_(OSet_AllocNode)(CC_table, sizeof(LineCC));
+ lineCC = VG_(OSetGen_AllocNode)(CC_table, sizeof(LineCC));
lineCC->loc.file = get_perm_string(loc.file);
lineCC->loc.fn = get_perm_string(loc.fn);
lineCC->loc.line = loc.line;
- VG_(OSet_Insert)(CC_table, lineCC);
+ VG_(OSetGen_Insert)(CC_table, lineCC);
}
return lineCC;
@@ -443,16 +443,16 @@
// If this assertion fails, there has been some screwup: some
// translations must have been discarded but Cachegrind hasn't discarded
// the corresponding entries in the instr-info table.
- sbInfo = VG_(OSet_Lookup)(instrInfoTable, &origAddr);
+ sbInfo = VG_(OSetGen_Lookup)(instrInfoTable, &origAddr);
tl_assert(NULL == sbInfo);
// BB never translated before (at this address, at least; could have
// been unloaded and then reloaded elsewhere in memory)
- sbInfo = VG_(OSet_AllocNode)(instrInfoTable,
+ sbInfo = VG_(OSetGen_AllocNode)(instrInfoTable,
sizeof(SB_info) + n_instrs*sizeof(InstrInfo));
sbInfo->SB_addr = origAddr;
sbInfo->n_instrs = n_instrs;
- VG_(OSet_Insert)( instrInfoTable, sbInfo );
+ VG_(OSetGen_Insert)( instrInfoTable, sbInfo );
distinct_instrs++;
return sbInfo;
@@ -1039,8 +1039,8 @@
VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
// Traverse every lineCC
- VG_(OSet_ResetIter)(CC_table);
- while ( (lineCC = VG_(OSet_Next)(CC_table)) ) {
+ VG_(OSetGen_ResetIter)(CC_table);
+ while ( (lineCC = VG_(OSetGen_Next)(CC_table)) ) {
Bool just_hit_a_new_file = False;
// If we've hit a new file, print a "fl=" line. Note that because
// each string is stored exactly once in the string table, we can use
@@ -1226,11 +1226,11 @@
buf4, no_debugs);
VG_(message)(Vg_DebugMsg, "cachegrind: string table size: %u",
- VG_(OSet_Size)(stringTable));
+ VG_(OSetGen_Size)(stringTable));
VG_(message)(Vg_DebugMsg, "cachegrind: CC table size: %u",
- VG_(OSet_Size)(CC_table));
+ VG_(OSetGen_Size)(CC_table));
VG_(message)(Vg_DebugMsg, "cachegrind: InstrInfo table size: %u",
- VG_(OSet_Size)(instrInfoTable));
+ VG_(OSetGen_Size)(instrInfoTable));
}
}
@@ -1256,9 +1256,9 @@
// Get BB info, remove from table, free BB info. Simple! Note that we
// use orig_addr, not the first instruction address in vge.
- sbInfo = VG_(OSet_Remove)(instrInfoTable, &orig_addr);
+ sbInfo = VG_(OSetGen_Remove)(instrInfoTable, &orig_addr);
tl_assert(NULL != sbInfo);
- VG_(OSet_FreeNode)(instrInfoTable, sbInfo);
+ VG_(OSetGen_FreeNode)(instrInfoTable, sbInfo);
}
/*--------------------------------------------------------------------*/
@@ -1403,15 +1403,18 @@
tl_assert( cachegrind_out_file[filename_szB-1] == 0 );
- CC_table = VG_(OSet_Create)(offsetof(LineCC, loc),
- cmp_CodeLoc_LineCC,
- VG_(malloc), VG_(free));
- instrInfoTable = VG_(OSet_Create)(/*keyOff*/0,
- NULL,
- VG_(malloc), VG_(free));
- stringTable = VG_(OSet_Create)(/*keyOff*/0,
- stringCmp,
- VG_(malloc), VG_(free));
+ CC_table =
+ VG_(OSetGen_Create)(offsetof(LineCC, loc),
+ cmp_CodeLoc_LineCC,
+ VG_(malloc), VG_(free));
+ instrInfoTable =
+ VG_(OSetGen_Create)(/*keyOff*/0,
+ NULL,
+ VG_(malloc), VG_(free));
+ stringTable =
+ VG_(OSetGen_Create)(/*keyOff*/0,
+ stringCmp,
+ VG_(malloc), VG_(free));
configure_caches(&I1c, &D1c, &L2c);
Modified: branches/MASSIF2/coregrind/m_debuginfo/readelf.c
===================================================================
--- branches/MASSIF2/coregrind/m_debuginfo/readelf.c 2007-09-17 05:35:10 UTC (rev 6842)
+++ branches/MASSIF2/coregrind/m_debuginfo/readelf.c 2007-09-17 05:45:40 UTC (rev 6843)
@@ -516,9 +516,9 @@
TRACE_SYMTAB("\nReading (ELF, ppc64-linux) %s (%d entries)\n", tab_name,
o_symtab_sz/sizeof(ElfXX_Sym) );
- oset = VG_(OSet_Create)( offsetof(TempSym,key),
- (OSetCmp_t)cmp_TempSymKey,
- oset_malloc, oset_free );
+ oset = VG_(OSetGen_Create)( offsetof(TempSym,key),
+ (OSetCmp_t)cmp_TempSymKey,
+ oset_malloc, oset_free );
vg_assert(oset);
/* Perhaps should start at i = 1; ELF docs suggest that entry
@@ -542,7 +542,7 @@
/* Check if we've seen this (name,addr) key before. */
key.addr = sym_addr_really;
key.name = sym_name_really;
- prev = VG_(OSet_Lookup)( oset, &key );
+ prev = VG_(OSetGen_Lookup)( oset, &key );
if (prev) {
@@ -604,13 +604,13 @@
} else {
/* A new (name,addr) key. Add and continue. */
- elem = VG_(OSet_AllocNode)(oset, sizeof(TempSym));
+ elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym));
vg_assert(elem);
elem->key = key;
elem->tocptr = sym_tocptr;
elem->size = sym_size;
elem->from_opd = from_opd;
- VG_(OSet_Insert)(oset, elem);
+ VG_(OSetGen_Insert)(oset, elem);
if (si->trace_symtab) {
VG_(printf)(" to-oset [%4d]: "
" val %010p, toc %010p, sz %4d %s\n",
@@ -629,9 +629,9 @@
build a "standard" symbol table, and nuke the oset. */
i = 0;
- VG_(OSet_ResetIter)( oset );
+ VG_(OSetGen_ResetIter)( oset );
- while ( (elem = VG_(OSet_Next)(oset)) ) {
+ while ( (elem = VG_(OSetGen_Next)(oset)) ) {
risym.addr = elem->key.addr;
risym.size = elem->size;
risym.name = ML_(addStr) ( si, elem->key.name, -1 );
@@ -651,7 +651,7 @@
i++;
}
- VG_(OSet_Destroy)( oset, NULL );
+ VG_(OSetGen_Destroy)( oset );
}
Modified: branches/MASSIF2/coregrind/m_oset.c
===================================================================
--- branches/MASSIF2/coregrind/m_oset.c 2007-09-17 05:35:10 UTC (rev 6842)
+++ branches/MASSIF2/coregrind/m_oset.c 2007-09-17 05:45:40 UTC (rev 6843)
@@ -56,7 +56,7 @@
// keyOff -> | key | elemSize
// +---------------+ v
//
-// Users have to allocate AvlNodes with OSet_AllocNode(), which allocates
+// Users have to allocate AvlNodes with OSetGen_AllocNode(), which allocates
// space for the metadata.
//
// The terminology used throughout this file:
@@ -70,7 +70,7 @@
// an AvlNode.
//
// Each tree also has an iterator. Note that we cannot use the iterator
-// internally within this file (eg. we could implement OSet_Size() by
+// internally within this file (eg. we could implement OSetGen_Size() by
// stepping through with the iterator and counting nodes) because it's
// non-reentrant -- the user might be using it themselves, and the
// concurrent uses would screw things up.
@@ -85,6 +85,8 @@
/*--- Types and constants ---*/
/*--------------------------------------------------------------------*/
+typedef struct _OSetNode OSetNode;
+
// Internal names for the OSet types.
typedef OSet AvlTree;
typedef OSetNode AvlNode;
@@ -133,7 +135,7 @@
vg_assert2(n->magic == OSET_MAGIC,
"bad magic on node %p = %x (expected %x)\n"
"possible causes:\n"
- " - node not allocated with VG_(OSet_AllocNode)()?\n"
+ " - node not allocated with VG_(OSetGen_AllocNode)()?\n"
" - node metadata corrupted by underwriting start of element?\n",
n, n->magic, OSET_MAGIC);
return n;
@@ -268,8 +270,8 @@
/*--------------------------------------------------------------------*/
// The underscores avoid GCC complaints about overshadowing global names.
-AvlTree* VG_(OSet_Create)(OffT _keyOff, OSetCmp_t _cmp,
- OSetAlloc_t _alloc, OSetFree_t _free)
+AvlTree* VG_(OSetGen_Create)(OffT _keyOff, OSetCmp_t _cmp,
+ OSetAlloc_t _alloc, OSetFree_t _free)
{
AvlTree* t;
@@ -293,8 +295,13 @@
return t;
}
+AvlTree* VG_(OSetWord_Create)(OSetAlloc_t _alloc, OSetFree_t _free)
+{
+ return VG_(OSetGen_Create)(/*keyOff*/0, /*cmp*/NULL, _alloc, _free);
+}
+
// Destructor, frees up all memory held by remaining nodes.
-void VG_(OSet_Destroy)(AvlTree* t, OSetNodeDestroy_t destroyNode)
+void VG_(OSetGen_Destroy)(AvlTree* t)
{
AvlNode* n = NULL;
Int i = 0, sz = 0;
@@ -304,8 +311,8 @@
if (t->root)
stackPush(t, t->root, 1);
- // Free all the AvlNodes. This is a post-order traversal, because we
- // must free all children of a node before the node itself.
+ /* Free all the AvlNodes. This is a post-order traversal, because we */
+ /* must free all children of a node before the node itself. */
while (stackPop(t, &n, &i)) {
switch (i) {
case 1:
@@ -317,7 +324,6 @@
if (n->right) stackPush(t, n->right, 1);
break;
case 3:
- if (destroyNode) destroyNode(n);
t->free(n);
sz++;
break;
@@ -325,12 +331,17 @@
}
vg_assert(sz == t->nElems);
- // Free the AvlTree itself.
+ /* Free the AvlTree itself. */
t->free(t);
}
+void VG_(OSetWord_Destroy)(AvlTree* t)
+{
+ VG_(OSetGen_Destroy)(t);
+}
+
// Allocate and initialise a new node.
-void* VG_(OSet_AllocNode)(AvlTree* t, SizeT elemSize)
+void* VG_(OSetGen_AllocNode)(AvlTree* t, SizeT elemSize)
{
Int nodeSize = sizeof(AvlNode) + elemSize;
AvlNode* n = t->alloc( nodeSize );
@@ -340,7 +351,7 @@
return elem_of_node(n);
}
-void VG_(OSet_FreeNode)(AvlTree* t, void* e)
+void VG_(OSetGen_FreeNode)(AvlTree* t, void* e)
{
t->free( node_of_elem(e) );
}
@@ -427,19 +438,19 @@
}
} else {
- vg_assert2(0, "OSet_Insert: duplicate element added");
+ vg_assert2(0, "OSet{Word,Gen}_Insert: duplicate element added");
}
}
// Insert element e into the AVL tree t. This is just a wrapper for
// avl_insert() which doesn't return a Bool.
-void VG_(OSet_Insert)(AvlTree* t, void* e)
+void VG_(OSetGen_Insert)(AvlTree* t, void* e)
{
AvlNode* n;
vg_assert(t);
- // Initialise. Even though OSet_AllocNode zeroes these fields, we should
+ // Initialise. Even though OSetGen_AllocNode zeroes these fields, we should
// do it again in case a node is removed and then re-added to the tree.
n = node_of_elem(e);
n->left = 0;
@@ -457,6 +468,13 @@
t->stackTop = 0; // So the iterator can't get out of sync
}
+void VG_(OSetWord_Insert)(AvlTree* t, Word val)
+{
+ Word* node = VG_(OSetGen_AllocNode)(t, sizeof(Word));
+ *node = val;
+ VG_(OSetGen_Insert)(t, node);
+}
+
/*--------------------------------------------------------------------*/
/*--- Lookup ---*/
/*--------------------------------------------------------------------*/
@@ -493,7 +511,7 @@
}
// Find the *element* in t matching k, or NULL if not found.
-void* VG_(OSet_Lookup)(AvlTree* t, void* k)
+void* VG_(OSetGen_Lookup)(AvlTree* t, void* k)
{
AvlNode* n;
vg_assert(t);
@@ -503,7 +521,7 @@
// Find the *element* in t matching k, or NULL if not found; use the given
// comparison function rather than the standard one.
-void* VG_(OSet_LookupWithCmp)(AvlTree* t, void* k, OSetCmp_t cmp)
+void* VG_(OSetGen_LookupWithCmp)(AvlTree* t, void* k, OSetCmp_t cmp)
{
// Save the normal one to the side, then restore once we're done.
void* e;
@@ -511,17 +529,22 @@
vg_assert(t);
tmpcmp = t->cmp;
t->cmp = cmp;
- e = VG_(OSet_Lookup)(t, k);
+ e = VG_(OSetGen_Lookup)(t, k);
t->cmp = tmpcmp;
return e;
}
// Is there an element matching k?
-Bool VG_(OSet_Contains)(AvlTree* t, void* k)
+Bool VG_(OSetGen_Contains)(AvlTree* t, void* k)
{
- return (NULL != VG_(OSet_Lookup)(t, k));
+ return (NULL != VG_(OSetGen_Lookup)(t, k));
}
+Bool VG_(OSetWord_Contains)(AvlTree* t, Word val)
+{
+ return (NULL != VG_(OSetGen_Lookup)(t, &val));
+}
+
/*--------------------------------------------------------------------*/
/*--- Deletion ---*/
/*--------------------------------------------------------------------*/
@@ -650,7 +673,7 @@
}
// Remove and return the element matching the key 'k', or NULL if not present.
-void* VG_(OSet_Remove)(AvlTree* t, void* k)
+void* VG_(OSetGen_Remove)(AvlTree* t, void* k)
{
// Have to find the node first, then remove it.
AvlNode* n = avl_lookup(t, k);
@@ -664,15 +687,26 @@
}
}
+Bool VG_(OSetWord_Remove)(AvlTree* t, Word val)
+{
+ void* n = VG_(OSetGen_Remove)(t, &val);
+ if (n) {
+ VG_(OSetGen_FreeNode)(t, n);
+ return True;
+ } else {
+ return False;
+ }
+}
+
/*--------------------------------------------------------------------*/
/*--- Iterator ---*/
/*--------------------------------------------------------------------*/
// The iterator is implemented using in-order traversal with an explicit
// stack, which lets us do the traversal one step at a time and remember
-// where we are between each call to OSet_Next().
+// where we are between each call to OSetGen_Next().
-void VG_(OSet_ResetIter)(AvlTree* t)
+void VG_(OSetGen_ResetIter)(AvlTree* t)
{
vg_assert(t);
stackClear(t);
@@ -680,8 +714,13 @@
stackPush(t, t->root, 1);
}
-void* VG_(OSet_Next)(AvlTree* t)
+void VG_(OSetWord_ResetIter)(AvlTree* t)
{
+ VG_(OSetGen_ResetIter)(t);
+}
+
+void* VG_(OSetGen_Next)(AvlTree* t)
+{
Int i = 0;
OSetNode* n = NULL;
@@ -710,16 +749,32 @@
return NULL;
}
+Bool VG_(OSetWord_Next)(AvlTree* t, Word* val)
+{
+ Word* n = VG_(OSetGen_Next)(t);
+ if (n) {
+ *val = *n;
+ return True;
+ } else {
+ return False;
+ }
+}
+
/*--------------------------------------------------------------------*/
/*--- Miscellaneous operations ---*/
/*--------------------------------------------------------------------*/
-Int VG_(OSet_Size)(AvlTree* t)
+Int VG_(OSetGen_Size)(AvlTree* t)
{
vg_assert(t);
return t->nElems;
}
+Int VG_(OSetWord_Size)(AvlTree* t)
+{
+ return VG_(OSetGen_Size)(t);
+}
+
static void OSet_Print2( AvlTree* t, AvlNode* n,
Char*(*strElem)(void *), Int p )
{
Modified: branches/MASSIF2/coregrind/m_redir.c
===================================================================
--- branches/MASSIF2/coregrind/m_redir.c 2007-09-17 05:35:10 UTC (rev 6842)
+++ branches/MASSIF2/coregrind/m_redir.c 2007-09-17 05:45:40 UTC (rev 6843)
@@ -544,7 +544,7 @@
goto bad;
}
- old = VG_(OSet_Lookup)( activeSet, &act.from_addr );
+ old = VG_(OSetGen_Lookup)( activeSet, &act.from_addr );
if (old) {
/* Dodgy. Conflicting binding. */
vg_assert(old->from_addr == act.from_addr);
@@ -559,10 +559,10 @@
/* XXXXXXXXXXX COMPLAIN if new and old parents differ */
}
} else {
- Active* a = VG_(OSet_AllocNode)(activeSet, sizeof(Active));
+ Active* a = VG_(OSetGen_AllocNode)(activeSet, sizeof(Active));
vg_assert(a);
*a = act;
- VG_(OSet_Insert)(activeSet, a);
+ VG_(OSetGen_Insert)(activeSet, a);
/* Now that a new from->to redirection is in force, we need to
get rid of any translations intersecting 'from' in order that
they get redirected to 'to'. So discard them. Just for
@@ -597,7 +597,7 @@
OSet* tmpSet;
Active* act;
Bool delMe;
- Addr* addrP;
+ Addr addr;
vg_assert(delsi);
@@ -617,13 +617,12 @@
/* Traverse the actives, copying the addresses of those we intend
to delete into tmpSet. */
- tmpSet = VG_(OSet_Create)( 0/*keyOff*/, NULL/*fastCmp*/,
- symtab_alloc, symtab_free);
+ tmpSet = VG_(OSetWord_Create)(symtab_alloc, symtab_free);
ts->mark = True;
- VG_(OSet_ResetIter)( activeSet );
- while ( (act = VG_(OSet_Next)(activeSet)) ) {
+ VG_(OSetGen_ResetIter)( activeSet );
+ while ( (act = VG_(OSetGen_Next)(activeSet)) ) {
delMe = act->parent_spec != NULL
&& act->parent_sym != NULL
&& act->parent_spec->seginfo != NULL
@@ -644,9 +643,7 @@
}
if (delMe) {
- addrP = VG_(OSet_AllocNode)( tmpSet, sizeof(Addr) );
- *addrP = act->from_addr;
- VG_(OSet_Insert)( tmpSet, addrP );
+ VG_(OSetWord_Insert)( tmpSet, act->from_addr );
/* While we have our hands on both the 'from' and 'to'
of this Active, do paranoid stuff with tt/tc. */
VG_(discard_translations)( (Addr64)act->from_addr, 1,
@@ -656,16 +653,15 @@
}
}
- /* Now traverse tmpSet, deleting corresponding elements in
- activeSet. */
- VG_(OSet_ResetIter)( tmpSet );
- while ( (addrP = VG_(OSet_Next)(tmpSet)) ) {
- act = VG_(OSet_Remove)( activeSet, addrP );
+ /* Now traverse tmpSet, deleting corresponding elements in activeSet. */
+ VG_(OSetWord_ResetIter)( tmpSet );
+ while ( VG_(OSetWord_Next)(tmpSet, &addr) ) {
+ act = VG_(OSetGen_Remove)( activeSet, &addr );
vg_assert(act);
- VG_(OSet_FreeNode)( activeSet, act );
+ VG_(OSetGen_FreeNode)( activeSet, act );
}
- VG_(OSet_Destroy)( tmpSet, NULL );
+ VG_(OSetWord_Destroy)( tmpSet );
/* The Actives set is now cleaned up. Free up this TopSpec and
everything hanging off it. */
@@ -698,7 +694,7 @@
just before translating a basic block. */
Addr VG_(redir_do_lookup) ( Addr orig, Bool* isWrap )
{
- Active* r = VG_(OSet_Lookup)(activeSet, &orig);
+ Active* r = VG_(OSetGen_Lookup)(activeSet, &orig);
if (r == NULL)
return orig;
@@ -776,10 +772,10 @@
vg_assert( VG_(next_seginfo)(NULL) == NULL );
// Initialise active mapping.
- activeSet = VG_(OSet_Create)(offsetof(Active, from_addr),
- NULL, // Use fast comparison
- symtab_alloc,
- symtab_free);
+ activeSet = VG_(OSetGen_Create)(offsetof(Active, from_addr),
+ NULL, // Use fast comparison
+ symtab_alloc,
+ symtab_free);
// The rest of this function just adds initial Specs.
@@ -1003,8 +999,8 @@
show_spec(" ", sp);
}
VG_(message)(Vg_DebugMsg, " ------ ACTIVE ------");
- VG_(OSet_ResetIter)( activeSet );
- while ( (act = VG_(OSet_Next)(activeSet)) ) {
+ VG_(OSetGen_ResetIter)( activeSet );
+ while ( (act = VG_(OSetGen_Next)(activeSet)) ) {
show_active(" ", act);
}
Modified: branches/MASSIF2/include/pub_tool_oset.h
===================================================================
--- branches/MASSIF2/include/pub_tool_oset.h 2007-09-17 05:35:10 UTC (rev 6842)
+++ branches/MASSIF2/include/pub_tool_oset.h 2007-09-17 05:45:40 UTC (rev 6843)
@@ -36,24 +36,32 @@
// elements. It does not allow duplicates, and will assert if you insert a
// duplicate to an OSet.
//
-// The structure is totally generic. The user provides the allocation and
-// deallocation functions. Also, each element has a key, which the lookup
-// is done with. The key may be the whole element (eg. in an OSet of
-// integers, each integer serves both as an element and a key), or it may be
-// only part of it (eg. if the key is a single field in a struct). The user
-// can provide a function that compares an element with a key; this is very
-// flexible, and with the right comparison function even a (non-overlapping)
-// interval list can be created. But the cost of calling a function for
-// every comparison can be high during lookup. If no comparison function is
-// provided, we assume that keys are (signed or unsigned) words, and that
-// the key is the first word in each element. This fast comparison is
-// suitable for an OSet of Words, or an OSet containing structs where the
-// first element is an Addr, for example.
+// It has two interfaces.
//
-// Each OSet also has an iterator, which makes it simple to traverse all the
-// nodes in order. Note that the iterator maintains state and so is
-// non-reentrant.
+// - The "OSetWord_" interface provides an easier-to-use interface for the
+// case where you just want to store Word-sized values. The user provides
+// the allocation and deallocation functions, and possibly a comparison
+// function.
//
+// - The "OSetGen_" interface provides a totally generic interface, which
+// allows any kind of structure to be put into the set. The user provides
+// the allocation and deallocation functions. Also, each element has a
+// key, which the lookup is done with. The key may be the whole element
+// (eg. in an OSet of integers, each integer serves both as an element and
+// a key), or it may be only part of it (eg. if the key is a single field
+// in a struct). The user can provide a function that compares an element
+// with a key; this is very flexible, and with the right comparison
+// function even a (non-overlapping) interval list can be created. But
+// the cost of calling a function for every comparison can be high during
+// lookup. If no comparison function is provided, we assume that keys are
+// (signed or unsigned) words, and that the key is the first word in each
+// element. This fast comparison is suitable for an OSet containing
+// structs where the first element is an Addr, for example.
+//
+// Each OSet interface also has an iterator, which makes it simple to
+// traverse all the nodes in order. Note that the iterator maintains state
+// and so is non-reentrant.
+//
// Note that once you insert an element into an OSet, if you modify any part
// of it looked at by your cmp() function, this may cause incorrect
// behaviour as the sorted order maintained will be wrong.
@@ -63,25 +71,97 @@
/*--------------------------------------------------------------------*/
typedef struct _OSet OSet;
-typedef struct _OSetNode OSetNode;
+// - Cmp: returns -1, 0 or 1 if key is <=, == or >= elem.
+// - Alloc: allocates a chunk of memory.
+// - Free: frees a chunk of memory allocated with Alloc.
+
typedef Word (*OSetCmp_t) ( void* key, void* elem );
typedef void* (*OSetAlloc_t) ( SizeT szB );
typedef void (*OSetFree_t) ( void* p );
-typedef void (*OSetNodeDestroy_t) ( void* elem );
/*--------------------------------------------------------------------*/
-/*--- Creating and destroying OSets and OSet members ---*/
+/*--- Creating and destroying OSets (Word) ---*/
/*--------------------------------------------------------------------*/
// * Create: allocates and initialises the OSet. Arguments:
+// - alloc The allocation function used internally for allocating the
+// OSet and all its nodes.
+// - free The deallocation function used internally for freeing nodes
+// called by VG_(OSetWord_Destroy)().
+//
+// * CreateWithCmp: like Create, but you specify your own comparison
+// function.
+//
+// * Destroy: frees all nodes in the table, plus the memory used by
+// the table itself. The passed-in function is called on each node first
+// to allow the destruction of any attached resources; if NULL it is not
+// called.
+
+extern OSet* VG_(OSetWord_Create) ( OSetAlloc_t alloc, OSetFree_t free );
+extern void VG_(OSetWord_Destroy) ( OSet* os );
+
+/*--------------------------------------------------------------------*/
+/*--- Operations on OSets (Word) ---*/
+/*--------------------------------------------------------------------*/
+
+// In everything that follows, the parameter 'key' is always the *address*
+// of the key, and 'elem' is *address* of the elem, as are the return values
+// of the functions that return elems.
+//
+// * Size: The number of elements in the set.
+//
+// * Contains: Determines if the value is in the set.
+//
+// * Insert: Inserts a new element into the set. Duplicates are forbidden,
+// and will cause assertion failures.
+//
+// * Remove: Removes the value from the set, if present. Returns a Bool
+// indicating if the value was removed.
+//
+// * ResetIter: Each OSet has an iterator. This resets it to point to the
+// first element in the OSet.
+//
+// * Next: Copies the next value according to the OSet's iterator into &val,
+// advances the iterator by one, and returns True; the elements are
+// visited in order. Or, returns False if the iterator has reached the
+// set's end.
+//
+// You can thus iterate in order through a set like this:
+//
+// Word val;
+// VG_(OSetWord_ResetIter)(oset);
+// while ( VG_(OSetWord_Next)(oset, &val) ) {
+// ... do stuff with 'val' ...
+// }
+//
+// Note that iterators are cleared any time an element is inserted or
+// removed from the OSet, to avoid possible mayhem caused by the iterator
+// getting out of sync with the OSet's contents. "Cleared" means that
+// they will return False if VG_(OSetWord_Next)() is called without an
+// intervening call to VG_(OSetWord_ResetIter)().
+
+extern Int VG_(OSetWord_Size) ( OSet* os );
+extern void VG_(OSetWord_Insert) ( OSet* os, Word val );
+extern Bool VG_(OSetWord_Contains) ( OSet* os, Word val );
+extern Bool VG_(OSetWord_Remove) ( OSet* os, Word val );
+extern void VG_(OSetWord_ResetIter) ( OSet* os );
+extern Bool VG_(OSetWord_Next) ( OSet* os, Word* val );
+
+
+/*--------------------------------------------------------------------*/
+/*--- Creating and destroying OSets and OSet members (Gen) ---*/
+/*--------------------------------------------------------------------*/
+
+// * Create: allocates and initialises the OSet. Arguments:
// - keyOff The offset of the key within the element.
// - cmp The comparison function between keys and elements, or NULL
// if the OSet should use fast comparisons.
// - alloc The allocation function used for allocating the OSet itself;
-// it's also called for each invocation of VG_(OSet_AllocNode)().
-// - free The deallocation function used by VG_(OSet_FreeNode)() and
-// VG_(OSet_Destroy)().
+// it's also called for each invocation of
+// VG_(OSetGen_AllocNode)().
+// - free The deallocation function used by VG_(OSetGen_FreeNode)() and
+// VG_(OSetGen_Destroy)().
//
// If cmp is NULL, keyOff must be zero. This is checked.
//
@@ -91,25 +171,25 @@
// called.
//
// * AllocNode: Allocate and zero memory for a node to go into the OSet.
-// Uses the alloc function given to VG_(OSet_Create)() to allocated a node
-// which is big enough for both an element and the OSet metadata.
+// Uses the alloc function given to VG_(OSetGen_Create)() to allocated a
+// node which is big enough for both an element and the OSet metadata.
// Not all elements in one OSet have to be the same size.
//
// Note that the element allocated will be at most word-aligned, which may
// be less aligned than the element type would normally be.
//
-// * FreeNode: Deallocate a node allocated with OSet_AllocNode(). Using
+// * FreeNode: Deallocate a node allocated with OSetGen_AllocNode(). Using
// a deallocation function (such as VG_(free)()) directly will likely
// lead to assertions in Valgrind's allocator.
-extern OSet* VG_(OSet_Create) ( OffT keyOff, OSetCmp_t cmp,
- OSetAlloc_t alloc, OSetFree_t free );
-extern void VG_(OSet_Destroy) ( OSet* os, OSetNodeDestroy_t destroyNode );
-extern void* VG_(OSet_AllocNode) ( OSet* os, SizeT elemSize );
-extern void VG_(OSet_FreeNode) ( OSet* os, void* elem );
+extern OSet* VG_(OSetGen_Create) ( OffT keyOff, OSetCmp_t cmp,
+ OSetAlloc_t alloc, OSetFree_t free );
+extern void VG_(OSetGen_Destroy) ( OSet* os );
+extern void* VG_(OSetGen_AllocNode) ( OSet* os, SizeT elemSize );
+extern void VG_(OSetGen_FreeNode) ( OSet* os, void* elem );
/*--------------------------------------------------------------------*/
-/*--- Operations on OSets ---*/
+/*--- Operations on OSets (Gen) ---*/
/*--------------------------------------------------------------------*/
// In everything that follows, the parameter 'key' is always the *address*
@@ -118,6 +198,11 @@
//
// * Size: The number of elements in the set.
//
+// * Insert: Inserts a new element into the set. Note that 'elem' must
+// have been allocated using VG_(OSetGen_AllocNode)(), otherwise you will
+// get assertion failures about "bad magic". Duplicates are forbidden,
+// and will also cause assertion failures.
+//
// * Contains: Determines if any element in the OSet matches the key.
//
// * Lookup: Returns a pointer to the element matching the key, if there is
@@ -126,11 +211,6 @@
// * LookupWithCmp: Like Lookup, but you specify the comparison function,
// which overrides the OSet's normal one.
//
-// * Insert: Inserts a new element into the list. Note that 'elem' must
-// have been allocated using VG_(OSet_AllocNode)(), otherwise you will get
-// assertion failures about "bad magic". Duplicates are forbidden, and
-// will also cause assertion failures.
-//
// * Remove: Removes the element matching the key, if there is one. Returns
// NULL if no element matches the key.
//
@@ -141,27 +221,27 @@
// iterator, and advances the iterator by one; the elements are visited
// in order. Or, returns NULL if the iterator has reached the OSet's end.
//
-// You can thus iterate in order through an OSet like this:
+// You can thus iterate in order through a set like this:
//
-// VG_(OSet_ResetIter)(oset);
-// while ( (elem = VG_(OSet_Next)(oset)) ) {
+// VG_(OSetGen_ResetIter)(oset);
+// while ( (elem = VG_(OSetGen_Next)(oset)) ) {
// ... do stuff with 'elem' ...
// }
//
// Note that iterators are cleared any time an element is inserted or
// removed from the OSet, to avoid possible mayhem caused by the iterator
// getting out of sync with the OSet's contents. "Cleared" means that
-// they will return NULL if VG_(OSet_Next)() is called without an
-// intervening call to VG_(OSet_ResetIter)().
+// they will return NULL if VG_(OSetGen_Next)() is called without an
+// intervening call to VG_(OSetGen_ResetIter)().
-extern Int VG_(OSet_Size) ( OSet* os );
-extern void VG_(OSet_Insert) ( OSet* os, void* elem );
-extern Bool VG_(OSet_Contains) ( OSet* os, void* key );
-extern void* VG_(OSet_Lookup) ( OSet* os, void* key );
-extern void* VG_(OSet_LookupWithCmp)( OSet* os, void* key, OSetCmp_t cmp );
-extern void* VG_(OSet_Remove) ( OSet* os, void* key );
-extern void VG_(OSet_ResetIter) ( OSet* os );
-extern void* VG_(OSet_Next) ( OSet* os );
+extern Int VG_(OSetGen_Size) ( OSet* os );
+extern void VG_(OSetGen_Insert) ( OSet* os, void* elem );
+extern Bool VG_(OSetGen_Contains) ( OSet* os, void* key );
+extern void* VG_(OSetGen_Lookup) ( OSet* os, void* key );
+extern void* VG_(OSetGen_LookupWithCmp)( OSet* os, void* key, OSetCmp_t cmp );
+extern void* VG_(OSetGen_Remove) ( OSet* os, void* key );
+extern void VG_(OSetGen_ResetIter) ( OSet* os );
+extern void* VG_(OSetGen_Next) ( OSet* os );
#endif // __PUB_TOOL_OSET_H
Modified: branches/MASSIF2/memcheck/mc_main.c
===================================================================
--- branches/MASSIF2/memcheck/mc_main.c 2007-09-17 05:35:10 UTC (rev 6842)
+++ branches/MASSIF2/memcheck/mc_main.c 2007-09-17 05:45:40 UTC (rev 6843)
@@ -387,9 +387,9 @@
tl_assert(0 == offsetof(AuxMapEnt,base));
tl_assert(sizeof(Addr) == sizeof(void*));
- auxmap_L2 = VG_(OSet_Create)( /*keyOff*/ offsetof(AuxMapEnt,base),
- /*fastCmp*/ NULL,
- VG_(malloc), VG_(free) );
+ auxmap_L2 = VG_(OSetGen_Create)( /*keyOff*/ offsetof(AuxMapEnt,base),
+ /*fastCmp*/ NULL,
+ VG_(malloc), VG_(free) );
}
/* Check representation invariants; if OK return NULL; else a
@@ -418,7 +418,7 @@
*n_secmaps_found = 0;
if (sizeof(void*) == 4) {
/* 32-bit platform */
- if (VG_(OSet_Size)(auxmap_L2) != 0)
+ if (VG_(OSetGen_Size)(auxmap_L2) != 0)
return "32-bit: auxmap_L2 is non-empty";
for (i = 0; i < N_AUXMAP_L1; i++)
if (auxmap_L1[i].base != 0 || auxmap_L1[i].ent != NULL)
@@ -429,8 +429,8 @@
AuxMapEnt *elem, *res;
AuxMapEnt key;
/* L2 table */
- VG_(OSet_ResetIter)(auxmap_L2);
- while ( (elem = VG_(OSet_Next)(auxmap_L2)) ) {
+ VG_(OSetGen_ResetIter)(auxmap_L2);
+ while ( (elem = VG_(OSetGen_Next)(auxmap_L2)) ) {
elems_seen++;
if (0 != (elem->base & (Addr)0xFFFF))
return "64-bit: nonzero .base & 0xFFFF in auxmap_L2";
@@ -458,7 +458,7 @@
/* Look it up in auxmap_L2. */
key.base = auxmap_L1[i].base;
key.sm = 0;
- res = VG_(OSet_Lookup)(auxmap_L2, &key);
+ res = VG_(OSetGen_Lookup)(auxmap_L2, &key);
if (res == NULL)
return "64-bit: _L1 .base not found in _L2";
if (res != auxmap_L1[i].ent)
@@ -544,7 +544,7 @@
key.base = a;
key.sm = 0;
- res = VG_(OSet_Lookup)(auxmap_L2, &key);
+ res = VG_(OSetGen_Lookup)(auxmap_L2, &key);
if (res)
insert_into_auxmap_L1_at( AUXMAP_L1_INSERT_IX, res );
return res;
@@ -563,11 +563,11 @@
to allocate one. */
a &= ~(Addr)0xFFFF;
- nyu = (AuxMapEnt*) VG_(OSet_AllocNode)( auxmap_L2, sizeof(AuxMapEnt) );
+ nyu = (AuxMapEnt*) VG_(OSetGen_AllocNode)( auxmap_L2, sizeof(AuxMapEnt) );
tl_assert(nyu);
nyu->base = a;
nyu->sm = &sm_distinguished[SM_DIST_NOACCESS];
- VG_(OSet_Insert)( auxmap_L2, nyu );
+ VG_(OSetGen_Insert)( auxmap_L2, nyu );
insert_into_auxmap_L1_at( AUXMAP_L1_INSERT_IX, nyu );
n_auxmap_L2_nodes++;
return nyu;
@@ -879,9 +879,9 @@
static OSet* createSecVBitTable(void)
{
- return VG_(OSet_Create)( offsetof(SecVBitNode, a),
- NULL, // use fast comparisons
- VG_(malloc), VG_(free) );
+ return VG_(OSetGen_Create)( offsetof(SecVBitNode, a),
+ NULL, // use fast comparisons
+ VG_(malloc), VG_(free) );
}
static void gcSecVBitTable(void)
@@ -896,8 +896,8 @@
secVBitTable2 = createSecVBitTable();
// Traverse the table, moving fresh nodes into the new table.
- VG_(OSet_ResetIter)(secVBitTable);
- while ( (n = VG_(OSet_Next)(secVBitTable)) ) {
+ VG_(OSetGen_ResetIter)(secVBitTable);
+ while ( (n = VG_(OSetGen_Next)(secVBitTable)) ) {
Bool keep = False;
if ( (GCs_done - n->last_touched) <= MAX_STALE_AGE ) {
// Keep node if it's been touched recently enough (regardless of
@@ -918,18 +918,18 @@
if ( keep ) {
// Insert a copy of the node into the new table.
SecVBitNode* n2 =
- VG_(OSet_AllocNode)(secVBitTable2, sizeof(SecVBitNode));
+ VG_(OSetGen_AllocNode)(secVBitTable2, sizeof(SecVBitNode));
*n2 = *n;
- VG_(OSet_Insert)(secVBitTable2, n2);
+ VG_(OSetGen_Insert)(secVBitTable2, n2);
}
}
// Get the before and after sizes.
- n_nodes = VG_(OSet_Size)(secVBitTable);
- n_survivors = VG_(OSet_Size)(secVBitTable2);
+ n_nodes = VG_(OSetGen_Size)(secVBitTable);
+ n_survivors = VG_(OSetGen_Size)(secVBitTable2);
// Destroy the old table, and put the new one in its place.
- VG_(OSet_Destroy)(secVBitTable, NULL);
+ VG_(OSetGen_Destroy)(secVBitTable);
secVBitTable = secVBitTable2;
if (VG_(clo_verbosity) > 1) {
@@ -952,7 +952,7 @@
{
Addr aAligned = VG_ROUNDDN(a, BYTES_PER_SEC_VBIT_NODE);
Int amod = a % BYTES_PER_SEC_VBIT_NODE;
- SecVBitNode* n = VG_(OSet_Lookup)(secVBitTable, &aAligned);
+ SecVBitNode* n = VG_(OSetGen_Lookup)(secVBitTable, &aAligned);
UChar vbits8;
tl_assert2(n, "get_sec_vbits8: no node for address %p (%p)\n", aAligned, a);
// Shouldn't be fully defined or fully undefined -- those cases shouldn't
@@ -966,7 +966,7 @@
{
Addr aAligned = VG_ROUNDDN(a, BYTES_PER_SEC_VBIT_NODE);
Int i, amod = a % BYTES_PER_SEC_VBIT_NODE;
- SecVBitNode* n = VG_(OSet_Lookup)(secVBitTable, &aAligned);
+ SecVBitNode* n = VG_(OSetGen_Lookup)(secVBitTable, &aAligned);
// Shouldn't be fully defined or fully undefined -- those cases shouldn't
// make it to the secondary V bits table.
tl_assert(V_BITS8_DEFINED != vbits8 && V_BITS8_UNDEFINED != vbits8);
@@ -977,7 +977,7 @@
} else {
// New node: assign the specific byte, make the rest invalid (they
// should never be read as-is, but be cautious).
- n = VG_(OSet_AllocNode)(secVBitTable, sizeof(SecVBitNode));
+ n = VG_(OSetGen_AllocNode)(secVBitTable, sizeof(SecVBitNode));
n->a = aAligned;
for (i = 0; i < BYTES_PER_SEC_VBIT_NODE; i++) {
n->vbits8[i] = V_BITS8_UNDEFINED;
@@ -987,15 +987,15 @@
// Do a table GC if necessary. Nb: do this before inserting the new
// node, to avoid erroneously GC'ing the new node.
- if (secVBitLimit == VG_(OSet_Size)(secVBitTable)) {
+ if (secVBitLimit == VG_(OSetGen_Size)(secVBitTable)) {
gcSecVBitTable();
}
// Insert the new node.
- VG_(OSet_Insert)(secVBitTable, n);
+ VG_(OSetGen_Insert)(secVBitTable, n);
sec_vbits_new_nodes++;
- n_secVBit_nodes = VG_(OSet_Size)(secVBitTable);
+ n_secVBit_nodes = VG_(OSetGen_Size)(secVBitTable);
if (n_secVBit_nodes > max_secVBit_nodes)
max_secVBit_nodes = n_secVBit_nodes;
}
@@ -4316,7 +4316,7 @@
/* If we're not checking for undefined value errors, the secondary V bit
* table should be empty. */
if (!MC_(clo_undef_value_errors)) {
- if (0 != VG_(OSet_Size)(secVBitTable))
+ if (0 != VG_(OSetGen_Size)(secVBitTable))
return False;
}
Modified: branches/MASSIF2/memcheck/tests/oset_test.c
===================================================================
--- branches/MASSIF2/memcheck/tests/oset_test.c 2007-09-17 05:35:10 UTC (rev 6842)
+++ branches/MASSIF2/memcheck/tests/oset_test.c 2007-09-17 05:45:40 UTC (rev 6843)
@@ -77,23 +77,24 @@
// Create a static OSet of Ints. This one uses fast (built-in)
// comparisons.
- OSet* oset1 = VG_(OSet_Create)(0,
+ OSet* oset = VG_(OSetGen_Create)(0,
NULL,
(void*)malloc, free);
// Try some operations on an empty OSet to ensure they don't screw up.
- vg_assert( ! VG_(OSet_Contains)(oset1, &v) );
- vg_assert( ! VG_(OSet_Lookup)(oset1, &v) );
- vg_assert( ! VG_(OSet_Remove)(oset1, &v) );
- vg_assert( ! VG_(OSet_Next)(oset1) );
- vg_assert( 0 == VG_(OSet_Size)(oset1) );
+ vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
+ vg_assert( 0 == VG_(OSetGen_Size)(oset) );
// Create some elements, with gaps (they're all even) but no dups,
// and shuffle them randomly.
for (i = 0; i < NN; i++) {
- vs[i] = VG_(OSet_AllocNode)(oset1, sizeof(Word));
+ vs[i] = VG_(OSetGen_AllocNode)(oset, sizeof(Word));
*(vs[i]) = 2*i;
}
+ seed = 0;
for (i = 0; i < NN; i++) {
Word r1 = myrandom() % NN;
Word r2 = myrandom() % NN;
@@ -104,32 +105,32 @@
// Insert the elements
for (i = 0; i < NN; i++) {
- VG_(OSet_Insert)(oset1, vs[i]);
+ VG_(OSetGen_Insert)(oset, vs[i]);
}
// Check the size
- vg_assert( NN == VG_(OSet_Size)(oset1) );
+ vg_assert( NN == VG_(OSetGen_Size)(oset) );
// Check we can find all the elements we inserted
for (i = 0; i < NN; i++) {
- assert( VG_(OSet_Contains)(oset1, vs[i]) );
+ assert( VG_(OSetGen_Contains)(oset, vs[i]) );
}
// Check we cannot find elements we did not insert, below, within (odd
// numbers), and above the inserted elements.
v = -1;
- assert( ! VG_(OSet_Contains)(oset1, &v) );
+ assert( ! VG_(OSetGen_Contains)(oset, &v) );
for (i = 0; i < NN; i++) {
v = *(vs[i]) + 1;
- assert( ! VG_(OSet_Contains)(oset1, &v) );
+ assert( ! VG_(OSetGen_Contains)(oset, &v) );
}
v = NN*2;
- assert( ! VG_(OSet_Contains)(oset1, &v) );
+ assert( ! VG_(OSetGen_Contains)(oset, &v) );
// Check we can find all the elements we inserted, and the right values
// are returned.
for (i = 0; i < NN; i++) {
- assert( vs[i] == VG_(OSet_Lookup)(oset1, vs[i]) );
+ assert( vs[i] == VG_(OSetGen_Lookup)(oset, vs[i]) );
}
// Check that we can iterate over the OSet elements in sorted order, and
@@ -137,70 +138,189 @@
n = 0;
pv = NULL;
prev = -1;
- VG_(OSet_ResetIter)(oset1);
- while ( (pv = VG_(OSet_Next)(oset1)) ) {
+ VG_(OSetGen_ResetIter)(oset);
+ while ( (pv = VG_(OSetGen_Next)(oset)) ) {
Word curr = *pv;
assert(prev < curr);
prev = curr;
n++;
}
assert(NN == n);
- vg_assert( ! VG_(OSet_Next)(oset1) );
- vg_assert( ! VG_(OSet_Next)(oset1) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
// Check that we can remove half of the elements, and that their values
// are as expected.
for (i = 0; i < NN; i += 2) {
- assert( pv = VG_(OSet_Remove)(oset1, vs[i]) );
+ assert( pv = VG_(OSetGen_Remove)(oset, vs[i]) );
assert( pv == vs[i] );
}
// Check the size
- vg_assert( NN/2 == VG_(OSet_Size)(oset1) );
+ vg_assert( NN/2 == VG_(OSetGen_Size)(oset) );
// Check we can find the remaining elements (with the right values).
for (i = 1; i < NN; i += 2) {
- assert( pv = VG_(OSet_LookupWithCmp)(oset1, vs[i], NULL) );
+ assert( pv = VG_(OSetGen_LookupWithCmp)(oset, vs[i], NULL) );
assert( pv == vs[i] );
}
// Check we cannot find any of the elements we removed.
for (i = 0; i < NN; i += 2) {
- assert( ! VG_(OSet_Contains)(oset1, vs[i]) );
+ assert( ! VG_(OSetGen_Contains)(oset, vs[i]) );
}
// Check that we can remove the remaining half of the elements, and that
// their values are as expected.
for (i = 1; i < NN; i += 2) {
- assert( pv = VG_(OSet_Remove)(oset1, vs[i]) );
+ assert( pv = VG_(OSetGen_Remove)(oset, vs[i]) );
assert( pv == vs[i] );
}
// Try some more operations on the empty OSet to ensure they don't screw up.
- vg_assert( ! VG_(OSet_Contains)(oset1, &v) );
- vg_assert( ! VG_(OSet_Lookup)(oset1, &v) );
- vg_assert( ! VG_(OSet_Remove)(oset1, &v) );
- vg_assert( ! VG_(OSet_Next)(oset1) );
- vg_assert( 0 == VG_(OSet_Size)(oset1) );
+ vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
+ vg_assert( 0 == VG_(OSetGen_Size)(oset) );
// Free a few elements
- VG_(OSet_FreeNode)(oset1, vs[0]);
- VG_(OSet_FreeNode)(oset1, vs[1]);
- VG_(OSet_FreeNode)(oset1, vs[2]);
+ VG_(OSetGen_FreeNode)(oset, vs[0]);
+ VG_(OSetGen_FreeNode)(oset, vs[1]);
+ VG_(OSetGen_FreeNode)(oset, vs[2]);
- // Re-insert remaining elements, to give OSet_Destroy something to work with.
+ // Re-insert remaining elements, to give OSetGen_Destroy something to
+ // work with.
for (i = 3; i < NN; i++) {
- VG_(OSet_Insert)(oset1, vs[i]);
+ VG_(OSetGen_Insert)(oset, vs[i]);
}
// Print the list
- OSet_Print(oset1, "foo", wordToStr);
+ OSet_Print(oset, "oset1", wordToStr);
// Destroy the OSet
- VG_(OSet_Destroy)(oset1, NULL);
+ VG_(OSetGen_Destroy)(oset);
}
+void example1b(void)
+{
+ Int i, n;
+ Word v = 0, prev;
+ Word vs[NN];
+ Word *pv;
+
+ // Create a static OSet of Ints. This one uses fast (built-in)
+ // comparisons.
+ OSet* oset = VG_(OSetWord_Create)( (void*)malloc, free);
+
+ // Try some operations on an empty OSet to ensure they don't screw up.
+ vg_assert( ! VG_(OSetWord_Contains)(oset, v) );
+ vg_assert( ! VG_(OSetWord_Remove)(oset, v) );
+ vg_assert( ! VG_(OSetWord_Next)(oset, &v) );
+ vg_assert( 0 == VG_(OSetWord_Size)(oset) );
+
+ // Create some elements, with gaps (they're all even) but no dups,
+ // and shuffle them randomly.
+ for (i = 0; i < NN; i++) {
+ vs[i] = 2*i;
+ }
+ seed = 0;
+ for (i = 0; i < NN; i++) {
+ Word r1 = myrandom() % NN;
+ Word r2 = myrandom() % NN;
+ Word tmp = vs[r1];
+ vs[r1] = vs[r2];
+ vs[r2] = tmp;
+ }
+
+ // Insert the elements
+ for (i = 0; i < NN; i++) {
+ VG_(OSetWord_Insert)(oset, vs[i]);
+ }
+
+ // Check the size
+ vg_assert( NN == VG_(OSetWord_Size)(oset) );
+
+ // Check we can find all the elements we inserted
+ for (i = 0; i < NN; i++) {
+ assert( VG_(OSetWord_Contains)(oset, vs[i]) );
+ }
+
+ // Check we cannot find elements we did not insert, below, within (odd
+ // numbers), and above the inserted elements.
+ v = -1;
+ assert( ! VG_(OSetWord_Contains)(oset, v) );
+ for (i = 0; i < NN; i++) {
+ v = vs[i] + 1;
+ assert( ! VG_(OSetWord_Contains)(oset, v) );
+ }
+ v = NN*2;
+ assert( ! VG_(OSetWord_Contains)(oset, v) );
+
+ // Check we can find all the elements we inserted.
+ for (i = 0; i < NN; i++) {
+ assert( VG_(OSetWord_Contains)(oset, vs[i]) );
+ }
+
+ // Check that we can iterate over the OSet elements in sorted order, and
+ // there is the right number of them.
+ n = 0;
+ prev = -1;
+ VG_(OSetWord_ResetIter)(oset);
+ while ( VG_(OSetWord_Next)(oset, &v) ) {
+ Word curr = v;
+ assert(prev < curr);
+ prev = curr;
+ n++;
+ }
+ assert(NN == n);
+ vg_assert( ! VG_(OSetWord_Next)(oset, &v) );
+ vg_assert( ! VG_(OSetWord_Next)(oset, &v) );
+
+ // Check that we can remove half of the elements.
+ for (i = 0; i < NN; i += 2) {
+ assert( VG_(OSetWord_Remove)(oset, vs[i]) );
+ }
+
+ // Check the size
+ vg_assert( NN/2 == VG_(OSetWord_Size)(oset) );
+
+ // Check we can find the remaining elements (with the right values).
+ for (i = 1; i < NN; i += 2) {
+ assert( VG_(OSetWord_Contains)(oset, vs[i]) );
+ }
+
+ // Check we cannot find any of the elements we removed.
+ for (i = 0; i < NN; i += 2) {
+ assert( ! VG_(OSetWord_Contains)(oset, vs[i]) );
+ }
+
+ // Check that we can remove the remaining half of the elements.
+ for (i = 1; i < NN; i += 2) {
+ assert( VG_(OSetWord_Remove)(oset, vs[i]) );
+ }
+
+ // Try some more operations on the empty OSet to ensure they don't screw up.
+ vg_assert( ! VG_(OSetWord_Contains)(oset, v) );
+ vg_assert( ! VG_(OSetWord_Remove)(oset, v) );
+ vg_assert( ! VG_(OSetWord_Next)(oset, &v) );
+ vg_assert( 0 == VG_(OSetWord_Size)(oset) );
+
+ // Re-insert remaining elements, to give OSetWord_Destroy something to
+ // work with.
+ for (i = 3; i < NN; i++) {
+ VG_(OSetWord_Insert)(oset, vs[i]);
+ }
+
+ // Print the list
+ OSet_Print(oset, "oset1b", wordToStr);
+
+ // Destroy the OSet
+ VG_(OSetWord_Destroy)(oset);
+}
+
+
//---------------------------------------------------------------------------
// Struct example
//---------------------------------------------------------------------------
@@ -248,26 +368,27 @@
// Create a dynamic OSet of Blocks. This one uses slow (custom)
// comparisons.
- OSet* oset2 = VG_(OSet_Create)(offsetof(Block, first),
+ OSet* oset = VG_(OSetGen_Create)(offsetof(Block, first),
blockCmp,
(void*)malloc, free);
// Try some operations on an empty OSet to ensure they don't screw up.
- vg_assert( ! VG_(OSet_Contains)(oset2, &v) );
- vg_assert( ! VG_(OSet_Lookup)(oset2, &v) );
- vg_assert( ! VG_(OSet_Remove)(oset2, &v) );
- vg_assert( ! VG_(OSet_Next)(oset2) );
- vg_assert( 0 == VG_(OSet_Size)(oset2) );
+ vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
+ vg_assert( 0 == VG_(OSetGen_Size)(oset) );
// Create some inputs, with gaps -- intervals are 1..3, 11..13, ... -- but
// no dups, and shuffle them randomly.
for (i = 0; i < NN; i++) {
- vs[i] = VG_(OSet_AllocNode)(oset2, sizeof(Block));
+ vs[i] = VG_(OSetGen_AllocNode)(oset, sizeof(Block));
vs[i]->b1 = i;
vs[i]->first = i*10 + 1;
vs[i]->last = vs[i]->first + 2;
vs[i]->b2 = i+1;
}
+ seed = 0;
for (i = 0; i < NN; i++) {
Int r1 = myrandom() % NN;
Int r2 = myrandom() % NN;
@@ -278,36 +399,36 @@
// Insert the elements
for (i = 0; i < NN; i++) {
- VG_(OSet_Insert)(oset2, vs[i]);
+ VG_(OSetGen_Insert)(oset, vs[i]);
}
// Check the size
- vg_assert( NN == VG_(OSet_Size)(oset2) );
+ vg_assert( NN == VG_(OSetGen_Size)(oset) );
// Check we can find all the elements we inserted, within the full range
// of each Block.
for (i = 0; i < NN; i++) {
- a = vs[i]->first + 0; assert( VG_(OSet_Contains)(oset2, &a) );
- a = vs[i]->first + 1; assert( VG_(OSet_Contains)(oset2, &a) );
- a = vs[i]->first + 2; assert( VG_(OSet_Contains)(oset2, &a) );
+ a = vs[i]->first + 0; assert( VG_(OSetGen_Contains)(oset, &a) );
+ a = vs[i]->first + 1; assert( VG_(OSetGen_Contains)(oset, &a) );
+ a = vs[i]->first + 2; assert( VG_(OSetGen_Contains)(oset, &a) );
}
// Check we cannot find elements we did not insert, below and above the
// ranges of the inserted elements.
a = 0;
- assert( ! VG_(OSet_Contains)(oset2, &a) );
+ assert( ! VG_(OSetGen_Contains)(oset, &a) );
for (i = 0; i < NN; i++) {
- a = vs[i]->first - 1; assert( ! VG_(OSet_Contains)(oset2, &a) );
- a = vs[i]->first + 3; assert( ! VG_(OSet_Contains)(oset2, &a) );
+ a = vs[i]->first - 1; assert( ! VG_(OSetGen_Contains)(oset, &a) );
+ a = vs[i]->first + 3; assert( ! VG_(OSetGen_Contains)(oset, &a) );
}
// Check we can find all the elements we inserted, and the right values
// are returned.
for (i = 0; i < NN; i++) {
- a = vs[i]->first + 0; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
- a = vs[i]->first + 1; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
- a = vs[i]->first + 2; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
- assert( vs[i] == VG_(OSet_LookupWithCmp)(oset2, &a, blockCmp) );
+ a = vs[i]->first + 0; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
+ a = vs[i]->first + 1; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
+ a = vs[i]->first + 2; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
+ assert( vs[i] == VG_(OSetGen_LookupWithCmp)(oset, &a, blockCmp) );
}
// Check that we can iterate over the OSet elements in sorted order, and
@@ -315,60 +436,60 @@
n = 0;
pv = NULL;
prev.last = 0;
- VG_(OSet_ResetIter)(oset2);
- while ( (pv = VG_(OSet_Next)(oset2)) ) {
+ VG_(OSetGen_ResetIter)(oset);
+ while ( (pv = VG_(OSetGen_Next)(oset)) ) {
Block curr = *pv;
assert(prev.last < curr.first);
prev = curr;
n++;
}
assert(NN == n);
- vg_assert( ! VG_(OSet_Next)(oset2) );
- vg_assert( ! VG_(OSet_Next)(oset2) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
// Check that we can remove half of the elements, and that their values
// are as expected.
for (i = 0; i < NN; i += 2) {
- a = vs[i]->first; assert( vs[i] == VG_(OSet_Remove)(oset2, &a) );
+ a = vs[i]->first; assert( vs[i] == VG_(OSetGen_Remove)(oset, &a) );
}
// Check the size
- vg_assert( NN/2 == VG_(OSet_Size)(oset2) );
+ vg_assert( NN/2 == VG_(OSetGen_Size)(oset) );
// Check we can find the remaining elements (with the right values).
for (i = 1; i < NN; i += 2) {
- a = vs[i]->first + 0; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
- a = vs[i]->first + 1; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
- a = vs[i]->first + 2; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
+ a = vs[i]->first + 0; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
+ a = vs[i]->first + 1; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
+ a = vs[i]->first + 2; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
}
// Check we cannot find any of the elements we removed.
for (i = 0; i < NN; i += 2) {
- a = vs[i]->first + 0; assert( ! VG_(OSet_Contains)(oset2, &a) );
- a = vs[i]->first + 1; assert( ! VG_(OSet_Contains)(oset2, &a) );
- a = vs[i]->first + 2; assert( ! VG_(OSet_Contains)(oset2, &a) );
+ a = vs[i]->first + 0; assert( ! VG_(OSetGen_Contains)(oset, &a) );
+ a = vs[i]->first + 1; assert( ! VG_(OSetGen_Contains)(oset, &a) );
+ a = vs[i]->first + 2; assert( ! VG_(OSetGen_Contains)(oset, &a) );
}
// Check that we can remove the remaining half of the elements, and that
// their values are as expected.
for (i = 1; i < NN; i += 2) {
- a = vs[i]->first; assert( vs[i] == VG_(OSet_Remove)(oset2, &a) );
+ a = vs[i]->first; assert( vs[i] == VG_(OSetGen_Remove)(oset, &a) );
}
// Try some more operations on the empty OSet to ensure they don't screw up.
- vg_assert( ! VG_(OSet_Contains)(oset2, &v) );
- vg_assert( ! VG_(OSet_Lookup)(oset2, &v) );
- vg_assert( ! VG_(OSet_Remove)(oset2, &v) );
- vg_assert( ! VG_(OSet_Next)(oset2) );
- vg_assert( 0 == VG_(OSet_Size)(oset2) );
+ vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
+ vg_assert( 0 == VG_(OSetGen_Size)(oset) );
- // Re-insert all elements, to give OSet_Destroy something to work with.
+ // Re-insert all elements, to give OSetGen_Destroy something to work with.
for (i = 0; i < NN; i++) {
- VG_(OSet_Insert)(oset2, vs[i]);
+ VG_(OSetGen_Insert)(oset, vs[i]);
}
// Destroy the OSet
- VG_(OSet_Destroy)(oset2, NULL);
+ VG_(OSetGen_Destroy)(oset);
}
//-----------------------------------------------------------------------
@@ -378,6 +499,7 @@
int main(void)
{
example1();
+ example1b();
example2();
return 0;
}
Modified: branches/MASSIF2/memcheck/tests/oset_test.stdout.exp
===================================================================
--- branches/MASSIF2/memcheck/tests/oset_test.stdout.exp 2007-09-17 05:35:10 UTC (rev 6842)
+++ branches/MASSIF2/memcheck/tests/oset_test.stdout.exp 2007-09-17 05:45:40 UTC (rev 6843)
@@ -1,4 +1,4 @@
--- start foo ----------------
+-- start oset1 ----------------
.. .. .. .. .. .. .. .. .. 1998
.. .. .. .. .. .. .. .. 1996
.. .. .. .. .. .. .. .. .. .. 1994
@@ -996,4 +996,1003 @@
.. .. .. .. .. .. .. .. .. 4
.. .. .. .. .. .. .. .. 2
.. .. .. .. .. .. .. .. .. 0
--- end foo ----------------
+-- end oset1 ----------------
+-- start oset1b ----------------
+.. .. .. .. .. .. .. .. .. 1998
+.. .. .. .. .. .. .. .. 1996
+.. .. .. .. .. .. .. .. .. .. 1994
+.. .. .. .. .. .. .. .. .. 1992
+.. .. .. .. .. .. .. .. .. .. 1990
+.. .. .. .. .. .. .. 1988
+.. .. .. .. .. .. .. .. .. 1986
+.. .. .. .. .. .. .. .. .. .. 1984
+.. .. .. .. .. .. .. .. 1982
+.. .. .. .. .. .. .. .. .. .. 1980
+.. .. .. .. .. .. .. .. .. 1978
+.. .. .. .. .. .. .. .. .. .. 1976
+.. .. .. .. .. .. 1974
+.. .. .. .. .. .. .. .. .. .. 1972
+.. .. .. .. .. .. .. .. .. 1970
+.. .. .. .. .. .. .. .. .. .. 1968
+.. .. .. .. .. .. .. .. 1966
+.. .. .. .. .. .. .. .. .. .. 1964
+.. .. .. .. .. .. .. .. .. 1962
+.. .. .. .. .. .. .. 1960
+.. .. .. .. .. .. .. .. .. .. 1958
+.. .. .. .. .. .. .. .. .. 1956
+.. .. .. .. .. .. .. .. 1954
+.. .. .. .. .. .. .. .. .. .. 1952
+.. .. .. .. .. .. .. .. .. 1950
+.. .. .. .. .. .. .. .. .. .. 1948
+.. .. .. .. .. 1946
+.. .. .. .. .. .. .. .. .. 1944
+.. .. .. .. .. .. .. .. 1942
+.. .. .. .. .. .. .. 1940
+.. .. .. .. .. .. .. .. .. .. 1938
+.. .. .. .. .. .. .. .. .. 1936
+.. .. .. .. .. .. .. .. 1934
+.. .. .. .. .. .. .. .. .. 1932
+.. .. .. .. .. .. 1930
+.. .. .. .. .. .. .. .. .. 1928
+.. .. .. .. .. .. .. .. .. .. 1926
+.. .. .. .. .. .. .. .. 1924
+.. .. .. .. .. .. .. .. .. .. 1922
+.. .. .. .. .. .. .. .. .. 1920
+.. .. .. .. .. .. .. .. .. .. 1918
+.. .. .. .. .. .. .. 1916
+.. .. .. .. .. .. .. .. .. 1914
+.. .. .. .. .. .. .. .. 1912
+.. .. .. .. .. .. .. .. .. .. 1910
+.. .. .. .. .. .. .. .. .. 1908
+.. .. .. .. .. .. .. .. .. .. 1906
+.. .. .. .. 1904
+.. .. .. .. .. .. .. .. .. 1902
+.. .. .. .. .. .. .. .. 1900
+.. .. .. .. .. .. .. 1898
+.. .. .. .. .. .. .. .. .. 1896
+.. .. .. .. .. .. .. .. 1894
+.. .. .. .. .. .. .. .. .. 1892
+.. .. .. .. .. .. 1890
+.. .. .. .. .. .. .. .. .. .. 1888
+.. .. .. .. .. .. .. .. .. 1886
+.. .. .. .. .. .. .. .. .. .. 1884
+.. .. .. .. .. .. .. .. 1882
+.. .. .. .. .. .. .. .. .. 1880
+.. .. .. .. .. .. .. 1878
+.. .. .. .. .. .. .. .. 1876
+.. .. .. .. .. .. .. .. .. 1874
+.. .. .. .. .. 1872
+.. .. .. .. .. .. .. .. .. .. 1870
+.. .. .. .. .. .. .. .. .. 1868
+.. .. .. .. .. .. .. .. .. .. 1866
+.. .. .. .. .. .. .. .. 1864
+.. .. .. .. .. .. .. .. .. 1862
+.. .. .. .. .. .. .. .. .. .. 1860
+.. .. .. .. .. .. .. 1858
+.. .. .. .. .. .. .. .. .. 1856
+.. .. .. .. .. .. .. .. 1854
+.. .. .. .. .. .. .. .. .. 1852
+.. .. .. .. .. .. 1848
+.. .. .. .. .. .. .. .. .. 1846
+.. .. .. .. .. .. .. .. 1844
+.. .. .. .. .. .. .. .. .. .. 1842
+.. .. .. .. .. .. .. .. .. 1...
[truncated message content] |
|
From: <sv...@va...> - 2007-09-17 05:35:10
|
Author: njn
Date: 2007-09-17 06:35:10 +0100 (Mon, 17 Sep 2007)
New Revision: 6842
Log:
temporary hack for ms_print
Modified:
branches/MASSIF2/massif/ms_print
Modified: branches/MASSIF2/massif/ms_print
===================================================================
--- branches/MASSIF2/massif/ms_print 2007-09-17 05:30:48 UTC (rev 6841)
+++ branches/MASSIF2/massif/ms_print 2007-09-17 05:35:10 UTC (rev 6842)
@@ -205,6 +205,7 @@
{
while (my $line = <INPUTFILE>) {
$line =~ s/#.*$//; # remove comments
+ $line =~ s/==\d+==.*$//; # remove Valgrind output lines XXX
if ($line !~ /^\s*$/) {
return $line; # return $line if non-empty
}
|
|
From: <sv...@va...> - 2007-09-17 05:30:52
|
Author: njn
Date: 2007-09-17 06:30:48 +0100 (Mon, 17 Sep 2007)
New Revision: 6841
Log:
Split the OSet interface into two parts: "OSetGen_", which is the existing
interface and provides full power; and "OSetWord_", which is an
easier-to-use interface for if you just want to store words.
Modified:
trunk/cachegrind/cg_main.c
trunk/coregrind/m_debuginfo/readelf.c
trunk/coregrind/m_oset.c
trunk/coregrind/m_redir.c
trunk/include/pub_tool_oset.h
trunk/memcheck/mc_main.c
trunk/memcheck/tests/oset_test.c
trunk/memcheck/tests/oset_test.stdout.exp
Modified: trunk/cachegrind/cg_main.c
===================================================================
--- trunk/cachegrind/cg_main.c 2007-09-17 00:41:18 UTC (rev 6840)
+++ trunk/cachegrind/cg_main.c 2007-09-17 05:30:48 UTC (rev 6841)
@@ -190,13 +190,13 @@
// been encountered before, or dup it and put it into the string table.
static Char* get_perm_string(Char* s)
{
- Char** s_ptr = VG_(OSet_Lookup)(stringTable, &s);
+ Char** s_ptr = VG_(OSetGen_Lookup)(stringTable, &s);
if (s_ptr) {
return *s_ptr;
} else {
- Char** s_node = VG_(OSet_AllocNode)(stringTable, sizeof(Char*));
+ Char** s_node = VG_(OSetGen_AllocNode)(stringTable, sizeof(Char*));
*s_node = VG_(strdup)(s);
- VG_(OSet_Insert)(stringTable, s_node);
+ VG_(OSetGen_Insert)(stringTable, s_node);
return *s_node;
}
}
@@ -258,10 +258,10 @@
loc.fn = fn;
loc.line = line;
- lineCC = VG_(OSet_Lookup)(CC_table, &loc);
+ lineCC = VG_(OSetGen_Lookup)(CC_table, &loc);
if (!lineCC) {
// Allocate and zero a new node.
- lineCC = VG_(OSet_AllocNode)(CC_table, sizeof(LineCC));
+ lineCC = VG_(OSetGen_AllocNode)(CC_table, sizeof(LineCC));
lineCC->loc.file = get_perm_string(loc.file);
lineCC->loc.fn = get_perm_string(loc.fn);
lineCC->loc.line = loc.line;
@@ -278,7 +278,7 @@
lineCC->Bc.mp = 0;
lineCC->Bi.b = 0;
lineCC->Bi.mp = 0;
- VG_(OSet_Insert)(CC_table, lineCC);
+ VG_(OSetGen_Insert)(CC_table, lineCC);
}
return lineCC;
@@ -560,16 +560,16 @@
// If this assertion fails, there has been some screwup: some
// translations must have been discarded but Cachegrind hasn't discarded
// the corresponding entries in the instr-info table.
- sbInfo = VG_(OSet_Lookup)(instrInfoTable, &origAddr);
+ sbInfo = VG_(OSetGen_Lookup)(instrInfoTable, &origAddr);
tl_assert(NULL == sbInfo);
// BB never translated before (at this address, at least; could have
// been unloaded and then reloaded elsewhere in memory)
- sbInfo = VG_(OSet_AllocNode)(instrInfoTable,
+ sbInfo = VG_(OSetGen_AllocNode)(instrInfoTable,
sizeof(SB_info) + n_instrs*sizeof(InstrInfo));
sbInfo->SB_addr = origAddr;
sbInfo->n_instrs = n_instrs;
- VG_(OSet_Insert)( instrInfoTable, sbInfo );
+ VG_(OSetGen_Insert)( instrInfoTable, sbInfo );
distinct_instrs++;
return sbInfo;
@@ -1330,8 +1330,8 @@
VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
// Traverse every lineCC
- VG_(OSet_ResetIter)(CC_table);
- while ( (lineCC = VG_(OSet_Next)(CC_table)) ) {
+ VG_(OSetGen_ResetIter)(CC_table);
+ while ( (lineCC = VG_(OSetGen_Next)(CC_table)) ) {
Bool just_hit_a_new_file = False;
// If we've hit a new file, print a "fl=" line. Note that because
// each string is stored exactly once in the string table, we can use
@@ -1610,11 +1610,11 @@
buf4, no_debugs);
VG_(message)(Vg_DebugMsg, "cachegrind: string table size: %u",
- VG_(OSet_Size)(stringTable));
+ VG_(OSetGen_Size)(stringTable));
VG_(message)(Vg_DebugMsg, "cachegrind: CC table size: %u",
- VG_(OSet_Size)(CC_table));
+ VG_(OSetGen_Size)(CC_table));
VG_(message)(Vg_DebugMsg, "cachegrind: InstrInfo table size: %u",
- VG_(OSet_Size)(instrInfoTable));
+ VG_(OSetGen_Size)(instrInfoTable));
}
}
@@ -1640,9 +1640,9 @@
// Get BB info, remove from table, free BB info. Simple! Note that we
// use orig_addr, not the first instruction address in vge.
- sbInfo = VG_(OSet_Remove)(instrInfoTable, &orig_addr);
+ sbInfo = VG_(OSetGen_Remove)(instrInfoTable, &orig_addr);
tl_assert(NULL != sbInfo);
- VG_(OSet_FreeNode)(instrInfoTable, sbInfo);
+ VG_(OSetGen_FreeNode)(instrInfoTable, sbInfo);
}
/*--------------------------------------------------------------------*/
@@ -1800,15 +1800,18 @@
tl_assert( cachegrind_out_file[filename_szB-1] == 0 );
- CC_table = VG_(OSet_Create)(offsetof(LineCC, loc),
- cmp_CodeLoc_LineCC,
- VG_(malloc), VG_(free));
- instrInfoTable = VG_(OSet_Create)(/*keyOff*/0,
- NULL,
- VG_(malloc), VG_(free));
- stringTable = VG_(OSet_Create)(/*keyOff*/0,
- stringCmp,
- VG_(malloc), VG_(free));
+ CC_table =
+ VG_(OSetGen_Create)(offsetof(LineCC, loc),
+ cmp_CodeLoc_LineCC,
+ VG_(malloc), VG_(free));
+ instrInfoTable =
+ VG_(OSetGen_Create)(/*keyOff*/0,
+ NULL,
+ VG_(malloc), VG_(free));
+ stringTable =
+ VG_(OSetGen_Create)(/*keyOff*/0,
+ stringCmp,
+ VG_(malloc), VG_(free));
configure_caches(&I1c, &D1c, &L2c);
Modified: trunk/coregrind/m_debuginfo/readelf.c
===================================================================
--- trunk/coregrind/m_debuginfo/readelf.c 2007-09-17 00:41:18 UTC (rev 6840)
+++ trunk/coregrind/m_debuginfo/readelf.c 2007-09-17 05:30:48 UTC (rev 6841)
@@ -516,9 +516,9 @@
TRACE_SYMTAB("\nReading (ELF, ppc64-linux) %s (%d entries)\n", tab_name,
o_symtab_sz/sizeof(ElfXX_Sym) );
- oset = VG_(OSet_Create)( offsetof(TempSym,key),
- (OSetCmp_t)cmp_TempSymKey,
- oset_malloc, oset_free );
+ oset = VG_(OSetGen_Create)( offsetof(TempSym,key),
+ (OSetCmp_t)cmp_TempSymKey,
+ oset_malloc, oset_free );
vg_assert(oset);
/* Perhaps should start at i = 1; ELF docs suggest that entry
@@ -542,7 +542,7 @@
/* Check if we've seen this (name,addr) key before. */
key.addr = sym_addr_really;
key.name = sym_name_really;
- prev = VG_(OSet_Lookup)( oset, &key );
+ prev = VG_(OSetGen_Lookup)( oset, &key );
if (prev) {
@@ -604,13 +604,13 @@
} else {
/* A new (name,addr) key. Add and continue. */
- elem = VG_(OSet_AllocNode)(oset, sizeof(TempSym));
+ elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym));
vg_assert(elem);
elem->key = key;
elem->tocptr = sym_tocptr;
elem->size = sym_size;
elem->from_opd = from_opd;
- VG_(OSet_Insert)(oset, elem);
+ VG_(OSetGen_Insert)(oset, elem);
if (si->trace_symtab) {
VG_(printf)(" to-oset [%4d]: "
" val %010p, toc %010p, sz %4d %s\n",
@@ -629,9 +629,9 @@
build a "standard" symbol table, and nuke the oset. */
i = 0;
- VG_(OSet_ResetIter)( oset );
+ VG_(OSetGen_ResetIter)( oset );
- while ( (elem = VG_(OSet_Next)(oset)) ) {
+ while ( (elem = VG_(OSetGen_Next)(oset)) ) {
risym.addr = elem->key.addr;
risym.size = elem->size;
risym.name = ML_(addStr) ( si, elem->key.name, -1 );
@@ -651,7 +651,7 @@
i++;
}
- VG_(OSet_Destroy)( oset, NULL );
+ VG_(OSetGen_Destroy)( oset );
}
Modified: trunk/coregrind/m_oset.c
===================================================================
--- trunk/coregrind/m_oset.c 2007-09-17 00:41:18 UTC (rev 6840)
+++ trunk/coregrind/m_oset.c 2007-09-17 05:30:48 UTC (rev 6841)
@@ -56,7 +56,7 @@
// keyOff -> | key | elemSize
// +---------------+ v
//
-// Users have to allocate AvlNodes with OSet_AllocNode(), which allocates
+// Users have to allocate AvlNodes with OSetGen_AllocNode(), which allocates
// space for the metadata.
//
// The terminology used throughout this file:
@@ -70,7 +70,7 @@
// an AvlNode.
//
// Each tree also has an iterator. Note that we cannot use the iterator
-// internally within this file (eg. we could implement OSet_Size() by
+// internally within this file (eg. we could implement OSetGen_Size() by
// stepping through with the iterator and counting nodes) because it's
// non-reentrant -- the user might be using it themselves, and the
// concurrent uses would screw things up.
@@ -85,6 +85,8 @@
/*--- Types and constants ---*/
/*--------------------------------------------------------------------*/
+typedef struct _OSetNode OSetNode;
+
// Internal names for the OSet types.
typedef OSet AvlTree;
typedef OSetNode AvlNode;
@@ -133,7 +135,7 @@
vg_assert2(n->magic == OSET_MAGIC,
"bad magic on node %p = %x (expected %x)\n"
"possible causes:\n"
- " - node not allocated with VG_(OSet_AllocNode)()?\n"
+ " - node not allocated with VG_(OSetGen_AllocNode)()?\n"
" - node metadata corrupted by underwriting start of element?\n",
n, n->magic, OSET_MAGIC);
return n;
@@ -268,8 +270,8 @@
/*--------------------------------------------------------------------*/
// The underscores avoid GCC complaints about overshadowing global names.
-AvlTree* VG_(OSet_Create)(OffT _keyOff, OSetCmp_t _cmp,
- OSetAlloc_t _alloc, OSetFree_t _free)
+AvlTree* VG_(OSetGen_Create)(OffT _keyOff, OSetCmp_t _cmp,
+ OSetAlloc_t _alloc, OSetFree_t _free)
{
AvlTree* t;
@@ -293,8 +295,13 @@
return t;
}
+AvlTree* VG_(OSetWord_Create)(OSetAlloc_t _alloc, OSetFree_t _free)
+{
+ return VG_(OSetGen_Create)(/*keyOff*/0, /*cmp*/NULL, _alloc, _free);
+}
+
// Destructor, frees up all memory held by remaining nodes.
-void VG_(OSet_Destroy)(AvlTree* t, OSetNodeDestroy_t destroyNode)
+void VG_(OSetGen_Destroy)(AvlTree* t)
{
AvlNode* n = NULL;
Int i = 0, sz = 0;
@@ -304,8 +311,8 @@
if (t->root)
stackPush(t, t->root, 1);
- // Free all the AvlNodes. This is a post-order traversal, because we
- // must free all children of a node before the node itself.
+ /* Free all the AvlNodes. This is a post-order traversal, because we */
+ /* must free all children of a node before the node itself. */
while (stackPop(t, &n, &i)) {
switch (i) {
case 1:
@@ -317,7 +324,6 @@
if (n->right) stackPush(t, n->right, 1);
break;
case 3:
- if (destroyNode) destroyNode(n);
t->free(n);
sz++;
break;
@@ -325,12 +331,17 @@
}
vg_assert(sz == t->nElems);
- // Free the AvlTree itself.
+ /* Free the AvlTree itself. */
t->free(t);
}
+void VG_(OSetWord_Destroy)(AvlTree* t)
+{
+ VG_(OSetGen_Destroy)(t);
+}
+
// Allocate and initialise a new node.
-void* VG_(OSet_AllocNode)(AvlTree* t, SizeT elemSize)
+void* VG_(OSetGen_AllocNode)(AvlTree* t, SizeT elemSize)
{
Int nodeSize = sizeof(AvlNode) + elemSize;
AvlNode* n = t->alloc( nodeSize );
@@ -340,7 +351,7 @@
return elem_of_node(n);
}
-void VG_(OSet_FreeNode)(AvlTree* t, void* e)
+void VG_(OSetGen_FreeNode)(AvlTree* t, void* e)
{
t->free( node_of_elem(e) );
}
@@ -427,19 +438,19 @@
}
} else {
- vg_assert2(0, "OSet_Insert: duplicate element added");
+ vg_assert2(0, "OSet{Word,Gen}_Insert: duplicate element added");
}
}
// Insert element e into the AVL tree t. This is just a wrapper for
// avl_insert() which doesn't return a Bool.
-void VG_(OSet_Insert)(AvlTree* t, void* e)
+void VG_(OSetGen_Insert)(AvlTree* t, void* e)
{
AvlNode* n;
vg_assert(t);
- // Initialise. Even though OSet_AllocNode zeroes these fields, we should
+ // Initialise. Even though OSetGen_AllocNode zeroes these fields, we should
// do it again in case a node is removed and then re-added to the tree.
n = node_of_elem(e);
n->left = 0;
@@ -457,6 +468,13 @@
t->stackTop = 0; // So the iterator can't get out of sync
}
+void VG_(OSetWord_Insert)(AvlTree* t, Word val)
+{
+ Word* node = VG_(OSetGen_AllocNode)(t, sizeof(Word));
+ *node = val;
+ VG_(OSetGen_Insert)(t, node);
+}
+
/*--------------------------------------------------------------------*/
/*--- Lookup ---*/
/*--------------------------------------------------------------------*/
@@ -493,7 +511,7 @@
}
// Find the *element* in t matching k, or NULL if not found.
-void* VG_(OSet_Lookup)(AvlTree* t, void* k)
+void* VG_(OSetGen_Lookup)(AvlTree* t, void* k)
{
AvlNode* n;
vg_assert(t);
@@ -503,7 +521,7 @@
// Find the *element* in t matching k, or NULL if not found; use the given
// comparison function rather than the standard one.
-void* VG_(OSet_LookupWithCmp)(AvlTree* t, void* k, OSetCmp_t cmp)
+void* VG_(OSetGen_LookupWithCmp)(AvlTree* t, void* k, OSetCmp_t cmp)
{
// Save the normal one to the side, then restore once we're done.
void* e;
@@ -511,17 +529,22 @@
vg_assert(t);
tmpcmp = t->cmp;
t->cmp = cmp;
- e = VG_(OSet_Lookup)(t, k);
+ e = VG_(OSetGen_Lookup)(t, k);
t->cmp = tmpcmp;
return e;
}
// Is there an element matching k?
-Bool VG_(OSet_Contains)(AvlTree* t, void* k)
+Bool VG_(OSetGen_Contains)(AvlTree* t, void* k)
{
- return (NULL != VG_(OSet_Lookup)(t, k));
+ return (NULL != VG_(OSetGen_Lookup)(t, k));
}
+Bool VG_(OSetWord_Contains)(AvlTree* t, Word val)
+{
+ return (NULL != VG_(OSetGen_Lookup)(t, &val));
+}
+
/*--------------------------------------------------------------------*/
/*--- Deletion ---*/
/*--------------------------------------------------------------------*/
@@ -650,7 +673,7 @@
}
// Remove and return the element matching the key 'k', or NULL if not present.
-void* VG_(OSet_Remove)(AvlTree* t, void* k)
+void* VG_(OSetGen_Remove)(AvlTree* t, void* k)
{
// Have to find the node first, then remove it.
AvlNode* n = avl_lookup(t, k);
@@ -664,15 +687,26 @@
}
}
+Bool VG_(OSetWord_Remove)(AvlTree* t, Word val)
+{
+ void* n = VG_(OSetGen_Remove)(t, &val);
+ if (n) {
+ VG_(OSetGen_FreeNode)(t, n);
+ return True;
+ } else {
+ return False;
+ }
+}
+
/*--------------------------------------------------------------------*/
/*--- Iterator ---*/
/*--------------------------------------------------------------------*/
// The iterator is implemented using in-order traversal with an explicit
// stack, which lets us do the traversal one step at a time and remember
-// where we are between each call to OSet_Next().
+// where we are between each call to OSetGen_Next().
-void VG_(OSet_ResetIter)(AvlTree* t)
+void VG_(OSetGen_ResetIter)(AvlTree* t)
{
vg_assert(t);
stackClear(t);
@@ -680,8 +714,13 @@
stackPush(t, t->root, 1);
}
-void* VG_(OSet_Next)(AvlTree* t)
+void VG_(OSetWord_ResetIter)(AvlTree* t)
{
+ VG_(OSetGen_ResetIter)(t);
+}
+
+void* VG_(OSetGen_Next)(AvlTree* t)
+{
Int i = 0;
OSetNode* n = NULL;
@@ -710,16 +749,32 @@
return NULL;
}
+Bool VG_(OSetWord_Next)(AvlTree* t, Word* val)
+{
+ Word* n = VG_(OSetGen_Next)(t);
+ if (n) {
+ *val = *n;
+ return True;
+ } else {
+ return False;
+ }
+}
+
/*--------------------------------------------------------------------*/
/*--- Miscellaneous operations ---*/
/*--------------------------------------------------------------------*/
-Int VG_(OSet_Size)(AvlTree* t)
+Int VG_(OSetGen_Size)(AvlTree* t)
{
vg_assert(t);
return t->nElems;
}
+Int VG_(OSetWord_Size)(AvlTree* t)
+{
+ return VG_(OSetGen_Size)(t);
+}
+
static void OSet_Print2( AvlTree* t, AvlNode* n,
Char*(*strElem)(void *), Int p )
{
Modified: trunk/coregrind/m_redir.c
===================================================================
--- trunk/coregrind/m_redir.c 2007-09-17 00:41:18 UTC (rev 6840)
+++ trunk/coregrind/m_redir.c 2007-09-17 05:30:48 UTC (rev 6841)
@@ -544,7 +544,7 @@
goto bad;
}
- old = VG_(OSet_Lookup)( activeSet, &act.from_addr );
+ old = VG_(OSetGen_Lookup)( activeSet, &act.from_addr );
if (old) {
/* Dodgy. Conflicting binding. */
vg_assert(old->from_addr == act.from_addr);
@@ -559,10 +559,10 @@
/* XXXXXXXXXXX COMPLAIN if new and old parents differ */
}
} else {
- Active* a = VG_(OSet_AllocNode)(activeSet, sizeof(Active));
+ Active* a = VG_(OSetGen_AllocNode)(activeSet, sizeof(Active));
vg_assert(a);
*a = act;
- VG_(OSet_Insert)(activeSet, a);
+ VG_(OSetGen_Insert)(activeSet, a);
/* Now that a new from->to redirection is in force, we need to
get rid of any translations intersecting 'from' in order that
they get redirected to 'to'. So discard them. Just for
@@ -597,7 +597,7 @@
OSet* tmpSet;
Active* act;
Bool delMe;
- Addr* addrP;
+ Addr addr;
vg_assert(delsi);
@@ -617,13 +617,12 @@
/* Traverse the actives, copying the addresses of those we intend
to delete into tmpSet. */
- tmpSet = VG_(OSet_Create)( 0/*keyOff*/, NULL/*fastCmp*/,
- symtab_alloc, symtab_free);
+ tmpSet = VG_(OSetWord_Create)(symtab_alloc, symtab_free);
ts->mark = True;
- VG_(OSet_ResetIter)( activeSet );
- while ( (act = VG_(OSet_Next)(activeSet)) ) {
+ VG_(OSetGen_ResetIter)( activeSet );
+ while ( (act = VG_(OSetGen_Next)(activeSet)) ) {
delMe = act->parent_spec != NULL
&& act->parent_sym != NULL
&& act->parent_spec->seginfo != NULL
@@ -644,9 +643,7 @@
}
if (delMe) {
- addrP = VG_(OSet_AllocNode)( tmpSet, sizeof(Addr) );
- *addrP = act->from_addr;
- VG_(OSet_Insert)( tmpSet, addrP );
+ VG_(OSetWord_Insert)( tmpSet, act->from_addr );
/* While we have our hands on both the 'from' and 'to'
of this Active, do paranoid stuff with tt/tc. */
VG_(discard_translations)( (Addr64)act->from_addr, 1,
@@ -656,16 +653,15 @@
}
}
- /* Now traverse tmpSet, deleting corresponding elements in
- activeSet. */
- VG_(OSet_ResetIter)( tmpSet );
- while ( (addrP = VG_(OSet_Next)(tmpSet)) ) {
- act = VG_(OSet_Remove)( activeSet, addrP );
+ /* Now traverse tmpSet, deleting corresponding elements in activeSet. */
+ VG_(OSetWord_ResetIter)( tmpSet );
+ while ( VG_(OSetWord_Next)(tmpSet, &addr) ) {
+ act = VG_(OSetGen_Remove)( activeSet, &addr );
vg_assert(act);
- VG_(OSet_FreeNode)( activeSet, act );
+ VG_(OSetGen_FreeNode)( activeSet, act );
}
- VG_(OSet_Destroy)( tmpSet, NULL );
+ VG_(OSetWord_Destroy)( tmpSet );
/* The Actives set is now cleaned up. Free up this TopSpec and
everything hanging off it. */
@@ -698,7 +694,7 @@
just before translating a basic block. */
Addr VG_(redir_do_lookup) ( Addr orig, Bool* isWrap )
{
- Active* r = VG_(OSet_Lookup)(activeSet, &orig);
+ Active* r = VG_(OSetGen_Lookup)(activeSet, &orig);
if (r == NULL)
return orig;
@@ -776,10 +772,10 @@
vg_assert( VG_(next_seginfo)(NULL) == NULL );
// Initialise active mapping.
- activeSet = VG_(OSet_Create)(offsetof(Active, from_addr),
- NULL, // Use fast comparison
- symtab_alloc,
- symtab_free);
+ activeSet = VG_(OSetGen_Create)(offsetof(Active, from_addr),
+ NULL, // Use fast comparison
+ symtab_alloc,
+ symtab_free);
// The rest of this function just adds initial Specs.
@@ -1003,8 +999,8 @@
show_spec(" ", sp);
}
VG_(message)(Vg_DebugMsg, " ------ ACTIVE ------");
- VG_(OSet_ResetIter)( activeSet );
- while ( (act = VG_(OSet_Next)(activeSet)) ) {
+ VG_(OSetGen_ResetIter)( activeSet );
+ while ( (act = VG_(OSetGen_Next)(activeSet)) ) {
show_active(" ", act);
}
Modified: trunk/include/pub_tool_oset.h
===================================================================
--- trunk/include/pub_tool_oset.h 2007-09-17 00:41:18 UTC (rev 6840)
+++ trunk/include/pub_tool_oset.h 2007-09-17 05:30:48 UTC (rev 6841)
@@ -36,24 +36,32 @@
// elements. It does not allow duplicates, and will assert if you insert a
// duplicate to an OSet.
//
-// The structure is totally generic. The user provides the allocation and
-// deallocation functions. Also, each element has a key, which the lookup
-// is done with. The key may be the whole element (eg. in an OSet of
-// integers, each integer serves both as an element and a key), or it may be
-// only part of it (eg. if the key is a single field in a struct). The user
-// can provide a function that compares an element with a key; this is very
-// flexible, and with the right comparison function even a (non-overlapping)
-// interval list can be created. But the cost of calling a function for
-// every comparison can be high during lookup. If no comparison function is
-// provided, we assume that keys are (signed or unsigned) words, and that
-// the key is the first word in each element. This fast comparison is
-// suitable for an OSet of Words, or an OSet containing structs where the
-// first element is an Addr, for example.
+// It has two interfaces.
//
-// Each OSet also has an iterator, which makes it simple to traverse all the
-// nodes in order. Note that the iterator maintains state and so is
-// non-reentrant.
+// - The "OSetWord_" interface provides an easier-to-use interface for the
+// case where you just want to store Word-sized values. The user provides
+// the allocation and deallocation functions, and possibly a comparison
+// function.
//
+// - The "OSetGen_" interface provides a totally generic interface, which
+// allows any kind of structure to be put into the set. The user provides
+// the allocation and deallocation functions. Also, each element has a
+// key, which the lookup is done with. The key may be the whole element
+// (eg. in an OSet of integers, each integer serves both as an element and
+// a key), or it may be only part of it (eg. if the key is a single field
+// in a struct). The user can provide a function that compares an element
+// with a key; this is very flexible, and with the right comparison
+// function even a (non-overlapping) interval list can be created. But
+// the cost of calling a function for every comparison can be high during
+// lookup. If no comparison function is provided, we assume that keys are
+// (signed or unsigned) words, and that the key is the first word in each
+// element. This fast comparison is suitable for an OSet containing
+// structs where the first element is an Addr, for example.
+//
+// Each OSet interface also has an iterator, which makes it simple to
+// traverse all the nodes in order. Note that the iterator maintains state
+// and so is non-reentrant.
+//
// Note that once you insert an element into an OSet, if you modify any part
// of it looked at by your cmp() function, this may cause incorrect
// behaviour as the sorted order maintained will be wrong.
@@ -63,25 +71,97 @@
/*--------------------------------------------------------------------*/
typedef struct _OSet OSet;
-typedef struct _OSetNode OSetNode;
+// - Cmp: returns -1, 0 or 1 if key is <=, == or >= elem.
+// - Alloc: allocates a chunk of memory.
+// - Free: frees a chunk of memory allocated with Alloc.
+
typedef Word (*OSetCmp_t) ( void* key, void* elem );
typedef void* (*OSetAlloc_t) ( SizeT szB );
typedef void (*OSetFree_t) ( void* p );
-typedef void (*OSetNodeDestroy_t) ( void* elem );
/*--------------------------------------------------------------------*/
-/*--- Creating and destroying OSets and OSet members ---*/
+/*--- Creating and destroying OSets (Word) ---*/
/*--------------------------------------------------------------------*/
// * Create: allocates and initialises the OSet. Arguments:
+// - alloc The allocation function used internally for allocating the
+// OSet and all its nodes.
+// - free The deallocation function used internally for freeing nodes
+// called by VG_(OSetWord_Destroy)().
+//
+// * CreateWithCmp: like Create, but you specify your own comparison
+// function.
+//
+// * Destroy: frees all nodes in the table, plus the memory used by
+// the table itself. The passed-in function is called on each node first
+// to allow the destruction of any attached resources; if NULL it is not
+// called.
+
+extern OSet* VG_(OSetWord_Create) ( OSetAlloc_t alloc, OSetFree_t free );
+extern void VG_(OSetWord_Destroy) ( OSet* os );
+
+/*--------------------------------------------------------------------*/
+/*--- Operations on OSets (Word) ---*/
+/*--------------------------------------------------------------------*/
+
+// In everything that follows, the parameter 'key' is always the *address*
+// of the key, and 'elem' is *address* of the elem, as are the return values
+// of the functions that return elems.
+//
+// * Size: The number of elements in the set.
+//
+// * Contains: Determines if the value is in the set.
+//
+// * Insert: Inserts a new element into the set. Duplicates are forbidden,
+// and will cause assertion failures.
+//
+// * Remove: Removes the value from the set, if present. Returns a Bool
+// indicating if the value was removed.
+//
+// * ResetIter: Each OSet has an iterator. This resets it to point to the
+// first element in the OSet.
+//
+// * Next: Copies the next value according to the OSet's iterator into &val,
+// advances the iterator by one, and returns True; the elements are
+// visited in order. Or, returns False if the iterator has reached the
+// set's end.
+//
+// You can thus iterate in order through a set like this:
+//
+// Word val;
+// VG_(OSetWord_ResetIter)(oset);
+// while ( VG_(OSetWord_Next)(oset, &val) ) {
+// ... do stuff with 'val' ...
+// }
+//
+// Note that iterators are cleared any time an element is inserted or
+// removed from the OSet, to avoid possible mayhem caused by the iterator
+// getting out of sync with the OSet's contents. "Cleared" means that
+// they will return False if VG_(OSetWord_Next)() is called without an
+// intervening call to VG_(OSetWord_ResetIter)().
+
+extern Int VG_(OSetWord_Size) ( OSet* os );
+extern void VG_(OSetWord_Insert) ( OSet* os, Word val );
+extern Bool VG_(OSetWord_Contains) ( OSet* os, Word val );
+extern Bool VG_(OSetWord_Remove) ( OSet* os, Word val );
+extern void VG_(OSetWord_ResetIter) ( OSet* os );
+extern Bool VG_(OSetWord_Next) ( OSet* os, Word* val );
+
+
+/*--------------------------------------------------------------------*/
+/*--- Creating and destroying OSets and OSet members (Gen) ---*/
+/*--------------------------------------------------------------------*/
+
+// * Create: allocates and initialises the OSet. Arguments:
// - keyOff The offset of the key within the element.
// - cmp The comparison function between keys and elements, or NULL
// if the OSet should use fast comparisons.
// - alloc The allocation function used for allocating the OSet itself;
-// it's also called for each invocation of VG_(OSet_AllocNode)().
-// - free The deallocation function used by VG_(OSet_FreeNode)() and
-// VG_(OSet_Destroy)().
+// it's also called for each invocation of
+// VG_(OSetGen_AllocNode)().
+// - free The deallocation function used by VG_(OSetGen_FreeNode)() and
+// VG_(OSetGen_Destroy)().
//
// If cmp is NULL, keyOff must be zero. This is checked.
//
@@ -91,25 +171,25 @@
// called.
//
// * AllocNode: Allocate and zero memory for a node to go into the OSet.
-// Uses the alloc function given to VG_(OSet_Create)() to allocated a node
-// which is big enough for both an element and the OSet metadata.
+// Uses the alloc function given to VG_(OSetGen_Create)() to allocated a
+// node which is big enough for both an element and the OSet metadata.
// Not all elements in one OSet have to be the same size.
//
// Note that the element allocated will be at most word-aligned, which may
// be less aligned than the element type would normally be.
//
-// * FreeNode: Deallocate a node allocated with OSet_AllocNode(). Using
+// * FreeNode: Deallocate a node allocated with OSetGen_AllocNode(). Using
// a deallocation function (such as VG_(free)()) directly will likely
// lead to assertions in Valgrind's allocator.
-extern OSet* VG_(OSet_Create) ( OffT keyOff, OSetCmp_t cmp,
- OSetAlloc_t alloc, OSetFree_t free );
-extern void VG_(OSet_Destroy) ( OSet* os, OSetNodeDestroy_t destroyNode );
-extern void* VG_(OSet_AllocNode) ( OSet* os, SizeT elemSize );
-extern void VG_(OSet_FreeNode) ( OSet* os, void* elem );
+extern OSet* VG_(OSetGen_Create) ( OffT keyOff, OSetCmp_t cmp,
+ OSetAlloc_t alloc, OSetFree_t free );
+extern void VG_(OSetGen_Destroy) ( OSet* os );
+extern void* VG_(OSetGen_AllocNode) ( OSet* os, SizeT elemSize );
+extern void VG_(OSetGen_FreeNode) ( OSet* os, void* elem );
/*--------------------------------------------------------------------*/
-/*--- Operations on OSets ---*/
+/*--- Operations on OSets (Gen) ---*/
/*--------------------------------------------------------------------*/
// In everything that follows, the parameter 'key' is always the *address*
@@ -118,6 +198,11 @@
//
// * Size: The number of elements in the set.
//
+// * Insert: Inserts a new element into the set. Note that 'elem' must
+// have been allocated using VG_(OSetGen_AllocNode)(), otherwise you will
+// get assertion failures about "bad magic". Duplicates are forbidden,
+// and will also cause assertion failures.
+//
// * Contains: Determines if any element in the OSet matches the key.
//
// * Lookup: Returns a pointer to the element matching the key, if there is
@@ -126,11 +211,6 @@
// * LookupWithCmp: Like Lookup, but you specify the comparison function,
// which overrides the OSet's normal one.
//
-// * Insert: Inserts a new element into the list. Note that 'elem' must
-// have been allocated using VG_(OSet_AllocNode)(), otherwise you will get
-// assertion failures about "bad magic". Duplicates are forbidden, and
-// will also cause assertion failures.
-//
// * Remove: Removes the element matching the key, if there is one. Returns
// NULL if no element matches the key.
//
@@ -141,27 +221,27 @@
// iterator, and advances the iterator by one; the elements are visited
// in order. Or, returns NULL if the iterator has reached the OSet's end.
//
-// You can thus iterate in order through an OSet like this:
+// You can thus iterate in order through a set like this:
//
-// VG_(OSet_ResetIter)(oset);
-// while ( (elem = VG_(OSet_Next)(oset)) ) {
+// VG_(OSetGen_ResetIter)(oset);
+// while ( (elem = VG_(OSetGen_Next)(oset)) ) {
// ... do stuff with 'elem' ...
// }
//
// Note that iterators are cleared any time an element is inserted or
// removed from the OSet, to avoid possible mayhem caused by the iterator
// getting out of sync with the OSet's contents. "Cleared" means that
-// they will return NULL if VG_(OSet_Next)() is called without an
-// intervening call to VG_(OSet_ResetIter)().
+// they will return NULL if VG_(OSetGen_Next)() is called without an
+// intervening call to VG_(OSetGen_ResetIter)().
-extern Int VG_(OSet_Size) ( OSet* os );
-extern void VG_(OSet_Insert) ( OSet* os, void* elem );
-extern Bool VG_(OSet_Contains) ( OSet* os, void* key );
-extern void* VG_(OSet_Lookup) ( OSet* os, void* key );
-extern void* VG_(OSet_LookupWithCmp)( OSet* os, void* key, OSetCmp_t cmp );
-extern void* VG_(OSet_Remove) ( OSet* os, void* key );
-extern void VG_(OSet_ResetIter) ( OSet* os );
-extern void* VG_(OSet_Next) ( OSet* os );
+extern Int VG_(OSetGen_Size) ( OSet* os );
+extern void VG_(OSetGen_Insert) ( OSet* os, void* elem );
+extern Bool VG_(OSetGen_Contains) ( OSet* os, void* key );
+extern void* VG_(OSetGen_Lookup) ( OSet* os, void* key );
+extern void* VG_(OSetGen_LookupWithCmp)( OSet* os, void* key, OSetCmp_t cmp );
+extern void* VG_(OSetGen_Remove) ( OSet* os, void* key );
+extern void VG_(OSetGen_ResetIter) ( OSet* os );
+extern void* VG_(OSetGen_Next) ( OSet* os );
#endif // __PUB_TOOL_OSET_H
Modified: trunk/memcheck/mc_main.c
===================================================================
--- trunk/memcheck/mc_main.c 2007-09-17 00:41:18 UTC (rev 6840)
+++ trunk/memcheck/mc_main.c 2007-09-17 05:30:48 UTC (rev 6841)
@@ -387,9 +387,9 @@
tl_assert(0 == offsetof(AuxMapEnt,base));
tl_assert(sizeof(Addr) == sizeof(void*));
- auxmap_L2 = VG_(OSet_Create)( /*keyOff*/ offsetof(AuxMapEnt,base),
- /*fastCmp*/ NULL,
- VG_(malloc), VG_(free) );
+ auxmap_L2 = VG_(OSetGen_Create)( /*keyOff*/ offsetof(AuxMapEnt,base),
+ /*fastCmp*/ NULL,
+ VG_(malloc), VG_(free) );
}
/* Check representation invariants; if OK return NULL; else a
@@ -418,7 +418,7 @@
*n_secmaps_found = 0;
if (sizeof(void*) == 4) {
/* 32-bit platform */
- if (VG_(OSet_Size)(auxmap_L2) != 0)
+ if (VG_(OSetGen_Size)(auxmap_L2) != 0)
return "32-bit: auxmap_L2 is non-empty";
for (i = 0; i < N_AUXMAP_L1; i++)
if (auxmap_L1[i].base != 0 || auxmap_L1[i].ent != NULL)
@@ -429,8 +429,8 @@
AuxMapEnt *elem, *res;
AuxMapEnt key;
/* L2 table */
- VG_(OSet_ResetIter)(auxmap_L2);
- while ( (elem = VG_(OSet_Next)(auxmap_L2)) ) {
+ VG_(OSetGen_ResetIter)(auxmap_L2);
+ while ( (elem = VG_(OSetGen_Next)(auxmap_L2)) ) {
elems_seen++;
if (0 != (elem->base & (Addr)0xFFFF))
return "64-bit: nonzero .base & 0xFFFF in auxmap_L2";
@@ -458,7 +458,7 @@
/* Look it up in auxmap_L2. */
key.base = auxmap_L1[i].base;
key.sm = 0;
- res = VG_(OSet_Lookup)(auxmap_L2, &key);
+ res = VG_(OSetGen_Lookup)(auxmap_L2, &key);
if (res == NULL)
return "64-bit: _L1 .base not found in _L2";
if (res != auxmap_L1[i].ent)
@@ -544,7 +544,7 @@
key.base = a;
key.sm = 0;
- res = VG_(OSet_Lookup)(auxmap_L2, &key);
+ res = VG_(OSetGen_Lookup)(auxmap_L2, &key);
if (res)
insert_into_auxmap_L1_at( AUXMAP_L1_INSERT_IX, res );
return res;
@@ -563,11 +563,11 @@
to allocate one. */
a &= ~(Addr)0xFFFF;
- nyu = (AuxMapEnt*) VG_(OSet_AllocNode)( auxmap_L2, sizeof(AuxMapEnt) );
+ nyu = (AuxMapEnt*) VG_(OSetGen_AllocNode)( auxmap_L2, sizeof(AuxMapEnt) );
tl_assert(nyu);
nyu->base = a;
nyu->sm = &sm_distinguished[SM_DIST_NOACCESS];
- VG_(OSet_Insert)( auxmap_L2, nyu );
+ VG_(OSetGen_Insert)( auxmap_L2, nyu );
insert_into_auxmap_L1_at( AUXMAP_L1_INSERT_IX, nyu );
n_auxmap_L2_nodes++;
return nyu;
@@ -879,9 +879,9 @@
static OSet* createSecVBitTable(void)
{
- return VG_(OSet_Create)( offsetof(SecVBitNode, a),
- NULL, // use fast comparisons
- VG_(malloc), VG_(free) );
+ return VG_(OSetGen_Create)( offsetof(SecVBitNode, a),
+ NULL, // use fast comparisons
+ VG_(malloc), VG_(free) );
}
static void gcSecVBitTable(void)
@@ -896,8 +896,8 @@
secVBitTable2 = createSecVBitTable();
// Traverse the table, moving fresh nodes into the new table.
- VG_(OSet_ResetIter)(secVBitTable);
- while ( (n = VG_(OSet_Next)(secVBitTable)) ) {
+ VG_(OSetGen_ResetIter)(secVBitTable);
+ while ( (n = VG_(OSetGen_Next)(secVBitTable)) ) {
Bool keep = False;
if ( (GCs_done - n->last_touched) <= MAX_STALE_AGE ) {
// Keep node if it's been touched recently enough (regardless of
@@ -918,18 +918,18 @@
if ( keep ) {
// Insert a copy of the node into the new table.
SecVBitNode* n2 =
- VG_(OSet_AllocNode)(secVBitTable2, sizeof(SecVBitNode));
+ VG_(OSetGen_AllocNode)(secVBitTable2, sizeof(SecVBitNode));
*n2 = *n;
- VG_(OSet_Insert)(secVBitTable2, n2);
+ VG_(OSetGen_Insert)(secVBitTable2, n2);
}
}
// Get the before and after sizes.
- n_nodes = VG_(OSet_Size)(secVBitTable);
- n_survivors = VG_(OSet_Size)(secVBitTable2);
+ n_nodes = VG_(OSetGen_Size)(secVBitTable);
+ n_survivors = VG_(OSetGen_Size)(secVBitTable2);
// Destroy the old table, and put the new one in its place.
- VG_(OSet_Destroy)(secVBitTable, NULL);
+ VG_(OSetGen_Destroy)(secVBitTable);
secVBitTable = secVBitTable2;
if (VG_(clo_verbosity) > 1) {
@@ -952,7 +952,7 @@
{
Addr aAligned = VG_ROUNDDN(a, BYTES_PER_SEC_VBIT_NODE);
Int amod = a % BYTES_PER_SEC_VBIT_NODE;
- SecVBitNode* n = VG_(OSet_Lookup)(secVBitTable, &aAligned);
+ SecVBitNode* n = VG_(OSetGen_Lookup)(secVBitTable, &aAligned);
UChar vbits8;
tl_assert2(n, "get_sec_vbits8: no node for address %p (%p)\n", aAligned, a);
// Shouldn't be fully defined or fully undefined -- those cases shouldn't
@@ -966,7 +966,7 @@
{
Addr aAligned = VG_ROUNDDN(a, BYTES_PER_SEC_VBIT_NODE);
Int i, amod = a % BYTES_PER_SEC_VBIT_NODE;
- SecVBitNode* n = VG_(OSet_Lookup)(secVBitTable, &aAligned);
+ SecVBitNode* n = VG_(OSetGen_Lookup)(secVBitTable, &aAligned);
// Shouldn't be fully defined or fully undefined -- those cases shouldn't
// make it to the secondary V bits table.
tl_assert(V_BITS8_DEFINED != vbits8 && V_BITS8_UNDEFINED != vbits8);
@@ -977,7 +977,7 @@
} else {
// New node: assign the specific byte, make the rest invalid (they
// should never be read as-is, but be cautious).
- n = VG_(OSet_AllocNode)(secVBitTable, sizeof(SecVBitNode));
+ n = VG_(OSetGen_AllocNode)(secVBitTable, sizeof(SecVBitNode));
n->a = aAligned;
for (i = 0; i < BYTES_PER_SEC_VBIT_NODE; i++) {
n->vbits8[i] = V_BITS8_UNDEFINED;
@@ -987,15 +987,15 @@
// Do a table GC if necessary. Nb: do this before inserting the new
// node, to avoid erroneously GC'ing the new node.
- if (secVBitLimit == VG_(OSet_Size)(secVBitTable)) {
+ if (secVBitLimit == VG_(OSetGen_Size)(secVBitTable)) {
gcSecVBitTable();
}
// Insert the new node.
- VG_(OSet_Insert)(secVBitTable, n);
+ VG_(OSetGen_Insert)(secVBitTable, n);
sec_vbits_new_nodes++;
- n_secVBit_nodes = VG_(OSet_Size)(secVBitTable);
+ n_secVBit_nodes = VG_(OSetGen_Size)(secVBitTable);
if (n_secVBit_nodes > max_secVBit_nodes)
max_secVBit_nodes = n_secVBit_nodes;
}
@@ -4316,7 +4316,7 @@
/* If we're not checking for undefined value errors, the secondary V bit
* table should be empty. */
if (!MC_(clo_undef_value_errors)) {
- if (0 != VG_(OSet_Size)(secVBitTable))
+ if (0 != VG_(OSetGen_Size)(secVBitTable))
return False;
}
Modified: trunk/memcheck/tests/oset_test.c
===================================================================
--- trunk/memcheck/tests/oset_test.c 2007-09-17 00:41:18 UTC (rev 6840)
+++ trunk/memcheck/tests/oset_test.c 2007-09-17 05:30:48 UTC (rev 6841)
@@ -77,23 +77,24 @@
// Create a static OSet of Ints. This one uses fast (built-in)
// comparisons.
- OSet* oset1 = VG_(OSet_Create)(0,
+ OSet* oset = VG_(OSetGen_Create)(0,
NULL,
(void*)malloc, free);
// Try some operations on an empty OSet to ensure they don't screw up.
- vg_assert( ! VG_(OSet_Contains)(oset1, &v) );
- vg_assert( ! VG_(OSet_Lookup)(oset1, &v) );
- vg_assert( ! VG_(OSet_Remove)(oset1, &v) );
- vg_assert( ! VG_(OSet_Next)(oset1) );
- vg_assert( 0 == VG_(OSet_Size)(oset1) );
+ vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
+ vg_assert( 0 == VG_(OSetGen_Size)(oset) );
// Create some elements, with gaps (they're all even) but no dups,
// and shuffle them randomly.
for (i = 0; i < NN; i++) {
- vs[i] = VG_(OSet_AllocNode)(oset1, sizeof(Word));
+ vs[i] = VG_(OSetGen_AllocNode)(oset, sizeof(Word));
*(vs[i]) = 2*i;
}
+ seed = 0;
for (i = 0; i < NN; i++) {
Word r1 = myrandom() % NN;
Word r2 = myrandom() % NN;
@@ -104,32 +105,32 @@
// Insert the elements
for (i = 0; i < NN; i++) {
- VG_(OSet_Insert)(oset1, vs[i]);
+ VG_(OSetGen_Insert)(oset, vs[i]);
}
// Check the size
- vg_assert( NN == VG_(OSet_Size)(oset1) );
+ vg_assert( NN == VG_(OSetGen_Size)(oset) );
// Check we can find all the elements we inserted
for (i = 0; i < NN; i++) {
- assert( VG_(OSet_Contains)(oset1, vs[i]) );
+ assert( VG_(OSetGen_Contains)(oset, vs[i]) );
}
// Check we cannot find elements we did not insert, below, within (odd
// numbers), and above the inserted elements.
v = -1;
- assert( ! VG_(OSet_Contains)(oset1, &v) );
+ assert( ! VG_(OSetGen_Contains)(oset, &v) );
for (i = 0; i < NN; i++) {
v = *(vs[i]) + 1;
- assert( ! VG_(OSet_Contains)(oset1, &v) );
+ assert( ! VG_(OSetGen_Contains)(oset, &v) );
}
v = NN*2;
- assert( ! VG_(OSet_Contains)(oset1, &v) );
+ assert( ! VG_(OSetGen_Contains)(oset, &v) );
// Check we can find all the elements we inserted, and the right values
// are returned.
for (i = 0; i < NN; i++) {
- assert( vs[i] == VG_(OSet_Lookup)(oset1, vs[i]) );
+ assert( vs[i] == VG_(OSetGen_Lookup)(oset, vs[i]) );
}
// Check that we can iterate over the OSet elements in sorted order, and
@@ -137,70 +138,189 @@
n = 0;
pv = NULL;
prev = -1;
- VG_(OSet_ResetIter)(oset1);
- while ( (pv = VG_(OSet_Next)(oset1)) ) {
+ VG_(OSetGen_ResetIter)(oset);
+ while ( (pv = VG_(OSetGen_Next)(oset)) ) {
Word curr = *pv;
assert(prev < curr);
prev = curr;
n++;
}
assert(NN == n);
- vg_assert( ! VG_(OSet_Next)(oset1) );
- vg_assert( ! VG_(OSet_Next)(oset1) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
// Check that we can remove half of the elements, and that their values
// are as expected.
for (i = 0; i < NN; i += 2) {
- assert( pv = VG_(OSet_Remove)(oset1, vs[i]) );
+ assert( pv = VG_(OSetGen_Remove)(oset, vs[i]) );
assert( pv == vs[i] );
}
// Check the size
- vg_assert( NN/2 == VG_(OSet_Size)(oset1) );
+ vg_assert( NN/2 == VG_(OSetGen_Size)(oset) );
// Check we can find the remaining elements (with the right values).
for (i = 1; i < NN; i += 2) {
- assert( pv = VG_(OSet_LookupWithCmp)(oset1, vs[i], NULL) );
+ assert( pv = VG_(OSetGen_LookupWithCmp)(oset, vs[i], NULL) );
assert( pv == vs[i] );
}
// Check we cannot find any of the elements we removed.
for (i = 0; i < NN; i += 2) {
- assert( ! VG_(OSet_Contains)(oset1, vs[i]) );
+ assert( ! VG_(OSetGen_Contains)(oset, vs[i]) );
}
// Check that we can remove the remaining half of the elements, and that
// their values are as expected.
for (i = 1; i < NN; i += 2) {
- assert( pv = VG_(OSet_Remove)(oset1, vs[i]) );
+ assert( pv = VG_(OSetGen_Remove)(oset, vs[i]) );
assert( pv == vs[i] );
}
// Try some more operations on the empty OSet to ensure they don't screw up.
- vg_assert( ! VG_(OSet_Contains)(oset1, &v) );
- vg_assert( ! VG_(OSet_Lookup)(oset1, &v) );
- vg_assert( ! VG_(OSet_Remove)(oset1, &v) );
- vg_assert( ! VG_(OSet_Next)(oset1) );
- vg_assert( 0 == VG_(OSet_Size)(oset1) );
+ vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
+ vg_assert( 0 == VG_(OSetGen_Size)(oset) );
// Free a few elements
- VG_(OSet_FreeNode)(oset1, vs[0]);
- VG_(OSet_FreeNode)(oset1, vs[1]);
- VG_(OSet_FreeNode)(oset1, vs[2]);
+ VG_(OSetGen_FreeNode)(oset, vs[0]);
+ VG_(OSetGen_FreeNode)(oset, vs[1]);
+ VG_(OSetGen_FreeNode)(oset, vs[2]);
- // Re-insert remaining elements, to give OSet_Destroy something to work with.
+ // Re-insert remaining elements, to give OSetGen_Destroy something to
+ // work with.
for (i = 3; i < NN; i++) {
- VG_(OSet_Insert)(oset1, vs[i]);
+ VG_(OSetGen_Insert)(oset, vs[i]);
}
// Print the list
- OSet_Print(oset1, "foo", wordToStr);
+ OSet_Print(oset, "oset1", wordToStr);
// Destroy the OSet
- VG_(OSet_Destroy)(oset1, NULL);
+ VG_(OSetGen_Destroy)(oset);
}
+void example1b(void)
+{
+ Int i, n;
+ Word v = 0, prev;
+ Word vs[NN];
+ Word *pv;
+
+ // Create a static OSet of Ints. This one uses fast (built-in)
+ // comparisons.
+ OSet* oset = VG_(OSetWord_Create)( (void*)malloc, free);
+
+ // Try some operations on an empty OSet to ensure they don't screw up.
+ vg_assert( ! VG_(OSetWord_Contains)(oset, v) );
+ vg_assert( ! VG_(OSetWord_Remove)(oset, v) );
+ vg_assert( ! VG_(OSetWord_Next)(oset, &v) );
+ vg_assert( 0 == VG_(OSetWord_Size)(oset) );
+
+ // Create some elements, with gaps (they're all even) but no dups,
+ // and shuffle them randomly.
+ for (i = 0; i < NN; i++) {
+ vs[i] = 2*i;
+ }
+ seed = 0;
+ for (i = 0; i < NN; i++) {
+ Word r1 = myrandom() % NN;
+ Word r2 = myrandom() % NN;
+ Word tmp = vs[r1];
+ vs[r1] = vs[r2];
+ vs[r2] = tmp;
+ }
+
+ // Insert the elements
+ for (i = 0; i < NN; i++) {
+ VG_(OSetWord_Insert)(oset, vs[i]);
+ }
+
+ // Check the size
+ vg_assert( NN == VG_(OSetWord_Size)(oset) );
+
+ // Check we can find all the elements we inserted
+ for (i = 0; i < NN; i++) {
+ assert( VG_(OSetWord_Contains)(oset, vs[i]) );
+ }
+
+ // Check we cannot find elements we did not insert, below, within (odd
+ // numbers), and above the inserted elements.
+ v = -1;
+ assert( ! VG_(OSetWord_Contains)(oset, v) );
+ for (i = 0; i < NN; i++) {
+ v = vs[i] + 1;
+ assert( ! VG_(OSetWord_Contains)(oset, v) );
+ }
+ v = NN*2;
+ assert( ! VG_(OSetWord_Contains)(oset, v) );
+
+ // Check we can find all the elements we inserted.
+ for (i = 0; i < NN; i++) {
+ assert( VG_(OSetWord_Contains)(oset, vs[i]) );
+ }
+
+ // Check that we can iterate over the OSet elements in sorted order, and
+ // there is the right number of them.
+ n = 0;
+ prev = -1;
+ VG_(OSetWord_ResetIter)(oset);
+ while ( VG_(OSetWord_Next)(oset, &v) ) {
+ Word curr = v;
+ assert(prev < curr);
+ prev = curr;
+ n++;
+ }
+ assert(NN == n);
+ vg_assert( ! VG_(OSetWord_Next)(oset, &v) );
+ vg_assert( ! VG_(OSetWord_Next)(oset, &v) );
+
+ // Check that we can remove half of the elements.
+ for (i = 0; i < NN; i += 2) {
+ assert( VG_(OSetWord_Remove)(oset, vs[i]) );
+ }
+
+ // Check the size
+ vg_assert( NN/2 == VG_(OSetWord_Size)(oset) );
+
+ // Check we can find the remaining elements (with the right values).
+ for (i = 1; i < NN; i += 2) {
+ assert( VG_(OSetWord_Contains)(oset, vs[i]) );
+ }
+
+ // Check we cannot find any of the elements we removed.
+ for (i = 0; i < NN; i += 2) {
+ assert( ! VG_(OSetWord_Contains)(oset, vs[i]) );
+ }
+
+ // Check that we can remove the remaining half of the elements.
+ for (i = 1; i < NN; i += 2) {
+ assert( VG_(OSetWord_Remove)(oset, vs[i]) );
+ }
+
+ // Try some more operations on the empty OSet to ensure they don't screw up.
+ vg_assert( ! VG_(OSetWord_Contains)(oset, v) );
+ vg_assert( ! VG_(OSetWord_Remove)(oset, v) );
+ vg_assert( ! VG_(OSetWord_Next)(oset, &v) );
+ vg_assert( 0 == VG_(OSetWord_Size)(oset) );
+
+ // Re-insert remaining elements, to give OSetWord_Destroy something to
+ // work with.
+ for (i = 3; i < NN; i++) {
+ VG_(OSetWord_Insert)(oset, vs[i]);
+ }
+
+ // Print the list
+ OSet_Print(oset, "oset1b", wordToStr);
+
+ // Destroy the OSet
+ VG_(OSetWord_Destroy)(oset);
+}
+
+
//---------------------------------------------------------------------------
// Struct example
//---------------------------------------------------------------------------
@@ -248,26 +368,27 @@
// Create a dynamic OSet of Blocks. This one uses slow (custom)
// comparisons.
- OSet* oset2 = VG_(OSet_Create)(offsetof(Block, first),
+ OSet* oset = VG_(OSetGen_Create)(offsetof(Block, first),
blockCmp,
(void*)malloc, free);
// Try some operations on an empty OSet to ensure they don't screw up.
- vg_assert( ! VG_(OSet_Contains)(oset2, &v) );
- vg_assert( ! VG_(OSet_Lookup)(oset2, &v) );
- vg_assert( ! VG_(OSet_Remove)(oset2, &v) );
- vg_assert( ! VG_(OSet_Next)(oset2) );
- vg_assert( 0 == VG_(OSet_Size)(oset2) );
+ vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
+ vg_assert( 0 == VG_(OSetGen_Size)(oset) );
// Create some inputs, with gaps -- intervals are 1..3, 11..13, ... -- but
// no dups, and shuffle them randomly.
for (i = 0; i < NN; i++) {
- vs[i] = VG_(OSet_AllocNode)(oset2, sizeof(Block));
+ vs[i] = VG_(OSetGen_AllocNode)(oset, sizeof(Block));
vs[i]->b1 = i;
vs[i]->first = i*10 + 1;
vs[i]->last = vs[i]->first + 2;
vs[i]->b2 = i+1;
}
+ seed = 0;
for (i = 0; i < NN; i++) {
Int r1 = myrandom() % NN;
Int r2 = myrandom() % NN;
@@ -278,36 +399,36 @@
// Insert the elements
for (i = 0; i < NN; i++) {
- VG_(OSet_Insert)(oset2, vs[i]);
+ VG_(OSetGen_Insert)(oset, vs[i]);
}
// Check the size
- vg_assert( NN == VG_(OSet_Size)(oset2) );
+ vg_assert( NN == VG_(OSetGen_Size)(oset) );
// Check we can find all the elements we inserted, within the full range
// of each Block.
for (i = 0; i < NN; i++) {
- a = vs[i]->first + 0; assert( VG_(OSet_Contains)(oset2, &a) );
- a = vs[i]->first + 1; assert( VG_(OSet_Contains)(oset2, &a) );
- a = vs[i]->first + 2; assert( VG_(OSet_Contains)(oset2, &a) );
+ a = vs[i]->first + 0; assert( VG_(OSetGen_Contains)(oset, &a) );
+ a = vs[i]->first + 1; assert( VG_(OSetGen_Contains)(oset, &a) );
+ a = vs[i]->first + 2; assert( VG_(OSetGen_Contains)(oset, &a) );
}
// Check we cannot find elements we did not insert, below and above the
// ranges of the inserted elements.
a = 0;
- assert( ! VG_(OSet_Contains)(oset2, &a) );
+ assert( ! VG_(OSetGen_Contains)(oset, &a) );
for (i = 0; i < NN; i++) {
- a = vs[i]->first - 1; assert( ! VG_(OSet_Contains)(oset2, &a) );
- a = vs[i]->first + 3; assert( ! VG_(OSet_Contains)(oset2, &a) );
+ a = vs[i]->first - 1; assert( ! VG_(OSetGen_Contains)(oset, &a) );
+ a = vs[i]->first + 3; assert( ! VG_(OSetGen_Contains)(oset, &a) );
}
// Check we can find all the elements we inserted, and the right values
// are returned.
for (i = 0; i < NN; i++) {
- a = vs[i]->first + 0; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
- a = vs[i]->first + 1; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
- a = vs[i]->first + 2; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
- assert( vs[i] == VG_(OSet_LookupWithCmp)(oset2, &a, blockCmp) );
+ a = vs[i]->first + 0; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
+ a = vs[i]->first + 1; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
+ a = vs[i]->first + 2; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
+ assert( vs[i] == VG_(OSetGen_LookupWithCmp)(oset, &a, blockCmp) );
}
// Check that we can iterate over the OSet elements in sorted order, and
@@ -315,60 +436,60 @@
n = 0;
pv = NULL;
prev.last = 0;
- VG_(OSet_ResetIter)(oset2);
- while ( (pv = VG_(OSet_Next)(oset2)) ) {
+ VG_(OSetGen_ResetIter)(oset);
+ while ( (pv = VG_(OSetGen_Next)(oset)) ) {
Block curr = *pv;
assert(prev.last < curr.first);
prev = curr;
n++;
}
assert(NN == n);
- vg_assert( ! VG_(OSet_Next)(oset2) );
- vg_assert( ! VG_(OSet_Next)(oset2) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
// Check that we can remove half of the elements, and that their values
// are as expected.
for (i = 0; i < NN; i += 2) {
- a = vs[i]->first; assert( vs[i] == VG_(OSet_Remove)(oset2, &a) );
+ a = vs[i]->first; assert( vs[i] == VG_(OSetGen_Remove)(oset, &a) );
}
// Check the size
- vg_assert( NN/2 == VG_(OSet_Size)(oset2) );
+ vg_assert( NN/2 == VG_(OSetGen_Size)(oset) );
// Check we can find the remaining elements (with the right values).
for (i = 1; i < NN; i += 2) {
- a = vs[i]->first + 0; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
- a = vs[i]->first + 1; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
- a = vs[i]->first + 2; assert( vs[i] == VG_(OSet_Lookup)(oset2, &a) );
+ a = vs[i]->first + 0; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
+ a = vs[i]->first + 1; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
+ a = vs[i]->first + 2; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
}
// Check we cannot find any of the elements we removed.
for (i = 0; i < NN; i += 2) {
- a = vs[i]->first + 0; assert( ! VG_(OSet_Contains)(oset2, &a) );
- a = vs[i]->first + 1; assert( ! VG_(OSet_Contains)(oset2, &a) );
- a = vs[i]->first + 2; assert( ! VG_(OSet_Contains)(oset2, &a) );
+ a = vs[i]->first + 0; assert( ! VG_(OSetGen_Contains)(oset, &a) );
+ a = vs[i]->first + 1; assert( ! VG_(OSetGen_Contains)(oset, &a) );
+ a = vs[i]->first + 2; assert( ! VG_(OSetGen_Contains)(oset, &a) );
}
// Check that we can remove the remaining half of the elements, and that
// their values are as expected.
for (i = 1; i < NN; i += 2) {
- a = vs[i]->first; assert( vs[i] == VG_(OSet_Remove)(oset2, &a) );
+ a = vs[i]->first; assert( vs[i] == VG_(OSetGen_Remove)(oset, &a) );
}
// Try some more operations on the empty OSet to ensure they don't screw up.
- vg_assert( ! VG_(OSet_Contains)(oset2, &v) );
- vg_assert( ! VG_(OSet_Lookup)(oset2, &v) );
- vg_assert( ! VG_(OSet_Remove)(oset2, &v) );
- vg_assert( ! VG_(OSet_Next)(oset2) );
- vg_assert( 0 == VG_(OSet_Size)(oset2) );
+ vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
+ vg_assert( ! VG_(OSetGen_Next)(oset) );
+ vg_assert( 0 == VG_(OSetGen_Size)(oset) );
- // Re-insert all elements, to give OSet_Destroy something to work with.
+ // Re-insert all elements, to give OSetGen_Destroy something to work with.
for (i = 0; i < NN; i++) {
- VG_(OSet_Insert)(oset2, vs[i]);
+ VG_(OSetGen_Insert)(oset, vs[i]);
}
// Destroy the OSet
- VG_(OSet_Destroy)(oset2, NULL);
+ VG_(OSetGen_Destroy)(oset);
}
//-----------------------------------------------------------------------
@@ -378,6 +499,7 @@
int main(void)
{
example1();
+ example1b();
example2();
return 0;
}
Modified: trunk/memcheck/tests/oset_test.stdout.exp
===================================================================
--- trunk/memcheck/tests/oset_test.stdout.exp 2007-09-17 00:41:18 UTC (rev 6840)
+++ trunk/memcheck/tests/oset_test.stdout.exp 2007-09-17 05:30:48 UTC (rev 6841)
@@ -1,4 +1,4 @@
--- start foo ----------------
+-- start oset1 ----------------
.. .. .. .. .. .. .. .. .. 1998
.. .. .. .. .. .. .. .. 1996
.. .. .. .. .. .. .. .. .. .. 1994
@@ -996,4 +996,1003 @@
.. .. .. .. .. .. .. .. .. 4
.. .. .. .. .. .. .. .. 2
.. .. .. .. .. .. .. .. .. 0
--- end foo ----------------
+-- end oset1 ----------------
+-- start oset1b ----------------
+.. .. .. .. .. .. .. .. .. 1998
+.. .. .. .. .. .. .. .. 1996
+.. .. .. .. .. .. .. .. .. .. 1994
+.. .. .. .. .. .. .. .. .. 1992
+.. .. .. .. .. .. .. .. .. .. 1990
+.. .. .. .. .. .. .. 1988
+.. .. .. .. .. .. .. .. .. 1986
+.. .. .. .. .. .. .. .. .. .. 1984
+.. .. .. .. .. .. .. .. 1982
+.. .. .. .. .. .. .. .. .. .. 1980
+.. .. .. .. .. .. .. .. .. 1978
+.. .. .. .. .. .. .. .. .. .. 1976
+.. .. .. .. .. .. 1974
+.. .. .. .. .. .. .. .. .. .. 1972
+.. .. .. .. .. .. .. .. .. 1970
+.. .. .. .. .. .. .. .. .. .. 1968
+.. .. .. .. .. .. .. .. 1966
+.. .. .. .. .. .. .. .. .. .. 1964
+.. .. .. .. .. .. .. .. .. 1962
+.. .. .. .. .. .. .. 1960
+.. .. .. .. .. .. .. .. .. .. 1958
+.. .. .. .. .. .. .. .. .. 1956
+.. .. .. .. .. .. .. .. 1954
+.. .. .. .. .. .. .. .. .. .. 1952
+.. .. .. .. .. .. .. .. .. 1950
+.. .. .. .. .. .. .. .. .. .. 1948
+.. .. .. .. .. 1946
+.. .. .. .. .. .. .. .. .. 1944
+.. .. .. .. .. .. .. .. 1942
+.. .. .. .. .. .. .. 1940
+.. .. .. .. .. .. .. .. .. .. 1938
+.. .. .. .. .. .. .. .. .. 1936
+.. .. .. .. .. .. .. .. 1934
+.. .. .. .. .. .. .. .. .. 1932
+.. .. .. .. .. .. 1930
+.. .. .. .. .. .. .. .. .. 1928
+.. .. .. .. .. .. .. .. .. .. 1926
+.. .. .. .. .. .. .. .. 1924
+.. .. .. .. .. .. .. .. .. .. 1922
+.. .. .. .. .. .. .. .. .. 1920
+.. .. .. .. .. .. .. .. .. .. 1918
+.. .. .. .. .. .. .. 1916
+.. .. .. .. .. .. .. .. .. 1914
+.. .. .. .. .. .. .. .. 1912
+.. .. .. .. .. .. .. .. .. .. 1910
+.. .. .. .. .. .. .. .. .. 1908
+.. .. .. .. .. .. .. .. .. .. 1906
+.. .. .. .. 1904
+.. .. .. .. .. .. .. .. .. 1902
+.. .. .. .. .. .. .. .. 1900
+.. .. .. .. .. .. .. 1898
+.. .. .. .. .. .. .. .. .. 1896
+.. .. .. .. .. .. .. .. 1894
+.. .. .. .. .. .. .. .. .. 1892
+.. .. .. .. .. .. 1890
+.. .. .. .. .. .. .. .. .. .. 1888
+.. .. .. .. .. .. .. .. .. 1886
+.. .. .. .. .. .. .. .. .. .. 1884
+.. .. .. .. .. .. .. .. 1882
+.. .. .. .. .. .. .. .. .. 1880
+.. .. .. .. .. .. .. 1878
+.. .. .. .. .. .. .. .. 1876
+.. .. .. .. .. .. .. .. .. 1874
+.. .. .. .. .. 1872
+.. .. .. .. .. .. .. .. .. .. 1870
+.. .. .. .. .. .. .. .. .. 1868
+.. .. .. .. .. .. .. .. .. .. 1866
+.. .. .. .. .. .. .. .. 1864
+.. .. .. .. .. .. .. .. .. 1862
+.. .. .. .. .. .. .. .. .. .. 1860
+.. .. .. .. .. .. .. 1858
+.. .. .. .. .. .. .. .. .. 1856
+.. .. .. .. .. .. .. .. 1854
+.. .. .. .. .. .. .. .. .. 1852
+.. .. .. .. .. .. 1848
+.. .. .. .. .. .. .. .. .. 1846
+.. .. .. .. .. .. .. .. 1844
+.. .. .. .. .. .. .. .. .. .. 1842
+.. .. .. .. .. .. .. .. .. 1840
+.. .. .. .. .. .. .. 1838
+.. .. .. .. .. .. .. .. .. .. 1836
+.. .. .. .. .. .. .. .. .. 18...
[truncated message content] |
|
From: Tom H. <th...@cy...> - 2007-09-17 02:31:06
|
Nightly build on alvis ( i686, Red Hat 7.3 ) started at 2007-09-17 03:15:02 BST Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 256 tests, 27 stderr failures, 1 stdout failure, 0 posttest failures == memcheck/tests/addressable (stderr) memcheck/tests/badjump (stderr) memcheck/tests/describe-block (stderr) memcheck/tests/erringfds (stderr) memcheck/tests/leak-0 (stderr) memcheck/tests/leak-cycle (stderr) memcheck/tests/leak-pool-0 (stderr) memcheck/tests/leak-pool-1 (stderr) memcheck/tests/leak-pool-2 (stderr) memcheck/tests/leak-pool-3 (stderr) memcheck/tests/leak-pool-4 (stderr) memcheck/tests/leak-pool-5 (stderr) memcheck/tests/leak-regroot (stderr) memcheck/tests/leak-tree (stderr) memcheck/tests/long_namespace_xml (stderr) memcheck/tests/match-overrun (stderr) memcheck/tests/partial_load_dflt (stderr) memcheck/tests/partial_load_ok (stderr) memcheck/tests/partiallydefinedeq (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/sigkill (stderr) memcheck/tests/stack_changes (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/x86/scalar_supp (stderr) memcheck/tests/x86/xor-undef-x86 (stderr) memcheck/tests/xml1 (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) |
|
From: Tom H. <th...@cy...> - 2007-09-17 02:23:28
|
Nightly build on dellow ( x86_64, Fedora 7 ) started at 2007-09-17 03:10:04 BST Results differ from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 293 tests, 4 stderr failures, 2 stdout failures, 0 posttest failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) memcheck/tests/xml1 (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 293 tests, 4 stderr failures, 4 stdout failures, 0 posttest failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) memcheck/tests/xml1 (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) none/tests/pth_cvsimple (stdout) none/tests/pth_detached (stdout) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Mon Sep 17 03:16:49 2007 --- new.short Mon Sep 17 03:23:24 2007 *************** *** 8,10 **** ! == 293 tests, 4 stderr failures, 4 stdout failures, 0 posttest failures == memcheck/tests/pointer-trace (stderr) --- 8,10 ---- ! == 293 tests, 4 stderr failures, 2 stdout failures, 0 posttest failures == memcheck/tests/pointer-trace (stderr) *************** *** 15,18 **** none/tests/mremap2 (stdout) - none/tests/pth_cvsimple (stdout) - none/tests/pth_detached (stdout) --- 15,16 ---- |
|
From: Tom H. <th...@cy...> - 2007-09-17 02:17:33
|
Nightly build on lloyd ( x86_64, Fedora Core 3 ) started at 2007-09-17 03:05:07 BST Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 293 tests, 6 stderr failures, 1 stdout failure, 0 posttest failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/stack_switch (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/x86/scalar_supp (stderr) memcheck/tests/xml1 (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) |
|
From: Tom H. <th...@cy...> - 2007-09-17 02:15:13
|
Nightly build on gill ( x86_64, Fedora Core 2 ) started at 2007-09-17 03:00:03 BST Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 295 tests, 6 stderr failures, 1 stdout failure, 0 posttest failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/stack_switch (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/x86/scalar_supp (stderr) none/tests/fdleak_fcntl (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) |
|
From: <sv...@va...> - 2007-09-17 00:41:18
|
Author: njn Date: 2007-09-17 01:41:18 +0100 (Mon, 17 Sep 2007) New Revision: 6840 Log: update Modified: trunk/NEWS Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-09-17 00:41:07 UTC (rev 6839) +++ trunk/NEWS 2007-09-17 00:41:18 UTC (rev 6840) @@ -26,6 +26,11 @@ traces. Second, a new option --trace-superblocks has been added, which shows the addresses of superblocks (code blocks) as they are executed. +- Cachegrind now uses directory names where possible in its output files. + This means that the -I option to 'cg_annotate' should not be needed in + most cases. It also means it can correctly handle the case where two + source files in different directories have the same name. + Developer-visible changes: - New debugging command line options: --debug-dump, --trace-symtab-patt... |