|
Packit |
d28291 |
See README.alpha for Linux on DEC AXP info.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
This file applies mostly to Linux/Intel IA32. Ports to Linux on an M68K,
|
|
Packit |
d28291 |
IA64, SPARC, MIPS, Alpha and PowerPC are integrated too. They should behave
|
|
Packit |
d28291 |
similarly, except that the PowerPC port lacks incremental GC support, and
|
|
Packit |
d28291 |
it is unknown to what extent the Linux threads code is functional.
|
|
Packit |
d28291 |
See below for M68K specific notes.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
Incremental GC is generally supported.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
Dynamic libraries are supported on an ELF system.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
The collector appears to work reliably with Linux threads, but beware
|
|
Packit |
d28291 |
of older versions of glibc and gdb.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
The garbage collector uses SIGPWR and SIGXCPU if it is used with
|
|
Packit |
d28291 |
Linux threads. These should not be touched by the client program.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
To use threads, you need to abide by the following requirements:
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
1) You need to use LinuxThreads or NPTL (which are included in libc6).
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
The collector relies on some implementation details of the LinuxThreads
|
|
Packit |
d28291 |
package. This code may not work on other
|
|
Packit |
d28291 |
pthread implementations (in particular it will *not* work with
|
|
Packit |
d28291 |
MIT pthreads).
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
2) You must compile the collector with -DGC_LINUX_THREADS (or
|
|
Packit |
d28291 |
just -DGC_THREADS) and -D_REENTRANT specified in the Makefile.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
3a) Every file that makes thread calls should define GC_LINUX_THREADS and
|
|
Packit |
d28291 |
_REENTRANT and then include gc.h. Gc.h redefines some of the
|
|
Packit |
d28291 |
pthread primitives as macros which also provide the collector with
|
|
Packit |
d28291 |
information it requires.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
3b) A new alternative to (3a) is to build the collector and compile GC clients
|
|
Packit |
d28291 |
with -DGC_USE_LD_WRAP, and to link the final program with
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
(for ld) --wrap dlopen --wrap pthread_create \
|
|
Packit |
d28291 |
--wrap pthread_join --wrap pthread_detach \
|
|
Packit |
d28291 |
--wrap pthread_sigmask --wrap pthread_exit --wrap pthread_cancel
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
(for gcc) -Wl,--wrap -Wl,dlopen -Wl,--wrap -Wl,pthread_create \
|
|
Packit |
d28291 |
-Wl,--wrap -Wl,pthread_join -Wl,--wrap -Wl,pthread_detach \
|
|
Packit |
d28291 |
-Wl,--wrap -Wl,pthread_sigmask -Wl,--wrap -Wl,pthread_exit \
|
|
Packit |
d28291 |
-Wl,--wrap -Wl,pthread_cancel
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
In any case, _REENTRANT should be defined during compilation.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
4) Dlopen() disables collection during its execution. (It can't run
|
|
Packit |
d28291 |
concurrently with the collector, since the collector looks at its
|
|
Packit |
d28291 |
data structures. It can't acquire the allocator lock, since arbitrary
|
|
Packit |
d28291 |
user startup code may run as part of dlopen().) Under unusual
|
|
Packit |
d28291 |
conditions, this may cause unexpected heap growth.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
5) The combination of GC_LINUX_THREADS, REDIRECT_MALLOC, and incremental
|
|
Packit |
d28291 |
collection is probably not fully reliable, though it now seems to work
|
|
Packit |
d28291 |
in simple cases.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
6) Thread local storage may not be viewed as part of the root set by the
|
|
Packit |
d28291 |
collector. This probably depends on the linuxthreads version. For the
|
|
Packit |
d28291 |
time being, any collectible memory referenced by thread local storage
|
|
Packit |
d28291 |
should also be referenced from elsewhere, or be allocated as uncollectible.
|
|
Packit |
d28291 |
(This is really a bug that should be fixed somehow. The current GC
|
|
Packit |
d28291 |
version probably gets things right if there are not too many tls locations
|
|
Packit |
d28291 |
and if dlopen is not used.)
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
M68K LINUX:
|
|
Packit |
d28291 |
(From Richard Zidlicky)
|
|
Packit |
d28291 |
The bad news is that it can crash every linux-m68k kernel on a 68040,
|
|
Packit |
d28291 |
so an additional test is needed somewhere on startup. I have meanwhile
|
|
Packit |
d28291 |
patches to correct the problem in 68040 buserror handler but it is not
|
|
Packit |
d28291 |
yet in any standard kernel.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
Here is a simple test program to detect whether the kernel has the
|
|
Packit |
d28291 |
problem. It could be run as a separate check in configure or tested
|
|
Packit |
d28291 |
upon startup. If it fails (return !0) than mprotect can't be used
|
|
Packit |
d28291 |
on that system.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
/*
|
|
Packit |
d28291 |
* test for bug that may crash 68040 based Linux
|
|
Packit |
d28291 |
*/
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
#include <sys/mman.h>
|
|
Packit |
d28291 |
#include <signal.h>
|
|
Packit |
d28291 |
#include <unistd.h>
|
|
Packit |
d28291 |
#include <stdio.h>
|
|
Packit |
d28291 |
#include <stdlib.h>
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
char *membase;
|
|
Packit |
d28291 |
int pagesize=4096;
|
|
Packit |
d28291 |
int pageshift=12;
|
|
Packit |
d28291 |
int x_taken=0;
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
int sighandler(int sig)
|
|
Packit |
d28291 |
{
|
|
Packit |
d28291 |
mprotect(membase,pagesize,PROT_READ|PROT_WRITE);
|
|
Packit |
d28291 |
x_taken=1;
|
|
Packit |
d28291 |
}
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
main()
|
|
Packit |
d28291 |
{
|
|
Packit |
d28291 |
long l;
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
signal(SIGSEGV,sighandler);
|
|
Packit |
d28291 |
l=(long)mmap(NULL,pagesize,PROT_READ,MAP_PRIVATE | MAP_ANON,-1,0);
|
|
Packit |
d28291 |
if (l==-1)
|
|
Packit |
d28291 |
{
|
|
Packit |
d28291 |
perror("mmap/malloc");
|
|
Packit |
d28291 |
abort();
|
|
Packit |
d28291 |
}
|
|
Packit |
d28291 |
membase=(char*)l;
|
|
Packit |
d28291 |
*(long*)(membase+sizeof(long))=123456789;
|
|
Packit |
d28291 |
if (*(long*)(membase+sizeof(long)) != 123456789 )
|
|
Packit |
d28291 |
{
|
|
Packit |
d28291 |
fprintf(stderr,"writeback failed !\n");
|
|
Packit |
d28291 |
exit(1);
|
|
Packit |
d28291 |
}
|
|
Packit |
d28291 |
if (!x_taken)
|
|
Packit |
d28291 |
{
|
|
Packit |
d28291 |
fprintf(stderr,"exception not taken !\n");
|
|
Packit |
d28291 |
exit(1);
|
|
Packit |
d28291 |
}
|
|
Packit |
d28291 |
fprintf(stderr,"vmtest Ok\n");
|
|
Packit |
d28291 |
exit(0);
|
|
Packit |
d28291 |
}
|