Back to index

plt-scheme  4.2.1
autostat.inc
Go to the documentation of this file.
00001 
00002 #if defined(_IBMR2)
00003   extern int end;
00004 # define DATASTART ((void *)0x20000000)
00005 # define DATAEND ((void *)(&end))
00006 # define USE_DATASTARTEND 1
00007 #endif
00008 
00009 #if defined(__FreeBSD__) && defined(i386)
00010   extern char etext;
00011   extern int end;
00012 # define DATASTART ((void *)(&etext))
00013 # define DATAEND ((void *)(&end))
00014 # define USE_DATASTARTEND 1
00015 #endif
00016 
00017 #if defined(linux) && defined(i386) && defined(__ELF__)
00018 # include <linux/version.h>
00019 # include <features.h>
00020 # if LINUX_VERSION_CODE >= 0x20000 && defined(__GLIBC__) && __GLIBC__ >= 2
00021   extern int __data_start;
00022 #  define DATASTART ((void *)(&__data_start))
00023 # else
00024    extern int _etext;
00025 #  define DATASTART ((void *)((((unsigned long) (&_etext)) + 0xfff) & ~0xfff))
00026 # endif
00027   extern int _end;
00028 # define DATAEND (&_end)
00029 # define USE_DATASTARTEND 1
00030 #endif
00031 
00032 #if defined(sun)
00033 # include <errno.h>
00034 # ifdef ECHRNG
00035 /* Solaris */
00036   extern char _etext;
00037   extern int _end;
00038 #  define DATASTART sysv_GetDataStart(0x10000, (int)&_etext)
00039 #  define DATAEND (void *)(&_end)
00040 #  define NEED_SYSV_GET_START
00041 # else
00042 #  define TEXTSTART 0x2000
00043 #  define DATASTART ((ptr_t)(*(int *)(TEXTSTART+0x4)+TEXTSTART))
00044 # endif
00045 # define USE_DATASTARTEND 1
00046 #endif
00047 
00048 #ifndef USE_DATASTARTEND
00049 # define USE_DATASTARTEND 0
00050 #endif
00051 
00052 #ifdef WIN32
00053 /* Mostly borrowed from conservative GC, Boehm et al. */
00054 static void cond_add_roots(char *base, char * limit, long allocation_granularity)
00055 {
00056   char dummy;
00057   char * stack_top;
00058   
00059   if (base == limit) return;
00060   
00061   stack_top = (char *) ((long)(&dummy) & ~(allocation_granularity-1));
00062   
00063   if (limit > stack_top && base < (char *)GC_stackbottom) {
00064     /* Part of the stack; ignore it. */
00065     return;
00066   }
00067   GC_add_roots(base, limit);
00068 }
00069   
00070 void register_static_variables()
00071 {
00072   MEMORY_BASIC_INFORMATION buf;
00073   SYSTEM_INFO sysinfo;
00074   DWORD result;
00075   DWORD protect;
00076   LPVOID p;
00077   char * base;
00078   char * limit, * new_limit;
00079   long allocation_granularity;
00080   
00081   GetSystemInfo(&sysinfo);
00082   base = limit = p = sysinfo.lpMinimumApplicationAddress;
00083   allocation_granularity = sysinfo.dwAllocationGranularity;
00084   while (p < sysinfo.lpMaximumApplicationAddress) {
00085     result = VirtualQuery(p, &buf, sizeof(buf));
00086     new_limit = (char *)p + buf.RegionSize;
00087     protect = buf.Protect;
00088     if (buf.State == MEM_COMMIT
00089        && (protect == PAGE_EXECUTE_READWRITE
00090            || protect == PAGE_READWRITE
00091            || protect == PAGE_WRITECOPY
00092            || protect == PAGE_EXECUTE_WRITECOPY)
00093        && !is_sector_segment(buf.AllocationBase)) {
00094       if ((char *)p == limit) {
00095        limit = new_limit;
00096       } else {
00097        cond_add_roots(base, limit, allocation_granularity);
00098        base = p;
00099        limit = new_limit;
00100       }
00101     }
00102     if (p > (LPVOID)new_limit /* overflow */) break;
00103     p = (LPVOID)new_limit;
00104   }
00105   cond_add_roots(base, limit, allocation_granularity);
00106 }
00107 
00108 long total_memory_use()
00109 {
00110   /* Try to count total used bytes in the heap. */
00111   MEMORY_BASIC_INFORMATION buf;
00112   SYSTEM_INFO sysinfo;
00113   LPVOID p;
00114   char * new_limit;
00115   long allocation_granularity;
00116   long total = 0;
00117     
00118   GetSystemInfo(&sysinfo);
00119   p = sysinfo.lpMinimumApplicationAddress;
00120   allocation_granularity = sysinfo.dwAllocationGranularity;
00121   while (p < sysinfo.lpMaximumApplicationAddress) {
00122     VirtualQuery(p, &buf, sizeof(buf));
00123     new_limit = (char *)p + buf.RegionSize;
00124     if (buf.State != MEM_FREE)
00125       total += buf.RegionSize;
00126     if (p > (LPVOID)new_limit /* overflow */) break;
00127     p = (LPVOID)new_limit;
00128   }
00129   
00130   return total;
00131 }
00132 #endif /* Win32 */
00133 
00134 #ifdef NEED_SYSV_GET_START
00135 /* Also borrowed conservative GC, Boehm et al. */
00136 #include <signal.h>
00137 # define MIN_PAGE_SIZE 256  /* Smallest conceivable page size, bytes */
00138 static jmp_buf sysv_jb;
00139     
00140 void sysv_fault_handler(int sig)
00141 {
00142   longjmp(sysv_jb, 1);
00143 }
00144 
00145 typedef void (*handler)(int);
00146 # ifdef sun
00147 static struct sigaction oldact;
00148 # else
00149 static handler old_segv_handler, old_bus_handler;
00150 # endif
00151 
00152 static void sysv_setup_temporary_fault_handler()
00153 {
00154 # ifdef sun
00155   struct sigaction act;
00156 
00157   act.sa_handler = sysv_fault_handler;
00158   act.sa_flags = SA_RESTART | SA_SIGINFO | SA_NODEFER;
00159   /* The presence of SA_NODEFER represents yet another gross    */
00160   /* hack.  Under Solaris 2.3, siglongjmp doesn't appear to     */
00161   /* interact correctly with -lthread.  We hide the confusion   */
00162   /* by making sure that signal handling doesn't affect the     */
00163   /* signal mask.                                               */
00164 
00165   (void) sigemptyset(&act.sa_mask);
00166   (void) sigaction(SIGSEGV, &act, &oldact);
00167 # else
00168   old_segv_handler = signal(SIGSEGV, sysv_fault_handler);
00169 # ifdef SIGBUS
00170  old_bus_handler = signal(SIGBUS, sysv_fault_handler);
00171 # endif
00172 # endif
00173 }
00174     
00175 void sysv_reset_fault_handler()
00176 {
00177 # ifdef sun
00178   (void) sigaction(SIGSEGV, &oldact, 0);
00179 # else
00180   (void) signal(SIGSEGV, old_segv_handler);
00181 # ifdef SIGBUS
00182   (void) signal(SIGBUS, old_bus_handler);
00183 # endif
00184 # endif
00185 }
00186 
00187 /* Return the first nonaddressible location > p (up) or        */
00188 /* the smallest location q s.t. [q,p] is addressible (!up).    */
00189 void *sysv_find_limit(void *p, int up)
00190 {
00191   static void *result;
00192   static char dummy;
00193   /* Needs to be static, since otherwise it may not be  */
00194   /* preserved across the longjmp.  Can safely be       */
00195   /* static since it's only called once, with the       */
00196   /* allocation lock held.                       */
00197   
00198   sysv_setup_temporary_fault_handler();
00199   if (setjmp(sysv_jb) == 0) {
00200     result = (void *)(((unsigned long)(p)) & ~(MIN_PAGE_SIZE-1));
00201     while(1) {
00202       if (up)
00203        result += MIN_PAGE_SIZE;
00204       else
00205        result -= MIN_PAGE_SIZE;
00206 
00207       dummy = *(char *)result;
00208     }
00209   }
00210   sysv_reset_fault_handler();
00211   if (!up)
00212     result += MIN_PAGE_SIZE;
00213   return result;
00214 }
00215 
00216 void *sysv_GetDataStart(int max_page_size, int etext_addr)
00217 {
00218   unsigned long text_end = (((unsigned long)(etext_addr) + sizeof(unsigned long) - 1)
00219                          & ~(sizeof(unsigned long) - 1));
00220   /* etext rounded to word boundary       */
00221   unsigned long next_page = ((text_end + (unsigned long)max_page_size - 1)
00222                           & ~((unsigned long)max_page_size - 1));
00223   unsigned long page_offset = (text_end & ((unsigned long)max_page_size - 1));
00224   char * result = (char *)(next_page + page_offset);
00225   /* Note that this isnt equivalent to just adding             */
00226   /* max_page_size to &etext if &etext is at a page boundary   */
00227   
00228   sysv_setup_temporary_fault_handler();
00229   if (setjmp(sysv_jb) == 0) {
00230     /* Try writing to the address. */
00231     *result = *result;
00232   } else {
00233     /* We got here via a longjmp.  The address is not readable.       */
00234     /* This is known to happen under Solaris 2.4 + gcc, which place   */
00235     /* string constants in the text segment, but after etext.  */
00236     /* Use plan B.  Note that we now know there is a gap between      */
00237     /* text and data segments, so plan A bought us something.  */
00238     result = (char *)sysv_find_limit((void *)(DATAEND) - MIN_PAGE_SIZE, 0);
00239   }
00240   sysv_reset_fault_handler();
00241   return (void *)result;
00242 }
00243 #endif /* SysV */