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