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