]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Create a new SkShmC segment type for shared memory segments so that we
authorTom Hughes <tom@compton.nu>
Tue, 4 Oct 2005 15:59:54 +0000 (15:59 +0000)
committerTom Hughes <tom@compton.nu>
Tue, 4 Oct 2005 15:59:54 +0000 (15:59 +0000)
can ensure they are never merged with adjacent segments. This makes
sure that we can find the right piece of memory to release when the
shmdt system call occurs.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4854

coregrind/m_aspacemgr/aspacemgr.c
coregrind/m_syswrap/syswrap-generic.c
coregrind/pub_core_aspacemgr.h
include/pub_tool_aspacemgr.h

index a95d73f0b9346f9f11f01b5d21ffc9604f856f01..611fd1e4b675656bd4bbce34bbf09044d765574b 100644 (file)
@@ -441,6 +441,7 @@ static HChar* show_SegKind ( SegKind sk )
       case SkAnonV: return "ANON";
       case SkFileC: return "file";
       case SkFileV: return "FILE";
+      case SkShmC:  return "shm ";
       case SkResvn: return "RSVN";
       default:      return "????";
    }
@@ -523,7 +524,7 @@ static void show_nsegment ( Int logLevel, Int segNo, NSegment* seg )
          );
          break;
 
-      case SkAnonC: case SkAnonV:
+      case SkAnonC: case SkAnonV: case SkShmC:
          VG_(debugLog)(
             logLevel, "aspacem",
             "%3d: %s %010llx-%010llx %s %c%c%c%c%c\n",
@@ -688,7 +689,7 @@ static Bool sane_NSegment ( NSegment* s )
             && !s->hasR && !s->hasW && !s->hasX && !s->hasT
             && !s->isCH;
 
-      case SkAnonC: case SkAnonV:
+      case SkAnonC: case SkAnonV: case SkShmC:
          return 
             s->smode == SmFixed 
             && s->dev == 0 && s->ino == 0 && s->offset == 0 && s->fnIdx == -1
@@ -754,6 +755,9 @@ static Bool maybe_merge_nsegments ( NSegment* s1, NSegment* s2 )
          }
          break;
 
+      case SkShmC:
+         return False;
+
       default:
          break;
    
@@ -890,7 +894,8 @@ static void sync_check_mapping_callback ( Addr addr, SizeT len, UInt prot,
       same = nsegments[i].kind == SkAnonC
              || nsegments[i].kind == SkAnonV
              || nsegments[i].kind == SkFileC
-             || nsegments[i].kind == SkFileV;
+             || nsegments[i].kind == SkFileV
+             || nsegments[i].kind == SkShmC;
 
       seg_prot = 0;
       if (nsegments[i].hasR) seg_prot |= VKI_PROT_READ;
@@ -1106,7 +1111,7 @@ NSegment* VG_(am_next_nsegment) ( NSegment* here, Bool fwds )
          return NULL;
    }
    switch (nsegments[i].kind) {
-      case SkFileC: case SkFileV: 
+      case SkFileC: case SkFileV: case SkShmC:
       case SkAnonC: case SkAnonV: case SkResvn:
          return &nsegments[i];
       default:
@@ -1169,6 +1174,7 @@ Bool is_valid_for_client( Addr start, SizeT len, UInt prot, Bool freeOk )
    for (i = iLo; i <= iHi; i++) {
       if ( (nsegments[i].kind == SkFileC 
             || nsegments[i].kind == SkAnonC
+            || nsegments[i].kind == SkShmC
             || (nsegments[i].kind == SkFree  && freeOk)
             || (nsegments[i].kind == SkResvn && freeOk))
            && (needR ? nsegments[i].hasR : True)
@@ -1638,6 +1644,7 @@ Addr VG_(am_get_advisory) ( MapRequest*  req,
          if (nsegments[i].kind == SkFree
              || nsegments[i].kind == SkFileC
              || nsegments[i].kind == SkAnonC
+             || nsegments[i].kind == SkShmC
              || nsegments[i].kind == SkResvn) {
             /* ok */
          } else {
@@ -1830,6 +1837,37 @@ VG_(am_notify_client_mmap)( Addr a, SizeT len, UInt prot, UInt flags,
    return needDiscard;
 }
 
+/* Notifies aspacem that the client completed a shmat successfully.
+   The segment array is updated accordingly.  If the returned Bool is
+   True, the caller should immediately discard translations from the
+   specified address range. */
+
+Bool
+VG_(am_notify_client_shmat)( Addr a, SizeT len, UInt prot )
+{
+   NSegment seg;
+   Bool     needDiscard;
+
+   aspacem_assert(len > 0);
+   aspacem_assert(VG_IS_PAGE_ALIGNED(a));
+   aspacem_assert(VG_IS_PAGE_ALIGNED(len));
+
+   /* Discard is needed if any of the just-trashed range had T. */
+   needDiscard = any_Ts_in_range( a, len );
+
+   init_nsegment( &seg );
+   seg.kind   = SkShmC;
+   seg.start  = a;
+   seg.end    = a + len - 1;
+   seg.offset = 0;
+   seg.hasR   = toBool(prot & VKI_PROT_READ);
+   seg.hasW   = toBool(prot & VKI_PROT_WRITE);
+   seg.hasX   = toBool(prot & VKI_PROT_EXEC);
+   add_segment( &seg );
+   AM_SANITY_CHECK;
+   return needDiscard;
+}
+
 /* Notifies aspacem that an mprotect was completed successfully.  The
    segment array is updated accordingly.  Note, as with
    VG_(am_notify_munmap), it is not the job of this function to reject
@@ -1866,7 +1904,7 @@ Bool VG_(am_notify_mprotect)( Addr start, SizeT len, UInt prot )
    for (i = iLo; i <= iHi; i++) {
       /* Apply the permissions to all relevant segments. */
       switch (nsegments[i].kind) {
-         case SkAnonC: case SkAnonV: case SkFileC: case SkFileV:
+         case SkAnonC: case SkAnonV: case SkFileC: case SkFileV: case SkShmC:
             nsegments[i].hasR = newR;
             nsegments[i].hasW = newW;
             nsegments[i].hasX = newX;
index 1d03b0c4448b8d53fe083add10404ad35d53a185..4d467fccb66c7fd0df8d87e6c8c6f8722cf66b3c 100644 (file)
@@ -1600,8 +1600,7 @@ ML_(generic_POST_sys_shmat) ( ThreadId tid,
          cope with the discrepancy, aspacem's sync checker omits the
          dev/ino correspondence check in cases where V does not know
          the dev/ino. */
-      d = VG_(am_notify_client_mmap)( res, VG_PGROUNDUP(segmentSize), 
-                                      prot, VKI_MAP_ANONYMOUS, 0,0);
+      d = VG_(am_notify_client_shmat)( res, VG_PGROUNDUP(segmentSize), prot );
 
       /* we don't distinguish whether it's read-only or
        * read-write -- it doesn't matter really. */
@@ -1630,7 +1629,11 @@ ML_(generic_POST_sys_shmdt) ( ThreadId tid, UWord res, UWord arg0 )
    if (s != NULL) {
       Addr  s_start = s->start;
       SizeT s_len   = s->end+1 - s->start;
-      Bool  d       = VG_(am_notify_munmap)(s_start, s_len);
+      Bool  d;
+
+      vg_assert(s->kind == SkShmC && s->start == arg0);
+
+      d = VG_(am_notify_munmap)(s_start, s_len);
       s = NULL; /* s is now invalid */
       VG_TRACK( die_mem_munmap, s_start, s_len );
       if (d)
index 6bf343ec4172c3e4c82edd29150995ea91ee8ef5..88b9127bd6322f57f2cd5b7e48eaa3793468e25b 100644 (file)
@@ -155,6 +155,12 @@ extern Addr VG_(am_get_advisory_client_simple)
 extern Bool VG_(am_notify_client_mmap)
    ( Addr a, SizeT len, UInt prot, UInt flags, Int fd, Off64T offset );
 
+/* Notifies aspacem that the client completed a shmat successfully.
+   The segment array is updated accordingly.  If the returned Bool is
+   True, the caller should immediately discard translations from the
+   specified address range. */
+extern Bool VG_(am_notify_client_shmat)( Addr a, SizeT len, UInt prot );
+
 /* Notifies aspacem that an mprotect was completed successfully.  The
    segment array is updated accordingly.  Note, as with
    VG_(am_notify_munmap), it is not the job of this function to reject
index 51240bb3d7a1c8c96b888e974a1f5b7c1c01b620..160a5aa1d366ca56b4b2f4edec31a50ff1a38021 100644 (file)
@@ -43,6 +43,7 @@ typedef
       SkAnonV,  // anonymous mapping belonging to valgrind
       SkFileC,  // file mapping belonging to the client
       SkFileV,  // file mapping belonging to valgrind
+      SkShmC,   // shared memory segment belonging to the client
       SkResvn   // reservation
    }
    SegKind;
@@ -73,6 +74,12 @@ typedef
         // there is an associated file
         // segment may have permissions
 
+     kind == SkShmC:
+        // smode==SmFixed
+        // there's no associated file:
+        dev==ino==foff = 0, fnidx == -1
+        // segment may have permissions
+
      kind == SkResvn
         // the segment may be resized if required
         // there's no associated file: