|
From: <sv...@va...> - 2005-09-13 22:43:50
|
Author: sewardj
Date: 2005-09-13 23:43:48 +0100 (Tue, 13 Sep 2005)
New Revision: 4649
Log:
- improve segment array printing
- add code for sanity checking segments
- add code for merging mergeable segments
Modified:
branches/ASPACEM/coregrind/m_aspacemgr/aspacemgr.c
branches/ASPACEM/coregrind/pub_core_aspacemgr.h
Modified: branches/ASPACEM/coregrind/m_aspacemgr/aspacemgr.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/ASPACEM/coregrind/m_aspacemgr/aspacemgr.c 2005-09-13 22:40:4=
1 UTC (rev 4648)
+++ branches/ASPACEM/coregrind/m_aspacemgr/aspacemgr.c 2005-09-13 22:43:4=
8 UTC (rev 4649)
@@ -1555,6 +1555,292 @@
=20
/*-----------------------------------------------------------------*/
/*--- ---*/
+/*--- Displaying the segment array. ---*/
+/*--- ---*/
+/*-----------------------------------------------------------------*/
+
+static HChar* show_SegKind ( SegKind sk )
+{
+ switch (sk) {
+ case SkFree: return " ";
+ case SkAnonC: return "anon";
+ case SkAnonV: return "ANON";
+ case SkFileC: return "file";
+ case SkFileV: return "FILE";
+ case SkResvn: return "RSVN";
+ default: return "????";
+ }
+}
+
+static HChar* show_ShrinkMode ( ShrinkMode sm )
+{
+ switch (sm) {
+ case SmLower: return "SmLower";
+ case SmUpper: return "SmUpper";
+ case SmFixed: return "SmFixed";
+ default: return "Sm?????";
+ }
+}
+
+static void show_Addr_concisely ( /*OUT*/HChar* buf, Addr aA )
+{
+ HChar* fmt;
+ ULong a =3D (ULong)aA;
+ if (a >=3D 10000000ULL) {
+ fmt =3D "%6llum";
+ a /=3D 1024*1024ULL;
+ } else {
+ fmt =3D "%7llu";
+ }
+ aspacem_sprintf(buf, fmt, a);
+}
+
+
+/* Show full details of an NSegment */
+
+static void show_nsegment_full ( Int logLevel, NSegment* seg )
+{
+ VG_(debugLog)(logLevel, "aspacem",
+ "NSegment{%s, start=3D0x%llx, end=3D0x%llx, smode=3D%s, dev=3D%u, =
"
+ "ino=3D%u, offset=3D%llu, fnIdx=3D%d, hasR=3D%d, hasW=3D%d, hasX=3D=
%d, "
+ "hasT=3D%d, mark=3D%d}\n",
+ show_SegKind(seg->kind),
+ (ULong)seg->start,
+ (ULong)seg->end,
+ show_ShrinkMode(seg->smode),
+ seg->dev, seg->ino, (ULong)seg->offset, seg->fnIdx,
+ (Int)seg->hasR, (Int)seg->hasW, (Int)seg->hasX, (Int)seg->hasT,
+ (Int)seg->mark
+ );
+}
+
+
+/* Show an NSegment in a user-friendly-ish way. */
+
+static void show_nsegment ( Int logLevel, Int segNo, NSegment* seg )
+{
+ HChar len_buf[20];
+ ULong len =3D ((ULong)seg->end) - ((ULong)seg->start) + 1;
+ show_Addr_concisely(len_buf, len);
+
+ switch (seg->kind) {
+
+ case SkFree:
+ VG_(debugLog)(
+ logLevel, "aspacem",
+ "%3d: %s %08llx-%08llx %s\n",
+ segNo, show_SegKind(seg->kind),
+ (ULong)seg->start, (ULong)seg->end, len_buf
+ );
+ break;
+
+ case SkAnonC: case SkAnonV:
+ VG_(debugLog)(
+ logLevel, "aspacem",
+ "%3d: %s %08llx-%08llx %s %c%c%c%c\n",
+ segNo, show_SegKind(seg->kind),
+ (ULong)seg->start, (ULong)seg->end, len_buf,
+ seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-',=20
+ seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-'=20
+ );
+ break;
+
+ case SkFileC: case SkFileV:
+ VG_(debugLog)(
+ logLevel, "aspacem",
+ "%3d: %s %08llx-%08llx %s %c%c%c%c d=3D0x%03x i=3D%-7d o=3D%=
-7lld (%d)\n",
+ segNo, show_SegKind(seg->kind),
+ (ULong)seg->start, (ULong)seg->end, len_buf,
+ seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-',=20
+ seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-',=20
+ seg->dev, seg->ino, (Long)seg->offset, seg->fnIdx
+ );
+ break;
+
+ case SkResvn:
+ VG_(debugLog)(
+ logLevel, "aspacem",
+ "%3d: %s %08llx-%08llx %s %c%c%c%c %s\n",
+ segNo, show_SegKind(seg->kind),
+ (ULong)seg->start, (ULong)seg->end, len_buf,
+ seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-',=20
+ seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-',=20
+ show_ShrinkMode(seg->smode)
+ );
+ break;
+
+ default:
+ VG_(debugLog)(
+ logLevel, "aspacem",
+ "%3d: ???? UNKNOWN SEGMENT KIND\n",=20
+ segNo=20
+ );
+ break;
+ }
+}
+
+/* Print out the segment array (debugging only!). */
+void VG_(am_show_nsegments) ( Int logLevel, HChar* who )
+{
+ Int i;
+ VG_(debugLog)(logLevel, "aspacem",
+ "<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",=20
+ who, segments_used, segnames_used);
+ for (i =3D 0; i < segnames_used; i++) {
+ if (!segnames[i].inUse)
+ continue;
+ VG_(debugLog)(logLevel, "aspacem",
+ "(%2d) %s\n", i, segnames[i].fname);
+ }
+ for (i =3D 0; i < nsegments_used; i++)
+ show_nsegment( logLevel, i, &nsegments[i] );
+ VG_(debugLog)(logLevel, "aspacem",
+ ">>>\n");
+}
+
+
+/*-----------------------------------------------------------------*/
+/*--- ---*/
+/*--- Sanity checking and preening of the segment array. ---*/
+/*--- ---*/
+/*-----------------------------------------------------------------*/
+
+/* Check representational invariants for NSegments. */
+
+static Bool sane_NSegment ( NSegment* s )
+{
+ if (s =3D=3D NULL) return False;
+
+ /* No zero sized segments and no wraparounds. */
+ if (s->start >=3D s->end) return False;
+
+ /* .mark is used for admin purposes only. */
+ if (s->mark) return False;
+
+ /* require page alignment */
+ if (!VG_IS_PAGE_ALIGNED(s->start)) return False;
+ if (!VG_IS_PAGE_ALIGNED(s->end+1)) return False;
+
+ switch (s->kind) {
+
+ case SkFree:
+ return=20
+ s->smode =3D=3D SmFixed
+ && s->dev =3D=3D 0 && s->ino =3D=3D 0 && s->offset =3D=3D 0 =
&& s->fnIdx =3D=3D -1=20
+ && !s->hasR && !s->hasW && !s->hasX && !s->hasT;
+
+ case SkAnonC: case SkAnonV:
+ return=20
+ s->smode =3D=3D SmFixed=20
+ && s->dev =3D=3D 0 && s->ino =3D=3D 0 && s->offset =3D=3D 0 =
&& s->fnIdx =3D=3D -1;
+
+ case SkFileC: case SkFileV:
+ return=20
+ s->smode =3D=3D SmFixed;
+
+ case SkResvn:=20
+ return=20
+ s->dev =3D=3D 0 && s->ino =3D=3D 0 && s->offset =3D=3D 0 && =
s->fnIdx =3D=3D -1=20
+ && !s->hasR && !s->hasW && !s->hasX && !s->hasT;
+
+ default:
+ return False;
+ }
+}
+
+
+/* Try merging s2 into s1, if possible. If successful, s1 is
+ modified, and True is returned. Otherwise s1 is unchanged and
+ False is returned. */
+
+static Bool maybe_merge_nsegments ( NSegment* s1, NSegment* s2 )
+{
+ if (s1->kind !=3D s2->kind)=20
+ return False;
+
+ if (s1->end+1 !=3D s2->start)
+ return False;
+
+ /* reject cases which would cause wraparound */
+ if (s1->start > s2->end)
+ return False;
+
+ switch (s1->kind) {
+
+ case SkFree:
+ s1->end =3D s2->end;
+ return True;
+
+ case SkAnonC: case SkAnonV:
+ if (s1->hasR =3D=3D s2->hasR=20
+ && s1->hasW =3D=3D s2->hasW && s1->hasX =3D=3D s2->hasX) {
+ s1->end =3D s2->end;
+ s1->hasT |=3D s2->hasT;
+ return True;
+ }
+ break;
+
+ case SkFileC: case SkFileV:
+ if (s1->hasR =3D=3D s2->hasR=20
+ && s1->hasW =3D=3D s2->hasW && s1->hasX =3D=3D s2->hasX
+ && s1->dev =3D=3D s2->dev && s1->ino =3D=3D s2->ino
+ && s2->offset =3D=3D s1->offset
+ + ((ULong)s2->start) - ((ULong)s1->start) =
) {
+ s1->end =3D s2->end;
+ s1->hasT |=3D s2->hasT;
+ return True;
+ }
+ break;
+
+ default:
+ break;
+ =20
+ }
+
+ return False;
+}
+
+
+/* Sanity-check and canonicalise the segment array (merge mergable
+ segments). */
+
+static void preen_nsegments ( void )
+{
+ Int i, r, w;
+
+ /* Pass 1: check the segment array covers the entire address space
+ exactly once, and also that each segment is sane. */
+ aspacem_assert(nsegments_used > 0);
+ aspacem_assert(nsegments[0].start =3D=3D Addr_MIN);
+ aspacem_assert(nsegments[nsegments_used-1].end =3D=3D Addr_MAX);
+
+ aspacem_assert(sane_NSegment(&nsegments[0]));
+ for (i =3D 1; i < nsegments_used; i++) {
+if (!sane_NSegment(&nsegments[i])) show_nsegment_full(0,&nsegments[i]);
+ aspacem_assert(sane_NSegment(&nsegments[i]));
+ aspacem_assert(nsegments[i-1].end+1 =3D=3D nsegments[i].start);
+ }
+
+ /* Pass 2: merge as much as possible, using
+ maybe_merge_segments. */
+ w =3D 0;
+ for (r =3D 1; r < nsegments_used; r++) {
+ if (maybe_merge_nsegments(&nsegments[w], &nsegments[r])) {
+ /* nothing */
+ } else {
+ w++;
+ if (w !=3D r)=20
+ nsegments[w] =3D nsegments[r];
+ }
+ }
+ w++;
+ aspacem_assert(w > 0 && w <=3D nsegments_used);
+ nsegments_used =3D w;
+}
+
+
+/*-----------------------------------------------------------------*/
+/*--- ---*/
/*--- Low level access / modification of the segment array. ---*/
/*--- ---*/
/*-----------------------------------------------------------------*/
@@ -1644,19 +1930,6 @@
}
=20
=20
-/* Sanity checking: ensure the segment array covers the entire address
- space exactly. */
-static void check_nsegments ( void )
-{
- Int i;
- aspacem_assert(nsegments_used > 0);
- aspacem_assert(nsegments[0].start =3D=3D Addr_MIN);
- aspacem_assert(nsegments[nsegments_used-1].end =3D=3D Addr_MAX);
- for (i =3D 1; i < nsegments_used; i++)
- aspacem_assert(nsegments[i-1].end+1 =3D=3D nsegments[i].start);
-}
-
-
/* Trivial fn: return the total amount of space in anonymous mappings,
both for V and the client. Is used for printing stats in
out-of-memory messages. */
@@ -1710,135 +1983,18 @@
=20
/*-----------------------------------------------------------------*/
/*--- ---*/
-/*--- Displaying the segment array. ---*/
+/*--- Modifying the segment array, and constructing segments. ---*/
/*--- ---*/
/*-----------------------------------------------------------------*/
=20
-static HChar* show_seg_kind ( NSegment* seg )
-{
- switch (seg->kind) {
- case SkFree: return " ";
- case SkAnonC: return "anon";
- case SkAnonV: return "ANON";
- case SkFileC: return "file";
- case SkFileV: return "FILE";
- case SkResvn: return "RSVN";
- default: return "????";
- }
-}
+/* Helper fn */
=20
-static HChar* show_ShrinkMode ( ShrinkMode sm )
+static Bool is_SkFile ( SegKind sk )
{
- switch (sm) {
- case SmLower: return "SmLower";
- case SmUpper: return "SmUpper";
- case SmFixed: return "SmFixed";
- default: return "Sm?????";
- }
+ return sk =3D=3D SkFileV || sk =3D=3D SkFileC;
}
=20
-static void show_Addr_concisely ( /*OUT*/HChar* buf, Addr aA )
-{
- HChar* fmt;
- ULong a =3D (ULong)aA;
- if (a >=3D 10000000ULL) {
- fmt =3D "%6llum";
- a /=3D 1024*1024ULL;
- } else {
- fmt =3D "%7llu";
- }
- aspacem_sprintf(buf, fmt, a);
-}
=20
-static void show_nsegment ( Int logLevel, Int segNo, NSegment* seg )
-{
- HChar len_buf[20];
- ULong len =3D ((ULong)seg->end) - ((ULong)seg->start) + 1;
- show_Addr_concisely(len_buf, len);
-
- switch (seg->kind) {
-
- case SkFree:
- VG_(debugLog)(
- logLevel, "aspacem",
- "%3d: %s %08llx-%08llx %s\n",
- segNo, show_seg_kind(seg),
- (ULong)seg->start, (ULong)seg->end, len_buf
- );
- break;
-
- case SkAnonC: case SkAnonV:
- VG_(debugLog)(
- logLevel, "aspacem",
- "%3d: %s %08llx-%08llx %s %c%c%c%c d=3D0x%03x i=3D%-7d o=3D%=
-7lld (%d)\n",
- segNo, show_seg_kind(seg),
- (ULong)seg->start, (ULong)seg->end, len_buf,
- seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-',=20
- seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-',=20
- seg->dev, seg->ino, (Long)seg->offset, seg->fnIdx
- );
- break;
-
- case SkFileC: case SkFileV:
- VG_(debugLog)(
- logLevel, "aspacem",
- "%3d: %s %08llx-%08llx %s %c%c%c%c d=3D0x%03x i=3D%-7d o=3D%=
-7lld (%d)\n",
- segNo, show_seg_kind(seg),
- (ULong)seg->start, (ULong)seg->end, len_buf,
- seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-',=20
- seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-',=20
- seg->dev, seg->ino, (Long)seg->offset, seg->fnIdx
- );
- break;
-
- case SkResvn:
- VG_(debugLog)(
- logLevel, "aspacem",
- "%3d: %s %08llx-%08llx %s %c%c%c%c %s\n",
- segNo, show_seg_kind(seg),
- (ULong)seg->start, (ULong)seg->end, len_buf,
- seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-',=20
- seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-',=20
- show_ShrinkMode(seg->smode)
- );
- break;
-
- default:
- VG_(debugLog)(
- logLevel, "aspacem",
- "%3d: ???? UNKNOWN SEGMENT KIND\n",=20
- segNo=20
- );
- break;
- }
-}
-
-/* Print out the segment array (debugging only!). */
-void VG_(am_show_nsegments) ( Int logLevel, HChar* who )
-{
- Int i;
- VG_(debugLog)(logLevel, "aspacem",
- "<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n",=20
- who, segments_used, segnames_used);
- for (i =3D 0; i < segnames_used; i++) {
- if (!segnames[i].inUse)
- continue;
- VG_(debugLog)(logLevel, "aspacem",
- "(%2d) %s\n", i, segnames[i].fname);
- }
- for (i =3D 0; i < nsegments_used; i++)
- show_nsegment( logLevel, i, &nsegments[i] );
- VG_(debugLog)(logLevel, "aspacem",
- ">>>\n");
-}
-
-
-/*-----------------------------------------------------------------*/
-/*--- ---*/
-/*--- Modifying the segment array, and constructing segments. ---*/
-/*--- ---*/
-/*-----------------------------------------------------------------*/
-
/* Add SEG to the collection, deleting/truncating any it overlaps.
This deals with all the tricky cases of splitting up segments as
needed. */
@@ -1854,6 +2010,7 @@
aspacem_assert(dStart <=3D dEnd);
aspacem_assert(VG_IS_PAGE_ALIGNED(dStart));
aspacem_assert(VG_IS_PAGE_ALIGNED(dEnd+1));
+ aspacem_assert(sane_NSegment(seg));
=20
nDeld =3D 0;
=20
@@ -1891,7 +2048,8 @@
nsegments[i+1] =3D nsegments[i];
nsegments[i].end =3D dStart-1;
nsegments[i+1].start =3D dEnd+1;
- nsegments[i+1].offset +=3D (nsegments[i+1].start - nsegments[i]=
.start);
+ if (is_SkFile(nsegments[i].kind))
+ nsegments[i+1].offset +=3D (nsegments[i+1].start - nsegments=
[i].start);
continue;
}
=20
@@ -1903,7 +2061,8 @@
=20
if (iEnd > dEnd && iStart >=3D dStart && iStart <=3D dEnd) {
/* interval to be deleted straddles lower boundary of i. */
- nsegments[i].offset +=3D (dEnd+1 - nsegments[i].start);
+ if (is_SkFile(nsegments[i].kind))
+ nsegments[i].offset +=3D (dEnd+1 - nsegments[i].start);
nsegments[i].start =3D dEnd+1;
continue;
}
@@ -1948,7 +2107,7 @@
=20
nsegments[k] =3D *seg;
=20
- check_nsegments();
+ preen_nsegments();
}
=20
=20
@@ -1964,7 +2123,7 @@
seg->ino =3D 0;
seg->offset =3D 0;
seg->fnIdx =3D -1;
- seg->hasR =3D seg->hasR =3D seg->hasW =3D seg->hasT =3D False;
+ seg->hasR =3D seg->hasW =3D seg->hasX =3D seg->hasT =3D False;
seg->mark =3D False;
}
=20
Modified: branches/ASPACEM/coregrind/pub_core_aspacemgr.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/ASPACEM/coregrind/pub_core_aspacemgr.h 2005-09-13 22:40:41 U=
TC (rev 4648)
+++ branches/ASPACEM/coregrind/pub_core_aspacemgr.h 2005-09-13 22:43:48 U=
TC (rev 4649)
@@ -182,7 +182,7 @@
SkFileV, // file mapping belonging to valgrind
SkResvn // reservation
}
- MKind;
+ SegKind;
=20
/* Describes how a reservation segment can be resized. */
typedef
@@ -199,13 +199,13 @@
// the only meaningful fields are .start and .end
=20
kind =3D=3D SkAnon{C,V}:
- // the segment may be resized if required
+ // smode=3D=3DSmFixed
// there's no associated file:
dev=3D=3Dino=3D=3Dfoff =3D 0, fnidx =3D=3D -1
// segment may have permissions
=20
kind =3D=3D SkFile{C,V}:
- // the segment may not be resized:
+ // smode=3D=3DSmFixed
moveLo =3D=3D moveHi =3D=3D NotMovable, maxlen =3D=3D 0
// there is an associated file
// segment may have permissions
@@ -222,7 +222,7 @@
*/
typedef
struct {
- MKind kind;
+ SegKind kind;
/* Extent (SkFree, SkAnon{C,V}, SkFile{C,V}, SkResvn) */
Addr start; // lowest address in range
Addr end; // highest address in range
|