changeset 900:177afbf5297b

Solaris compatibility and proc map parsing #183, thanks BlueZeniX!
author Christian Kamm <kamm incasoftware de>
date Thu, 22 Jan 2009 18:53:32 +0100
parents 23d36edea021
children d51551cb3a85
files dmd/mars.c dmd/mtype.c gen/linker.cpp runtime/internal/memory.d
diffstat 4 files changed, 98 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/mars.c	Thu Jan 22 18:23:30 2009 +0100
+++ b/dmd/mars.c	Thu Jan 22 18:53:32 2009 +0100
@@ -190,7 +190,7 @@
   -m<arch>       emit code specific to <arch> being one of:\n\
                  x86 x86-64 ppc32 ppc64 arm thumb\n\
   -t<os>         emit code specific to <os> being one of:\n\
-                 Linux, Windows, MacOSX, FreeBSD\n\
+                 Linux, Windows, MacOSX, FreeBSD, Solaris\n\
 \n\
   -g, -gc        add symbolic debug info\n\
 \n\
--- a/dmd/mtype.c	Thu Jan 22 18:23:30 2009 +0100
+++ b/dmd/mtype.c	Thu Jan 22 18:53:32 2009 +0100
@@ -45,8 +45,10 @@
 static double zero = 0;
 #elif __GNUC__
 #include <math.h>
+#if !(defined (__SVR4) && defined (__sun))
 #include <bits/nan.h>
 #include <bits/mathdef.h>
+#endif
 static double zero = 0;
 #endif
 
--- a/gen/linker.cpp	Thu Jan 22 18:23:30 2009 +0100
+++ b/gen/linker.cpp	Thu Jan 22 18:53:32 2009 +0100
@@ -286,14 +286,21 @@
 
     // default libs
     switch(global.params.os) {
-    case OSLinux:
+    case OSLinux: 
     case OSMacOSX:
         args.push_back("-ldl");
+        // fallthrough
     case OSFreeBSD:
         args.push_back("-lpthread");
         args.push_back("-lm");
         break;
 
+    case OSSolaris:
+        args.push_back("-lm");
+        args.push_back("-lumem");
+        // solaris TODO
+        break;
+
     case OSWindows:
         // FIXME: I'd assume kernel32 etc
         break;
--- a/runtime/internal/memory.d	Thu Jan 22 18:23:30 2009 +0100
+++ b/runtime/internal/memory.d	Thu Jan 22 18:53:32 2009 +0100
@@ -27,11 +27,14 @@
 
 version = GC_Use_Dynamic_Ranges;
 
-// does Posix suffice?
 version(Posix)
 {
     version = GC_Use_Data_Proc_Maps;
 }
+version(solaris)
+{
+    version = GC_Use_Data_Proc_Maps;
+}
 
 version(GC_Use_Data_Proc_Maps)
 {
@@ -167,10 +170,10 @@
         {
             extern int _data_start__;
             extern int _bss_end__;
+        }
 
-            alias _data_start__ Data_Start;
-            alias _bss_end__    Data_End;
-        }
+        alias _data_start__ Data_Start;
+        alias _bss_end__    Data_End;
     }
     else version( linux )
     {
@@ -186,8 +189,19 @@
             extern int __fini_array_end;
         }
 
-            alias __data_start  Data_Start;
-            alias _end          Data_End;
+        alias __data_start  Data_Start;
+        alias _end          Data_End;
+    }
+    else version( solaris )
+    {
+        extern(C)
+        {
+            extern int _edata;
+            extern int _end;
+        }
+
+        alias _edata        Data_Start;
+        alias _end          Data_End;
     }
 
     version( GC_Use_Dynamic_Ranges )
@@ -280,14 +294,79 @@
         dataStart = adjust_up( &Data_Start );
         dataEnd   = adjust_down( &Data_End );
     }
+    else version(solaris)
+    {
+        dataStart = adjust_up( &Data_Start );
+        dataEnd   = adjust_down( &Data_End );
+    }
     else
     {
         static assert( false, "Operating system not supported." );
     }
 
-    //TODO: This could use cleanup!
     version( GC_Use_Data_Proc_Maps )
     {
+        parseDataProcMaps();
+    }
+}
+
+version( GC_Use_Data_Proc_Maps )
+{
+version(solaris)
+{
+    typedef long offset_t;
+    enum : uint { PRMAPSZ = 64, MA_WRITE = 0x02 }
+    extern(C)
+    {
+        struct prmap {
+            uintptr_t pr_vaddr;         /* virtual address of mapping */
+            size_t pr_size;             /* size of mapping in bytes */
+            char[PRMAPSZ]  pr_mapname;  /* name in /proc/<pid>/object */
+            private offset_t pr_offset; /* offset into mapped object, if any */
+            int pr_mflags;              /* protection and attribute flags (see below) */
+            int pr_pagesize;            /* pagesize (bytes) for this mapping */
+            int pr_shmid;               /* SysV shmid, -1 if not SysV shared memory */
+
+            private int[1] pr_filler;
+        }
+    }
+
+    void parseDataProcMaps()
+    {
+        debug (ProcMaps) printf("initStaticDataPtrs()\n");
+        // http://docs.sun.com/app/docs/doc/816-5174/proc-4
+        prmap pr;
+
+        int   fd = open("/proc/self/map", O_RDONLY);
+        scope (exit) close(fd);
+
+        while (prmap.sizeof == read(fd, &pr, prmap.sizeof))
+        if (pr.pr_mflags & MA_WRITE)
+        {
+            void* start = cast(void*) pr.pr_vaddr;
+            void* end   = cast(void*)(pr.pr_vaddr + pr.pr_size);
+            debug (ProcMaps) printf("  vmem at %p - %p with size %d bytes\n", start, end, pr.pr_size);
+
+            // Exclude stack  and  dataStart..dataEnd
+            if ( ( !dataEnd ||
+                !( dataStart >= start && dataEnd <= end ) ) &&
+                !( &pr >= start && &pr < end ) )
+            {
+                // we already have static data from this region.  anything else
+                // is heap (%% check)
+                debug (ProcMaps) printf("  Adding map range %p - %p\n", start, end);
+                _d_gc_add_range(start, end);
+            }
+        }
+    }
+}
+else
+{
+    const int S = (void*).sizeof;
+
+    // TODO: This could use cleanup!
+    void parseDataProcMaps()
+    {
         // TODO: Exclude zero-mapped regions
 
         int   fd = open("/proc/self/maps", O_RDONLY);
@@ -415,3 +494,4 @@
         }
     }
 }
+}
\ No newline at end of file