| 1 | See README.alpha for Linux on DEC AXP info. | 
|---|
| 2 |  | 
|---|
| 3 | This file applies mostly to Linux/Intel IA32.  Ports to Linux on an M68K, IA64, | 
|---|
| 4 | SPARC, MIPS, Alpha and PowerPC are also integrated.  They should behave | 
|---|
| 5 | similarly, except that the PowerPC port lacks incremental GC support, and | 
|---|
| 6 | it is unknown to what extent the Linux threads code is functional. | 
|---|
| 7 | See below for M68K specific notes. | 
|---|
| 8 |  | 
|---|
| 9 | Incremental GC is generally supported. | 
|---|
| 10 |  | 
|---|
| 11 | Dynamic libraries are supported on an ELF system.  A static executable | 
|---|
| 12 | should be linked with the gcc option "-Wl,-defsym,_DYNAMIC=0". | 
|---|
| 13 |  | 
|---|
| 14 | The collector appears to work reliably with Linux threads, but beware | 
|---|
| 15 | of older versions of glibc and gdb. | 
|---|
| 16 |  | 
|---|
| 17 | The garbage collector uses SIGPWR and SIGXCPU if it is used with | 
|---|
| 18 | Linux threads.  These should not be touched by the client program. | 
|---|
| 19 |  | 
|---|
| 20 | To use threads, you need to abide by the following requirements: | 
|---|
| 21 |  | 
|---|
| 22 | 1) You need to use LinuxThreads or NPTL (which are included in libc6). | 
|---|
| 23 |  | 
|---|
| 24 | The collector relies on some implementation details of the LinuxThreads | 
|---|
| 25 | package.  This code may not work on other | 
|---|
| 26 | pthread implementations (in particular it will *not* work with | 
|---|
| 27 | MIT pthreads). | 
|---|
| 28 |  | 
|---|
| 29 | 2) You must compile the collector with -DGC_LINUX_THREADS and -D_REENTRANT | 
|---|
| 30 | specified in the Makefile. | 
|---|
| 31 |  | 
|---|
| 32 | 3a) Every file that makes thread calls should define GC_LINUX_THREADS and | 
|---|
| 33 | _REENTRANT and then include gc.h.  Gc.h redefines some of the | 
|---|
| 34 | pthread primitives as macros which also provide the collector with | 
|---|
| 35 | information it requires. | 
|---|
| 36 |  | 
|---|
| 37 | 3b) A new alternative to (3a) is to build the collector and compile GC clients | 
|---|
| 38 | with -DGC_USE_LD_WRAP, and to link the final program with | 
|---|
| 39 |  | 
|---|
| 40 | (for ld) --wrap read --wrap dlopen --wrap pthread_create \ | 
|---|
| 41 | --wrap pthread_join --wrap pthread_detach \ | 
|---|
| 42 | --wrap pthread_sigmask --wrap sleep | 
|---|
| 43 |  | 
|---|
| 44 | (for gcc) -Wl,--wrap -Wl,read -Wl,--wrap -Wl,dlopen -Wl,--wrap \ | 
|---|
| 45 | -Wl,pthread_create -Wl,--wrap -Wl,pthread_join -Wl,--wrap \ | 
|---|
| 46 | -Wl,pthread_detach -Wl,--wrap -Wl,pthread_sigmask \ | 
|---|
| 47 | -Wl,--wrap -Wl,sleep | 
|---|
| 48 |  | 
|---|
| 49 | In any case, _REENTRANT should be defined during compilation. | 
|---|
| 50 |  | 
|---|
| 51 | 4) Dlopen() disables collection during its execution.  (It can't run | 
|---|
| 52 | concurrently with the collector, since the collector looks at its | 
|---|
| 53 | data structures.  It can't acquire the allocator lock, since arbitrary | 
|---|
| 54 | user startup code may run as part of dlopen().)  Under unusual | 
|---|
| 55 | conditions, this may cause unexpected heap growth. | 
|---|
| 56 |  | 
|---|
| 57 | 5) The combination of GC_LINUX_THREADS, REDIRECT_MALLOC, and incremental | 
|---|
| 58 | collection fails in seemingly random places.  This hasn't been tracked | 
|---|
| 59 | down yet, but is perhaps not completely astonishing.  The thread package | 
|---|
| 60 | uses malloc, and thus can presumably get SIGSEGVs while inside the | 
|---|
| 61 | package.  There is no real guarantee that signals are handled properly | 
|---|
| 62 | at that point. | 
|---|
| 63 |  | 
|---|
| 64 | 6) Thread local storage may not be viewed as part of the root set by the | 
|---|
| 65 | collector.  This probably depends on the linuxthreads version.  For the | 
|---|
| 66 | time being, any collectable memory referenced by thread local storage should | 
|---|
| 67 | also be referenced from elsewhere, or be allocated as uncollectable. | 
|---|
| 68 | (This is really a bug that should be fixed somehow.) | 
|---|
| 69 |  | 
|---|
| 70 |  | 
|---|
| 71 | M68K LINUX: | 
|---|
| 72 | (From Richard Zidlicky) | 
|---|
| 73 | The bad news is that it can crash every linux-m68k kernel on a 68040, | 
|---|
| 74 | so an additional test is needed somewhere on startup. I have meanwhile | 
|---|
| 75 | patches to correct the problem in 68040 buserror handler but it is not | 
|---|
| 76 | yet in any standard kernel. | 
|---|
| 77 |  | 
|---|
| 78 | Here is a simple test program to detect whether the kernel has the | 
|---|
| 79 | problem. It could be run as a separate check in configure or tested | 
|---|
| 80 | upon startup. If it fails (return !0) than mprotect can't be used | 
|---|
| 81 | on that system. | 
|---|
| 82 |  | 
|---|
| 83 | /* | 
|---|
| 84 | * test for bug that may crash 68040 based Linux | 
|---|
| 85 | */ | 
|---|
| 86 |  | 
|---|
| 87 | #include <sys/mman.h> | 
|---|
| 88 | #include <signal.h> | 
|---|
| 89 | #include <unistd.h> | 
|---|
| 90 | #include <stdio.h> | 
|---|
| 91 | #include <stdlib.h> | 
|---|
| 92 |  | 
|---|
| 93 |  | 
|---|
| 94 | char *membase; | 
|---|
| 95 | int pagesize=4096; | 
|---|
| 96 | int pageshift=12; | 
|---|
| 97 | int x_taken=0; | 
|---|
| 98 |  | 
|---|
| 99 | int sighandler(int sig) | 
|---|
| 100 | { | 
|---|
| 101 | mprotect(membase,pagesize,PROT_READ|PROT_WRITE); | 
|---|
| 102 | x_taken=1; | 
|---|
| 103 | } | 
|---|
| 104 |  | 
|---|
| 105 | main() | 
|---|
| 106 | { | 
|---|
| 107 | long l; | 
|---|
| 108 |  | 
|---|
| 109 | signal(SIGSEGV,sighandler); | 
|---|
| 110 | l=(long)mmap(NULL,pagesize,PROT_READ,MAP_PRIVATE | MAP_ANON,-1,0); | 
|---|
| 111 | if (l==-1) | 
|---|
| 112 | { | 
|---|
| 113 | perror("mmap/malloc"); | 
|---|
| 114 | abort(); | 
|---|
| 115 | } | 
|---|
| 116 | membase=(char*)l; | 
|---|
| 117 | *(long*)(membase+sizeof(long))=123456789; | 
|---|
| 118 | if (*(long*)(membase+sizeof(long)) != 123456789 ) | 
|---|
| 119 | { | 
|---|
| 120 | fprintf(stderr,"writeback failed !\n"); | 
|---|
| 121 | exit(1); | 
|---|
| 122 | } | 
|---|
| 123 | if (!x_taken) | 
|---|
| 124 | { | 
|---|
| 125 | fprintf(stderr,"exception not taken !\n"); | 
|---|
| 126 | exit(1); | 
|---|
| 127 | } | 
|---|
| 128 | fprintf(stderr,"vmtest Ok\n"); | 
|---|
| 129 | exit(0); | 
|---|
| 130 | } | 
|---|
| 131 |  | 
|---|
| 132 |  | 
|---|