C:/Users/Dennis/src/lang/russell.orig/src/gc/os_dep.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1991-1993 by Xerox Corporation.  All rights reserved.
00003  *
00004  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
00005  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
00006  *
00007  * Permission is hereby granted to copy this garbage collector for any purpose,
00008  * provided the above notices are retained on all copies.
00009  */
00010 # include "gc_private.h"
00011 # include <stdio.h>
00012 # include <signal.h>
00013 
00014 /* Blatantly OS dependent routines, except for those that are related   */
00015 /* dynamic loading.                                                     */
00016 
00017 /* Disable and enable signals during nontrivial allocations     */
00018 
00019 # ifdef OS2
00020 
00021 # define INCL_DOSEXCEPTIONS
00022 # define INCL_DOSPROCESS
00023 # define INCL_DOSERRORS
00024 # define INCL_DOSMODULEMGR
00025 # include <os2.h>
00026 
00027 /* A kludge to get around what appears to be a header file bug */
00028 # ifndef WORD
00029 #   define WORD unsigned short
00030 # endif
00031 # ifndef DWORD
00032 #   define DWORD unsigned long
00033 # endif
00034 
00035 # define EXE386 1
00036 # include <newexe.h>
00037 # include <exe386.h>
00038 
00039 void GC_disable_signals(void)
00040 {
00041     ULONG nest;
00042     
00043     DosEnterMustComplete(&nest);
00044     if (nest != 1) ABORT("nested GC_disable_signals");
00045 }
00046 
00047 void GC_enable_signals(void)
00048 {
00049     ULONG nest;
00050     
00051     DosExitMustComplete(&nest);
00052     if (nest != 0) ABORT("GC_enable_signals");
00053 }
00054 
00055 
00056 # else
00057 
00058 #  ifndef PCR
00059 
00060 #   ifdef sigmask
00061         /* Use the traditional BSD interface */
00062 #       define SIGSET_T int
00063 #       define SIG_DEL(set, signal) (set) &= ~(sigmask(signal))
00064 #       define SIG_FILL(set)  (set) = 0x7fffffff
00065           /* Setting the leading bit appears to provoke a bug in some   */
00066           /* longjmp implementations.  Most systems appear not to have  */
00067           /* a signal 32.                                               */
00068 #       define SIGSETMASK(old, new) (old) = sigsetmask(new)
00069 #   else
00070         /* Use POSIX/SYSV interface     */
00071 #       define SIGSET_T sigset_t
00072 #       define SIG_DEL(set, signal) sigdelset(&(set), (signal))
00073 #       define SIG_FILL(set) sigfillset(&set)
00074 #       define SIGSETMASK(old, new) sigprocmask(SIG_SETMASK, &(new), &(old))
00075 #   endif
00076 
00077 static bool mask_initialized = FALSE;
00078 
00079 static SIGSET_T new_mask;
00080 
00081 static SIGSET_T old_mask;
00082 
00083 static SIGSET_T dummy;
00084 
00085 void GC_disable_signals()
00086 {
00087     if (!mask_initialized) {
00088         SIG_FILL(new_mask);
00089 
00090         SIG_DEL(new_mask, SIGSEGV);
00091         SIG_DEL(new_mask, SIGILL);
00092         SIG_DEL(new_mask, SIGQUIT);
00093 #       ifdef SIGBUS
00094             SIG_DEL(new_mask, SIGBUS);
00095 #       endif
00096 #       ifdef SIGIOT
00097             SIG_DEL(new_mask, SIGIOT);
00098 #       endif
00099 #       ifdef SIGEMT
00100             SIG_DEL(new_mask, SIGEMT);
00101 #       endif
00102 #       ifdef SIGTRAP
00103             SIG_DEL(new_mask, SIGTRAP);
00104 #       endif 
00105         mask_initialized = TRUE;
00106     }     
00107     SIGSETMASK(old_mask,new_mask);
00108 }
00109 
00110 void GC_enable_signals()
00111 {
00112     SIGSETMASK(dummy,old_mask);
00113 }
00114 
00115 #  endif  /* !PCR */
00116 
00117 # endif 
00119 /*
00120  * Find the base of the stack.
00121  * Used only in single-threaded environment.
00122  * With threads, GC_mark_roots needs to know how to do this.
00123  * Called with allocator lock held.
00124  */
00125 
00126 # ifdef OS2
00127 
00128 ptr_t GC_get_stack_base()
00129 {
00130     PTIB ptib;
00131     PPIB ppib;
00132     
00133     if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
00134         GC_err_printf0("DosGetInfoBlocks failed\n");
00135         ABORT("DosGetInfoBlocks failed\n");
00136     }
00137     return((ptr_t)(ptib -> tib_pstacklimit));
00138 }
00139 
00140 # else
00141 
00142 # if !defined(THREADS) && !defined(STACKBOTTOM) && defined(HEURISTIC2)
00143   /* Some tools to implement HEURISTIC2 */
00144 #   define MIN_PAGE_SIZE 256    /* Smallest conceivable page size, bytes */
00145 #   include <setjmp.h>
00146     /* static */ jmp_buf GC_jmp_buf;
00147     
00148     /*ARGSUSED*/
00149     void GC_fault_handler(sig)
00150     int sig;
00151     {
00152         longjmp(GC_jmp_buf, 1);
00153     }
00154 # endif
00155 
00156 ptr_t GC_get_stack_base()
00157 {
00158     word dummy;
00159     static ptr_t result;
00160                 /* Needs to be static, since otherwise it may not be    */
00161                 /* preserved across the longjmp.  Can safely be         */
00162                 /* static since it's only called once, with the         */
00163                 /* allocation lock held.                                */
00164 #   ifdef __STDC__
00165         typedef void (*handler)(int);
00166 #   else
00167         typedef void (*handler)();
00168 #   endif
00169 #   ifdef HEURISTIC2
00170       static handler old_segv_handler, old_bus_handler;
00171                 /* See above for static declaration.                    */
00172 #   endif
00173 #   define STACKBOTTOM_ALIGNMENT_M1 0xffffff
00174 
00175 #   ifdef STACKBOTTOM
00176         return(STACKBOTTOM);
00177 #   else
00178 #       ifdef HEURISTIC1
00179 #          ifdef STACK_GROWS_DOWN
00180              result = (ptr_t)((((word)(&dummy))
00181                                + STACKBOTTOM_ALIGNMENT_M1)
00182                               & ~STACKBOTTOM_ALIGNMENT_M1);
00183 #          else
00184              result = (ptr_t)(((word)(&dummy))
00185                               & ~STACKBOTTOM_ALIGNMENT_M1);
00186 #          endif
00187 #       endif /* HEURISTIC1 */
00188 #       ifdef HEURISTIC2
00189            old_segv_handler = signal(SIGSEGV, GC_fault_handler);
00190 #          ifdef SIGBUS
00191              old_bus_handler = signal(SIGBUS, GC_fault_handler);
00192 #          endif
00193            if (setjmp(GC_jmp_buf) == 0) {
00194              result = (ptr_t)(((word)(&dummy))
00195                               & ~(MIN_PAGE_SIZE-1));
00196              for (;;) {
00197 #                ifdef STACK_GROWS_DOWN
00198                    result += MIN_PAGE_SIZE;
00199 #                else
00200                    result -= MIN_PAGE_SIZE;
00201 #                endif
00202                  GC_noop(*result);
00203              }
00204            }
00205            (void) signal(SIGSEGV, old_segv_handler);
00206 #          ifdef SIGBUS
00207                (void) signal(SIGBUS, old_bus_handler);
00208 #          endif
00209 #          ifdef STACK_GROWS_UP
00210               result += MIN_PAGE_SIZE;
00211 #          endif
00212 #       endif /* HEURISTIC2 */
00213         return(result);
00214 #   endif /* STACKBOTTOM */
00215 }
00216 
00217 # endif /* ! OS2 */
00218 
00219 /*
00220  * Register static data segment(s) as roots.
00221  * If more data segments are added later then they need to be registered
00222  * add that point (as we do with SunOS dynamic loading),
00223  * or GC_mark_roots needs to check for them (as we do with PCR).
00224  * Called with allocator lock held.
00225  */
00226 
00227 # ifdef OS2
00228 
00229 void GC_register_data_segments()
00230 {
00231     PTIB ptib;
00232     PPIB ppib;
00233     HMODULE module_handle;
00234 #   define PBUFSIZ 512
00235     UCHAR path[PBUFSIZ];
00236     FILE * myexefile;
00237     struct exe_hdr hdrdos;      /* MSDOS header.        */
00238     struct e32_exe hdr386;      /* Real header for my executable */
00239     struct o32_obj seg; /* Currrent segment */
00240     int nsegs;
00241     
00242     
00243     if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
00244         GC_err_printf0("DosGetInfoBlocks failed\n");
00245         ABORT("DosGetInfoBlocks failed\n");
00246     }
00247     module_handle = ppib -> pib_hmte;
00248     if (DosQueryModuleName(module_handle, PBUFSIZ, path) != NO_ERROR) {
00249         GC_err_printf0("DosQueryModuleName failed\n");
00250         ABORT("DosGetInfoBlocks failed\n");
00251     }
00252     myexefile = fopen(path, "rb");
00253     if (myexefile == 0) {
00254         GC_err_puts("Couldn't open executable ");
00255         GC_err_puts(path); GC_err_puts("\n");
00256         ABORT("Failed to open executable\n");
00257     }
00258     if (fread((char *)(&hdrdos), 1, sizeof hdrdos, myexefile) < sizeof hdrdos) {
00259         GC_err_puts("Couldn't read MSDOS header from ");
00260         GC_err_puts(path); GC_err_puts("\n");
00261         ABORT("Couldn't read MSDOS header");
00262     }
00263     if (E_MAGIC(hdrdos) != EMAGIC) {
00264         GC_err_puts("Executable has wrong DOS magic number: ");
00265         GC_err_puts(path); GC_err_puts("\n");
00266         ABORT("Bad DOS magic number");
00267     }
00268     if (fseek(myexefile, E_LFANEW(hdrdos), SEEK_SET) != 0) {
00269         GC_err_puts("Seek to new header failed in ");
00270         GC_err_puts(path); GC_err_puts("\n");
00271         ABORT("Bad DOS magic number");
00272     }
00273     if (fread((char *)(&hdr386), 1, sizeof hdr386, myexefile) < sizeof hdr386) {
00274         GC_err_puts("Couldn't read MSDOS header from ");
00275         GC_err_puts(path); GC_err_puts("\n");
00276         ABORT("Couldn't read OS/2 header");
00277     }
00278     if (E32_MAGIC1(hdr386) != E32MAGIC1 || E32_MAGIC2(hdr386) != E32MAGIC2) {
00279         GC_err_puts("Executable has wrong OS/2 magic number:");
00280         GC_err_puts(path); GC_err_puts("\n");
00281         ABORT("Bad OS/2 magic number");
00282     }
00283     if ( E32_BORDER(hdr386) != E32LEBO || E32_WORDER(hdr386) != E32LEWO) {
00284         GC_err_puts("Executable %s has wrong byte order: ");
00285         GC_err_puts(path); GC_err_puts("\n");
00286         ABORT("Bad byte order");
00287     }
00288     if ( E32_CPU(hdr386) == E32CPU286) {
00289         GC_err_puts("GC can't handle 80286 executables: ");
00290         GC_err_puts(path); GC_err_puts("\n");
00291         EXIT();
00292     }
00293     if (fseek(myexefile, E_LFANEW(hdrdos) + E32_OBJTAB(hdr386),
00294               SEEK_SET) != 0) {
00295         GC_err_puts("Seek to object table failed: ");
00296         GC_err_puts(path); GC_err_puts("\n");
00297         ABORT("Seek to object table failed");
00298     }
00299     for (nsegs = E32_OBJCNT(hdr386); nsegs > 0; nsegs--) {
00300       int flags;
00301       if (fread((char *)(&seg), 1, sizeof seg, myexefile) < sizeof seg) {
00302         GC_err_puts("Couldn't read obj table entry from ");
00303         GC_err_puts(path); GC_err_puts("\n");
00304         ABORT("Couldn't read obj table entry");
00305       }
00306       flags = O32_FLAGS(seg);
00307       if (!(flags & OBJWRITE)) continue;
00308       if (!(flags & OBJREAD)) continue;
00309       if (flags & OBJINVALID) {
00310           GC_err_printf0("Object with invalid pages?\n");
00311           continue;
00312       } 
00313       GC_add_roots_inner(O32_BASE(seg), O32_BASE(seg)+O32_SIZE(seg));
00314     }
00315 }
00316 
00317 # else
00318 
00319 void GC_register_data_segments()
00320 {
00321     extern int end;
00322  
00323 #   ifndef PCR      
00324       GC_add_roots_inner(DATASTART, (char *)(&end));
00325 #   endif
00326     /* Dynamic libraries are added at every collection, since they may  */
00327     /* change.                                                          */
00328 }
00329 
00330 # endif  /* ! OS2 */

Generated on Fri Jan 25 10:39:45 2008 for russell by  doxygen 1.5.4