upgrade to Boehm GC version 6.7
svn: r3634
This commit is contained in:
parent
154329bf0e
commit
ac267d077f
|
@ -8,13 +8,12 @@
|
||||||
|
|
||||||
11/22/94 pcb StripAddress the temporary memory handle for 24-bit mode.
|
11/22/94 pcb StripAddress the temporary memory handle for 24-bit mode.
|
||||||
11/30/94 pcb Tracking all memory usage so we can deallocate it all at once.
|
11/30/94 pcb Tracking all memory usage so we can deallocate it all at once.
|
||||||
02/10/96 pcb Added routine to perform a final collection when unloading shared library.
|
02/10/96 pcb Added routine to perform a final collection when
|
||||||
|
unloading shared library.
|
||||||
|
|
||||||
by Patrick C. Beard.
|
by Patrick C. Beard.
|
||||||
|
|
||||||
PLTSCHEME: this file is substantially modified for MzScheme/MrEd.
|
|
||||||
*/
|
*/
|
||||||
/* Boehm, November 17, 1995 11:50 am PST */
|
/* Boehm, February 15, 1996 2:55 pm PST */
|
||||||
|
|
||||||
#include <Resources.h>
|
#include <Resources.h>
|
||||||
#include <Memory.h>
|
#include <Memory.h>
|
||||||
|
@ -24,7 +23,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "gc.h"
|
#include "gc.h"
|
||||||
#include "private/gc_priv.h"
|
#include "gc_priv.h"
|
||||||
|
|
||||||
// use 'CODE' resource 0 to get exact location of the beginning of global space.
|
// use 'CODE' resource 0 to get exact location of the beginning of global space.
|
||||||
|
|
||||||
|
@ -48,20 +47,6 @@ void* GC_MacGetDataStart()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PLTSCHEME: Function for handling CW Pro 3 far data */
|
|
||||||
void* GC_MacGetDataEnd()
|
|
||||||
{
|
|
||||||
CodeZeroHandle code0 = (CodeZeroHandle)GetResource('CODE', 0);
|
|
||||||
if (code0) {
|
|
||||||
long aboveA5Size = (**code0).aboveA5;
|
|
||||||
ReleaseResource((Handle)code0);
|
|
||||||
return (LMGetCurrentA5() + aboveA5Size);
|
|
||||||
}
|
|
||||||
fprintf(stderr, "Couldn't load the jump table.");
|
|
||||||
exit(-1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* track the use of temporary memory so it can be freed all at once. */
|
/* track the use of temporary memory so it can be freed all at once. */
|
||||||
|
|
||||||
typedef struct TemporaryMemoryBlock TemporaryMemoryBlock, **TemporaryMemoryHandle;
|
typedef struct TemporaryMemoryBlock TemporaryMemoryBlock, **TemporaryMemoryHandle;
|
||||||
|
@ -81,27 +66,7 @@ Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory)
|
||||||
static Boolean firstTime = true;
|
static Boolean firstTime = true;
|
||||||
OSErr result;
|
OSErr result;
|
||||||
TemporaryMemoryHandle tempMemBlock;
|
TemporaryMemoryHandle tempMemBlock;
|
||||||
Ptr tempPtr;
|
Ptr tempPtr = nil;
|
||||||
|
|
||||||
/* PLTSCHEME: IM requests that temp memory not be locked across
|
|
||||||
calls to GetNextEvent or WaitNextEvent. So, we'll use regular
|
|
||||||
pointers, but grab temp memory if we run out completely.
|
|
||||||
Also, we'll be nicer about not grabbing *all* of temp memory,
|
|
||||||
as this seems to bring down the whole system. */
|
|
||||||
if ((FreeMem() - size) >= 65536) { /* resort to tmp mem if local < some amount */
|
|
||||||
if (clearMemory)
|
|
||||||
tempPtr = NewPtrClear(size);
|
|
||||||
else
|
|
||||||
tempPtr = NewPtr(size);
|
|
||||||
if (tempPtr)
|
|
||||||
return tempPtr;
|
|
||||||
} else
|
|
||||||
tempPtr = NULL;
|
|
||||||
|
|
||||||
if ((TempFreeMem() - size) < 65536) {
|
|
||||||
/* Not much temp mem availabl, either. Give up. */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tempMemBlock = (TemporaryMemoryHandle)TempNewHandle(size + sizeof(TemporaryMemoryBlock), &result);
|
tempMemBlock = (TemporaryMemoryHandle)TempNewHandle(size + sizeof(TemporaryMemoryBlock), &result);
|
||||||
if (tempMemBlock && result == noErr) {
|
if (tempMemBlock && result == noErr) {
|
||||||
|
@ -114,52 +79,76 @@ Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory)
|
||||||
(**tempMemBlock).nextBlock = theTemporaryMemory;
|
(**tempMemBlock).nextBlock = theTemporaryMemory;
|
||||||
theTemporaryMemory = tempMemBlock;
|
theTemporaryMemory = tempMemBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(SHARED_LIBRARY_BUILD)
|
# if !defined(SHARED_LIBRARY_BUILD)
|
||||||
// install an exit routine to clean up the memory used at the end.
|
// install an exit routine to clean up the memory used at the end.
|
||||||
if (firstTime) {
|
if (firstTime) {
|
||||||
atexit(&GC_MacFreeTemporaryMemory);
|
atexit(&GC_MacFreeTemporaryMemory);
|
||||||
firstTime = false;
|
firstTime = false;
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
return tempPtr;
|
return tempPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern word GC_fo_entries;
|
||||||
|
|
||||||
static void perform_final_collection()
|
static void perform_final_collection()
|
||||||
{
|
{
|
||||||
int i;
|
unsigned i;
|
||||||
|
word last_fo_entries = 0;
|
||||||
/* adjust the stack bottom, because CFM calls us from another stack location. */
|
|
||||||
GC_stackbottom = (ptr_t)&i;
|
/* adjust the stack bottom, because CFM calls us from another stack
|
||||||
|
location. */
|
||||||
/* try to collect everything in sight (from test.c). Is this safe? */
|
GC_stackbottom = (ptr_t)&i;
|
||||||
while (GC_collect_a_little()) ;
|
|
||||||
for (i = 0; i < 16; i++)
|
/* try to collect and finalize everything in sight */
|
||||||
GC_gcollect();
|
for (i = 0; i < 2 || GC_fo_entries < last_fo_entries; i++) {
|
||||||
|
last_fo_entries = GC_fo_entries;
|
||||||
|
GC_gcollect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GC_MacFreeTemporaryMemory()
|
void GC_MacFreeTemporaryMemory()
|
||||||
{
|
{
|
||||||
#if defined(SHARED_LIBRARY_BUILD)
|
# if defined(SHARED_LIBRARY_BUILD)
|
||||||
/* collect all memory, and invoke all finalizers. */
|
/* if possible, collect all memory, and invoke all finalizers. */
|
||||||
perform_final_collection();
|
perform_final_collection();
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
if (theTemporaryMemory != NULL) {
|
if (theTemporaryMemory != NULL) {
|
||||||
long totalMemoryUsed = 0;
|
long totalMemoryUsed = 0;
|
||||||
TemporaryMemoryHandle tempMemBlock = theTemporaryMemory;
|
TemporaryMemoryHandle tempMemBlock = theTemporaryMemory;
|
||||||
while (tempMemBlock != NULL) {
|
while (tempMemBlock != NULL) {
|
||||||
TemporaryMemoryHandle nextBlock = (**tempMemBlock).nextBlock;
|
TemporaryMemoryHandle nextBlock = (**tempMemBlock).nextBlock;
|
||||||
totalMemoryUsed += GetHandleSize((Handle)tempMemBlock);
|
totalMemoryUsed += GetHandleSize((Handle)tempMemBlock);
|
||||||
DisposeHandle((Handle)tempMemBlock);
|
DisposeHandle((Handle)tempMemBlock);
|
||||||
tempMemBlock = nextBlock;
|
tempMemBlock = nextBlock;
|
||||||
}
|
|
||||||
theTemporaryMemory = NULL;
|
|
||||||
|
|
||||||
#if !defined(SILENT) && !defined(SHARED_LIBRARY_BUILD)
|
|
||||||
fprintf(stdout, "[total memory used: %ld bytes.]\n", totalMemoryUsed);
|
|
||||||
fprintf(stdout, "[total collections: %ld.]\n", GC_gc_no);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
theTemporaryMemory = NULL;
|
||||||
|
|
||||||
|
# if !defined(SILENT) && !defined(SHARED_LIBRARY_BUILD)
|
||||||
|
fprintf(stdout, "[total memory used: %ld bytes.]\n",
|
||||||
|
totalMemoryUsed);
|
||||||
|
fprintf(stdout, "[total collections: %ld.]\n", GC_gc_no);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __option(far_data)
|
||||||
|
|
||||||
|
void* GC_MacGetDataEnd()
|
||||||
|
{
|
||||||
|
CodeZeroHandle code0 = (CodeZeroHandle)GetResource('CODE', 0);
|
||||||
|
if (code0) {
|
||||||
|
long aboveA5Size = (**code0).aboveA5;
|
||||||
|
ReleaseResource((Handle)code0);
|
||||||
|
return (LMGetCurrentA5() + aboveA5Size);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Couldn't load the jump table.");
|
||||||
|
exit(-1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __option(far_data) */
|
||||||
|
|
|
@ -45,7 +45,7 @@ asm_libgc_sources =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
libgc_la_SOURCES = allchblk.c alloc.c blacklst.c checksums.c dbg_mlc.c \
|
libgc_la_SOURCES = allchblk.c alloc.c blacklst.c checksums.c dbg_mlc.c \
|
||||||
dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c headers.c aix_irix_threads.c \
|
dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c headers.c \
|
||||||
malloc.c mallocx.c mark.c mark_rts.c misc.c new_hblk.c \
|
malloc.c mallocx.c mark.c mark_rts.c misc.c new_hblk.c \
|
||||||
obj_map.c os_dep.c pcr_interface.c ptr_chck.c real_malloc.c reclaim.c \
|
obj_map.c os_dep.c pcr_interface.c ptr_chck.c real_malloc.c reclaim.c \
|
||||||
solaris_pthreads.c solaris_threads.c specific.c stubborn.c typd_mlc.c \
|
solaris_pthreads.c solaris_threads.c specific.c stubborn.c typd_mlc.c \
|
||||||
|
@ -53,9 +53,9 @@ backgraph.c win32_threads.c \
|
||||||
pthread_support.c pthread_stop_world.c darwin_stop_world.c \
|
pthread_support.c pthread_stop_world.c darwin_stop_world.c \
|
||||||
$(asm_libgc_sources)
|
$(asm_libgc_sources)
|
||||||
|
|
||||||
# Include THREADLIBS here to ensure that the correct versions of
|
# Include THREADDLLIBS here to ensure that the correct versions of
|
||||||
# linuxthread semaphore functions get linked:
|
# linuxthread semaphore functions get linked:
|
||||||
libgc_la_LIBADD = @addobjs@ $(THREADLIBS) $(UNWINDLIBS)
|
libgc_la_LIBADD = @addobjs@ $(THREADDLLIBS) $(UNWINDLIBS)
|
||||||
libgc_la_DEPENDENCIES = @addobjs@
|
libgc_la_DEPENDENCIES = @addobjs@
|
||||||
libgc_la_LDFLAGS = -version-info 1:2:0
|
libgc_la_LDFLAGS = -version-info 1:2:0
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ EXTRA_libgc_la_SOURCES = alpha_mach_dep.S \
|
||||||
sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
|
sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
|
||||||
|
|
||||||
libgccpp_la_SOURCES = gc_cpp.cc
|
libgccpp_la_SOURCES = gc_cpp.cc
|
||||||
libgccpp_la_LIBADD = $(THREADLIBS) $(UNWINDLIBS)
|
libgccpp_la_LIBADD = $(THREADDLLIBS) $(UNWINDLIBS)
|
||||||
libgccpp_la_LDFLAGS = -version-info 1:2:0
|
libgccpp_la_LDFLAGS = -version-info 1:2:0
|
||||||
|
|
||||||
EXTRA_DIST += alpha_mach_dep.S mips_sgi_mach_dep.s sparc_mach_dep.S
|
EXTRA_DIST += alpha_mach_dep.S mips_sgi_mach_dep.s sparc_mach_dep.S
|
||||||
|
@ -91,11 +91,11 @@ test_cpp.o: $(srcdir)/tests/test_cpp.cc
|
||||||
## are included in the distribution
|
## are included in the distribution
|
||||||
# gctest_OBJECTS = test.o
|
# gctest_OBJECTS = test.o
|
||||||
gctest_SOURCES = tests/test.c
|
gctest_SOURCES = tests/test.c
|
||||||
gctest_LDADD = ./libgc.la $(THREADLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
|
gctest_LDADD = ./libgc.la $(THREADDLLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
|
||||||
test_cpp_SOURCES = tests/test_cpp.cc
|
test_cpp_SOURCES = tests/test_cpp.cc
|
||||||
test_cpp_LDADD = ./libgc.la ./libgccpp.la $(THREADLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
|
test_cpp_LDADD = ./libgc.la ./libgccpp.la $(THREADDLLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
|
||||||
|
|
||||||
TESTS = gctest $(extra_checks)
|
TESTS = $(check_PROGRAMS)
|
||||||
|
|
||||||
## FIXME: relies on internal code generated by automake.
|
## FIXME: relies on internal code generated by automake.
|
||||||
all_objs = @addobjs@ $(libgc_la_OBJECTS)
|
all_objs = @addobjs@ $(libgc_la_OBJECTS)
|
||||||
|
@ -105,10 +105,18 @@ include/gc_pthread_redirects.h include/gc_config_macros.h \
|
||||||
include/gc_mark.h @addincludes@
|
include/gc_mark.h @addincludes@
|
||||||
|
|
||||||
## FIXME: we shouldn't have to do this, but automake forces us to.
|
## FIXME: we shouldn't have to do this, but automake forces us to.
|
||||||
|
if COMPILER_XLC
|
||||||
|
## XLC neither requires nor tolerates the unnecessary assembler goop
|
||||||
|
ASM_CPP_OPTIONS =
|
||||||
|
else
|
||||||
|
## We use -Wp,-P to strip #line directives. Irix `as' chokes on
|
||||||
|
## these.
|
||||||
|
ASM_CPP_OPTIONS = -Wp,-P -x assembler-with-cpp
|
||||||
|
endif
|
||||||
.s.lo:
|
.s.lo:
|
||||||
## We use -Wp,-P to strip #line directives. Irix `as' chokes on
|
## We use -Wp,-P to strip #line directives. Irix `as' chokes on
|
||||||
## these.
|
## these.
|
||||||
$(LTCOMPILE) -Wp,-P -x assembler-with-cpp -c $<
|
$(LTCOMPILE) $(ASM_CPP_OPTIONS) -c $<
|
||||||
|
|
||||||
## We have our own definition of LTCOMPILE because we want to use our
|
## We have our own definition of LTCOMPILE because we want to use our
|
||||||
## CFLAGS, not those passed in from the top level make.
|
## CFLAGS, not those passed in from the top level make.
|
||||||
|
|
|
@ -36,7 +36,7 @@ CFLAGS= -O -I$(srcdir)/include -DATOMIC_UNCOLLECTABLE -DNO_SIGNALS -DNO_EXECUTE_
|
||||||
# -DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC
|
# -DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC
|
||||||
# To build the parallel collector in a static library on HP/UX,
|
# To build the parallel collector in a static library on HP/UX,
|
||||||
# add to the above:
|
# add to the above:
|
||||||
# -DGC_HPUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC -D_POSIX_C_SOURCE=199506L
|
# -DGC_HPUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC -D_POSIX_C_SOURCE=199506L -mt
|
||||||
# To build the thread-safe collector on Tru64, add to the above:
|
# To build the thread-safe collector on Tru64, add to the above:
|
||||||
# -pthread -DGC_OSF1_THREADS
|
# -pthread -DGC_OSF1_THREADS
|
||||||
|
|
||||||
|
@ -70,10 +70,11 @@ HOSTCFLAGS=$(CFLAGS)
|
||||||
# Also requires -D_REENTRANT or -D_POSIX_C_SOURCE=199506L. See README.hp.
|
# Also requires -D_REENTRANT or -D_POSIX_C_SOURCE=199506L. See README.hp.
|
||||||
# -DGC_LINUX_THREADS enables support for Xavier Leroy's Linux threads.
|
# -DGC_LINUX_THREADS enables support for Xavier Leroy's Linux threads.
|
||||||
# see README.linux. -D_REENTRANT may also be required.
|
# see README.linux. -D_REENTRANT may also be required.
|
||||||
# -DGC_OSF1_THREADS enables support for Tru64 pthreads. Untested.
|
# -DGC_OSF1_THREADS enables support for Tru64 pthreads.
|
||||||
# -DGC_FREEBSD_THREADS enables support for FreeBSD pthreads. Untested.
|
# -DGC_FREEBSD_THREADS enables support for FreeBSD pthreads.
|
||||||
# Appeared to run into some underlying thread problems.
|
# Appeared to run into some underlying thread problems.
|
||||||
# -DGC_DARWIN_THREADS enables support for Mac OS X pthreads. Untested.
|
# -DGC_DARWIN_THREADS enables support for Mac OS X pthreads.
|
||||||
|
# -DGC_AIX_THREADS enables support for IBM AIX threads.
|
||||||
# -DGC_DGUX386_THREADS enables support for DB/UX on I386 threads.
|
# -DGC_DGUX386_THREADS enables support for DB/UX on I386 threads.
|
||||||
# See README.DGUX386.
|
# See README.DGUX386.
|
||||||
# -DGC_WIN32_THREADS enables support for win32 threads. That makes sense
|
# -DGC_WIN32_THREADS enables support for win32 threads. That makes sense
|
||||||
|
@ -143,9 +144,9 @@ HOSTCFLAGS=$(CFLAGS)
|
||||||
# -DJAVA_FINALIZATION makes it somewhat safer to finalize objects out of
|
# -DJAVA_FINALIZATION makes it somewhat safer to finalize objects out of
|
||||||
# order by specifying a nonstandard finalization mark procedure (see
|
# order by specifying a nonstandard finalization mark procedure (see
|
||||||
# finalize.c). Objects reachable from finalizable objects will be marked
|
# finalize.c). Objects reachable from finalizable objects will be marked
|
||||||
# in a sepearte postpass, and hence their memory won't be reclaimed.
|
# in a separate postpass, and hence their memory won't be reclaimed.
|
||||||
# Not recommended unless you are implementing a language that specifies
|
# Not recommended unless you are implementing a language that specifies
|
||||||
# these semantics. Since 5.0, determines only only the initial value
|
# these semantics. Since 5.0, determines only the initial value
|
||||||
# of GC_java_finalization variable.
|
# of GC_java_finalization variable.
|
||||||
# -DFINALIZE_ON_DEMAND causes finalizers to be run only in response
|
# -DFINALIZE_ON_DEMAND causes finalizers to be run only in response
|
||||||
# to explicit GC_invoke_finalizers() calls.
|
# to explicit GC_invoke_finalizers() calls.
|
||||||
|
@ -233,8 +234,8 @@ HOSTCFLAGS=$(CFLAGS)
|
||||||
# -DTHREAD_LOCAL_ALLOC defines GC_local_malloc(), GC_local_malloc_atomic()
|
# -DTHREAD_LOCAL_ALLOC defines GC_local_malloc(), GC_local_malloc_atomic()
|
||||||
# and GC_local_gcj_malloc(). Needed for gc_gcj.h interface. These allocate
|
# and GC_local_gcj_malloc(). Needed for gc_gcj.h interface. These allocate
|
||||||
# in a way that usually does not involve acquisition of a global lock.
|
# in a way that usually does not involve acquisition of a global lock.
|
||||||
# Currently requires -DGC_LINUX_THREADS, but should be easy to port to
|
# Currently works only on platforms such as Linux which use pthread_support.c.
|
||||||
# other pthreads environments. Recommended for multiprocessors.
|
# Recommended for multiprocessors.
|
||||||
# -DUSE_COMPILER_TLS causes thread local allocation to use compiler-supported
|
# -DUSE_COMPILER_TLS causes thread local allocation to use compiler-supported
|
||||||
# "__thread" thread-local variables. This is the default in HP/UX. It
|
# "__thread" thread-local variables. This is the default in HP/UX. It
|
||||||
# may help performance on recent Linux installations. (It failed for
|
# may help performance on recent Linux installations. (It failed for
|
||||||
|
@ -276,6 +277,10 @@ HOSTCFLAGS=$(CFLAGS)
|
||||||
# -DPOINTER_SHIFT=n causes the collector to left shift candidate pointers
|
# -DPOINTER_SHIFT=n causes the collector to left shift candidate pointers
|
||||||
# by the indicated amount before trying to interpret them. Applied
|
# by the indicated amount before trying to interpret them. Applied
|
||||||
# after POINTER_MASK. EXPERIMENTAL. See also the preceding macro.
|
# after POINTER_MASK. EXPERIMENTAL. See also the preceding macro.
|
||||||
|
# -DDARWIN_DONT_PARSE_STACK Causes the Darwin port to discover thread
|
||||||
|
# stack bounds in the same way as other pthread ports, without trying to
|
||||||
|
# walk the frames onthe stack. This is recommended only as a fallback
|
||||||
|
# for applications that don't support proper stack unwinding.
|
||||||
#
|
#
|
||||||
|
|
||||||
CXXFLAGS= $(CFLAGS)
|
CXXFLAGS= $(CFLAGS)
|
||||||
|
@ -283,9 +288,9 @@ AR= ar
|
||||||
RANLIB= ranlib
|
RANLIB= ranlib
|
||||||
|
|
||||||
|
|
||||||
OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dbg_mlc.o malloc.o stubborn.o checksums.o solaris_threads.o aix_irix_threads.o pthread_support.o pthread_stop_world.o darwin_stop_world.o typd_mlc.o ptr_chck.o mallocx.o solaris_pthreads.o gcj_mlc.o specific.o gc_dlopen.o backgraph.o win32_threads.o
|
OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dbg_mlc.o malloc.o stubborn.o checksums.o solaris_threads.o pthread_support.o pthread_stop_world.o darwin_stop_world.o typd_mlc.o ptr_chck.o mallocx.o solaris_pthreads.o gcj_mlc.o specific.o gc_dlopen.o backgraph.o win32_threads.o
|
||||||
|
|
||||||
CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c checksums.c solaris_threads.c aix_irix_threads.c pthread_support.c pthread_stop_world.c darwin_stop_world.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.c gcj_mlc.c specific.c gc_dlopen.c backgraph.c win32_threads.c
|
CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c checksums.c solaris_threads.c pthread_support.c pthread_stop_world.c darwin_stop_world.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.c gcj_mlc.c specific.c gc_dlopen.c backgraph.c win32_threads.c
|
||||||
|
|
||||||
CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordtest.c include/cord.h include/ec.h include/private/cord_pos.h cord/de_win.c cord/de_win.h cord/de_cmds.h cord/de_win.ICO cord/de_win.RC
|
CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordtest.c include/cord.h include/ec.h include/private/cord_pos.h cord/de_win.c cord/de_win.h cord/de_cmds.h cord/de_win.ICO cord/de_win.RC
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ CFLAGS= $(BASEFLAGS) @PROFFLAGS@ $(OPTIONS) -DNO_EXECUTE_PERMISSION -DSILENT -DN
|
||||||
# -DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC
|
# -DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC
|
||||||
# To build the parallel collector in a static library on HP/UX,
|
# To build the parallel collector in a static library on HP/UX,
|
||||||
# add to the above:
|
# add to the above:
|
||||||
# -DGC_HPUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC -D_POSIX_C_SOURCE=199506L
|
# -DGC_HPUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC -D_POSIX_C_SOURCE=199506L -mt
|
||||||
# To build the thread-safe collector on Tru64, add to the above:
|
# To build the thread-safe collector on Tru64, add to the above:
|
||||||
# -pthread -DGC_OSF1_THREADS
|
# -pthread -DGC_OSF1_THREADS
|
||||||
|
|
||||||
|
@ -72,10 +72,11 @@ HOSTCFLAGS=$(BASEFLAGS)
|
||||||
# Also requires -D_REENTRANT or -D_POSIX_C_SOURCE=199506L. See README.hp.
|
# Also requires -D_REENTRANT or -D_POSIX_C_SOURCE=199506L. See README.hp.
|
||||||
# -DGC_LINUX_THREADS enables support for Xavier Leroy's Linux threads.
|
# -DGC_LINUX_THREADS enables support for Xavier Leroy's Linux threads.
|
||||||
# see README.linux. -D_REENTRANT may also be required.
|
# see README.linux. -D_REENTRANT may also be required.
|
||||||
# -DGC_OSF1_THREADS enables support for Tru64 pthreads. Untested.
|
# -DGC_OSF1_THREADS enables support for Tru64 pthreads.
|
||||||
# -DGC_FREEBSD_THREADS enables support for FreeBSD pthreads. Untested.
|
# -DGC_FREEBSD_THREADS enables support for FreeBSD pthreads.
|
||||||
# Appeared to run into some underlying thread problems.
|
# Appeared to run into some underlying thread problems.
|
||||||
# -DGC_DARWIN_THREADS enables support for Mac OS X pthreads. Untested.
|
# -DGC_DARWIN_THREADS enables support for Mac OS X pthreads.
|
||||||
|
# -DGC_AIX_THREADS enables support for IBM AIX threads.
|
||||||
# -DGC_DGUX386_THREADS enables support for DB/UX on I386 threads.
|
# -DGC_DGUX386_THREADS enables support for DB/UX on I386 threads.
|
||||||
# See README.DGUX386.
|
# See README.DGUX386.
|
||||||
# -DGC_WIN32_THREADS enables support for win32 threads. That makes sense
|
# -DGC_WIN32_THREADS enables support for win32 threads. That makes sense
|
||||||
|
@ -145,9 +146,9 @@ HOSTCFLAGS=$(BASEFLAGS)
|
||||||
# -DJAVA_FINALIZATION makes it somewhat safer to finalize objects out of
|
# -DJAVA_FINALIZATION makes it somewhat safer to finalize objects out of
|
||||||
# order by specifying a nonstandard finalization mark procedure (see
|
# order by specifying a nonstandard finalization mark procedure (see
|
||||||
# finalize.c). Objects reachable from finalizable objects will be marked
|
# finalize.c). Objects reachable from finalizable objects will be marked
|
||||||
# in a sepearte postpass, and hence their memory won't be reclaimed.
|
# in a seperate postpass, and hence their memory won't be reclaimed.
|
||||||
# Not recommended unless you are implementing a language that specifies
|
# Not recommended unless you are implementing a language that specifies
|
||||||
# these semantics. Since 5.0, determines only only the initial value
|
# these semantics. Since 5.0, determines only the initial value
|
||||||
# of GC_java_finalization variable.
|
# of GC_java_finalization variable.
|
||||||
# -DFINALIZE_ON_DEMAND causes finalizers to be run only in response
|
# -DFINALIZE_ON_DEMAND causes finalizers to be run only in response
|
||||||
# to explicit GC_invoke_finalizers() calls.
|
# to explicit GC_invoke_finalizers() calls.
|
||||||
|
@ -235,8 +236,8 @@ HOSTCFLAGS=$(BASEFLAGS)
|
||||||
# -DTHREAD_LOCAL_ALLOC defines GC_local_malloc(), GC_local_malloc_atomic()
|
# -DTHREAD_LOCAL_ALLOC defines GC_local_malloc(), GC_local_malloc_atomic()
|
||||||
# and GC_local_gcj_malloc(). Needed for gc_gcj.h interface. These allocate
|
# and GC_local_gcj_malloc(). Needed for gc_gcj.h interface. These allocate
|
||||||
# in a way that usually does not involve acquisition of a global lock.
|
# in a way that usually does not involve acquisition of a global lock.
|
||||||
# Currently requires -DGC_LINUX_THREADS, but should be easy to port to
|
# Currently works only on platforms such as Linux which use pthread_support.c.
|
||||||
# other pthreads environments. Recommended for multiprocessors.
|
# Recommended for multiprocessors.
|
||||||
# -DUSE_COMPILER_TLS causes thread local allocation to use compiler-supported
|
# -DUSE_COMPILER_TLS causes thread local allocation to use compiler-supported
|
||||||
# "__thread" thread-local variables. This is the default in HP/UX. It
|
# "__thread" thread-local variables. This is the default in HP/UX. It
|
||||||
# may help performance on recent Linux installations. (It failed for
|
# may help performance on recent Linux installations. (It failed for
|
||||||
|
@ -278,6 +279,10 @@ HOSTCFLAGS=$(BASEFLAGS)
|
||||||
# -DPOINTER_SHIFT=n causes the collector to left shift candidate pointers
|
# -DPOINTER_SHIFT=n causes the collector to left shift candidate pointers
|
||||||
# by the indicated amount before trying to interpret them. Applied
|
# by the indicated amount before trying to interpret them. Applied
|
||||||
# after POINTER_MASK. EXPERIMENTAL. See also the preceding macro.
|
# after POINTER_MASK. EXPERIMENTAL. See also the preceding macro.
|
||||||
|
# -DDARWIN_DONT_PARSE_STACK Causes the Darwin port to discover thread
|
||||||
|
# stack bounds in the same way as other pthread ports, without trying to
|
||||||
|
# walk the frames onthe stack. This is recommended only as a fallback
|
||||||
|
# for applications that don't support proper stack unwinding.
|
||||||
#
|
#
|
||||||
|
|
||||||
CXXFLAGS= $(CFLAGS)
|
CXXFLAGS= $(CFLAGS)
|
||||||
|
@ -286,9 +291,9 @@ ARFLAGS= @ARFLAGS@
|
||||||
RANLIB= @RANLIB@
|
RANLIB= @RANLIB@
|
||||||
|
|
||||||
|
|
||||||
OBJS= alloc.@LTO@ reclaim.@LTO@ allchblk.@LTO@ misc.@LTO@ mach_dep.@LTO@ os_dep.@LTO@ mark_rts.@LTO@ headers.@LTO@ mark.@LTO@ obj_map.@LTO@ blacklst.@LTO@ finalize.@LTO@ new_hblk.@LTO@ dbg_mlc.@LTO@ malloc.@LTO@ stubborn.@LTO@ checksums.@LTO@ solaris_threads.@LTO@ aix_irix_threads.@LTO@ pthread_support.@LTO@ pthread_stop_world.@LTO@ darwin_stop_world.@LTO@ typd_mlc.@LTO@ ptr_chck.@LTO@ mallocx.@LTO@ solaris_pthreads.@LTO@ gcj_mlc.@LTO@ specific.@LTO@ gc_dlopen.@LTO@ backgraph.@LTO@ win32_threads.@LTO@
|
OBJS= alloc.@LTO@ reclaim.@LTO@ allchblk.@LTO@ misc.@LTO@ mach_dep.@LTO@ os_dep.@LTO@ mark_rts.@LTO@ headers.@LTO@ mark.@LTO@ obj_map.@LTO@ blacklst.@LTO@ finalize.@LTO@ new_hblk.@LTO@ dbg_mlc.@LTO@ malloc.@LTO@ stubborn.@LTO@ checksums.@LTO@ solaris_threads.@LTO@ pthread_support.@LTO@ pthread_stop_world.@LTO@ darwin_stop_world.@LTO@ typd_mlc.@LTO@ ptr_chck.@LTO@ mallocx.@LTO@ solaris_pthreads.@LTO@ gcj_mlc.@LTO@ specific.@LTO@ gc_dlopen.@LTO@ backgraph.@LTO@ win32_threads.@LTO@
|
||||||
|
|
||||||
CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c checksums.c solaris_threads.c aix_irix_threads.c pthread_support.c pthread_stop_world.c darwin_stop_world.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.c gcj_mlc.c specific.c gc_dlopen.c backgraph.c win32_threads.c
|
CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c checksums.c solaris_threads.c pthread_support.c pthread_stop_world.c darwin_stop_world.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.c gcj_mlc.c specific.c gc_dlopen.c backgraph.c win32_threads.c
|
||||||
|
|
||||||
CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordtest.c include/cord.h include/ec.h include/private/cord_pos.h cord/de_win.c cord/de_win.h cord/de_cmds.h cord/de_win.ICO cord/de_win.RC
|
CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordtest.c include/cord.h include/ec.h include/private/cord_pos.h cord/de_win.c cord/de_win.h cord/de_cmds.h cord/de_win.ICO cord/de_win.RC
|
||||||
|
|
||||||
|
@ -729,9 +734,6 @@ solaris_threads.@LTO@: $(srcdir)/solaris_threads.c
|
||||||
win32_threads.@LTO@: $(srcdir)/win32_threads.c
|
win32_threads.@LTO@: $(srcdir)/win32_threads.c
|
||||||
$(CC) $(CFLAGS) -c $(srcdir)/win32_threads.c
|
$(CC) $(CFLAGS) -c $(srcdir)/win32_threads.c
|
||||||
|
|
||||||
aix_irix_threads.@LTO@: $(srcdir)/aix_irix_threads.c
|
|
||||||
$(CC) $(CFLAGS) -c $(srcdir)/aix_irix_threads.c
|
|
||||||
|
|
||||||
pthread_support.@LTO@: $(srcdir)/pthread_support.c
|
pthread_support.@LTO@: $(srcdir)/pthread_support.c
|
||||||
$(CC) $(CFLAGS) -c $(srcdir)/pthread_support.c
|
$(CC) $(CFLAGS) -c $(srcdir)/pthread_support.c
|
||||||
|
|
||||||
|
|
4570
src/mzscheme/gc/aclocal.m4
vendored
4570
src/mzscheme/gc/aclocal.m4
vendored
File diff suppressed because it is too large
Load Diff
|
@ -1,688 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
|
|
||||||
* Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
|
|
||||||
* Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.
|
|
||||||
*
|
|
||||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
|
||||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted to use or copy this program
|
|
||||||
* for any purpose, provided the above notices are retained on all copies.
|
|
||||||
* Permission to modify the code and to distribute modified code is granted,
|
|
||||||
* provided the above notices are retained, and a notice that the code was
|
|
||||||
* modified is included with the above copyright notice.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* Support code for Irix (>=6.2) Pthreads and for AIX pthreads.
|
|
||||||
* This relies on properties
|
|
||||||
* not guaranteed by the Pthread standard. It may or may not be portable
|
|
||||||
* to other implementations.
|
|
||||||
*
|
|
||||||
* Note that there is a lot of code duplication between this file and
|
|
||||||
* (pthread_support.c, pthread_stop_world.c). They should be merged.
|
|
||||||
* Pthread_support.c should be directly usable.
|
|
||||||
*
|
|
||||||
* Please avoid adding new ports here; use the generic pthread support
|
|
||||||
* as a base instead.
|
|
||||||
*/
|
|
||||||
|
|
||||||
# if defined(GC_IRIX_THREADS) || defined(GC_AIX_THREADS)
|
|
||||||
|
|
||||||
# include "private/gc_priv.h"
|
|
||||||
# include <pthread.h>
|
|
||||||
# include <assert.h>
|
|
||||||
# include <semaphore.h>
|
|
||||||
# include <time.h>
|
|
||||||
# include <errno.h>
|
|
||||||
# include <unistd.h>
|
|
||||||
# include <sys/mman.h>
|
|
||||||
# include <sys/time.h>
|
|
||||||
|
|
||||||
#undef pthread_create
|
|
||||||
#undef pthread_sigmask
|
|
||||||
#undef pthread_join
|
|
||||||
|
|
||||||
#if defined(GC_IRIX_THREADS) && !defined(MUTEX_RECURSIVE_NP)
|
|
||||||
#define MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void GC_thr_init();
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
void GC_print_sig_mask()
|
|
||||||
{
|
|
||||||
sigset_t blocked;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (pthread_sigmask(SIG_BLOCK, NULL, &blocked) != 0)
|
|
||||||
ABORT("pthread_sigmask");
|
|
||||||
GC_printf0("Blocked: ");
|
|
||||||
for (i = 1; i <= MAXSIG; i++) {
|
|
||||||
if (sigismember(&blocked, i)) { GC_printf1("%ld ",(long) i); }
|
|
||||||
}
|
|
||||||
GC_printf0("\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We use the allocation lock to protect thread-related data structures. */
|
|
||||||
|
|
||||||
/* The set of all known threads. We intercept thread creation and */
|
|
||||||
/* joins. We never actually create detached threads. We allocate all */
|
|
||||||
/* new thread stacks ourselves. These allow us to maintain this */
|
|
||||||
/* data structure. */
|
|
||||||
/* Protected by GC_thr_lock. */
|
|
||||||
/* Some of this should be declared volatile, but that's incosnsistent */
|
|
||||||
/* with some library routine declarations. */
|
|
||||||
typedef struct GC_Thread_Rep {
|
|
||||||
struct GC_Thread_Rep * next; /* More recently allocated threads */
|
|
||||||
/* with a given pthread id come */
|
|
||||||
/* first. (All but the first are */
|
|
||||||
/* guaranteed to be dead, but we may */
|
|
||||||
/* not yet have registered the join.) */
|
|
||||||
pthread_t id;
|
|
||||||
word stop;
|
|
||||||
# define NOT_STOPPED 0
|
|
||||||
# define PLEASE_STOP 1
|
|
||||||
# define STOPPED 2
|
|
||||||
word flags;
|
|
||||||
# define FINISHED 1 /* Thread has exited. */
|
|
||||||
# define DETACHED 2 /* Thread is intended to be detached. */
|
|
||||||
ptr_t stack_cold; /* cold end of the stack */
|
|
||||||
ptr_t stack_hot; /* Valid only when stopped. */
|
|
||||||
/* But must be within stack region at */
|
|
||||||
/* all times. */
|
|
||||||
void * status; /* Used only to avoid premature */
|
|
||||||
/* reclamation of any data it might */
|
|
||||||
/* reference. */
|
|
||||||
} * GC_thread;
|
|
||||||
|
|
||||||
GC_thread GC_lookup_thread(pthread_t id);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The only way to suspend threads given the pthread interface is to send
|
|
||||||
* signals. Unfortunately, this means we have to reserve
|
|
||||||
* a signal, and intercept client calls to change the signal mask.
|
|
||||||
*/
|
|
||||||
#if 0 /* DOB: 6.1 */
|
|
||||||
# if defined(GC_AIX_THREADS)
|
|
||||||
# define SIG_SUSPEND SIGUSR1
|
|
||||||
# else
|
|
||||||
# define SIG_SUSPEND (SIGRTMIN + 6)
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pthread_mutex_t GC_suspend_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
/* Number of threads stopped so far */
|
|
||||||
pthread_cond_t GC_suspend_ack_cv = PTHREAD_COND_INITIALIZER;
|
|
||||||
pthread_cond_t GC_continue_cv = PTHREAD_COND_INITIALIZER;
|
|
||||||
|
|
||||||
void GC_suspend_handler(int sig)
|
|
||||||
{
|
|
||||||
int dummy;
|
|
||||||
GC_thread me;
|
|
||||||
sigset_t all_sigs;
|
|
||||||
sigset_t old_sigs;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (sig != SIG_SUSPEND) ABORT("Bad signal in suspend_handler");
|
|
||||||
me = GC_lookup_thread(pthread_self());
|
|
||||||
/* The lookup here is safe, since I'm doing this on behalf */
|
|
||||||
/* of a thread which holds the allocation lock in order */
|
|
||||||
/* to stop the world. Thus concurrent modification of the */
|
|
||||||
/* data structure is impossible. */
|
|
||||||
if (PLEASE_STOP != me -> stop) {
|
|
||||||
/* Misdirected signal. */
|
|
||||||
pthread_mutex_unlock(&GC_suspend_lock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pthread_mutex_lock(&GC_suspend_lock);
|
|
||||||
me -> stack_hot = (ptr_t)(&dummy);
|
|
||||||
me -> stop = STOPPED;
|
|
||||||
pthread_cond_signal(&GC_suspend_ack_cv);
|
|
||||||
pthread_cond_wait(&GC_continue_cv, &GC_suspend_lock);
|
|
||||||
pthread_mutex_unlock(&GC_suspend_lock);
|
|
||||||
/* GC_printf1("Continuing 0x%x\n", pthread_self()); */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GC_bool GC_thr_initialized = FALSE;
|
|
||||||
|
|
||||||
|
|
||||||
# define THREAD_TABLE_SZ 128 /* Must be power of 2 */
|
|
||||||
volatile GC_thread GC_threads[THREAD_TABLE_SZ];
|
|
||||||
|
|
||||||
void GC_push_thread_structures GC_PROTO((void))
|
|
||||||
{
|
|
||||||
GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add a thread to GC_threads. We assume it wasn't already there. */
|
|
||||||
/* Caller holds allocation lock. */
|
|
||||||
GC_thread GC_new_thread(pthread_t id)
|
|
||||||
{
|
|
||||||
int hv = ((word)id) % THREAD_TABLE_SZ;
|
|
||||||
GC_thread result;
|
|
||||||
static struct GC_Thread_Rep first_thread;
|
|
||||||
static GC_bool first_thread_used = FALSE;
|
|
||||||
|
|
||||||
GC_ASSERT(I_HOLD_LOCK());
|
|
||||||
if (!first_thread_used) {
|
|
||||||
result = &first_thread;
|
|
||||||
first_thread_used = TRUE;
|
|
||||||
/* Dont acquire allocation lock, since we may already hold it. */
|
|
||||||
} else {
|
|
||||||
result = (struct GC_Thread_Rep *)
|
|
||||||
GC_generic_malloc_inner(sizeof(struct GC_Thread_Rep), NORMAL);
|
|
||||||
}
|
|
||||||
if (result == 0) return(0);
|
|
||||||
result -> id = id;
|
|
||||||
result -> next = GC_threads[hv];
|
|
||||||
GC_threads[hv] = result;
|
|
||||||
/* result -> flags = 0; */
|
|
||||||
/* result -> stop = 0; */
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delete a thread from GC_threads. We assume it is there. */
|
|
||||||
/* (The code intentionally traps if it wasn't.) */
|
|
||||||
/* Caller holds allocation lock. */
|
|
||||||
/* We explicitly pass in the GC_thread we're looking for, since */
|
|
||||||
/* if a thread has been joined, but we have not yet */
|
|
||||||
/* been notified, then there may be more than one thread */
|
|
||||||
/* in the table with the same pthread id. */
|
|
||||||
/* This is OK, but we need a way to delete a specific one. */
|
|
||||||
void GC_delete_gc_thread(pthread_t id, GC_thread gc_id)
|
|
||||||
{
|
|
||||||
int hv = ((word)id) % THREAD_TABLE_SZ;
|
|
||||||
register GC_thread p = GC_threads[hv];
|
|
||||||
register GC_thread prev = 0;
|
|
||||||
|
|
||||||
GC_ASSERT(I_HOLD_LOCK());
|
|
||||||
while (p != gc_id) {
|
|
||||||
prev = p;
|
|
||||||
p = p -> next;
|
|
||||||
}
|
|
||||||
if (prev == 0) {
|
|
||||||
GC_threads[hv] = p -> next;
|
|
||||||
} else {
|
|
||||||
prev -> next = p -> next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return a GC_thread corresponding to a given thread_t. */
|
|
||||||
/* Returns 0 if it's not there. */
|
|
||||||
/* Caller holds allocation lock or otherwise inhibits */
|
|
||||||
/* updates. */
|
|
||||||
/* If there is more than one thread with the given id we */
|
|
||||||
/* return the most recent one. */
|
|
||||||
GC_thread GC_lookup_thread(pthread_t id)
|
|
||||||
{
|
|
||||||
int hv = ((word)id) % THREAD_TABLE_SZ;
|
|
||||||
register GC_thread p = GC_threads[hv];
|
|
||||||
|
|
||||||
/* I either hold the lock, or i'm being called from the stop-the-world
|
|
||||||
* handler. */
|
|
||||||
#if defined(GC_AIX_THREADS)
|
|
||||||
GC_ASSERT(I_HOLD_LOCK()); /* no stop-the-world handler needed on AIX */
|
|
||||||
#endif
|
|
||||||
while (p != 0 && !pthread_equal(p -> id, id)) p = p -> next;
|
|
||||||
return(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(GC_AIX_THREADS)
|
|
||||||
void GC_stop_world()
|
|
||||||
{
|
|
||||||
pthread_t my_thread = pthread_self();
|
|
||||||
register int i;
|
|
||||||
register GC_thread p;
|
|
||||||
register int result;
|
|
||||||
struct timespec timeout;
|
|
||||||
|
|
||||||
GC_ASSERT(I_HOLD_LOCK());
|
|
||||||
for (i = 0; i < THREAD_TABLE_SZ; i++) {
|
|
||||||
for (p = GC_threads[i]; p != 0; p = p -> next) {
|
|
||||||
if (p -> id != my_thread) {
|
|
||||||
pthread_suspend_np(p->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* GC_printf1("World stopped 0x%x\n", pthread_self()); */
|
|
||||||
}
|
|
||||||
|
|
||||||
void GC_start_world()
|
|
||||||
{
|
|
||||||
GC_thread p;
|
|
||||||
unsigned i;
|
|
||||||
pthread_t my_thread = pthread_self();
|
|
||||||
|
|
||||||
/* GC_printf0("World starting\n"); */
|
|
||||||
GC_ASSERT(I_HOLD_LOCK());
|
|
||||||
for (i = 0; i < THREAD_TABLE_SZ; i++) {
|
|
||||||
for (p = GC_threads[i]; p != 0; p = p -> next) {
|
|
||||||
if (p -> id != my_thread) {
|
|
||||||
pthread_continue_np(p->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* GC_AIX_THREADS */
|
|
||||||
|
|
||||||
/* Caller holds allocation lock. */
|
|
||||||
void GC_stop_world()
|
|
||||||
{
|
|
||||||
pthread_t my_thread = pthread_self();
|
|
||||||
register int i;
|
|
||||||
register GC_thread p;
|
|
||||||
register int result;
|
|
||||||
struct timespec timeout;
|
|
||||||
|
|
||||||
GC_ASSERT(I_HOLD_LOCK());
|
|
||||||
for (i = 0; i < THREAD_TABLE_SZ; i++) {
|
|
||||||
for (p = GC_threads[i]; p != 0; p = p -> next) {
|
|
||||||
if (p -> id != my_thread) {
|
|
||||||
if (p -> flags & FINISHED) {
|
|
||||||
p -> stop = STOPPED;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
p -> stop = PLEASE_STOP;
|
|
||||||
result = pthread_kill(p -> id, SIG_SUSPEND);
|
|
||||||
/* GC_printf1("Sent signal to 0x%x\n", p -> id); */
|
|
||||||
switch(result) {
|
|
||||||
case ESRCH:
|
|
||||||
/* Not really there anymore. Possible? */
|
|
||||||
p -> stop = STOPPED;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ABORT("pthread_kill failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pthread_mutex_lock(&GC_suspend_lock);
|
|
||||||
for (i = 0; i < THREAD_TABLE_SZ; i++) {
|
|
||||||
for (p = GC_threads[i]; p != 0; p = p -> next) {
|
|
||||||
while (p -> id != my_thread && p -> stop != STOPPED) {
|
|
||||||
clock_gettime(CLOCK_REALTIME, &timeout);
|
|
||||||
timeout.tv_nsec += 50000000; /* 50 msecs */
|
|
||||||
if (timeout.tv_nsec >= 1000000000) {
|
|
||||||
timeout.tv_nsec -= 1000000000;
|
|
||||||
++timeout.tv_sec;
|
|
||||||
}
|
|
||||||
result = pthread_cond_timedwait(&GC_suspend_ack_cv,
|
|
||||||
&GC_suspend_lock,
|
|
||||||
&timeout);
|
|
||||||
if (result == ETIMEDOUT) {
|
|
||||||
/* Signal was lost or misdirected. Try again. */
|
|
||||||
/* Duplicate signals should be benign. */
|
|
||||||
result = pthread_kill(p -> id, SIG_SUSPEND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&GC_suspend_lock);
|
|
||||||
/* GC_printf1("World stopped 0x%x\n", pthread_self()); */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Caller holds allocation lock. */
|
|
||||||
void GC_start_world()
|
|
||||||
{
|
|
||||||
GC_thread p;
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
/* GC_printf0("World starting\n"); */
|
|
||||||
GC_ASSERT(I_HOLD_LOCK());
|
|
||||||
for (i = 0; i < THREAD_TABLE_SZ; i++) {
|
|
||||||
for (p = GC_threads[i]; p != 0; p = p -> next) {
|
|
||||||
p -> stop = NOT_STOPPED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pthread_mutex_lock(&GC_suspend_lock);
|
|
||||||
/* All other threads are at pthread_cond_wait in signal handler. */
|
|
||||||
/* Otherwise we couldn't have acquired the lock. */
|
|
||||||
pthread_mutex_unlock(&GC_suspend_lock);
|
|
||||||
pthread_cond_broadcast(&GC_continue_cv);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* GC_AIX_THREADS */
|
|
||||||
|
|
||||||
|
|
||||||
/* We hold allocation lock. Should do exactly the right thing if the */
|
|
||||||
/* world is stopped. Should not fail if it isn't. */
|
|
||||||
void GC_push_all_stacks()
|
|
||||||
{
|
|
||||||
register int i;
|
|
||||||
register GC_thread p;
|
|
||||||
register ptr_t hot, cold;
|
|
||||||
pthread_t me = pthread_self();
|
|
||||||
|
|
||||||
/* GC_init() should have been called before GC_push_all_stacks is
|
|
||||||
* invoked, and GC_init calls GC_thr_init(), which sets
|
|
||||||
* GC_thr_initialized. */
|
|
||||||
GC_ASSERT(GC_thr_initialized);
|
|
||||||
|
|
||||||
/* GC_printf1("Pushing stacks from thread 0x%x\n", me); */
|
|
||||||
GC_ASSERT(I_HOLD_LOCK());
|
|
||||||
for (i = 0; i < THREAD_TABLE_SZ; i++) {
|
|
||||||
for (p = GC_threads[i]; p != 0; p = p -> next) {
|
|
||||||
if (p -> flags & FINISHED) continue;
|
|
||||||
cold = p->stack_cold;
|
|
||||||
if (!cold) cold=GC_stackbottom; /* 0 indicates 'original stack' */
|
|
||||||
if (pthread_equal(p -> id, me)) {
|
|
||||||
hot = GC_approx_sp();
|
|
||||||
} else {
|
|
||||||
# ifdef GC_AIX_THREADS
|
|
||||||
/* AIX doesn't use signals to suspend, so we need to get an */
|
|
||||||
/* accurate hot stack pointer. */
|
|
||||||
/* See http://publib16.boulder.ibm.com/pseries/en_US/libs/basetrf1/pthread_getthrds_np.htm */
|
|
||||||
pthread_t id = p -> id;
|
|
||||||
struct __pthrdsinfo pinfo;
|
|
||||||
int regbuf[64];
|
|
||||||
int val = sizeof(regbuf);
|
|
||||||
int retval = pthread_getthrds_np(&id, PTHRDSINFO_QUERY_ALL, &pinfo,
|
|
||||||
sizeof(pinfo), regbuf, &val);
|
|
||||||
if (retval != 0) {
|
|
||||||
printf("ERROR: pthread_getthrds_np() failed in GC\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
/* according to the AIX ABI,
|
|
||||||
"the lowest possible valid stack address is 288 bytes (144 + 144)
|
|
||||||
less than the current value of the stack pointer. Functions may
|
|
||||||
use this stack space as volatile storage which is not preserved
|
|
||||||
across function calls."
|
|
||||||
ftp://ftp.penguinppc64.org/pub/people/amodra/PPC-elf64abi.txt.gz
|
|
||||||
*/
|
|
||||||
hot = (ptr_t)(unsigned long)pinfo.__pi_ustk-288;
|
|
||||||
cold = (ptr_t)pinfo.__pi_stackend; /* more precise */
|
|
||||||
/* push the registers too, because they won't be on stack */
|
|
||||||
GC_push_all_eager((ptr_t)&pinfo.__pi_context,
|
|
||||||
(ptr_t)((&pinfo.__pi_context)+1));
|
|
||||||
GC_push_all_eager((ptr_t)regbuf, ((ptr_t)regbuf)+val);
|
|
||||||
# else
|
|
||||||
hot = p -> stack_hot;
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
# ifdef STACK_GROWS_UP
|
|
||||||
GC_push_all_stack(cold, hot);
|
|
||||||
# else
|
|
||||||
/* printf("thread 0x%x: hot=0x%08x cold=0x%08x\n", p -> id, hot, cold); */
|
|
||||||
GC_push_all_stack(hot, cold);
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* We hold the allocation lock. */
|
|
||||||
void GC_thr_init()
|
|
||||||
{
|
|
||||||
GC_thread t;
|
|
||||||
struct sigaction act;
|
|
||||||
|
|
||||||
if (GC_thr_initialized) return;
|
|
||||||
GC_ASSERT(I_HOLD_LOCK());
|
|
||||||
GC_thr_initialized = TRUE;
|
|
||||||
#ifndef GC_AIX_THREADS
|
|
||||||
(void) sigaction(SIG_SUSPEND, 0, &act);
|
|
||||||
if (act.sa_handler != SIG_DFL)
|
|
||||||
ABORT("Previously installed SIG_SUSPEND handler");
|
|
||||||
/* Install handler. */
|
|
||||||
act.sa_handler = GC_suspend_handler;
|
|
||||||
act.sa_flags = SA_RESTART;
|
|
||||||
(void) sigemptyset(&act.sa_mask);
|
|
||||||
if (0 != sigaction(SIG_SUSPEND, &act, 0))
|
|
||||||
ABORT("Failed to install SIG_SUSPEND handler");
|
|
||||||
#endif
|
|
||||||
/* Add the initial thread, so we can stop it. */
|
|
||||||
t = GC_new_thread(pthread_self());
|
|
||||||
/* use '0' to indicate GC_stackbottom, since GC_init() has not
|
|
||||||
* completed by the time we are called (from GC_init_inner()) */
|
|
||||||
t -> stack_cold = 0; /* the original stack. */
|
|
||||||
t -> stack_hot = (ptr_t)(&t);
|
|
||||||
t -> flags = DETACHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
|
|
||||||
{
|
|
||||||
sigset_t fudged_set;
|
|
||||||
|
|
||||||
#ifdef GC_AIX_THREADS
|
|
||||||
return(pthread_sigmask(how, set, oset));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (set != NULL && (how == SIG_BLOCK || how == SIG_SETMASK)) {
|
|
||||||
fudged_set = *set;
|
|
||||||
sigdelset(&fudged_set, SIG_SUSPEND);
|
|
||||||
set = &fudged_set;
|
|
||||||
}
|
|
||||||
return(pthread_sigmask(how, set, oset));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct start_info {
|
|
||||||
void *(*start_routine)(void *);
|
|
||||||
void *arg;
|
|
||||||
word flags;
|
|
||||||
pthread_mutex_t registeredlock;
|
|
||||||
pthread_cond_t registered;
|
|
||||||
int volatile registereddone;
|
|
||||||
};
|
|
||||||
|
|
||||||
void GC_thread_exit_proc(void *arg)
|
|
||||||
{
|
|
||||||
GC_thread me;
|
|
||||||
|
|
||||||
LOCK();
|
|
||||||
me = GC_lookup_thread(pthread_self());
|
|
||||||
me -> flags |= FINISHED;
|
|
||||||
/* reclaim DETACHED thread right away; otherwise wait until join() */
|
|
||||||
if (me -> flags & DETACHED) {
|
|
||||||
GC_delete_gc_thread(pthread_self(), me);
|
|
||||||
}
|
|
||||||
UNLOCK();
|
|
||||||
}
|
|
||||||
|
|
||||||
int GC_pthread_join(pthread_t thread, void **retval)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
GC_thread thread_gc_id;
|
|
||||||
|
|
||||||
LOCK();
|
|
||||||
thread_gc_id = GC_lookup_thread(thread);
|
|
||||||
/* This is guaranteed to be the intended one, since the thread id */
|
|
||||||
/* cant have been recycled by pthreads. */
|
|
||||||
UNLOCK();
|
|
||||||
GC_ASSERT(!(thread_gc_id->flags & DETACHED));
|
|
||||||
result = pthread_join(thread, retval);
|
|
||||||
/* Some versions of the Irix pthreads library can erroneously */
|
|
||||||
/* return EINTR when the call succeeds. */
|
|
||||||
if (EINTR == result) result = 0;
|
|
||||||
GC_ASSERT(thread_gc_id->flags & FINISHED);
|
|
||||||
LOCK();
|
|
||||||
/* Here the pthread thread id may have been recycled. */
|
|
||||||
GC_delete_gc_thread(thread, thread_gc_id);
|
|
||||||
UNLOCK();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void * GC_start_routine(void * arg)
|
|
||||||
{
|
|
||||||
int dummy;
|
|
||||||
struct start_info * si = arg;
|
|
||||||
void * result;
|
|
||||||
GC_thread me;
|
|
||||||
pthread_t my_pthread;
|
|
||||||
void *(*start)(void *);
|
|
||||||
void *start_arg;
|
|
||||||
|
|
||||||
my_pthread = pthread_self();
|
|
||||||
/* If a GC occurs before the thread is registered, that GC will */
|
|
||||||
/* ignore this thread. That's fine, since it will block trying to */
|
|
||||||
/* acquire the allocation lock, and won't yet hold interesting */
|
|
||||||
/* pointers. */
|
|
||||||
LOCK();
|
|
||||||
/* We register the thread here instead of in the parent, so that */
|
|
||||||
/* we don't need to hold the allocation lock during pthread_create. */
|
|
||||||
/* Holding the allocation lock there would make REDIRECT_MALLOC */
|
|
||||||
/* impossible. It probably still doesn't work, but we're a little */
|
|
||||||
/* closer ... */
|
|
||||||
/* This unfortunately means that we have to be careful the parent */
|
|
||||||
/* doesn't try to do a pthread_join before we're registered. */
|
|
||||||
me = GC_new_thread(my_pthread);
|
|
||||||
me -> flags = si -> flags;
|
|
||||||
me -> stack_cold = (ptr_t) &dummy; /* this now the 'start of stack' */
|
|
||||||
me -> stack_hot = me->stack_cold;/* this field should always be sensible */
|
|
||||||
UNLOCK();
|
|
||||||
start = si -> start_routine;
|
|
||||||
start_arg = si -> arg;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&(si->registeredlock));
|
|
||||||
si->registereddone = 1;
|
|
||||||
pthread_cond_signal(&(si->registered));
|
|
||||||
pthread_mutex_unlock(&(si->registeredlock));
|
|
||||||
/* si went away as soon as we did this unlock */
|
|
||||||
|
|
||||||
pthread_cleanup_push(GC_thread_exit_proc, 0);
|
|
||||||
result = (*start)(start_arg);
|
|
||||||
me -> status = result;
|
|
||||||
pthread_cleanup_pop(1);
|
|
||||||
/* This involves acquiring the lock, ensuring that we can't exit */
|
|
||||||
/* while a collection that thinks we're alive is trying to stop */
|
|
||||||
/* us. */
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
GC_pthread_create(pthread_t *new_thread,
|
|
||||||
const pthread_attr_t *attr,
|
|
||||||
void *(*start_routine)(void *), void *arg)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
GC_thread t;
|
|
||||||
int detachstate;
|
|
||||||
word my_flags = 0;
|
|
||||||
struct start_info * si;
|
|
||||||
/* This is otherwise saved only in an area mmapped by the thread */
|
|
||||||
/* library, which isn't visible to the collector. */
|
|
||||||
|
|
||||||
LOCK();
|
|
||||||
/* GC_INTERNAL_MALLOC implicitly calls GC_init() if required */
|
|
||||||
si = (struct start_info *)GC_INTERNAL_MALLOC(sizeof(struct start_info),
|
|
||||||
NORMAL);
|
|
||||||
GC_ASSERT(GC_thr_initialized); /* initialized by GC_init() */
|
|
||||||
UNLOCK();
|
|
||||||
if (0 == si) return(ENOMEM);
|
|
||||||
pthread_mutex_init(&(si->registeredlock), NULL);
|
|
||||||
pthread_cond_init(&(si->registered),NULL);
|
|
||||||
pthread_mutex_lock(&(si->registeredlock));
|
|
||||||
si -> start_routine = start_routine;
|
|
||||||
si -> arg = arg;
|
|
||||||
|
|
||||||
pthread_attr_getdetachstate(attr, &detachstate);
|
|
||||||
if (PTHREAD_CREATE_DETACHED == detachstate) my_flags |= DETACHED;
|
|
||||||
si -> flags = my_flags;
|
|
||||||
result = pthread_create(new_thread, attr, GC_start_routine, si);
|
|
||||||
|
|
||||||
/* Wait until child has been added to the thread table. */
|
|
||||||
/* This also ensures that we hold onto si until the child is done */
|
|
||||||
/* with it. Thus it doesn't matter whether it is otherwise */
|
|
||||||
/* visible to the collector. */
|
|
||||||
|
|
||||||
if (0 == result) {
|
|
||||||
si->registereddone = 0;
|
|
||||||
while (!si->registereddone)
|
|
||||||
pthread_cond_wait(&(si->registered), &(si->registeredlock));
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&(si->registeredlock));
|
|
||||||
|
|
||||||
pthread_cond_destroy(&(si->registered));
|
|
||||||
pthread_mutex_destroy(&(si->registeredlock));
|
|
||||||
LOCK();
|
|
||||||
GC_INTERNAL_FREE(si);
|
|
||||||
UNLOCK();
|
|
||||||
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For now we use the pthreads locking primitives on HP/UX */
|
|
||||||
|
|
||||||
VOLATILE GC_bool GC_collecting = 0; /* A hint that we're in the collector and */
|
|
||||||
/* holding the allocation lock for an */
|
|
||||||
/* extended period. */
|
|
||||||
|
|
||||||
/* Reasonably fast spin locks. Basically the same implementation */
|
|
||||||
/* as STL alloc.h. */
|
|
||||||
|
|
||||||
#define SLEEP_THRESHOLD 3
|
|
||||||
|
|
||||||
volatile unsigned int GC_allocate_lock = 0;
|
|
||||||
#define GC_TRY_LOCK() !GC_test_and_set(&GC_allocate_lock)
|
|
||||||
#define GC_LOCK_TAKEN GC_allocate_lock
|
|
||||||
|
|
||||||
void GC_lock()
|
|
||||||
{
|
|
||||||
# define low_spin_max 30 /* spin cycles if we suspect uniprocessor */
|
|
||||||
# define high_spin_max 1000 /* spin cycles for multiprocessor */
|
|
||||||
static unsigned spin_max = low_spin_max;
|
|
||||||
unsigned my_spin_max;
|
|
||||||
static unsigned last_spins = 0;
|
|
||||||
unsigned my_last_spins;
|
|
||||||
volatile unsigned junk;
|
|
||||||
# define PAUSE junk *= junk; junk *= junk; junk *= junk; junk *= junk
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (GC_TRY_LOCK()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
junk = 0;
|
|
||||||
my_spin_max = spin_max;
|
|
||||||
my_last_spins = last_spins;
|
|
||||||
for (i = 0; i < my_spin_max; i++) {
|
|
||||||
if (GC_collecting) goto yield;
|
|
||||||
if (i < my_last_spins/2 || GC_LOCK_TAKEN) {
|
|
||||||
PAUSE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (GC_TRY_LOCK()) {
|
|
||||||
/*
|
|
||||||
* got it!
|
|
||||||
* Spinning worked. Thus we're probably not being scheduled
|
|
||||||
* against the other process with which we were contending.
|
|
||||||
* Thus it makes sense to spin longer the next time.
|
|
||||||
*/
|
|
||||||
last_spins = i;
|
|
||||||
spin_max = high_spin_max;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* We are probably being scheduled against the other process. Sleep. */
|
|
||||||
spin_max = low_spin_max;
|
|
||||||
yield:
|
|
||||||
for (i = 0;; ++i) {
|
|
||||||
if (GC_TRY_LOCK()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (i < SLEEP_THRESHOLD) {
|
|
||||||
sched_yield();
|
|
||||||
} else {
|
|
||||||
struct timespec ts;
|
|
||||||
|
|
||||||
if (i > 26) i = 26;
|
|
||||||
/* Don't wait for more than about 60msecs, even */
|
|
||||||
/* under extreme contention. */
|
|
||||||
ts.tv_sec = 0;
|
|
||||||
ts.tv_nsec = 1 << i;
|
|
||||||
nanosleep(&ts, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# else /* !GC_IRIX_THREADS && !GC_AIX_THREADS */
|
|
||||||
|
|
||||||
#ifndef LINT
|
|
||||||
int GC_no_Irix_threads;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# endif /* IRIX_THREADS */
|
|
||||||
|
|
|
@ -285,8 +285,8 @@ int n;
|
||||||
GET_HDR(hhdr -> hb_prev, phdr);
|
GET_HDR(hhdr -> hb_prev, phdr);
|
||||||
phdr -> hb_next = hhdr -> hb_next;
|
phdr -> hb_next = hhdr -> hb_next;
|
||||||
}
|
}
|
||||||
|
FREE_ASSERT(GC_free_bytes[index] >= hhdr -> hb_sz);
|
||||||
INCR_FREE_BYTES(index, - (signed_word)(hhdr -> hb_sz));
|
INCR_FREE_BYTES(index, - (signed_word)(hhdr -> hb_sz));
|
||||||
FREE_ASSERT(GC_free_bytes[index] >= 0);
|
|
||||||
if (0 != hhdr -> hb_next) {
|
if (0 != hhdr -> hb_next) {
|
||||||
hdr * nhdr;
|
hdr * nhdr;
|
||||||
GC_ASSERT(!IS_FORWARDING_ADDR_OR_NIL(NHDR(hhdr)));
|
GC_ASSERT(!IS_FORWARDING_ADDR_OR_NIL(NHDR(hhdr)));
|
||||||
|
@ -529,7 +529,7 @@ int index; /* Index of free list */
|
||||||
/* free blocks in GC_add_to_fl. */
|
/* free blocks in GC_add_to_fl. */
|
||||||
# endif
|
# endif
|
||||||
# ifdef USE_MUNMAP
|
# ifdef USE_MUNMAP
|
||||||
hhdr -> hb_last_reclaimed = GC_gc_no;
|
hhdr -> hb_last_reclaimed = (unsigned short)GC_gc_no;
|
||||||
# endif
|
# endif
|
||||||
hhdr -> hb_sz = h_size;
|
hhdr -> hb_sz = h_size;
|
||||||
GC_add_to_fl(h, hhdr);
|
GC_add_to_fl(h, hhdr);
|
||||||
|
@ -590,8 +590,9 @@ int n;
|
||||||
GET_HDR(hbp, hhdr);
|
GET_HDR(hbp, hhdr);
|
||||||
size_avail = hhdr->hb_sz;
|
size_avail = hhdr->hb_sz;
|
||||||
if (size_avail < size_needed) continue;
|
if (size_avail < size_needed) continue;
|
||||||
if (!GC_use_entire_heap
|
if (size_avail != size_needed
|
||||||
&& size_avail != size_needed
|
&& !GC_use_entire_heap
|
||||||
|
&& !GC_dont_gc
|
||||||
&& USED_HEAP_SIZE >= GC_requested_heapsize
|
&& USED_HEAP_SIZE >= GC_requested_heapsize
|
||||||
&& !TRUE_INCREMENTAL && GC_should_collect()) {
|
&& !TRUE_INCREMENTAL && GC_should_collect()) {
|
||||||
# ifdef USE_MUNMAP
|
# ifdef USE_MUNMAP
|
||||||
|
@ -608,7 +609,8 @@ int n;
|
||||||
/* If we are deallocating lots of memory from */
|
/* If we are deallocating lots of memory from */
|
||||||
/* finalizers, fail and collect sooner rather */
|
/* finalizers, fail and collect sooner rather */
|
||||||
/* than later. */
|
/* than later. */
|
||||||
if (GC_finalizer_mem_freed > (GC_heapsize >> 4)) {
|
if (WORDS_TO_BYTES(GC_finalizer_mem_freed)
|
||||||
|
> (GC_heapsize >> 4)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
# endif /* !USE_MUNMAP */
|
# endif /* !USE_MUNMAP */
|
||||||
|
@ -701,7 +703,7 @@ int n;
|
||||||
struct hblk * h;
|
struct hblk * h;
|
||||||
struct hblk * prev = hhdr -> hb_prev;
|
struct hblk * prev = hhdr -> hb_prev;
|
||||||
|
|
||||||
GC_words_wasted += total_size;
|
GC_words_wasted += BYTES_TO_WORDS(total_size);
|
||||||
GC_large_free_bytes -= total_size;
|
GC_large_free_bytes -= total_size;
|
||||||
GC_remove_from_fl(hhdr, n);
|
GC_remove_from_fl(hhdr, n);
|
||||||
for (h = hbp; h < limit; h++) {
|
for (h = hbp; h < limit; h++) {
|
||||||
|
@ -794,7 +796,7 @@ signed_word size;
|
||||||
GC_remove_counts(hbp, (word)size);
|
GC_remove_counts(hbp, (word)size);
|
||||||
hhdr->hb_sz = size;
|
hhdr->hb_sz = size;
|
||||||
# ifdef USE_MUNMAP
|
# ifdef USE_MUNMAP
|
||||||
hhdr -> hb_last_reclaimed = GC_gc_no;
|
hhdr -> hb_last_reclaimed = (unsigned short)GC_gc_no;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
/* Check for duplicate deallocation in the easy case */
|
/* Check for duplicate deallocation in the easy case */
|
||||||
|
@ -822,7 +824,7 @@ signed_word size;
|
||||||
GC_remove_from_fl(prevhdr, FL_UNKNOWN);
|
GC_remove_from_fl(prevhdr, FL_UNKNOWN);
|
||||||
prevhdr -> hb_sz += hhdr -> hb_sz;
|
prevhdr -> hb_sz += hhdr -> hb_sz;
|
||||||
# ifdef USE_MUNMAP
|
# ifdef USE_MUNMAP
|
||||||
prevhdr -> hb_last_reclaimed = GC_gc_no;
|
prevhdr -> hb_last_reclaimed = (unsigned short)GC_gc_no;
|
||||||
# endif
|
# endif
|
||||||
GC_remove_header(hbp);
|
GC_remove_header(hbp);
|
||||||
hbp = prev;
|
hbp = prev;
|
||||||
|
|
|
@ -92,6 +92,16 @@ char * GC_copyright[] =
|
||||||
|
|
||||||
# include "version.h"
|
# include "version.h"
|
||||||
|
|
||||||
|
#if defined(SAVE_CALL_CHAIN) && \
|
||||||
|
!(defined(REDIRECT_MALLOC) && defined(GC_HAVE_BUILTIN_BACKTRACE))
|
||||||
|
# define SAVE_CALL_CHAIN_IN_GC
|
||||||
|
/* This is only safe if the call chain save mechanism won't end up */
|
||||||
|
/* calling GC_malloc. The GNU C library documentation suggests */
|
||||||
|
/* that backtrace doesn't use malloc, but at least the initial */
|
||||||
|
/* call in some versions does seem to invoke the dynamic linker, */
|
||||||
|
/* which uses malloc. */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* some more variables */
|
/* some more variables */
|
||||||
|
|
||||||
extern signed_word GC_mem_found; /* Number of reclaimed longwords */
|
extern signed_word GC_mem_found; /* Number of reclaimed longwords */
|
||||||
|
@ -104,8 +114,6 @@ word GC_free_space_divisor = 4; /* PLTSCHEME: 3 -> 4 */
|
||||||
extern GC_bool GC_collection_in_progress();
|
extern GC_bool GC_collection_in_progress();
|
||||||
/* Collection is in progress, or was abandoned. */
|
/* Collection is in progress, or was abandoned. */
|
||||||
|
|
||||||
extern GC_bool GC_print_back_height;
|
|
||||||
|
|
||||||
int GC_never_stop_func GC_PROTO((void)) { return(0); }
|
int GC_never_stop_func GC_PROTO((void)) { return(0); }
|
||||||
|
|
||||||
unsigned long GC_time_limit = TIME_LIMIT;
|
unsigned long GC_time_limit = TIME_LIMIT;
|
||||||
|
@ -198,7 +206,8 @@ word GC_adj_words_allocd()
|
||||||
/* had been reallocated this round. Finalization is user */
|
/* had been reallocated this round. Finalization is user */
|
||||||
/* visible progress. And if we don't count this, we have */
|
/* visible progress. And if we don't count this, we have */
|
||||||
/* stability problems for programs that finalize all objects. */
|
/* stability problems for programs that finalize all objects. */
|
||||||
result += GC_words_wasted;
|
if ((signed_word)(GC_words_wasted >> 3) < result)
|
||||||
|
result += GC_words_wasted;
|
||||||
/* This doesn't reflect useful work. But if there is lots of */
|
/* This doesn't reflect useful work. But if there is lots of */
|
||||||
/* new fragmentation, the same is probably true of the heap, */
|
/* new fragmentation, the same is probably true of the heap, */
|
||||||
/* and the collection will be correspondingly cheaper. */
|
/* and the collection will be correspondingly cheaper. */
|
||||||
|
@ -223,6 +232,8 @@ void GC_clear_a_few_frames()
|
||||||
{
|
{
|
||||||
# define NWORDS 64
|
# define NWORDS 64
|
||||||
word frames[NWORDS];
|
word frames[NWORDS];
|
||||||
|
/* Some compilers will warn that frames was set but never used. */
|
||||||
|
/* That's the whole idea ... */
|
||||||
register int i;
|
register int i;
|
||||||
|
|
||||||
for (i = 0; i < NWORDS; i++) frames[i] = 0;
|
for (i = 0; i < NWORDS; i++) frames[i] = 0;
|
||||||
|
@ -295,7 +306,7 @@ void GC_maybe_gc()
|
||||||
# endif
|
# endif
|
||||||
if (GC_stopped_mark(GC_time_limit == GC_TIME_UNLIMITED?
|
if (GC_stopped_mark(GC_time_limit == GC_TIME_UNLIMITED?
|
||||||
GC_never_stop_func : GC_timeout_stop_func)) {
|
GC_never_stop_func : GC_timeout_stop_func)) {
|
||||||
# ifdef SAVE_CALL_CHAIN
|
# ifdef SAVE_CALL_CHAIN_IN_GC
|
||||||
GC_save_callers(GC_last_stack);
|
GC_save_callers(GC_last_stack);
|
||||||
# endif
|
# endif
|
||||||
GC_finish_collection();
|
GC_finish_collection();
|
||||||
|
@ -366,7 +377,7 @@ GC_stop_func stop_func;
|
||||||
}
|
}
|
||||||
GC_invalidate_mark_state(); /* Flush mark stack. */
|
GC_invalidate_mark_state(); /* Flush mark stack. */
|
||||||
GC_clear_marks();
|
GC_clear_marks();
|
||||||
# ifdef SAVE_CALL_CHAIN
|
# ifdef SAVE_CALL_CHAIN_IN_GC
|
||||||
GC_save_callers(GC_last_stack);
|
GC_save_callers(GC_last_stack);
|
||||||
# endif
|
# endif
|
||||||
GC_is_full_gc = TRUE;
|
GC_is_full_gc = TRUE;
|
||||||
|
@ -400,7 +411,7 @@ GC_stop_func stop_func;
|
||||||
/*
|
/*
|
||||||
* Perform n units of garbage collection work. A unit is intended to touch
|
* Perform n units of garbage collection work. A unit is intended to touch
|
||||||
* roughly GC_RATE pages. Every once in a while, we do more than that.
|
* roughly GC_RATE pages. Every once in a while, we do more than that.
|
||||||
* This needa to be a fairly large number with our current incremental
|
* This needs to be a fairly large number with our current incremental
|
||||||
* GC strategy, since otherwise we allocate too much during GC, and the
|
* GC strategy, since otherwise we allocate too much during GC, and the
|
||||||
* cleanup gets expensive.
|
* cleanup gets expensive.
|
||||||
*/
|
*/
|
||||||
|
@ -424,7 +435,7 @@ int n;
|
||||||
for (i = GC_deficit; i < GC_RATE*n; i++) {
|
for (i = GC_deficit; i < GC_RATE*n; i++) {
|
||||||
if (GC_mark_some((ptr_t)0)) {
|
if (GC_mark_some((ptr_t)0)) {
|
||||||
/* Need to finish a collection */
|
/* Need to finish a collection */
|
||||||
# ifdef SAVE_CALL_CHAIN
|
# ifdef SAVE_CALL_CHAIN_IN_GC
|
||||||
GC_save_callers(GC_last_stack);
|
GC_save_callers(GC_last_stack);
|
||||||
# endif
|
# endif
|
||||||
# ifdef PARALLEL_MARK
|
# ifdef PARALLEL_MARK
|
||||||
|
@ -940,7 +951,7 @@ word n;
|
||||||
# endif
|
# endif
|
||||||
expansion_slop = WORDS_TO_BYTES(min_words_allocd()) + 4*MAXHINCR*HBLKSIZE;
|
expansion_slop = WORDS_TO_BYTES(min_words_allocd()) + 4*MAXHINCR*HBLKSIZE;
|
||||||
if (GC_last_heap_addr == 0 && !((word)space & SIGNB)
|
if (GC_last_heap_addr == 0 && !((word)space & SIGNB)
|
||||||
|| GC_last_heap_addr != 0 && GC_last_heap_addr < (ptr_t)space) {
|
|| (GC_last_heap_addr != 0 && GC_last_heap_addr < (ptr_t)space)) {
|
||||||
/* Assume the heap is growing up */
|
/* Assume the heap is growing up */
|
||||||
GC_greatest_plausible_heap_addr =
|
GC_greatest_plausible_heap_addr =
|
||||||
(GC_PTR)GC_max((ptr_t)GC_greatest_plausible_heap_addr,
|
(GC_PTR)GC_max((ptr_t)GC_greatest_plausible_heap_addr,
|
||||||
|
@ -1006,7 +1017,7 @@ word needed_blocks;
|
||||||
GC_bool ignore_off_page;
|
GC_bool ignore_off_page;
|
||||||
{
|
{
|
||||||
if (!GC_incremental && !GC_dont_gc &&
|
if (!GC_incremental && !GC_dont_gc &&
|
||||||
(GC_dont_expand && GC_words_allocd > 0 || GC_should_collect())) {
|
((GC_dont_expand && GC_words_allocd > 0) || GC_should_collect())) {
|
||||||
GC_gcollect_inner();
|
GC_gcollect_inner();
|
||||||
} else {
|
} else {
|
||||||
word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor)
|
word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor)
|
||||||
|
@ -1015,6 +1026,9 @@ GC_bool ignore_off_page;
|
||||||
if (blocks_to_get > MAXHINCR) {
|
if (blocks_to_get > MAXHINCR) {
|
||||||
word slop;
|
word slop;
|
||||||
|
|
||||||
|
/* Get the minimum required to make it likely that we */
|
||||||
|
/* can satisfy the current request in the presence of black- */
|
||||||
|
/* listing. This will probably be more than MAXHINCR. */
|
||||||
if (ignore_off_page) {
|
if (ignore_off_page) {
|
||||||
slop = 4;
|
slop = 4;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# $Id: alpha_mach_dep.S,v 1.1 2004/07/21 13:07:52 mflatt Exp $
|
|
||||||
.arch ev6
|
.arch ev6
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
@ -12,13 +11,13 @@ GC_push_regs:
|
||||||
.mask 0x04000000, 0
|
.mask 0x04000000, 0
|
||||||
.frame $sp, 16, $26, 0
|
.frame $sp, 16, $26, 0
|
||||||
|
|
||||||
# $0 integer result
|
/* $0 integer result */
|
||||||
# $1-$8 temp regs - not preserved cross calls
|
/* $1-$8 temp regs - not preserved cross calls */
|
||||||
# $9-$15 call saved regs
|
/* $9-$15 call saved regs */
|
||||||
# $16-$21 argument regs - not preserved cross calls
|
/* $16-$21 argument regs - not preserved cross calls */
|
||||||
# $22-$28 temp regs - not preserved cross calls
|
/* $22-$28 temp regs - not preserved cross calls */
|
||||||
# $29 global pointer - not preserved cross calls
|
/* $29 global pointer - not preserved cross calls */
|
||||||
# $30 stack pointer
|
/* $30 stack pointer */
|
||||||
|
|
||||||
# define call_push(x) \
|
# define call_push(x) \
|
||||||
mov x, $16; \
|
mov x, $16; \
|
||||||
|
@ -33,12 +32,12 @@ GC_push_regs:
|
||||||
call_push($14)
|
call_push($14)
|
||||||
call_push($15)
|
call_push($15)
|
||||||
|
|
||||||
# $f0-$f1 floating point results
|
/* $f0-$f1 floating point results */
|
||||||
# $f2-$f9 call saved regs
|
/* $f2-$f9 call saved regs */
|
||||||
# $f10-$f30 temp regs - not preserved cross calls
|
/* $f10-$f30 temp regs - not preserved cross calls */
|
||||||
|
|
||||||
# Use the most efficient transfer method for this hardware.
|
/* Use the most efficient transfer method for this hardware. */
|
||||||
# Bit 1 detects the FIX extension, which includes ftoit.
|
/* Bit 1 detects the FIX extension, which includes ftoit. */
|
||||||
amask 2, $0
|
amask 2, $0
|
||||||
bne $0, $use_stack
|
bne $0, $use_stack
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ static back_edges * new_back_edges(void)
|
||||||
{
|
{
|
||||||
if (0 == back_edge_space) {
|
if (0 == back_edge_space) {
|
||||||
back_edge_space = (back_edges *)
|
back_edge_space = (back_edges *)
|
||||||
sbrk(MAX_BACK_EDGE_STRUCTS*sizeof(back_edges));
|
GET_MEM(MAX_BACK_EDGE_STRUCTS*sizeof(back_edges));
|
||||||
}
|
}
|
||||||
if (0 != avail_back_edges) {
|
if (0 != avail_back_edges) {
|
||||||
back_edges * result = avail_back_edges;
|
back_edges * result = avail_back_edges;
|
||||||
|
@ -113,17 +113,31 @@ static void deallocate_back_edges(back_edges *p)
|
||||||
/* Table of objects that are currently on the depth-first search */
|
/* Table of objects that are currently on the depth-first search */
|
||||||
/* stack. Only objects with in-degree one are in this table. */
|
/* stack. Only objects with in-degree one are in this table. */
|
||||||
/* Other objects are identified using HEIGHT_IN_PROGRESS. */
|
/* Other objects are identified using HEIGHT_IN_PROGRESS. */
|
||||||
/* This data structure NEEDS IMPROVEMENT. */
|
/* FIXME: This data structure NEEDS IMPROVEMENT. */
|
||||||
#define MAX_IN_PROGRESS 10000
|
#define INITIAL_IN_PROGRESS 10000
|
||||||
static ptr_t * in_progress_space = 0;
|
static ptr_t * in_progress_space = 0;
|
||||||
static int n_in_progress = 0;
|
static size_t in_progress_size = 0;
|
||||||
|
static size_t n_in_progress = 0;
|
||||||
|
|
||||||
static void push_in_progress(ptr_t p)
|
static void push_in_progress(ptr_t p)
|
||||||
{
|
{
|
||||||
|
if (n_in_progress >= in_progress_size)
|
||||||
|
if (in_progress_size == 0) {
|
||||||
|
in_progress_size = INITIAL_IN_PROGRESS;
|
||||||
|
in_progress_space = (ptr_t *)GET_MEM(in_progress_size * sizeof(ptr_t));
|
||||||
|
} else {
|
||||||
|
ptr_t * new_in_progress_space;
|
||||||
|
in_progress_size *= 2;
|
||||||
|
new_in_progress_space = (ptr_t *)
|
||||||
|
GET_MEM(in_progress_size * sizeof(ptr_t));
|
||||||
|
BCOPY(in_progress_space, new_in_progress_space,
|
||||||
|
n_in_progress * sizeof(ptr_t));
|
||||||
|
in_progress_space = new_in_progress_space;
|
||||||
|
/* FIXME: This just drops the old space. */
|
||||||
|
}
|
||||||
if (in_progress_space == 0)
|
if (in_progress_space == 0)
|
||||||
in_progress_space = sbrk(MAX_IN_PROGRESS * sizeof(ptr_t));
|
ABORT("MAKE_BACK_GRAPH: Out of in-progress space: "
|
||||||
if (n_in_progress == MAX_IN_PROGRESS)
|
"Huge linear data structure?");
|
||||||
ABORT("Exceeded MAX_IN_PROGRESS");
|
|
||||||
in_progress_space[n_in_progress++] = p;
|
in_progress_space[n_in_progress++] = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,8 +332,8 @@ static void add_back_edges(ptr_t p, word n_words, word gc_descr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Rebuild the reprentation of the backward reachability graph. */
|
/* Rebuild the representation of the backward reachability graph. */
|
||||||
/* Does not examine mark bits. Can be called before GC. */
|
/* Does not examine mark bits. Can be called before GC. */
|
||||||
void GC_build_back_graph(void)
|
void GC_build_back_graph(void)
|
||||||
{
|
{
|
||||||
GC_apply_to_each_object(add_back_edges);
|
GC_apply_to_each_object(add_back_edges);
|
||||||
|
@ -424,15 +438,20 @@ static void update_max_height(ptr_t p, word n_words, word gc_descr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
word GC_max_max_height = 0;
|
||||||
|
|
||||||
void GC_traverse_back_graph(void)
|
void GC_traverse_back_graph(void)
|
||||||
{
|
{
|
||||||
static word max_max_height = 0;
|
|
||||||
GC_max_height = 0;
|
GC_max_height = 0;
|
||||||
GC_apply_to_each_object(update_max_height);
|
GC_apply_to_each_object(update_max_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GC_print_back_graph_stats(void)
|
||||||
|
{
|
||||||
GC_printf2("Maximum backwards height of reachable objects at GC %lu is %ld\n",
|
GC_printf2("Maximum backwards height of reachable objects at GC %lu is %ld\n",
|
||||||
(unsigned long) GC_gc_no, GC_max_height);
|
(unsigned long) GC_gc_no, GC_max_height);
|
||||||
if (GC_max_height > max_max_height) {
|
if (GC_max_height > GC_max_max_height) {
|
||||||
max_max_height = GC_max_height;
|
GC_max_max_height = GC_max_height;
|
||||||
GC_printf0("The following unreachable object is last in a longest chain "
|
GC_printf0("The following unreachable object is last in a longest chain "
|
||||||
"of unreachable objects:\n");
|
"of unreachable objects:\n");
|
||||||
GC_print_heap_obj(GC_deepest_obj);
|
GC_print_heap_obj(GC_deepest_obj);
|
||||||
|
|
3055
src/mzscheme/gc/configure
vendored
3055
src/mzscheme/gc/configure
vendored
File diff suppressed because it is too large
Load Diff
|
@ -17,12 +17,12 @@ dnl Process this file with autoconf to produce configure.
|
||||||
# Initialization
|
# Initialization
|
||||||
# ==============
|
# ==============
|
||||||
|
|
||||||
AC_INIT(gc,6.3,Hans.Boehm@hp.com)
|
AC_INIT(gc,6.7,Hans.Boehm@hp.com)
|
||||||
## version must conform to [0-9]+[.][0-9]+(alpha[0-9]+)?
|
## version must conform to [0-9]+[.][0-9]+(alpha[0-9]+)?
|
||||||
AC_CONFIG_SRCDIR(gcj_mlc.c)
|
AC_CONFIG_SRCDIR(gcj_mlc.c)
|
||||||
AC_CANONICAL_TARGET
|
AC_CANONICAL_TARGET
|
||||||
AC_PREREQ(2.53)
|
AC_PREREQ(2.53)
|
||||||
AC_REVISION($Revision: 1.3 $)
|
AC_REVISION($Revision: 1.2 $)
|
||||||
GC_SET_VERSION
|
GC_SET_VERSION
|
||||||
AM_INIT_AUTOMAKE
|
AM_INIT_AUTOMAKE
|
||||||
|
|
||||||
|
@ -68,14 +68,15 @@ AC_ARG_ENABLE(cplusplus,
|
||||||
)
|
)
|
||||||
|
|
||||||
INCLUDES=-I${srcdir}/include
|
INCLUDES=-I${srcdir}/include
|
||||||
THREADLIBS=
|
THREADDLLIBS=
|
||||||
|
## Libraries needed to support dynamic loading and/or threads.
|
||||||
case "$THREADS" in
|
case "$THREADS" in
|
||||||
no | none | single)
|
no | none | single)
|
||||||
THREADS=none
|
THREADS=none
|
||||||
;;
|
;;
|
||||||
posix | pthreads)
|
posix | pthreads)
|
||||||
THREADS=posix
|
THREADS=posix
|
||||||
THREADLIBS=-lpthread
|
THREADDLLIBS=-lpthread
|
||||||
case "$host" in
|
case "$host" in
|
||||||
x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* | alpha-*-linux*)
|
x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* | alpha-*-linux*)
|
||||||
AC_DEFINE(GC_LINUX_THREADS)
|
AC_DEFINE(GC_LINUX_THREADS)
|
||||||
|
@ -101,14 +102,21 @@ case "$THREADS" in
|
||||||
AC_DEFINE(PARALLEL_MARK)
|
AC_DEFINE(PARALLEL_MARK)
|
||||||
fi
|
fi
|
||||||
AC_DEFINE(THREAD_LOCAL_ALLOC)
|
AC_DEFINE(THREAD_LOCAL_ALLOC)
|
||||||
THREADLIBS="-lpthread -lrt"
|
THREADDLLIBS="-lpthread -lrt"
|
||||||
;;
|
;;
|
||||||
*-*-freebsd*)
|
*-*-freebsd*)
|
||||||
AC_MSG_WARN("FreeBSD does not yet fully support threads with Boehm GC.")
|
AC_MSG_WARN("FreeBSD does not yet fully support threads with Boehm GC.")
|
||||||
AC_DEFINE(GC_FREEBSD_THREADS)
|
AC_DEFINE(GC_FREEBSD_THREADS)
|
||||||
INCLUDES="$INCLUDES -pthread"
|
INCLUDES="$INCLUDES -pthread"
|
||||||
THREADLIBS=-pthread
|
THREADDLLIBS=-pthread
|
||||||
;;
|
;;
|
||||||
|
*-*-netbsd*)
|
||||||
|
AC_MSG_WARN("Only on NetBSD 2.0 or later.")
|
||||||
|
AC_DEFINE(GC_NETBSD_THREADS)
|
||||||
|
AC_DEFINE(_REENTRANT)
|
||||||
|
AC_DEFINE(_PTHREADS)
|
||||||
|
THREADDLLIBS="-lpthread -lrt"
|
||||||
|
;;
|
||||||
*-*-solaris*)
|
*-*-solaris*)
|
||||||
AC_DEFINE(GC_SOLARIS_THREADS)
|
AC_DEFINE(GC_SOLARIS_THREADS)
|
||||||
AC_DEFINE(GC_SOLARIS_PTHREADS)
|
AC_DEFINE(GC_SOLARIS_PTHREADS)
|
||||||
|
@ -135,7 +143,10 @@ case "$THREADS" in
|
||||||
# Measurements havent yet been done.
|
# Measurements havent yet been done.
|
||||||
fi
|
fi
|
||||||
INCLUDES="$INCLUDES -pthread"
|
INCLUDES="$INCLUDES -pthread"
|
||||||
THREADLIBS="-lpthread -lrt"
|
THREADDLLIBS="-lpthread -lrt"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR("Pthreads not supported by the GC on this platform.")
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
@ -146,9 +157,9 @@ case "$THREADS" in
|
||||||
;;
|
;;
|
||||||
dgux386)
|
dgux386)
|
||||||
THREADS=dgux386
|
THREADS=dgux386
|
||||||
AC_MSG_RESULT($THREADLIBS)
|
AC_MSG_RESULT($THREADDLLIBS)
|
||||||
# Use pthread GCC switch
|
# Use pthread GCC switch
|
||||||
THREADLIBS=-pthread
|
THREADDLLIBS=-pthread
|
||||||
if test "${enable_parallel_mark}" = yes; then
|
if test "${enable_parallel_mark}" = yes; then
|
||||||
AC_DEFINE(PARALLEL_MARK)
|
AC_DEFINE(PARALLEL_MARK)
|
||||||
fi
|
fi
|
||||||
|
@ -160,7 +171,7 @@ case "$THREADS" in
|
||||||
;;
|
;;
|
||||||
aix)
|
aix)
|
||||||
THREADS=posix
|
THREADS=posix
|
||||||
THREADLIBS=-lpthread
|
THREADDLLIBS=-lpthread
|
||||||
AC_DEFINE(GC_AIX_THREADS)
|
AC_DEFINE(GC_AIX_THREADS)
|
||||||
AC_DEFINE(_REENTRANT)
|
AC_DEFINE(_REENTRANT)
|
||||||
;;
|
;;
|
||||||
|
@ -171,7 +182,7 @@ case "$THREADS" in
|
||||||
AC_MSG_ERROR($THREADS is an unknown thread package)
|
AC_MSG_ERROR($THREADS is an unknown thread package)
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
AC_SUBST(THREADLIBS)
|
AC_SUBST(THREADDLLIBS)
|
||||||
|
|
||||||
case "$host" in
|
case "$host" in
|
||||||
powerpc-*-darwin*)
|
powerpc-*-darwin*)
|
||||||
|
@ -180,12 +191,25 @@ case "$host" in
|
||||||
esac
|
esac
|
||||||
AM_CONDITIONAL(POWERPC_DARWIN,test x$powerpc_darwin = xtrue)
|
AM_CONDITIONAL(POWERPC_DARWIN,test x$powerpc_darwin = xtrue)
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(for xlc)
|
||||||
|
AC_TRY_COMPILE([],[
|
||||||
|
#ifndef __xlC__
|
||||||
|
# error
|
||||||
|
#endif
|
||||||
|
], [compiler_xlc=yes], [compiler_xlc=no])
|
||||||
|
AC_MSG_RESULT($compiler_xlc)
|
||||||
|
AM_CONDITIONAL(COMPILER_XLC,test $compiler_xlc = yes)
|
||||||
|
if test $compiler_xlc = yes -a "$powerpc_darwin" = true; then
|
||||||
|
# the darwin stack-frame-walking code is completely broken on xlc
|
||||||
|
AC_DEFINE(DARWIN_DONT_PARSE_STACK)
|
||||||
|
fi
|
||||||
|
|
||||||
# We never want libdl on darwin. It is a fake libdl that just ends up making
|
# We never want libdl on darwin. It is a fake libdl that just ends up making
|
||||||
# dyld calls anyway
|
# dyld calls anyway
|
||||||
case "$host" in
|
case "$host" in
|
||||||
*-*-darwin*) ;;
|
*-*-darwin*) ;;
|
||||||
*)
|
*)
|
||||||
AC_CHECK_LIB(dl, dlopen, EXTRA_TEST_LIBS="$EXTRA_TEST_LIBS -ldl")
|
AC_CHECK_LIB(dl, dlopen, THREADDLLIBS="$THREADDLLIBS -ldl")
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -286,7 +310,7 @@ case "$host" in
|
||||||
machdep="sparc_mach_dep.lo"
|
machdep="sparc_mach_dep.lo"
|
||||||
AC_DEFINE(SUNOS53_SHARED_LIB)
|
AC_DEFINE(SUNOS53_SHARED_LIB)
|
||||||
;;
|
;;
|
||||||
sparc-sun-solaris2.*)
|
sparc*-sun-solaris2.*)
|
||||||
machdep="sparc_mach_dep.lo"
|
machdep="sparc_mach_dep.lo"
|
||||||
;;
|
;;
|
||||||
ia64-*-*)
|
ia64-*-*)
|
||||||
|
@ -345,10 +369,10 @@ fi
|
||||||
|
|
||||||
dnl As of 4.13a2, the collector will not properly work on Solaris when
|
dnl As of 4.13a2, the collector will not properly work on Solaris when
|
||||||
dnl built with gcc and -O. So we remove -O in the appropriate case.
|
dnl built with gcc and -O. So we remove -O in the appropriate case.
|
||||||
dnl
|
dnl Not needed anymore on Solaris.
|
||||||
AC_MSG_CHECKING(whether Solaris gcc optimization fix is necessary)
|
AC_MSG_CHECKING(whether Solaris gcc optimization fix is necessary)
|
||||||
case "$host" in
|
case "$host" in
|
||||||
sparc-sun-solaris2*|*aix*)
|
*aix*)
|
||||||
if test "$GCC" = yes; then
|
if test "$GCC" = yes; then
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
new_CFLAGS=
|
new_CFLAGS=
|
||||||
|
|
|
@ -59,7 +59,7 @@ static int extract_conv_spec(CORD_pos source, char *buf,
|
||||||
register int result = 0;
|
register int result = 0;
|
||||||
register int current_number = 0;
|
register int current_number = 0;
|
||||||
register int saw_period = 0;
|
register int saw_period = 0;
|
||||||
register int saw_number;
|
register int saw_number = 0;
|
||||||
register int chars_so_far = 0;
|
register int chars_so_far = 0;
|
||||||
register char current;
|
register char current;
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
|
||||||
char * str = va_arg(args, char *);
|
char * str = va_arg(args, char *);
|
||||||
register char c;
|
register char c;
|
||||||
|
|
||||||
while (c = *str++) {
|
while ((c = *str++)) {
|
||||||
CORD_ec_append(result, c);
|
CORD_ec_append(result, c);
|
||||||
}
|
}
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -320,7 +320,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
|
||||||
if (buf != result[0].ec_bufptr) {
|
if (buf != result[0].ec_bufptr) {
|
||||||
register char c;
|
register char c;
|
||||||
|
|
||||||
while (c = *buf++) {
|
while ((c = *buf++)) {
|
||||||
CORD_ec_append(result, c);
|
CORD_ec_append(result, c);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -221,7 +221,7 @@ void test_printf()
|
||||||
if (CORD_cmp(result, result2) != 0)ABORT("CORD_sprintf goofed 5");
|
if (CORD_cmp(result, result2) != 0)ABORT("CORD_sprintf goofed 5");
|
||||||
}
|
}
|
||||||
|
|
||||||
main()
|
int main()
|
||||||
{
|
{
|
||||||
# ifdef THINK_C
|
# ifdef THINK_C
|
||||||
printf("cordtest:\n");
|
printf("cordtest:\n");
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "private/pthread_support.h"
|
#include "private/pthread_support.h"
|
||||||
|
|
||||||
|
/* This probably needs more porting work to ppc64. */
|
||||||
|
|
||||||
# if defined(GC_DARWIN_THREADS)
|
# if defined(GC_DARWIN_THREADS)
|
||||||
|
|
||||||
/* From "Inside Mac OS X - Mach-O Runtime Architecture" published by Apple
|
/* From "Inside Mac OS X - Mach-O Runtime Architecture" published by Apple
|
||||||
|
@ -12,23 +14,33 @@
|
||||||
Page 50: "If a leaf procedure's red zone usage would exceed 224 bytes, then
|
Page 50: "If a leaf procedure's red zone usage would exceed 224 bytes, then
|
||||||
it must set up a stack frame just like routines that call other routines."
|
it must set up a stack frame just like routines that call other routines."
|
||||||
*/
|
*/
|
||||||
#define PPC_RED_ZONE_SIZE 224
|
#ifdef POWERPC
|
||||||
|
# if CPP_WORDSZ == 32
|
||||||
|
# define PPC_RED_ZONE_SIZE 224
|
||||||
|
# elif CPP_WORDSZ == 64
|
||||||
|
# define PPC_RED_ZONE_SIZE 320
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Not 64-bit clean. Wait until Apple defines their 64-bit ABI */
|
|
||||||
typedef struct StackFrame {
|
typedef struct StackFrame {
|
||||||
unsigned int savedSP;
|
unsigned long savedSP;
|
||||||
unsigned int savedCR;
|
unsigned long savedCR;
|
||||||
unsigned int savedLR;
|
unsigned long savedLR;
|
||||||
unsigned int reserved[2];
|
unsigned long reserved[2];
|
||||||
unsigned int savedRTOC;
|
unsigned long savedRTOC;
|
||||||
} StackFrame;
|
} StackFrame;
|
||||||
|
|
||||||
|
unsigned long FindTopOfStack(unsigned int stack_start) {
|
||||||
unsigned int FindTopOfStack(unsigned int stack_start) {
|
|
||||||
StackFrame *frame;
|
StackFrame *frame;
|
||||||
|
|
||||||
if (stack_start == 0) {
|
if (stack_start == 0) {
|
||||||
__asm__ volatile("lwz %0,0(r1)" : "=r" (frame));
|
# ifdef POWERPC
|
||||||
|
# if CPP_WORDSZ == 32
|
||||||
|
__asm__ volatile("lwz %0,0(r1)" : "=r" (frame));
|
||||||
|
# else
|
||||||
|
__asm__ volatile("ld %0,0(r1)" : "=r" (frame));
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
} else {
|
} else {
|
||||||
frame = (StackFrame *)stack_start;
|
frame = (StackFrame *)stack_start;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +49,7 @@ unsigned int FindTopOfStack(unsigned int stack_start) {
|
||||||
/* GC_printf1("FindTopOfStack start at sp = %p\n", frame); */
|
/* GC_printf1("FindTopOfStack start at sp = %p\n", frame); */
|
||||||
# endif
|
# endif
|
||||||
do {
|
do {
|
||||||
if (frame->savedSP == NULL) break;
|
if (frame->savedSP == 0) break;
|
||||||
/* if there are no more stack frames, stop */
|
/* if there are no more stack frames, stop */
|
||||||
|
|
||||||
frame = (StackFrame*)frame->savedSP;
|
frame = (StackFrame*)frame->savedSP;
|
||||||
|
@ -53,9 +65,108 @@ unsigned int FindTopOfStack(unsigned int stack_start) {
|
||||||
/* GC_printf1("FindTopOfStack finish at sp = %p\n", frame); */
|
/* GC_printf1("FindTopOfStack finish at sp = %p\n", frame); */
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
return (unsigned int)frame;
|
return (unsigned long)frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DARWIN_DONT_PARSE_STACK
|
||||||
|
void GC_push_all_stacks() {
|
||||||
|
int i;
|
||||||
|
kern_return_t r;
|
||||||
|
GC_thread p;
|
||||||
|
pthread_t me;
|
||||||
|
ptr_t lo, hi;
|
||||||
|
#if defined(POWERPC)
|
||||||
|
ppc_thread_state_t state;
|
||||||
|
#elif defined(I386)
|
||||||
|
i386_thread_state_t state;
|
||||||
|
#else
|
||||||
|
# error FIXME for non-x86 || ppc architectures
|
||||||
|
#endif
|
||||||
|
mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
|
||||||
|
|
||||||
|
me = pthread_self();
|
||||||
|
if (!GC_thr_initialized) GC_thr_init();
|
||||||
|
|
||||||
|
for(i=0;i<THREAD_TABLE_SZ;i++) {
|
||||||
|
for(p=GC_threads[i];p!=0;p=p->next) {
|
||||||
|
if(p -> flags & FINISHED) continue;
|
||||||
|
if(pthread_equal(p->id,me)) {
|
||||||
|
lo = GC_approx_sp();
|
||||||
|
} else {
|
||||||
|
/* Get the thread state (registers, etc) */
|
||||||
|
r = thread_get_state(
|
||||||
|
p->stop_info.mach_thread,
|
||||||
|
MACHINE_THREAD_STATE,
|
||||||
|
(natural_t*)&state,
|
||||||
|
&thread_state_count);
|
||||||
|
if(r != KERN_SUCCESS) ABORT("thread_get_state failed");
|
||||||
|
|
||||||
|
#if defined(I386)
|
||||||
|
lo = state.esp;
|
||||||
|
|
||||||
|
GC_push_one(state.eax);
|
||||||
|
GC_push_one(state.ebx);
|
||||||
|
GC_push_one(state.ecx);
|
||||||
|
GC_push_one(state.edx);
|
||||||
|
GC_push_one(state.edi);
|
||||||
|
GC_push_one(state.esi);
|
||||||
|
GC_push_one(state.ebp);
|
||||||
|
#elif defined(POWERPC)
|
||||||
|
lo = (void*)(state.r1 - PPC_RED_ZONE_SIZE);
|
||||||
|
|
||||||
|
GC_push_one(state.r0);
|
||||||
|
GC_push_one(state.r2);
|
||||||
|
GC_push_one(state.r3);
|
||||||
|
GC_push_one(state.r4);
|
||||||
|
GC_push_one(state.r5);
|
||||||
|
GC_push_one(state.r6);
|
||||||
|
GC_push_one(state.r7);
|
||||||
|
GC_push_one(state.r8);
|
||||||
|
GC_push_one(state.r9);
|
||||||
|
GC_push_one(state.r10);
|
||||||
|
GC_push_one(state.r11);
|
||||||
|
GC_push_one(state.r12);
|
||||||
|
GC_push_one(state.r13);
|
||||||
|
GC_push_one(state.r14);
|
||||||
|
GC_push_one(state.r15);
|
||||||
|
GC_push_one(state.r16);
|
||||||
|
GC_push_one(state.r17);
|
||||||
|
GC_push_one(state.r18);
|
||||||
|
GC_push_one(state.r19);
|
||||||
|
GC_push_one(state.r20);
|
||||||
|
GC_push_one(state.r21);
|
||||||
|
GC_push_one(state.r22);
|
||||||
|
GC_push_one(state.r23);
|
||||||
|
GC_push_one(state.r24);
|
||||||
|
GC_push_one(state.r25);
|
||||||
|
GC_push_one(state.r26);
|
||||||
|
GC_push_one(state.r27);
|
||||||
|
GC_push_one(state.r28);
|
||||||
|
GC_push_one(state.r29);
|
||||||
|
GC_push_one(state.r30);
|
||||||
|
GC_push_one(state.r31);
|
||||||
|
#else
|
||||||
|
# error FIXME for non-x86 || ppc architectures
|
||||||
|
#endif
|
||||||
|
} /* p != me */
|
||||||
|
if(p->flags & MAIN_THREAD)
|
||||||
|
hi = GC_stackbottom;
|
||||||
|
else
|
||||||
|
hi = p->stack_end;
|
||||||
|
#if DEBUG_THREADS
|
||||||
|
GC_printf3("Darwin: Stack for thread 0x%lx = [%lx,%lx)\n",
|
||||||
|
(unsigned long) p -> id,
|
||||||
|
(unsigned long) lo,
|
||||||
|
(unsigned long) hi
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
GC_push_all_stack(lo,hi);
|
||||||
|
} /* for(p=GC_threads[i]...) */
|
||||||
|
} /* for(i=0;i<THREAD_TABLE_SZ...) */
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !DARWIN_DONT_PARSE_STACK; Use FindTopOfStack() */
|
||||||
|
|
||||||
void GC_push_all_stacks() {
|
void GC_push_all_stacks() {
|
||||||
int i;
|
int i;
|
||||||
kern_return_t r;
|
kern_return_t r;
|
||||||
|
@ -75,8 +186,12 @@ void GC_push_all_stacks() {
|
||||||
lo = GC_approx_sp();
|
lo = GC_approx_sp();
|
||||||
hi = (ptr_t)FindTopOfStack(0);
|
hi = (ptr_t)FindTopOfStack(0);
|
||||||
} else {
|
} else {
|
||||||
# ifdef POWERPC
|
# if defined(POWERPC)
|
||||||
|
# if CPP_WORDSZ == 32
|
||||||
ppc_thread_state_t info;
|
ppc_thread_state_t info;
|
||||||
|
# else
|
||||||
|
ppc_thread_state64_t info;
|
||||||
|
# endif
|
||||||
mach_msg_type_number_t outCount = THREAD_STATE_MAX;
|
mach_msg_type_number_t outCount = THREAD_STATE_MAX;
|
||||||
r = thread_get_state(thread, MACHINE_THREAD_STATE,
|
r = thread_get_state(thread, MACHINE_THREAD_STATE,
|
||||||
(natural_t *)&info, &outCount);
|
(natural_t *)&info, &outCount);
|
||||||
|
@ -154,7 +269,9 @@ void GC_push_all_stacks() {
|
||||||
# endif
|
# endif
|
||||||
GC_push_all_stack(lo, hi);
|
GC_push_all_stack(lo, hi);
|
||||||
} /* for(p=GC_threads[i]...) */
|
} /* for(p=GC_threads[i]...) */
|
||||||
|
vm_deallocate(current_task(), (vm_address_t)act_list, sizeof(thread_t) * listcount);
|
||||||
}
|
}
|
||||||
|
#endif /* !DARWIN_DONT_PARSE_STACK */
|
||||||
|
|
||||||
static mach_port_t GC_mach_handler_thread;
|
static mach_port_t GC_mach_handler_thread;
|
||||||
static int GC_use_mach_handler_thread = 0;
|
static int GC_use_mach_handler_thread = 0;
|
||||||
|
@ -296,6 +413,7 @@ void GC_stop_world()
|
||||||
changes = result;
|
changes = result;
|
||||||
prev_list = act_list;
|
prev_list = act_list;
|
||||||
prevcount = listcount;
|
prevcount = listcount;
|
||||||
|
vm_deallocate(current_task(), (vm_address_t)act_list, sizeof(thread_t) * listcount);
|
||||||
} while (changes);
|
} while (changes);
|
||||||
|
|
||||||
|
|
||||||
|
@ -324,6 +442,8 @@ void GC_start_world()
|
||||||
kern_return_t kern_result;
|
kern_return_t kern_result;
|
||||||
thread_act_array_t act_list;
|
thread_act_array_t act_list;
|
||||||
mach_msg_type_number_t listcount;
|
mach_msg_type_number_t listcount;
|
||||||
|
struct thread_basic_info info;
|
||||||
|
mach_msg_type_number_t outCount = THREAD_INFO_MAX;
|
||||||
|
|
||||||
# if DEBUG_THREADS
|
# if DEBUG_THREADS
|
||||||
GC_printf0("World starting\n");
|
GC_printf0("World starting\n");
|
||||||
|
@ -350,8 +470,6 @@ void GC_start_world()
|
||||||
# endif
|
# endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
struct thread_basic_info info;
|
|
||||||
mach_msg_type_number_t outCount = THREAD_INFO_MAX;
|
|
||||||
kern_result = thread_info(thread, THREAD_BASIC_INFO,
|
kern_result = thread_info(thread, THREAD_BASIC_INFO,
|
||||||
(thread_info_t)&info, &outCount);
|
(thread_info_t)&info, &outCount);
|
||||||
if(kern_result != KERN_SUCCESS) ABORT("thread_info failed");
|
if(kern_result != KERN_SUCCESS) ABORT("thread_info failed");
|
||||||
|
@ -367,6 +485,7 @@ void GC_start_world()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
vm_deallocate(current_task(), (vm_address_t)act_list, sizeof(thread_t) * listcount);
|
||||||
# if DEBUG_THREADS
|
# if DEBUG_THREADS
|
||||||
GC_printf0("World started\n");
|
GC_printf0("World started\n");
|
||||||
# endif
|
# endif
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
* modified is included with the above copyright notice.
|
* modified is included with the above copyright notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
#include "private/dbg_mlc.h"
|
#include "private/dbg_mlc.h"
|
||||||
|
|
||||||
void GC_default_print_heap_obj_proc();
|
void GC_default_print_heap_obj_proc();
|
||||||
|
@ -713,6 +715,26 @@ GC_PTR p;
|
||||||
return (GC_store_debug_info(result, (word)lb, s, (word)i));
|
return (GC_store_debug_info(result, (word)lb, s, (word)i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ifdef __STDC__
|
||||||
|
char *GC_debug_strdup(const char *str, GC_EXTRA_PARAMS)
|
||||||
|
#else
|
||||||
|
char *GC_debug_strdup(str, s, i)
|
||||||
|
char *str;
|
||||||
|
char *s;
|
||||||
|
int i;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
char *copy;
|
||||||
|
if (str == NULL) return NULL;
|
||||||
|
copy = GC_debug_malloc_atomic(strlen(str) + 1, OPT_RA s, i);
|
||||||
|
if (copy == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
strcpy(copy, str);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
# ifdef __STDC__
|
# ifdef __STDC__
|
||||||
GC_PTR GC_debug_malloc_uncollectable(size_t lb, GC_EXTRA_PARAMS)
|
GC_PTR GC_debug_malloc_uncollectable(size_t lb, GC_EXTRA_PARAMS)
|
||||||
# else
|
# else
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# Makefile.in generated by automake 1.6.3 from Makefile.am.
|
# Makefile.in generated by automake 1.9.3 from Makefile.am.
|
||||||
# @configure_input@
|
# @configure_input@
|
||||||
|
|
||||||
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||||
# Free Software Foundation, Inc.
|
# 2003, 2004 Free Software Foundation, Inc.
|
||||||
# This Makefile.in is free software; the Free Software Foundation
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
# with or without modifications, as long as this notice is preserved.
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
@ -26,96 +26,174 @@
|
||||||
# modified is included with the above copyright notice.
|
# modified is included with the above copyright notice.
|
||||||
#
|
#
|
||||||
# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
|
# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
|
||||||
SHELL = @SHELL@
|
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
prefix = @prefix@
|
|
||||||
exec_prefix = @exec_prefix@
|
|
||||||
|
|
||||||
bindir = @bindir@
|
|
||||||
sbindir = @sbindir@
|
|
||||||
libexecdir = @libexecdir@
|
|
||||||
datadir = @datadir@
|
|
||||||
sysconfdir = @sysconfdir@
|
|
||||||
sharedstatedir = @sharedstatedir@
|
|
||||||
localstatedir = @localstatedir@
|
|
||||||
libdir = @libdir@
|
|
||||||
infodir = @infodir@
|
|
||||||
mandir = @mandir@
|
|
||||||
includedir = @includedir@
|
|
||||||
oldincludedir = /usr/include
|
|
||||||
pkgdatadir = $(datadir)/@PACKAGE@
|
pkgdatadir = $(datadir)/@PACKAGE@
|
||||||
pkglibdir = $(libdir)/@PACKAGE@
|
pkglibdir = $(libdir)/@PACKAGE@
|
||||||
pkgincludedir = $(includedir)/@PACKAGE@
|
pkgincludedir = $(includedir)/@PACKAGE@
|
||||||
top_builddir = ..
|
top_builddir = ..
|
||||||
|
|
||||||
ACLOCAL = @ACLOCAL@
|
|
||||||
AUTOCONF = @AUTOCONF@
|
|
||||||
AUTOMAKE = @AUTOMAKE@
|
|
||||||
AUTOHEADER = @AUTOHEADER@
|
|
||||||
|
|
||||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||||
INSTALL = @INSTALL@
|
INSTALL = @INSTALL@
|
||||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
|
||||||
INSTALL_DATA = @INSTALL_DATA@
|
|
||||||
install_sh_DATA = $(install_sh) -c -m 644
|
install_sh_DATA = $(install_sh) -c -m 644
|
||||||
install_sh_PROGRAM = $(install_sh) -c
|
install_sh_PROGRAM = $(install_sh) -c
|
||||||
install_sh_SCRIPT = $(install_sh) -c
|
install_sh_SCRIPT = $(install_sh) -c
|
||||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
|
||||||
INSTALL_HEADER = $(INSTALL_DATA)
|
INSTALL_HEADER = $(INSTALL_DATA)
|
||||||
transform = @program_transform_name@
|
transform = $(program_transform_name)
|
||||||
NORMAL_INSTALL = :
|
NORMAL_INSTALL = :
|
||||||
PRE_INSTALL = :
|
PRE_INSTALL = :
|
||||||
POST_INSTALL = :
|
POST_INSTALL = :
|
||||||
NORMAL_UNINSTALL = :
|
NORMAL_UNINSTALL = :
|
||||||
PRE_UNINSTALL = :
|
PRE_UNINSTALL = :
|
||||||
POST_UNINSTALL = :
|
POST_UNINSTALL = :
|
||||||
host_alias = @host_alias@
|
build_triplet = @build@
|
||||||
host_triplet = @host@
|
host_triplet = @host@
|
||||||
|
target_triplet = @target@
|
||||||
EXEEXT = @EXEEXT@
|
subdir = doc
|
||||||
OBJEXT = @OBJEXT@
|
DIST_COMMON = README $(dist_pkgdata_DATA) $(srcdir)/Makefile.am \
|
||||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
$(srcdir)/Makefile.in
|
||||||
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
|
||||||
|
$(top_srcdir)/libtool.m4 $(top_srcdir)/configure.in
|
||||||
|
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
|
$(ACLOCAL_M4)
|
||||||
|
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
|
CONFIG_CLEAN_FILES =
|
||||||
|
SOURCES =
|
||||||
|
DIST_SOURCES =
|
||||||
|
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||||
|
am__vpath_adj = case $$p in \
|
||||||
|
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
|
*) f=$$p;; \
|
||||||
|
esac;
|
||||||
|
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
||||||
|
am__installdirs = "$(DESTDIR)$(pkgdatadir)"
|
||||||
|
dist_pkgdataDATA_INSTALL = $(INSTALL_DATA)
|
||||||
|
DATA = $(dist_pkgdata_DATA)
|
||||||
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
ACLOCAL = @ACLOCAL@
|
||||||
|
AMDEP_FALSE = @AMDEP_FALSE@
|
||||||
|
AMDEP_TRUE = @AMDEP_TRUE@
|
||||||
AMTAR = @AMTAR@
|
AMTAR = @AMTAR@
|
||||||
AR = @AR@
|
AR = @AR@
|
||||||
AS = @AS@
|
AUTOCONF = @AUTOCONF@
|
||||||
|
AUTOHEADER = @AUTOHEADER@
|
||||||
|
AUTOMAKE = @AUTOMAKE@
|
||||||
AWK = @AWK@
|
AWK = @AWK@
|
||||||
CC = @CC@
|
CC = @CC@
|
||||||
CCAS = @CCAS@
|
CCAS = @CCAS@
|
||||||
CCASFLAGS = @CCASFLAGS@
|
CCASFLAGS = @CCASFLAGS@
|
||||||
|
CCDEPMODE = @CCDEPMODE@
|
||||||
CFLAGS = @CFLAGS@
|
CFLAGS = @CFLAGS@
|
||||||
|
COMPILER_XLC_FALSE = @COMPILER_XLC_FALSE@
|
||||||
|
COMPILER_XLC_TRUE = @COMPILER_XLC_TRUE@
|
||||||
|
CPLUSPLUS_FALSE = @CPLUSPLUS_FALSE@
|
||||||
|
CPLUSPLUS_TRUE = @CPLUSPLUS_TRUE@
|
||||||
|
CPP = @CPP@
|
||||||
|
CPPFLAGS = @CPPFLAGS@
|
||||||
CXX = @CXX@
|
CXX = @CXX@
|
||||||
|
CXXDEPMODE = @CXXDEPMODE@
|
||||||
CXXFLAGS = @CXXFLAGS@
|
CXXFLAGS = @CXXFLAGS@
|
||||||
CXXINCLUDES = @CXXINCLUDES@
|
CXXINCLUDES = @CXXINCLUDES@
|
||||||
|
CYGPATH_W = @CYGPATH_W@
|
||||||
|
DEFS = @DEFS@
|
||||||
DEPDIR = @DEPDIR@
|
DEPDIR = @DEPDIR@
|
||||||
DLLTOOL = @DLLTOOL@
|
|
||||||
ECHO = @ECHO@
|
ECHO = @ECHO@
|
||||||
|
ECHO_C = @ECHO_C@
|
||||||
|
ECHO_N = @ECHO_N@
|
||||||
|
ECHO_T = @ECHO_T@
|
||||||
|
EGREP = @EGREP@
|
||||||
|
EXEEXT = @EXEEXT@
|
||||||
EXTRA_TEST_LIBS = @EXTRA_TEST_LIBS@
|
EXTRA_TEST_LIBS = @EXTRA_TEST_LIBS@
|
||||||
GC_CFLAGS = @GC_CFLAGS@
|
GC_CFLAGS = @GC_CFLAGS@
|
||||||
GC_VERSION = @GC_VERSION@
|
GC_VERSION = @GC_VERSION@
|
||||||
INCLUDES = @INCLUDES@
|
INCLUDES = @INCLUDES@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
LIBOBJS = @LIBOBJS@
|
||||||
|
LIBS = @LIBS@
|
||||||
LIBTOOL = @LIBTOOL@
|
LIBTOOL = @LIBTOOL@
|
||||||
LN_S = @LN_S@
|
LN_S = @LN_S@
|
||||||
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
MAINT = @MAINT@
|
MAINT = @MAINT@
|
||||||
|
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
|
||||||
|
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
|
||||||
|
MAKEINFO = @MAKEINFO@
|
||||||
MY_CFLAGS = @MY_CFLAGS@
|
MY_CFLAGS = @MY_CFLAGS@
|
||||||
OBJDUMP = @OBJDUMP@
|
OBJEXT = @OBJEXT@
|
||||||
PACKAGE = @PACKAGE@
|
PACKAGE = @PACKAGE@
|
||||||
|
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||||
|
PACKAGE_NAME = @PACKAGE_NAME@
|
||||||
|
PACKAGE_STRING = @PACKAGE_STRING@
|
||||||
|
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||||
|
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||||
|
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||||
|
POWERPC_DARWIN_FALSE = @POWERPC_DARWIN_FALSE@
|
||||||
|
POWERPC_DARWIN_TRUE = @POWERPC_DARWIN_TRUE@
|
||||||
RANLIB = @RANLIB@
|
RANLIB = @RANLIB@
|
||||||
|
SET_MAKE = @SET_MAKE@
|
||||||
|
SHELL = @SHELL@
|
||||||
STRIP = @STRIP@
|
STRIP = @STRIP@
|
||||||
THREADLIBS = @THREADLIBS@
|
THREADDLLIBS = @THREADDLLIBS@
|
||||||
UNWINDLIBS = @UNWINDLIBS@
|
UNWINDLIBS = @UNWINDLIBS@
|
||||||
|
USE_LIBDIR_FALSE = @USE_LIBDIR_FALSE@
|
||||||
|
USE_LIBDIR_TRUE = @USE_LIBDIR_TRUE@
|
||||||
VERSION = @VERSION@
|
VERSION = @VERSION@
|
||||||
|
ac_ct_AR = @ac_ct_AR@
|
||||||
|
ac_ct_CC = @ac_ct_CC@
|
||||||
|
ac_ct_CXX = @ac_ct_CXX@
|
||||||
|
ac_ct_RANLIB = @ac_ct_RANLIB@
|
||||||
|
ac_ct_STRIP = @ac_ct_STRIP@
|
||||||
addincludes = @addincludes@
|
addincludes = @addincludes@
|
||||||
addlibs = @addlibs@
|
addlibs = @addlibs@
|
||||||
addobjs = @addobjs@
|
addobjs = @addobjs@
|
||||||
addtests = @addtests@
|
addtests = @addtests@
|
||||||
|
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||||
|
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||||
|
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||||
|
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||||
am__include = @am__include@
|
am__include = @am__include@
|
||||||
|
am__leading_dot = @am__leading_dot@
|
||||||
am__quote = @am__quote@
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
|
bindir = @bindir@
|
||||||
|
build = @build@
|
||||||
|
build_alias = @build_alias@
|
||||||
|
build_cpu = @build_cpu@
|
||||||
|
build_os = @build_os@
|
||||||
|
build_vendor = @build_vendor@
|
||||||
|
datadir = @datadir@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
host = @host@
|
||||||
|
host_alias = @host_alias@
|
||||||
|
host_cpu = @host_cpu@
|
||||||
|
host_os = @host_os@
|
||||||
|
host_vendor = @host_vendor@
|
||||||
|
includedir = @includedir@
|
||||||
|
infodir = @infodir@
|
||||||
install_sh = @install_sh@
|
install_sh = @install_sh@
|
||||||
|
libdir = @libdir@
|
||||||
|
libexecdir = @libexecdir@
|
||||||
|
localstatedir = @localstatedir@
|
||||||
|
mandir = @mandir@
|
||||||
|
mkdir_p = @mkdir_p@
|
||||||
|
oldincludedir = @oldincludedir@
|
||||||
|
prefix = @prefix@
|
||||||
|
program_transform_name = @program_transform_name@
|
||||||
|
sbindir = @sbindir@
|
||||||
|
sharedstatedir = @sharedstatedir@
|
||||||
|
sysconfdir = @sysconfdir@
|
||||||
|
target = @target@
|
||||||
|
target_alias = @target_alias@
|
||||||
target_all = @target_all@
|
target_all = @target_all@
|
||||||
|
target_cpu = @target_cpu@
|
||||||
|
target_os = @target_os@
|
||||||
|
target_vendor = @target_vendor@
|
||||||
|
|
||||||
# installed documentation
|
# installed documentation
|
||||||
#
|
#
|
||||||
|
@ -129,21 +207,38 @@ dist_pkgdata_DATA = barrett_diagram debugging.html gc.man \
|
||||||
tree.html leak.html gcinterface.html scale.html \
|
tree.html leak.html gcinterface.html scale.html \
|
||||||
README.darwin simple_example.html
|
README.darwin simple_example.html
|
||||||
|
|
||||||
subdir = doc
|
|
||||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
|
||||||
CONFIG_CLEAN_FILES =
|
|
||||||
DIST_SOURCES =
|
|
||||||
DATA = $(dist_pkgdata_DATA)
|
|
||||||
|
|
||||||
DIST_COMMON = README $(dist_pkgdata_DATA) Makefile.am Makefile.in
|
|
||||||
all: all-am
|
all: all-am
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||||
|
@for dep in $?; do \
|
||||||
|
case '$(am__configure_deps)' in \
|
||||||
|
*$$dep*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||||
|
&& exit 0; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \
|
||||||
cd $(top_srcdir) && \
|
cd $(top_srcdir) && \
|
||||||
$(AUTOMAKE) --gnu doc/Makefile
|
$(AUTOMAKE) --gnu doc/Makefile
|
||||||
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
|
.PRECIOUS: Makefile
|
||||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
|
@case '$?' in \
|
||||||
|
*config.status*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||||
|
*) \
|
||||||
|
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||||
|
esac;
|
||||||
|
|
||||||
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
|
||||||
|
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
|
||||||
mostlyclean-libtool:
|
mostlyclean-libtool:
|
||||||
-rm -f *.lo
|
-rm -f *.lo
|
||||||
|
@ -154,39 +249,43 @@ clean-libtool:
|
||||||
distclean-libtool:
|
distclean-libtool:
|
||||||
-rm -f libtool
|
-rm -f libtool
|
||||||
uninstall-info-am:
|
uninstall-info-am:
|
||||||
dist_pkgdataDATA_INSTALL = $(INSTALL_DATA)
|
|
||||||
install-dist_pkgdataDATA: $(dist_pkgdata_DATA)
|
install-dist_pkgdataDATA: $(dist_pkgdata_DATA)
|
||||||
@$(NORMAL_INSTALL)
|
@$(NORMAL_INSTALL)
|
||||||
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
|
test -z "$(pkgdatadir)" || $(mkdir_p) "$(DESTDIR)$(pkgdatadir)"
|
||||||
@list='$(dist_pkgdata_DATA)'; for p in $$list; do \
|
@list='$(dist_pkgdata_DATA)'; for p in $$list; do \
|
||||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " $(dist_pkgdataDATA_INSTALL) $$d$$p $(DESTDIR)$(pkgdatadir)/$$f"; \
|
echo " $(dist_pkgdataDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgdatadir)/$$f'"; \
|
||||||
$(dist_pkgdataDATA_INSTALL) $$d$$p $(DESTDIR)$(pkgdatadir)/$$f; \
|
$(dist_pkgdataDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgdatadir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
|
||||||
uninstall-dist_pkgdataDATA:
|
uninstall-dist_pkgdataDATA:
|
||||||
@$(NORMAL_UNINSTALL)
|
@$(NORMAL_UNINSTALL)
|
||||||
@list='$(dist_pkgdata_DATA)'; for p in $$list; do \
|
@list='$(dist_pkgdata_DATA)'; for p in $$list; do \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " rm -f $(DESTDIR)$(pkgdatadir)/$$f"; \
|
echo " rm -f '$(DESTDIR)$(pkgdatadir)/$$f'"; \
|
||||||
rm -f $(DESTDIR)$(pkgdatadir)/$$f; \
|
rm -f "$(DESTDIR)$(pkgdatadir)/$$f"; \
|
||||||
done
|
done
|
||||||
tags: TAGS
|
tags: TAGS
|
||||||
TAGS:
|
TAGS:
|
||||||
|
|
||||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
ctags: CTAGS
|
||||||
|
CTAGS:
|
||||||
|
|
||||||
top_distdir = ..
|
|
||||||
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
|
|
||||||
|
|
||||||
distdir: $(DISTFILES)
|
distdir: $(DISTFILES)
|
||||||
@list='$(DISTFILES)'; for file in $$list; do \
|
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||||
|
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||||
|
list='$(DISTFILES)'; for file in $$list; do \
|
||||||
|
case $$file in \
|
||||||
|
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
|
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||||
|
esac; \
|
||||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||||
dir="/$$dir"; \
|
dir="/$$dir"; \
|
||||||
$(mkinstalldirs) "$(distdir)$$dir"; \
|
$(mkdir_p) "$(distdir)$$dir"; \
|
||||||
else \
|
else \
|
||||||
dir=''; \
|
dir=''; \
|
||||||
fi; \
|
fi; \
|
||||||
|
@ -204,10 +303,10 @@ distdir: $(DISTFILES)
|
||||||
check-am: all-am
|
check-am: all-am
|
||||||
check: check-am
|
check: check-am
|
||||||
all-am: Makefile $(DATA)
|
all-am: Makefile $(DATA)
|
||||||
|
|
||||||
installdirs:
|
installdirs:
|
||||||
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
|
for dir in "$(DESTDIR)$(pkgdatadir)"; do \
|
||||||
|
test -z "$$dir" || $(mkdir_p) "$$dir"; \
|
||||||
|
done
|
||||||
install: install-am
|
install: install-am
|
||||||
install-exec: install-exec-am
|
install-exec: install-exec-am
|
||||||
install-data: install-data-am
|
install-data: install-data-am
|
||||||
|
@ -219,7 +318,7 @@ install-am: all-am
|
||||||
installcheck: installcheck-am
|
installcheck: installcheck-am
|
||||||
install-strip:
|
install-strip:
|
||||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
INSTALL_STRIP_FLAG=-s \
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
`test -z '$(STRIP)' || \
|
`test -z '$(STRIP)' || \
|
||||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||||
mostlyclean-generic:
|
mostlyclean-generic:
|
||||||
|
@ -227,7 +326,7 @@ mostlyclean-generic:
|
||||||
clean-generic:
|
clean-generic:
|
||||||
|
|
||||||
distclean-generic:
|
distclean-generic:
|
||||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
maintainer-clean-generic:
|
maintainer-clean-generic:
|
||||||
@echo "This command is intended for maintainers to use"
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@ -237,13 +336,15 @@ clean: clean-am
|
||||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||||
|
|
||||||
distclean: distclean-am
|
distclean: distclean-am
|
||||||
|
-rm -f Makefile
|
||||||
distclean-am: clean-am distclean-generic distclean-libtool
|
distclean-am: clean-am distclean-generic distclean-libtool
|
||||||
|
|
||||||
dvi: dvi-am
|
dvi: dvi-am
|
||||||
|
|
||||||
dvi-am:
|
dvi-am:
|
||||||
|
|
||||||
|
html: html-am
|
||||||
|
|
||||||
info: info-am
|
info: info-am
|
||||||
|
|
||||||
info-am:
|
info-am:
|
||||||
|
@ -259,24 +360,33 @@ install-man:
|
||||||
installcheck-am:
|
installcheck-am:
|
||||||
|
|
||||||
maintainer-clean: maintainer-clean-am
|
maintainer-clean: maintainer-clean-am
|
||||||
|
-rm -f Makefile
|
||||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||||
|
|
||||||
mostlyclean: mostlyclean-am
|
mostlyclean: mostlyclean-am
|
||||||
|
|
||||||
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||||
|
|
||||||
|
pdf: pdf-am
|
||||||
|
|
||||||
|
pdf-am:
|
||||||
|
|
||||||
|
ps: ps-am
|
||||||
|
|
||||||
|
ps-am:
|
||||||
|
|
||||||
uninstall-am: uninstall-dist_pkgdataDATA uninstall-info-am
|
uninstall-am: uninstall-dist_pkgdataDATA uninstall-info-am
|
||||||
|
|
||||||
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
|
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
|
||||||
distclean distclean-generic distclean-libtool distdir dvi \
|
distclean distclean-generic distclean-libtool distdir dvi \
|
||||||
dvi-am info info-am install install-am install-data \
|
dvi-am html html-am info info-am install install-am \
|
||||||
install-data-am install-dist_pkgdataDATA install-exec \
|
install-data install-data-am install-dist_pkgdataDATA \
|
||||||
install-exec-am install-info install-info-am install-man \
|
install-exec install-exec-am install-info install-info-am \
|
||||||
install-strip installcheck installcheck-am installdirs \
|
install-man install-strip installcheck installcheck-am \
|
||||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
installdirs maintainer-clean maintainer-clean-generic \
|
||||||
mostlyclean-generic mostlyclean-libtool uninstall uninstall-am \
|
mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
|
||||||
uninstall-dist_pkgdataDATA uninstall-info-am
|
ps ps-am uninstall uninstall-am uninstall-dist_pkgdataDATA \
|
||||||
|
uninstall-info-am
|
||||||
|
|
||||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
|
|
@ -28,7 +28,7 @@ are GPL'ed, but with an exception that should cover all uses in the
|
||||||
collector. (If you are concerned about such things, I recommend you look
|
collector. (If you are concerned about such things, I recommend you look
|
||||||
at the notice in config.guess or ltmain.sh.)
|
at the notice in config.guess or ltmain.sh.)
|
||||||
|
|
||||||
This is version 6.3 of a conservative garbage collector for C and C++.
|
This is version 6.7 of a conservative garbage collector for C and C++.
|
||||||
|
|
||||||
You might find a more recent version of this at
|
You might find a more recent version of this at
|
||||||
|
|
||||||
|
|
|
@ -2100,7 +2100,190 @@ Since gc6.3alpha6:
|
||||||
to Andrew Begel.)
|
to Andrew Begel.)
|
||||||
- Fix GC_task_self declaration in os_dep.c. (Thanks to Andrew Pinski.)
|
- Fix GC_task_self declaration in os_dep.c. (Thanks to Andrew Pinski.)
|
||||||
- Increase INITIAL_BUF_SZ in os_dep.c for Solaris /proc reads.
|
- Increase INITIAL_BUF_SZ in os_dep.c for Solaris /proc reads.
|
||||||
|
|
||||||
|
Since 6.3:
|
||||||
|
- Merge gcconfig.h changes from gcc tree.
|
||||||
|
- Unconditionally include gc_priv.h in solaris_pthreads.c, win32_threads.h,
|
||||||
|
aix_irix_threads.c, and solaris_threads.c to get thread definitions.
|
||||||
|
- Start marker threads in GC_thr_init, so that they get started even
|
||||||
|
if no other threads are ever started. (Oddly enough, the parallel
|
||||||
|
collector worked correctly, though not well, with no helper threads.)
|
||||||
|
- Go ahead and split large blocks in GC_allochblk_nth if GC_dont_gc
|
||||||
|
is set. (Thanks to Alexander Petrossian.)
|
||||||
|
- GC_PRINT_BACK_HEIGHT would deadlock with thread support.
|
||||||
|
- Let in_progress_space in backgraph.s grow dynamically.
|
||||||
|
- Fix README.solaris2. The GC_thr_init() hack doesn't work anymore.
|
||||||
|
- Convert GC_finalizer_mem_freed to bytes in allchblk.c.
|
||||||
|
- Add missing declaration for GC_generic_malloc_words_small_inner.
|
||||||
|
Without it, s390x breaks. (Thanks to Ulrich Weigand.)
|
||||||
|
- Applied several MacOSX patches to support older tool chains.
|
||||||
|
(Thanks to Stefan Ring.)
|
||||||
|
- Bug fix for NetBSD/amd64. (Thanks to Marc Recht.) Add NetBSD/sh3
|
||||||
|
support. (Thanks to Uchiyama Yasushi.)
|
||||||
|
- Fixed an uninitialized variable in cordprnt.c. (Thanks to gcc for
|
||||||
|
providing the warning.)
|
||||||
|
- Eliminated some, but not all, gcc -Wall warnings.
|
||||||
|
- Changed some old style casts to reinterpret_cast in new_gc_alloc.h.
|
||||||
|
(Thanks to Dan Grayson.)
|
||||||
|
- GC_extend_size_map shouldn't adjust for GC_all_interior_pointers if
|
||||||
|
GC_DONT_ADD_BYTE_AT_END is set.
|
||||||
|
- Changed some (long) casts to (word) in preparation for win64.
|
||||||
|
(Thanks to Peter Colson.)
|
||||||
|
- Changed "int stack_size" declaration in pthread_support.c to use
|
||||||
|
size_t. (Only mattered with GC_ASSERTIONS enabled.)
|
||||||
|
- Added CRIS (etrax) support. (Thanks to Simon Posnjak and
|
||||||
|
Hans-Peter Nilsson.)
|
||||||
|
- Removed GC_IGNORE_FB frame buffer recognition, and replaced
|
||||||
|
it with a check that the mapping type is MEM_IMAGE.
|
||||||
|
In theory, this should work much better, but it is a high
|
||||||
|
risk change for win32. (Thanks to Ashley Bone for the crucial
|
||||||
|
experimental data behind this, and to Rutger Ovidus for
|
||||||
|
some further experiments.)
|
||||||
|
- Fixed print_block_list to print the correct kind number for
|
||||||
|
STUBBORN. (Thanks to Rutger Ovidus.)
|
||||||
|
- GC_allochblk_nth incremented GC_words_wasted by bytes rather than
|
||||||
|
words.
|
||||||
|
- Consider GC_words_wasted in GC_adj_words_allocd only if it is within
|
||||||
|
reason. (A hack to avoid some extremely unlikely scenarios in which
|
||||||
|
we manage to allocate only "wasted" space. 7.0 has a better fix.)
|
||||||
|
- Changed PowerPC GC_clear implementation to use lwsync instead of
|
||||||
|
eieio, since the documentation recommends against eieio, and
|
||||||
|
it seems to be incorrect if the preceding memory op is a load.
|
||||||
|
- Fixed print_block_list to print the correct kind number for
|
||||||
|
STUBBORN. (Thanks to Rutger Ovidus.)
|
||||||
|
- Have configure.in generate an error if it is asked to support
|
||||||
|
pthreads, but doesn't know how to.
|
||||||
|
- Added Kazuhiro Inaoka's patch for Renesas M32R support.
|
||||||
|
- Have the GNU build mechanism link with -ldl. Rename THREADLIBS
|
||||||
|
to THREADDLLIBS to reflect this. (Thanks to Sven Verdoolaege.)
|
||||||
|
- Added Hannes Mehnert's patch for FreeBSD/SPARC support.
|
||||||
|
- Merged some FreeBSD specific patches to threadlibs.c and dyn_load.c.
|
||||||
|
(Thanks tp John Merryweather Cooper.)
|
||||||
|
- Define MPROTECT_VDB on MACOSX only if threads are being used, since the
|
||||||
|
dirty page tracking mechanism uses threads. (This avoids an undefined
|
||||||
|
reference to _GC_darwin_register_mach_handler_thread.)
|
||||||
|
- By popular demand, use __libc symbols only if we are built with
|
||||||
|
USE_LIBC_PRIVATES, which is off by default, and not otherwise documented.
|
||||||
|
- Ignore GC_enable_incremental() requests when KEEP_BACK_PTRS is set.
|
||||||
|
The GC itself will dirty lots of pages in this cases, probably making
|
||||||
|
it counterproductive on all platforms. And the DARWIN port crashes.
|
||||||
|
|
||||||
|
Since GC6.4:
|
||||||
|
- Integrated Paolo Molaro's patch to deal with EINTR in sem_wait.
|
||||||
|
- Make GC_approx_sp() write to dummy location to ensure that stack
|
||||||
|
is grown here, when sp looks reasonable, rather than later, when
|
||||||
|
it might look like a bad memory reference. (Problem was never
|
||||||
|
observed that I know of. But on rereading the code it seemed
|
||||||
|
dubious.)
|
||||||
|
- Separate out GC_with_callee_saves_pushed and sometimes call
|
||||||
|
it from GC_suspend_handler in pthread_stop_world.c. Callee-save
|
||||||
|
register values sometimes failed to get traced under HP/UX on
|
||||||
|
PA-RISC. Linux/IA64 had the same problem, though non-stacked
|
||||||
|
callee-save registers seem to be so rarely used there that nobody
|
||||||
|
ever noticed.
|
||||||
|
- Integrated an ancient Darwin powerpc_darwin_machine_dep.s patch
|
||||||
|
from Andreas Tobler, which I had lost.
|
||||||
|
- Fix compare_and_exchange implementation for gcc/IA64 to deal with
|
||||||
|
pickier compiler versions.
|
||||||
|
- Fixed Itanium 32-bit ABI support (HP/UX). In particular, the
|
||||||
|
compare_and_exchange implementation didn't consider that possibility.
|
||||||
|
- Undefine GC_pthread_detach in win32_threads.c. (Thanks to
|
||||||
|
Tagliapietra Tommaso.)
|
||||||
|
- Fixed inclusion of frame.h for NETBSD in os_dep.c.
|
||||||
|
- Applied Dan Bonachea's patch to use mmap on AIX.
|
||||||
|
- Several fixes to resurrect the Irix port on recent OS versions.
|
||||||
|
- Change ALPHA to use LINUX_STACKBOTTOM.
|
||||||
|
- Change SPARC64/LINUX to also use LINUX_STACKBOTTOM. Deal with potential
|
||||||
|
bad values of __libc_stack_end on that platform. (Thanks to David Miller.)
|
||||||
|
- Relax gctest to allow larger heap if ALIGN_DOUBLE isn't set.
|
||||||
|
(Unnecessary in 7.0)
|
||||||
|
- Force a define of __STDC__=0 for the IBM compiler on AIX, so that
|
||||||
|
we get prototypes. (Unnecessary in 7.0)
|
||||||
|
- GC_INIT definition for AIX and CYGWIN referred to DATASTART and DATAEND
|
||||||
|
which are only defined in private include files.
|
||||||
|
- Integrated some small gcconfig.h patches from Dan Bonachea. Also
|
||||||
|
relaxed assertion about FreeBSD stack size in pthread_support.c.
|
||||||
|
- Integrated Andrew Begel's darwin_stop_world.c patch for 64-bit
|
||||||
|
support. This may need additional work.
|
||||||
|
- Avoided potentially infinite recursion in GC_save_callers if
|
||||||
|
the system backtrace calls malloc. The workaround currently requires
|
||||||
|
__thread support if this code is used with threads.
|
||||||
|
- Avoided another similar infinite recursion by conditionally
|
||||||
|
invoking GC_save_callers in alloc.c. (Thanks to Matthias Andree
|
||||||
|
for helping to track down both of these.)
|
||||||
|
- Removed all traces of aix_irix_threads.c. AIX and Irix now use
|
||||||
|
pthread_support.c and pthread_stop_world.c. The old code appeared
|
||||||
|
to be unreliable for AIX, and was not regularly maintained.
|
||||||
|
- On Irix, ignore segments with MA_FETCHOP or MA_NOTCACHED attributed;
|
||||||
|
they're not always safe to read.
|
||||||
|
- Fixed a previously vacuous assertion (diagnosed by the SGI compiler)
|
||||||
|
in GC_remove_from_fl.
|
||||||
|
- Fix stack_size assertion in GC_pthread_create.
|
||||||
|
- Fix assertion in GC_steal_mark_stack.
|
||||||
|
|
||||||
|
Since 6.5
|
||||||
|
- Fix CPU count detection for Irix and FreeBSD. (Thanks to Dan Bonachea.)
|
||||||
|
- Integrate Dan Bonachea's patch for the IBM XLC compiler on Darwin.
|
||||||
|
- Integrated Andreas Tobler's FreeBSD/PowerPC patch.
|
||||||
|
- Don't access the GC thread structure from the restart handler. It's
|
||||||
|
unsafe, since the handler may run too late. (Thanks to Ben Maurer for
|
||||||
|
tracking this down.)
|
||||||
|
- Applied Christian Thalinger's patch to change comment syntax in
|
||||||
|
alpha_mach_dep.S.
|
||||||
|
- Added test for GC_no_dls in GC_dyld_image_add for DARWIN. (Thanks to
|
||||||
|
Juan Jose Garcia Ripoli).
|
||||||
|
- Use LINUX_STACKBOTTOM for Linux/SH and LINUX/ARM. (Thanks to Sugioka
|
||||||
|
Toshinobu and Christian Thalinger.)
|
||||||
|
- Rewrote GC_parse_map_entry. This assumed a fixed column layout of
|
||||||
|
/proc/self/maps on Linux. This ceased to be true about 2 years ago.
|
||||||
|
The old code is probably quite problemetic with -DREDIRECT_MALLOC. It
|
||||||
|
is also used by default for IA64, though I haven't seen actual failures
|
||||||
|
there.
|
||||||
|
- More consistently define HBLKSIZE to 4096 on 64 bit architectures with
|
||||||
|
4K pages. (Thanks to Andrew Haley.)
|
||||||
|
- With win32 threads, GC_stop_world needs to acquire GC_write_cs. (Thanks
|
||||||
|
to Ben Hutchings for the observation and patch.)
|
||||||
|
- Move up struct callinfo declaration to make gcc 4.0.2. happy.
|
||||||
|
|
||||||
|
Since 6.6:
|
||||||
|
- Add "int" to Solaris "end" and "etext" declaration in gc.h. Declared
|
||||||
|
the symbols with underscores and as arrays, since that's what's actually
|
||||||
|
used. Perhaps this could all just be removed? (Thanks to John Bowman.)
|
||||||
|
- Fixed ARM GC_test_and_set code. (Thanks to Kazu Hirata and Paul Brook.)
|
||||||
|
- Added casts for assignments to hb_last_reclaimed, which truncate the
|
||||||
|
value. Added a cast to GC_adj_words_allocd. Use GetModuleHandleA
|
||||||
|
when retrieving a handle to kernel32.dll under win32. (Thanks to the
|
||||||
|
Visual Prolog developers.)
|
||||||
|
- Added Tandem S-Series support. (Thanks to Craig McDaniel. A modified
|
||||||
|
version of his patch was applied, and hence breakage is probably not
|
||||||
|
his fault.)
|
||||||
|
- Remove spurious gc:: qualifier for operator delete[] in gc_cpp.h.
|
||||||
|
(Thanks to Hanno Boeck.)
|
||||||
|
- Changed a test for LINUX in config_macros.h to one for __linux__.
|
||||||
|
- Fix ppc 64 test_and_set code by removing it. (Thanks to Christian
|
||||||
|
Thalinger.)
|
||||||
|
- Add prototypes for GC_finalizer_notifier and GC_thr_init. (Thanks to
|
||||||
|
David Ayers.)
|
||||||
|
- Use ld instead of nonexistent ldz instruction in Darwin FindTopOfStack.
|
||||||
|
(Thanks to Andreas Tobler.)
|
||||||
|
- Add support for Darwin/X86. (Thanks to Geoff Norton and the Mono
|
||||||
|
developers.)
|
||||||
|
- Merge in some recent gcc fixes. Add ppc64 asm code. (Thanks to Bryce
|
||||||
|
McKinley and other gcj developers.)
|
||||||
|
- Scan MEM_PRIVATE sections under Windows ME and predecessors.
|
||||||
|
- Interior pointers with some largish offsets into large objects could
|
||||||
|
be ignored, if GC_all_interior_pointers was set. (Oddly this worked
|
||||||
|
correctly for stack references if it was not set. Otherwise it failed
|
||||||
|
for both stack and heap references.) Thanks to Andrew McKinlay for the
|
||||||
|
critical test case.
|
||||||
|
- Integrated Tatsuya Bizenn's NETBSD threads support, with some
|
||||||
|
minimally tested changes.
|
||||||
|
- Added GC_strdup and friends to make leak detection work correctly
|
||||||
|
for strdup clients. (Thanks to Jon Moore.) Fixed the existing strdup
|
||||||
|
with malloc redirection to handle a null malloc return correctly.
|
||||||
|
- Fix Makefile.am, so it handles exe extensions under Cygwin correctly
|
||||||
|
for gctest.
|
||||||
|
|
||||||
To do:
|
To do:
|
||||||
- The USE_MUNMAP code should really use a separate data structure
|
- The USE_MUNMAP code should really use a separate data structure
|
||||||
indexed by physical page to keep track of time since last use of
|
indexed by physical page to keep track of time since last use of
|
||||||
|
|
|
@ -1,3 +1,16 @@
|
||||||
|
6.5 update:
|
||||||
|
I disabled incremental GC on Darwin in this version, since I couldn't
|
||||||
|
get gctest to pass when the GC was built as a dynamic library. Building
|
||||||
|
with -DMPROTECT_VDB (and threads) on the command line should get you
|
||||||
|
back to the old state. - HB
|
||||||
|
|
||||||
|
./configure --enable-cplusplus results in a "make check" failure, probably
|
||||||
|
because the ::delete override ends up in a separate dl, and Darwin dynamic
|
||||||
|
loader semantics appear to be such that this is not really visible to the
|
||||||
|
main program, unlike on ELF systems. Someone who understands dynamic
|
||||||
|
loading needs to lookat this. For now, gc_cpp.o needs to be linked
|
||||||
|
statically, if needed. - HB
|
||||||
|
|
||||||
Darwin/MacOSX Support - December 16, 2003
|
Darwin/MacOSX Support - December 16, 2003
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,7 @@ GC_IGNORE_FB[=<n>] - (Win32 only.) Try to avoid treating a mapped
|
||||||
are never honored, eliminating this risk for most,
|
are never honored, eliminating this risk for most,
|
||||||
but not all, applications. This feature is likely to disappear
|
but not all, applications. This feature is likely to disappear
|
||||||
if/when we find a less disgusting "solution".
|
if/when we find a less disgusting "solution".
|
||||||
|
IN VERSION 6.4 AND LATER, THIS SHOULD BE UNNECESSARY.
|
||||||
|
|
||||||
The following turn on runtime flags that are also program settable. Checked
|
The following turn on runtime flags that are also program settable. Checked
|
||||||
only during initialization. We expect that they will usually be set through
|
only during initialization. We expect that they will usually be set through
|
||||||
|
|
|
@ -19,10 +19,10 @@ Linux threads. These should not be touched by the client program.
|
||||||
|
|
||||||
To use threads, you need to abide by the following requirements:
|
To use threads, you need to abide by the following requirements:
|
||||||
|
|
||||||
1) You need to use LinuxThreads (which are included in libc6).
|
1) You need to use LinuxThreads or NPTL (which are included in libc6).
|
||||||
|
|
||||||
The collector relies on some implementation details of the LinuxThreads
|
The collector relies on some implementation details of the LinuxThreads
|
||||||
package. It is unlikely that this code will work on other
|
package. This code may not work on other
|
||||||
pthread implementations (in particular it will *not* work with
|
pthread implementations (in particular it will *not* work with
|
||||||
MIT pthreads).
|
MIT pthreads).
|
||||||
|
|
||||||
|
|
|
@ -43,9 +43,7 @@ can result in unpleasant heap growth. But it seems better than the
|
||||||
race/deadlock issues we had before.
|
race/deadlock issues we had before.
|
||||||
|
|
||||||
If solaris_threads are used on an X86 processor with malloc redirected to
|
If solaris_threads are used on an X86 processor with malloc redirected to
|
||||||
GC_malloc, it is necessary to call GC_thr_init explicitly before forking the
|
GC_malloc a deadlock is likely to result.
|
||||||
first thread. (This avoids a deadlock arising from calling GC_thr_init
|
|
||||||
with the allocation lock held.)
|
|
||||||
|
|
||||||
It appears that there is a problem in using gc_cpp.h in conjunction with
|
It appears that there is a problem in using gc_cpp.h in conjunction with
|
||||||
Solaris threads and Sun's C++ runtime. Apparently the overloaded new operator
|
Solaris threads and Sun's C++ runtime. Apparently the overloaded new operator
|
||||||
|
|
|
@ -34,6 +34,12 @@ after defining the appropriate <TT>GC_</tt><I>XXXX</i><TT>_THREADS</tt> macro.
|
||||||
The header file <TT>gc.h</tt> must be included
|
The header file <TT>gc.h</tt> must be included
|
||||||
in files that use either GC or threads primitives, since threads primitives
|
in files that use either GC or threads primitives, since threads primitives
|
||||||
will be redefined to cooperate with the GC on many platforms.
|
will be redefined to cooperate with the GC on many platforms.
|
||||||
|
<P>
|
||||||
|
Thread users should also be aware that on many platforms objects reachable
|
||||||
|
only from thread-local variables may be prematurely reclaimed.
|
||||||
|
Thus objects pointed to by thread-local variables should also be pointed to
|
||||||
|
by a globally visible data structure. (This is viewed as a bug, but as
|
||||||
|
one that is exceedingly hard to fix without some libc hooks.)
|
||||||
<DL>
|
<DL>
|
||||||
<DT> <B>void * GC_MALLOC(size_t <I>nbytes</i>)</b>
|
<DT> <B>void * GC_MALLOC(size_t <I>nbytes</i>)</b>
|
||||||
<DD>
|
<DD>
|
||||||
|
@ -180,6 +186,11 @@ but are scanned for pointers to collectable objects.
|
||||||
They are allocated by <TT>GC_MALLOC_UNCOLLECTABLE</tt>, as described
|
They are allocated by <TT>GC_MALLOC_UNCOLLECTABLE</tt>, as described
|
||||||
above, and through some interfaces described below.
|
above, and through some interfaces described below.
|
||||||
<P>
|
<P>
|
||||||
|
(On most platforms, the collector may not trace correctly from in-flight
|
||||||
|
exception objects. Thus objects thrown as exceptions should only
|
||||||
|
point to otherwise reachable memory. This is another bug whose
|
||||||
|
proper repair requires platform hooks.)
|
||||||
|
<P>
|
||||||
The easiest way to ensure that collectable objects are properly referenced
|
The easiest way to ensure that collectable objects are properly referenced
|
||||||
is to allocate only collectable objects. This requires that every
|
is to allocate only collectable objects. This requires that every
|
||||||
allocation go through one of the following interfaces, each one of
|
allocation go through one of the following interfaces, each one of
|
||||||
|
|
|
@ -80,6 +80,11 @@
|
||||||
# define l_name lm_name
|
# define l_name lm_name
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(NETBSD)
|
||||||
|
# include <machine/elf_machdep.h>
|
||||||
|
# define ELFSIZE ARCH_ELFSIZE
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
|
#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
|
||||||
(defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \
|
(defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \
|
||||||
(defined(NETBSD) && defined(__ELF__)) || defined(HURD)
|
(defined(NETBSD) && defined(__ELF__)) || defined(HURD)
|
||||||
|
@ -91,17 +96,25 @@
|
||||||
/* Newer versions of GNU/Linux define this macro. We
|
/* Newer versions of GNU/Linux define this macro. We
|
||||||
* define it similarly for any ELF systems that don't. */
|
* define it similarly for any ELF systems that don't. */
|
||||||
# ifndef ElfW
|
# ifndef ElfW
|
||||||
# ifdef __NetBSD__
|
# if defined(FREEBSD)
|
||||||
# if ELFSIZE == 32
|
# if __ELF_WORD_SIZE == 32
|
||||||
# define ElfW(type) Elf32_##type
|
# define ElfW(type) Elf32_##type
|
||||||
# else
|
# else
|
||||||
# define ElfW(type) Elf64_##type
|
# define ElfW(type) Elf64_##type
|
||||||
# endif
|
# endif
|
||||||
# else
|
# else
|
||||||
# if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
|
# ifdef NETBSD
|
||||||
# define ElfW(type) Elf32_##type
|
# if ELFSIZE == 32
|
||||||
|
# define ElfW(type) Elf32_##type
|
||||||
|
# else
|
||||||
|
# define ElfW(type) Elf64_##type
|
||||||
|
# endif
|
||||||
# else
|
# else
|
||||||
# define ElfW(type) Elf64_##type
|
# if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
|
||||||
|
# define ElfW(type) Elf32_##type
|
||||||
|
# else
|
||||||
|
# define ElfW(type) Elf64_##type
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
@ -480,7 +493,6 @@ static struct link_map *
|
||||||
GC_FirstDLOpenedLinkMap()
|
GC_FirstDLOpenedLinkMap()
|
||||||
{
|
{
|
||||||
ElfW(Dyn) *dp;
|
ElfW(Dyn) *dp;
|
||||||
struct r_debug *r;
|
|
||||||
static struct link_map *cachedResult = 0;
|
static struct link_map *cachedResult = 0;
|
||||||
|
|
||||||
if( _DYNAMIC == 0) {
|
if( _DYNAMIC == 0) {
|
||||||
|
@ -489,6 +501,12 @@ GC_FirstDLOpenedLinkMap()
|
||||||
if( cachedResult == 0 ) {
|
if( cachedResult == 0 ) {
|
||||||
int tag;
|
int tag;
|
||||||
for( dp = _DYNAMIC; (tag = dp->d_tag) != 0; dp++ ) {
|
for( dp = _DYNAMIC; (tag = dp->d_tag) != 0; dp++ ) {
|
||||||
|
/* FIXME: The DT_DEBUG header is not mandated by the */
|
||||||
|
/* ELF spec. This code appears to be dependent on */
|
||||||
|
/* idiosynchracies of older GNU tool chains. If this code */
|
||||||
|
/* fails for you, the real problem is probably that it is */
|
||||||
|
/* being used at all. You should be getting the */
|
||||||
|
/* dl_iterate_phdr version. */
|
||||||
if( tag == DT_DEBUG ) {
|
if( tag == DT_DEBUG ) {
|
||||||
struct link_map *lm
|
struct link_map *lm
|
||||||
= ((struct r_debug *)(dp->d_un.d_ptr))->r_map;
|
= ((struct r_debug *)(dp->d_un.d_ptr))->r_map;
|
||||||
|
@ -613,7 +631,8 @@ void GC_register_dynamic_libraries()
|
||||||
}
|
}
|
||||||
for (i = 0; i < needed_sz; i++) {
|
for (i = 0; i < needed_sz; i++) {
|
||||||
flags = addr_map[i].pr_mflags;
|
flags = addr_map[i].pr_mflags;
|
||||||
if ((flags & (MA_BREAK | MA_STACK | MA_PHYS)) != 0) goto irrelevant;
|
if ((flags & (MA_BREAK | MA_STACK | MA_PHYS
|
||||||
|
| MA_FETCHOP | MA_NOTCACHED)) != 0) goto irrelevant;
|
||||||
if ((flags & (MA_READ | MA_WRITE)) != (MA_READ | MA_WRITE))
|
if ((flags & (MA_READ | MA_WRITE)) != (MA_READ | MA_WRITE))
|
||||||
goto irrelevant;
|
goto irrelevant;
|
||||||
/* The latter test is empirically useless in very old Irix */
|
/* The latter test is empirically useless in very old Irix */
|
||||||
|
@ -735,6 +754,10 @@ void GC_register_dynamic_libraries()
|
||||||
|
|
||||||
# define HAVE_REGISTER_MAIN_STATIC_DATA
|
# define HAVE_REGISTER_MAIN_STATIC_DATA
|
||||||
|
|
||||||
|
/* The frame buffer testing code is dead in this version. */
|
||||||
|
/* We leave it here temporarily in case the switch to just */
|
||||||
|
/* testing for MEM_IMAGE sections causes un expected */
|
||||||
|
/* problems. */
|
||||||
GC_bool GC_warn_fb = TRUE; /* Warn about traced likely */
|
GC_bool GC_warn_fb = TRUE; /* Warn about traced likely */
|
||||||
/* graphics memory. */
|
/* graphics memory. */
|
||||||
GC_bool GC_disallow_ignore_fb = FALSE;
|
GC_bool GC_disallow_ignore_fb = FALSE;
|
||||||
|
@ -749,25 +772,27 @@ void GC_register_dynamic_libraries()
|
||||||
|
|
||||||
/* Should [start, start+len) be treated as a frame buffer */
|
/* Should [start, start+len) be treated as a frame buffer */
|
||||||
/* and ignored? */
|
/* and ignored? */
|
||||||
/* Unfortunately, we currently have no real way to tell */
|
/* Unfortunately, we currently are not quite sure how to tell */
|
||||||
/* automatically, and rely largely on user input. */
|
/* this automatically, and rely largely on user input. */
|
||||||
/* FIXME: If we had more data on this phenomenon (e.g. */
|
/* We expect that any mapping with type MEM_MAPPED (which */
|
||||||
/* is start aligned to a MB multiple?) we should be able to */
|
/* apparently excludes library data sections) can be safely */
|
||||||
/* do better. */
|
/* ignored. But we're too completely remove this code in */
|
||||||
|
/* this version. */
|
||||||
/* Based on a very limited sample, it appears that: */
|
/* Based on a very limited sample, it appears that: */
|
||||||
/* - Frame buffer mappings appear as mappings of length */
|
/* - Frame buffer mappings appear as mappings of large */
|
||||||
/* 2**n MB - 192K. (We guess the 192K can vary a bit.) */
|
/* length, usually a bit less than a power of two. */
|
||||||
/* - Have a stating address at best 64K aligned. */
|
/* - The definition of "a bit less" in the above cannot */
|
||||||
/* I'd love more information about the mapping, since I */
|
/* be made more precise. */
|
||||||
/* can't reproduce the problem. */
|
/* - Have a starting address at best 64K aligned. */
|
||||||
static GC_bool is_frame_buffer(ptr_t start, size_t len)
|
/* - Have type == MEM_MAPPED. */
|
||||||
|
static GC_bool is_frame_buffer(ptr_t start, size_t len, DWORD tp)
|
||||||
{
|
{
|
||||||
static GC_bool initialized = FALSE;
|
static GC_bool initialized = FALSE;
|
||||||
# define MB (1024*1024)
|
# define MB (1024*1024)
|
||||||
# define DEFAULT_FB_MB 15
|
# define DEFAULT_FB_MB 15
|
||||||
# define MIN_FB_MB 3
|
# define MIN_FB_MB 3
|
||||||
|
|
||||||
if (GC_disallow_ignore_fb) return FALSE;
|
if (GC_disallow_ignore_fb || tp != MEM_MAPPED) return FALSE;
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
char * ignore_fb_string = GETENV("GC_IGNORE_FB");
|
char * ignore_fb_string = GETENV("GC_IGNORE_FB");
|
||||||
|
|
||||||
|
@ -819,6 +844,9 @@ void GC_register_dynamic_libraries()
|
||||||
}
|
}
|
||||||
# endif /* DEBUG_VIRTUALQUERY */
|
# endif /* DEBUG_VIRTUALQUERY */
|
||||||
|
|
||||||
|
extern GC_bool GC_wnt; /* Is Windows NT derivative. */
|
||||||
|
/* Defined and set in os_dep.c. */
|
||||||
|
|
||||||
void GC_register_dynamic_libraries()
|
void GC_register_dynamic_libraries()
|
||||||
{
|
{
|
||||||
MEMORY_BASIC_INFORMATION buf;
|
MEMORY_BASIC_INFORMATION buf;
|
||||||
|
@ -856,7 +884,16 @@ void GC_register_dynamic_libraries()
|
||||||
&& (protect == PAGE_EXECUTE_READWRITE
|
&& (protect == PAGE_EXECUTE_READWRITE
|
||||||
|| protect == PAGE_READWRITE)
|
|| protect == PAGE_READWRITE)
|
||||||
&& !GC_is_heap_base(buf.AllocationBase)
|
&& !GC_is_heap_base(buf.AllocationBase)
|
||||||
&& !is_frame_buffer(p, buf.RegionSize)) {
|
/* This used to check for
|
||||||
|
* !is_frame_buffer(p, buf.RegionSize, buf.Type)
|
||||||
|
* instead of just checking for MEM_IMAGE.
|
||||||
|
* If something breaks, change it back. */
|
||||||
|
/* There is some evidence that we cannot always
|
||||||
|
* ignore MEM_PRIVATE sections under Windows ME
|
||||||
|
* and predecessors. Hence we now also check for
|
||||||
|
* that case. */
|
||||||
|
&& (buf.Type == MEM_IMAGE ||
|
||||||
|
!GC_wnt && buf.Type == MEM_PRIVATE)) {
|
||||||
# ifdef DEBUG_VIRTUALQUERY
|
# ifdef DEBUG_VIRTUALQUERY
|
||||||
GC_dump_meminfo(&buf);
|
GC_dump_meminfo(&buf);
|
||||||
# endif
|
# endif
|
||||||
|
@ -1112,21 +1149,22 @@ static const char *GC_dyld_name_for_hdr(struct mach_header *hdr) {
|
||||||
static void GC_dyld_image_add(struct mach_header* hdr, unsigned long slide) {
|
static void GC_dyld_image_add(struct mach_header* hdr, unsigned long slide) {
|
||||||
unsigned long start,end,i;
|
unsigned long start,end,i;
|
||||||
const struct section *sec;
|
const struct section *sec;
|
||||||
|
if (GC_no_dls) return;
|
||||||
for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
|
for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
|
||||||
sec = getsectbynamefromheader(
|
sec = getsectbynamefromheader(
|
||||||
hdr,GC_dyld_sections[i].seg,GC_dyld_sections[i].sect);
|
hdr,GC_dyld_sections[i].seg,GC_dyld_sections[i].sect);
|
||||||
if(sec == NULL || sec->size == 0) continue;
|
if(sec == NULL || sec->size == 0) continue;
|
||||||
start = slide + sec->addr;
|
start = slide + sec->addr;
|
||||||
end = start + sec->size;
|
end = start + sec->size;
|
||||||
# ifdef DARWIN_DEBUG
|
|
||||||
GC_printf4("Adding section at %p-%p (%lu bytes) from image %s\n",
|
|
||||||
start,end,sec->size,GC_dyld_name_for_hdr(hdr));
|
|
||||||
# endif
|
|
||||||
GC_add_roots((char*)start,(char*)end);
|
|
||||||
}
|
|
||||||
# ifdef DARWIN_DEBUG
|
# ifdef DARWIN_DEBUG
|
||||||
GC_print_static_roots();
|
GC_printf4("Adding section at %p-%p (%lu bytes) from image %s\n",
|
||||||
# endif
|
start,end,sec->size,GC_dyld_name_for_hdr(hdr));
|
||||||
|
# endif
|
||||||
|
GC_add_roots((char*)start,(char*)end);
|
||||||
|
}
|
||||||
|
# ifdef DARWIN_DEBUG
|
||||||
|
GC_print_static_roots();
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This should never be called by a thread holding the lock */
|
/* This should never be called by a thread holding the lock */
|
||||||
|
@ -1139,15 +1177,15 @@ static void GC_dyld_image_remove(struct mach_header* hdr, unsigned long slide) {
|
||||||
if(sec == NULL || sec->size == 0) continue;
|
if(sec == NULL || sec->size == 0) continue;
|
||||||
start = slide + sec->addr;
|
start = slide + sec->addr;
|
||||||
end = start + sec->size;
|
end = start + sec->size;
|
||||||
# ifdef DARWIN_DEBUG
|
# ifdef DARWIN_DEBUG
|
||||||
GC_printf4("Removing section at %p-%p (%lu bytes) from image %s\n",
|
GC_printf4("Removing section at %p-%p (%lu bytes) from image %s\n",
|
||||||
start,end,sec->size,GC_dyld_name_for_hdr(hdr));
|
start,end,sec->size,GC_dyld_name_for_hdr(hdr));
|
||||||
# endif
|
# endif
|
||||||
GC_remove_roots((char*)start,(char*)end);
|
GC_remove_roots((char*)start,(char*)end);
|
||||||
}
|
}
|
||||||
# ifdef DARWIN_DEBUG
|
# ifdef DARWIN_DEBUG
|
||||||
GC_print_static_roots();
|
GC_print_static_roots();
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void GC_register_dynamic_libraries() {
|
void GC_register_dynamic_libraries() {
|
||||||
|
@ -1166,7 +1204,7 @@ void GC_init_dyld() {
|
||||||
char *bind_fully_env = NULL;
|
char *bind_fully_env = NULL;
|
||||||
|
|
||||||
if(initialized) return;
|
if(initialized) return;
|
||||||
|
|
||||||
/* PLTSCHEME: not if dls are disabled */
|
/* PLTSCHEME: not if dls are disabled */
|
||||||
if (GC_no_dls) {
|
if (GC_no_dls) {
|
||||||
initialized = TRUE;
|
initialized = TRUE;
|
||||||
|
|
|
@ -210,7 +210,7 @@ register struct hblk * h;
|
||||||
result = alloc_hdr();
|
result = alloc_hdr();
|
||||||
SET_HDR(h, result);
|
SET_HDR(h, result);
|
||||||
# ifdef USE_MUNMAP
|
# ifdef USE_MUNMAP
|
||||||
result -> hb_last_reclaimed = GC_gc_no;
|
result -> hb_last_reclaimed = (unsigned short)GC_gc_no;
|
||||||
# endif
|
# endif
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# Makefile.in generated by automake 1.6.3 from Makefile.am.
|
# Makefile.in generated by automake 1.9.3 from Makefile.am.
|
||||||
# @configure_input@
|
# @configure_input@
|
||||||
|
|
||||||
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||||
# Free Software Foundation, Inc.
|
# 2003, 2004 Free Software Foundation, Inc.
|
||||||
# This Makefile.in is free software; the Free Software Foundation
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
# with or without modifications, as long as this notice is preserved.
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
@ -26,96 +26,176 @@
|
||||||
# modified is included with the above copyright notice.
|
# modified is included with the above copyright notice.
|
||||||
#
|
#
|
||||||
# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
|
# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
|
||||||
SHELL = @SHELL@
|
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
prefix = @prefix@
|
|
||||||
exec_prefix = @exec_prefix@
|
|
||||||
|
|
||||||
bindir = @bindir@
|
|
||||||
sbindir = @sbindir@
|
|
||||||
libexecdir = @libexecdir@
|
|
||||||
datadir = @datadir@
|
|
||||||
sysconfdir = @sysconfdir@
|
|
||||||
sharedstatedir = @sharedstatedir@
|
|
||||||
localstatedir = @localstatedir@
|
|
||||||
libdir = @libdir@
|
|
||||||
infodir = @infodir@
|
|
||||||
mandir = @mandir@
|
|
||||||
includedir = @includedir@
|
|
||||||
oldincludedir = /usr/include
|
|
||||||
pkgdatadir = $(datadir)/@PACKAGE@
|
pkgdatadir = $(datadir)/@PACKAGE@
|
||||||
pkglibdir = $(libdir)/@PACKAGE@
|
pkglibdir = $(libdir)/@PACKAGE@
|
||||||
pkgincludedir = $(includedir)/@PACKAGE@
|
pkgincludedir = $(includedir)/@PACKAGE@
|
||||||
top_builddir = ..
|
top_builddir = ..
|
||||||
|
|
||||||
ACLOCAL = @ACLOCAL@
|
|
||||||
AUTOCONF = @AUTOCONF@
|
|
||||||
AUTOMAKE = @AUTOMAKE@
|
|
||||||
AUTOHEADER = @AUTOHEADER@
|
|
||||||
|
|
||||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||||
INSTALL = @INSTALL@
|
INSTALL = @INSTALL@
|
||||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
|
||||||
INSTALL_DATA = @INSTALL_DATA@
|
|
||||||
install_sh_DATA = $(install_sh) -c -m 644
|
install_sh_DATA = $(install_sh) -c -m 644
|
||||||
install_sh_PROGRAM = $(install_sh) -c
|
install_sh_PROGRAM = $(install_sh) -c
|
||||||
install_sh_SCRIPT = $(install_sh) -c
|
install_sh_SCRIPT = $(install_sh) -c
|
||||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
|
||||||
INSTALL_HEADER = $(INSTALL_DATA)
|
INSTALL_HEADER = $(INSTALL_DATA)
|
||||||
transform = @program_transform_name@
|
transform = $(program_transform_name)
|
||||||
NORMAL_INSTALL = :
|
NORMAL_INSTALL = :
|
||||||
PRE_INSTALL = :
|
PRE_INSTALL = :
|
||||||
POST_INSTALL = :
|
POST_INSTALL = :
|
||||||
NORMAL_UNINSTALL = :
|
NORMAL_UNINSTALL = :
|
||||||
PRE_UNINSTALL = :
|
PRE_UNINSTALL = :
|
||||||
POST_UNINSTALL = :
|
POST_UNINSTALL = :
|
||||||
host_alias = @host_alias@
|
build_triplet = @build@
|
||||||
host_triplet = @host@
|
host_triplet = @host@
|
||||||
|
target_triplet = @target@
|
||||||
EXEEXT = @EXEEXT@
|
subdir = include
|
||||||
OBJEXT = @OBJEXT@
|
DIST_COMMON = $(dist_noinst_HEADERS) $(pkginclude_HEADERS) \
|
||||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
$(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||||
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
|
||||||
|
$(top_srcdir)/libtool.m4 $(top_srcdir)/configure.in
|
||||||
|
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
|
$(ACLOCAL_M4)
|
||||||
|
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
|
CONFIG_CLEAN_FILES =
|
||||||
|
SOURCES =
|
||||||
|
DIST_SOURCES =
|
||||||
|
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||||
|
am__vpath_adj = case $$p in \
|
||||||
|
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
|
*) f=$$p;; \
|
||||||
|
esac;
|
||||||
|
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
||||||
|
am__installdirs = "$(DESTDIR)$(pkgincludedir)"
|
||||||
|
pkgincludeHEADERS_INSTALL = $(INSTALL_HEADER)
|
||||||
|
HEADERS = $(dist_noinst_HEADERS) $(pkginclude_HEADERS)
|
||||||
|
ETAGS = etags
|
||||||
|
CTAGS = ctags
|
||||||
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
ACLOCAL = @ACLOCAL@
|
||||||
|
AMDEP_FALSE = @AMDEP_FALSE@
|
||||||
|
AMDEP_TRUE = @AMDEP_TRUE@
|
||||||
AMTAR = @AMTAR@
|
AMTAR = @AMTAR@
|
||||||
AR = @AR@
|
AR = @AR@
|
||||||
AS = @AS@
|
AUTOCONF = @AUTOCONF@
|
||||||
|
AUTOHEADER = @AUTOHEADER@
|
||||||
|
AUTOMAKE = @AUTOMAKE@
|
||||||
AWK = @AWK@
|
AWK = @AWK@
|
||||||
CC = @CC@
|
CC = @CC@
|
||||||
CCAS = @CCAS@
|
CCAS = @CCAS@
|
||||||
CCASFLAGS = @CCASFLAGS@
|
CCASFLAGS = @CCASFLAGS@
|
||||||
|
CCDEPMODE = @CCDEPMODE@
|
||||||
CFLAGS = @CFLAGS@
|
CFLAGS = @CFLAGS@
|
||||||
|
COMPILER_XLC_FALSE = @COMPILER_XLC_FALSE@
|
||||||
|
COMPILER_XLC_TRUE = @COMPILER_XLC_TRUE@
|
||||||
|
CPLUSPLUS_FALSE = @CPLUSPLUS_FALSE@
|
||||||
|
CPLUSPLUS_TRUE = @CPLUSPLUS_TRUE@
|
||||||
|
CPP = @CPP@
|
||||||
|
CPPFLAGS = @CPPFLAGS@
|
||||||
CXX = @CXX@
|
CXX = @CXX@
|
||||||
|
CXXDEPMODE = @CXXDEPMODE@
|
||||||
CXXFLAGS = @CXXFLAGS@
|
CXXFLAGS = @CXXFLAGS@
|
||||||
CXXINCLUDES = @CXXINCLUDES@
|
CXXINCLUDES = @CXXINCLUDES@
|
||||||
|
CYGPATH_W = @CYGPATH_W@
|
||||||
|
DEFS = @DEFS@
|
||||||
DEPDIR = @DEPDIR@
|
DEPDIR = @DEPDIR@
|
||||||
DLLTOOL = @DLLTOOL@
|
|
||||||
ECHO = @ECHO@
|
ECHO = @ECHO@
|
||||||
|
ECHO_C = @ECHO_C@
|
||||||
|
ECHO_N = @ECHO_N@
|
||||||
|
ECHO_T = @ECHO_T@
|
||||||
|
EGREP = @EGREP@
|
||||||
|
EXEEXT = @EXEEXT@
|
||||||
EXTRA_TEST_LIBS = @EXTRA_TEST_LIBS@
|
EXTRA_TEST_LIBS = @EXTRA_TEST_LIBS@
|
||||||
GC_CFLAGS = @GC_CFLAGS@
|
GC_CFLAGS = @GC_CFLAGS@
|
||||||
GC_VERSION = @GC_VERSION@
|
GC_VERSION = @GC_VERSION@
|
||||||
INCLUDES = @INCLUDES@
|
INCLUDES = @INCLUDES@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
LIBOBJS = @LIBOBJS@
|
||||||
|
LIBS = @LIBS@
|
||||||
LIBTOOL = @LIBTOOL@
|
LIBTOOL = @LIBTOOL@
|
||||||
LN_S = @LN_S@
|
LN_S = @LN_S@
|
||||||
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
MAINT = @MAINT@
|
MAINT = @MAINT@
|
||||||
|
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
|
||||||
|
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
|
||||||
|
MAKEINFO = @MAKEINFO@
|
||||||
MY_CFLAGS = @MY_CFLAGS@
|
MY_CFLAGS = @MY_CFLAGS@
|
||||||
OBJDUMP = @OBJDUMP@
|
OBJEXT = @OBJEXT@
|
||||||
PACKAGE = @PACKAGE@
|
PACKAGE = @PACKAGE@
|
||||||
|
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||||
|
PACKAGE_NAME = @PACKAGE_NAME@
|
||||||
|
PACKAGE_STRING = @PACKAGE_STRING@
|
||||||
|
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||||
|
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||||
|
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||||
|
POWERPC_DARWIN_FALSE = @POWERPC_DARWIN_FALSE@
|
||||||
|
POWERPC_DARWIN_TRUE = @POWERPC_DARWIN_TRUE@
|
||||||
RANLIB = @RANLIB@
|
RANLIB = @RANLIB@
|
||||||
|
SET_MAKE = @SET_MAKE@
|
||||||
|
SHELL = @SHELL@
|
||||||
STRIP = @STRIP@
|
STRIP = @STRIP@
|
||||||
THREADLIBS = @THREADLIBS@
|
THREADDLLIBS = @THREADDLLIBS@
|
||||||
UNWINDLIBS = @UNWINDLIBS@
|
UNWINDLIBS = @UNWINDLIBS@
|
||||||
|
USE_LIBDIR_FALSE = @USE_LIBDIR_FALSE@
|
||||||
|
USE_LIBDIR_TRUE = @USE_LIBDIR_TRUE@
|
||||||
VERSION = @VERSION@
|
VERSION = @VERSION@
|
||||||
|
ac_ct_AR = @ac_ct_AR@
|
||||||
|
ac_ct_CC = @ac_ct_CC@
|
||||||
|
ac_ct_CXX = @ac_ct_CXX@
|
||||||
|
ac_ct_RANLIB = @ac_ct_RANLIB@
|
||||||
|
ac_ct_STRIP = @ac_ct_STRIP@
|
||||||
addincludes = @addincludes@
|
addincludes = @addincludes@
|
||||||
addlibs = @addlibs@
|
addlibs = @addlibs@
|
||||||
addobjs = @addobjs@
|
addobjs = @addobjs@
|
||||||
addtests = @addtests@
|
addtests = @addtests@
|
||||||
|
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||||
|
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||||
|
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||||
|
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||||
am__include = @am__include@
|
am__include = @am__include@
|
||||||
|
am__leading_dot = @am__leading_dot@
|
||||||
am__quote = @am__quote@
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
|
bindir = @bindir@
|
||||||
|
build = @build@
|
||||||
|
build_alias = @build_alias@
|
||||||
|
build_cpu = @build_cpu@
|
||||||
|
build_os = @build_os@
|
||||||
|
build_vendor = @build_vendor@
|
||||||
|
datadir = @datadir@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
host = @host@
|
||||||
|
host_alias = @host_alias@
|
||||||
|
host_cpu = @host_cpu@
|
||||||
|
host_os = @host_os@
|
||||||
|
host_vendor = @host_vendor@
|
||||||
|
includedir = @includedir@
|
||||||
|
infodir = @infodir@
|
||||||
install_sh = @install_sh@
|
install_sh = @install_sh@
|
||||||
|
libdir = @libdir@
|
||||||
|
libexecdir = @libexecdir@
|
||||||
|
localstatedir = @localstatedir@
|
||||||
|
mandir = @mandir@
|
||||||
|
mkdir_p = @mkdir_p@
|
||||||
|
oldincludedir = @oldincludedir@
|
||||||
|
prefix = @prefix@
|
||||||
|
program_transform_name = @program_transform_name@
|
||||||
|
sbindir = @sbindir@
|
||||||
|
sharedstatedir = @sharedstatedir@
|
||||||
|
sysconfdir = @sysconfdir@
|
||||||
|
target = @target@
|
||||||
|
target_alias = @target_alias@
|
||||||
target_all = @target_all@
|
target_all = @target_all@
|
||||||
|
target_cpu = @target_cpu@
|
||||||
|
target_os = @target_os@
|
||||||
|
target_vendor = @target_vendor@
|
||||||
|
|
||||||
# installed headers
|
# installed headers
|
||||||
#
|
#
|
||||||
|
@ -139,22 +219,38 @@ dist_noinst_HEADERS = private/gc_hdrs.h \
|
||||||
private/darwin_semaphore.h private/darwin_stop_world.h \
|
private/darwin_semaphore.h private/darwin_stop_world.h \
|
||||||
cord.h ec.h javaxfc.h
|
cord.h ec.h javaxfc.h
|
||||||
|
|
||||||
subdir = include
|
|
||||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
|
||||||
CONFIG_CLEAN_FILES =
|
|
||||||
DIST_SOURCES =
|
|
||||||
HEADERS = $(dist_noinst_HEADERS) $(pkginclude_HEADERS)
|
|
||||||
|
|
||||||
DIST_COMMON = $(dist_noinst_HEADERS) $(pkginclude_HEADERS) Makefile.am \
|
|
||||||
Makefile.in
|
|
||||||
all: all-am
|
all: all-am
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||||
|
@for dep in $?; do \
|
||||||
|
case '$(am__configure_deps)' in \
|
||||||
|
*$$dep*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||||
|
&& exit 0; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \
|
||||||
cd $(top_srcdir) && \
|
cd $(top_srcdir) && \
|
||||||
$(AUTOMAKE) --gnu include/Makefile
|
$(AUTOMAKE) --gnu include/Makefile
|
||||||
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
|
.PRECIOUS: Makefile
|
||||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
|
@case '$?' in \
|
||||||
|
*config.status*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||||
|
*) \
|
||||||
|
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||||
|
esac;
|
||||||
|
|
||||||
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
|
||||||
|
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
|
||||||
mostlyclean-libtool:
|
mostlyclean-libtool:
|
||||||
-rm -f *.lo
|
-rm -f *.lo
|
||||||
|
@ -165,30 +261,24 @@ clean-libtool:
|
||||||
distclean-libtool:
|
distclean-libtool:
|
||||||
-rm -f libtool
|
-rm -f libtool
|
||||||
uninstall-info-am:
|
uninstall-info-am:
|
||||||
pkgincludeHEADERS_INSTALL = $(INSTALL_HEADER)
|
|
||||||
install-pkgincludeHEADERS: $(pkginclude_HEADERS)
|
install-pkgincludeHEADERS: $(pkginclude_HEADERS)
|
||||||
@$(NORMAL_INSTALL)
|
@$(NORMAL_INSTALL)
|
||||||
$(mkinstalldirs) $(DESTDIR)$(pkgincludedir)
|
test -z "$(pkgincludedir)" || $(mkdir_p) "$(DESTDIR)$(pkgincludedir)"
|
||||||
@list='$(pkginclude_HEADERS)'; for p in $$list; do \
|
@list='$(pkginclude_HEADERS)'; for p in $$list; do \
|
||||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " $(pkgincludeHEADERS_INSTALL) $$d$$p $(DESTDIR)$(pkgincludedir)/$$f"; \
|
echo " $(pkgincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgincludedir)/$$f'"; \
|
||||||
$(pkgincludeHEADERS_INSTALL) $$d$$p $(DESTDIR)$(pkgincludedir)/$$f; \
|
$(pkgincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgincludedir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
|
||||||
uninstall-pkgincludeHEADERS:
|
uninstall-pkgincludeHEADERS:
|
||||||
@$(NORMAL_UNINSTALL)
|
@$(NORMAL_UNINSTALL)
|
||||||
@list='$(pkginclude_HEADERS)'; for p in $$list; do \
|
@list='$(pkginclude_HEADERS)'; for p in $$list; do \
|
||||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
f=$(am__strip_dir) \
|
||||||
echo " rm -f $(DESTDIR)$(pkgincludedir)/$$f"; \
|
echo " rm -f '$(DESTDIR)$(pkgincludedir)/$$f'"; \
|
||||||
rm -f $(DESTDIR)$(pkgincludedir)/$$f; \
|
rm -f "$(DESTDIR)$(pkgincludedir)/$$f"; \
|
||||||
done
|
done
|
||||||
|
|
||||||
ETAGS = etags
|
|
||||||
ETAGSFLAGS =
|
|
||||||
|
|
||||||
tags: TAGS
|
|
||||||
|
|
||||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||||
unique=`for i in $$list; do \
|
unique=`for i in $$list; do \
|
||||||
|
@ -197,6 +287,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||||
$(AWK) ' { files[$$0] = 1; } \
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
END { for (i in files) print i; }'`; \
|
END { for (i in files) print i; }'`; \
|
||||||
mkid -fID $$unique
|
mkid -fID $$unique
|
||||||
|
tags: TAGS
|
||||||
|
|
||||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
$(TAGS_FILES) $(LISP)
|
$(TAGS_FILES) $(LISP)
|
||||||
|
@ -208,8 +299,24 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
done | \
|
done | \
|
||||||
$(AWK) ' { files[$$0] = 1; } \
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
END { for (i in files) print i; }'`; \
|
END { for (i in files) print i; }'`; \
|
||||||
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||||
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$tags $$unique; \
|
||||||
|
fi
|
||||||
|
ctags: CTAGS
|
||||||
|
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
|
$(TAGS_FILES) $(LISP)
|
||||||
|
tags=; \
|
||||||
|
here=`pwd`; \
|
||||||
|
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||||
|
unique=`for i in $$list; do \
|
||||||
|
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||||
|
done | \
|
||||||
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
|
END { for (i in files) print i; }'`; \
|
||||||
|
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||||
|
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||||
$$tags $$unique
|
$$tags $$unique
|
||||||
|
|
||||||
GTAGS:
|
GTAGS:
|
||||||
|
@ -218,20 +325,22 @@ GTAGS:
|
||||||
&& gtags -i $(GTAGS_ARGS) $$here
|
&& gtags -i $(GTAGS_ARGS) $$here
|
||||||
|
|
||||||
distclean-tags:
|
distclean-tags:
|
||||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
|
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
|
||||||
|
|
||||||
top_distdir = ..
|
|
||||||
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
|
|
||||||
|
|
||||||
distdir: $(DISTFILES)
|
distdir: $(DISTFILES)
|
||||||
$(mkinstalldirs) $(distdir)/private
|
$(mkdir_p) $(distdir)/private
|
||||||
@list='$(DISTFILES)'; for file in $$list; do \
|
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||||
|
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||||
|
list='$(DISTFILES)'; for file in $$list; do \
|
||||||
|
case $$file in \
|
||||||
|
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
|
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||||
|
esac; \
|
||||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||||
dir="/$$dir"; \
|
dir="/$$dir"; \
|
||||||
$(mkinstalldirs) "$(distdir)$$dir"; \
|
$(mkdir_p) "$(distdir)$$dir"; \
|
||||||
else \
|
else \
|
||||||
dir=''; \
|
dir=''; \
|
||||||
fi; \
|
fi; \
|
||||||
|
@ -249,10 +358,10 @@ distdir: $(DISTFILES)
|
||||||
check-am: all-am
|
check-am: all-am
|
||||||
check: check-am
|
check: check-am
|
||||||
all-am: Makefile $(HEADERS)
|
all-am: Makefile $(HEADERS)
|
||||||
|
|
||||||
installdirs:
|
installdirs:
|
||||||
$(mkinstalldirs) $(DESTDIR)$(pkgincludedir)
|
for dir in "$(DESTDIR)$(pkgincludedir)"; do \
|
||||||
|
test -z "$$dir" || $(mkdir_p) "$$dir"; \
|
||||||
|
done
|
||||||
install: install-am
|
install: install-am
|
||||||
install-exec: install-exec-am
|
install-exec: install-exec-am
|
||||||
install-data: install-data-am
|
install-data: install-data-am
|
||||||
|
@ -264,7 +373,7 @@ install-am: all-am
|
||||||
installcheck: installcheck-am
|
installcheck: installcheck-am
|
||||||
install-strip:
|
install-strip:
|
||||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
INSTALL_STRIP_FLAG=-s \
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
`test -z '$(STRIP)' || \
|
`test -z '$(STRIP)' || \
|
||||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||||
mostlyclean-generic:
|
mostlyclean-generic:
|
||||||
|
@ -272,7 +381,7 @@ mostlyclean-generic:
|
||||||
clean-generic:
|
clean-generic:
|
||||||
|
|
||||||
distclean-generic:
|
distclean-generic:
|
||||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
maintainer-clean-generic:
|
maintainer-clean-generic:
|
||||||
@echo "This command is intended for maintainers to use"
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@ -282,7 +391,7 @@ clean: clean-am
|
||||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||||
|
|
||||||
distclean: distclean-am
|
distclean: distclean-am
|
||||||
|
-rm -f Makefile
|
||||||
distclean-am: clean-am distclean-generic distclean-libtool \
|
distclean-am: clean-am distclean-generic distclean-libtool \
|
||||||
distclean-tags
|
distclean-tags
|
||||||
|
|
||||||
|
@ -290,6 +399,8 @@ dvi: dvi-am
|
||||||
|
|
||||||
dvi-am:
|
dvi-am:
|
||||||
|
|
||||||
|
html: html-am
|
||||||
|
|
||||||
info: info-am
|
info: info-am
|
||||||
|
|
||||||
info-am:
|
info-am:
|
||||||
|
@ -305,25 +416,34 @@ install-man:
|
||||||
installcheck-am:
|
installcheck-am:
|
||||||
|
|
||||||
maintainer-clean: maintainer-clean-am
|
maintainer-clean: maintainer-clean-am
|
||||||
|
-rm -f Makefile
|
||||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||||
|
|
||||||
mostlyclean: mostlyclean-am
|
mostlyclean: mostlyclean-am
|
||||||
|
|
||||||
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||||
|
|
||||||
|
pdf: pdf-am
|
||||||
|
|
||||||
|
pdf-am:
|
||||||
|
|
||||||
|
ps: ps-am
|
||||||
|
|
||||||
|
ps-am:
|
||||||
|
|
||||||
uninstall-am: uninstall-info-am uninstall-pkgincludeHEADERS
|
uninstall-am: uninstall-info-am uninstall-pkgincludeHEADERS
|
||||||
|
|
||||||
.PHONY: GTAGS all all-am check check-am clean clean-generic \
|
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||||
clean-libtool distclean distclean-generic distclean-libtool \
|
clean-libtool ctags distclean distclean-generic \
|
||||||
distclean-tags distdir dvi dvi-am info info-am install \
|
distclean-libtool distclean-tags distdir dvi dvi-am html \
|
||||||
install-am install-data install-data-am install-exec \
|
html-am info info-am install install-am install-data \
|
||||||
install-exec-am install-info install-info-am install-man \
|
install-data-am install-exec install-exec-am install-info \
|
||||||
install-pkgincludeHEADERS install-strip installcheck \
|
install-info-am install-man install-pkgincludeHEADERS \
|
||||||
installcheck-am installdirs maintainer-clean \
|
install-strip installcheck installcheck-am installdirs \
|
||||||
maintainer-clean-generic mostlyclean mostlyclean-generic \
|
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||||
mostlyclean-libtool tags uninstall uninstall-am \
|
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||||
uninstall-info-am uninstall-pkgincludeHEADERS
|
tags uninstall uninstall-am uninstall-info-am \
|
||||||
|
uninstall-pkgincludeHEADERS
|
||||||
|
|
||||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
# include "gc_config_macros.h"
|
# include "gc_config_macros.h"
|
||||||
|
|
||||||
# if defined(__STDC__) || defined(__cplusplus)
|
# if defined(__STDC__) || defined(__cplusplus) || defined(_AIX)
|
||||||
# define GC_PROTO(args) args
|
# define GC_PROTO(args) args
|
||||||
typedef void * GC_PTR;
|
typedef void * GC_PTR;
|
||||||
# define GC_CONST const
|
# define GC_CONST const
|
||||||
|
@ -129,7 +129,7 @@ GC_API int GC_java_finalization;
|
||||||
/* ordered finalization. Default value is */
|
/* ordered finalization. Default value is */
|
||||||
/* determined by JAVA_FINALIZATION macro. */
|
/* determined by JAVA_FINALIZATION macro. */
|
||||||
|
|
||||||
GC_API void (* GC_finalizer_notifier)();
|
GC_API void (* GC_finalizer_notifier) GC_PROTO((void));
|
||||||
/* Invoked by the collector when there are */
|
/* Invoked by the collector when there are */
|
||||||
/* objects to be finalized. Invoked at most */
|
/* objects to be finalized. Invoked at most */
|
||||||
/* once per GC cycle. Never invoked unless */
|
/* once per GC cycle. Never invoked unless */
|
||||||
|
@ -191,7 +191,7 @@ GC_API GC_word GC_free_space_divisor;
|
||||||
/* least N/GC_free_space_divisor bytes between */
|
/* least N/GC_free_space_divisor bytes between */
|
||||||
/* collections, where N is the heap size plus */
|
/* collections, where N is the heap size plus */
|
||||||
/* a rough estimate of the root set size. */
|
/* a rough estimate of the root set size. */
|
||||||
/* Initially, GC_free_space_divisor = 4. */
|
/* Initially, GC_free_space_divisor = 3. */
|
||||||
/* Increasing its value will use less space */
|
/* Increasing its value will use less space */
|
||||||
/* but more collection time. Decreasing it */
|
/* but more collection time. Decreasing it */
|
||||||
/* will appreciably decrease collection time */
|
/* will appreciably decrease collection time */
|
||||||
|
@ -267,6 +267,7 @@ GC_API void GC_init GC_PROTO((void));
|
||||||
*/
|
*/
|
||||||
GC_API GC_PTR GC_malloc GC_PROTO((size_t size_in_bytes));
|
GC_API GC_PTR GC_malloc GC_PROTO((size_t size_in_bytes));
|
||||||
GC_API GC_PTR GC_malloc_atomic GC_PROTO((size_t size_in_bytes));
|
GC_API GC_PTR GC_malloc_atomic GC_PROTO((size_t size_in_bytes));
|
||||||
|
GC_API char *GC_strdup GC_PROTO((const char *str));
|
||||||
GC_API GC_PTR GC_malloc_uncollectable GC_PROTO((size_t size_in_bytes));
|
GC_API GC_PTR GC_malloc_uncollectable GC_PROTO((size_t size_in_bytes));
|
||||||
GC_API GC_PTR GC_malloc_stubborn GC_PROTO((size_t size_in_bytes));
|
GC_API GC_PTR GC_malloc_stubborn GC_PROTO((size_t size_in_bytes));
|
||||||
|
|
||||||
|
@ -308,6 +309,9 @@ GC_API void GC_end_stubborn_change GC_PROTO((GC_PTR));
|
||||||
/* the base of the user object. */
|
/* the base of the user object. */
|
||||||
/* Return 0 if displaced_pointer doesn't point to within a valid */
|
/* Return 0 if displaced_pointer doesn't point to within a valid */
|
||||||
/* object. */
|
/* object. */
|
||||||
|
/* Note that a deallocated object in the garbage collected heap */
|
||||||
|
/* may be considered valid, even if it has been deallocated with */
|
||||||
|
/* GC_free. */
|
||||||
GC_API GC_PTR GC_base GC_PROTO((GC_PTR displaced_pointer));
|
GC_API GC_PTR GC_base GC_PROTO((GC_PTR displaced_pointer));
|
||||||
|
|
||||||
/* Given a pointer to the base of an object, return its size in bytes. */
|
/* Given a pointer to the base of an object, return its size in bytes. */
|
||||||
|
@ -520,6 +524,8 @@ GC_API GC_PTR GC_debug_malloc
|
||||||
GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS));
|
GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS));
|
||||||
GC_API GC_PTR GC_debug_malloc_atomic
|
GC_API GC_PTR GC_debug_malloc_atomic
|
||||||
GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS));
|
GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS));
|
||||||
|
GC_API char *GC_debug_strdup
|
||||||
|
GC_PROTO((const char *str, GC_EXTRA_PARAMS));
|
||||||
GC_API GC_PTR GC_debug_malloc_uncollectable
|
GC_API GC_PTR GC_debug_malloc_uncollectable
|
||||||
GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS));
|
GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS));
|
||||||
GC_API GC_PTR GC_debug_malloc_stubborn
|
GC_API GC_PTR GC_debug_malloc_stubborn
|
||||||
|
@ -554,6 +560,7 @@ GC_API GC_PTR GC_debug_realloc_replacement
|
||||||
# ifdef GC_DEBUG
|
# ifdef GC_DEBUG
|
||||||
# define GC_MALLOC(sz) GC_debug_malloc(sz, GC_EXTRAS)
|
# define GC_MALLOC(sz) GC_debug_malloc(sz, GC_EXTRAS)
|
||||||
# define GC_MALLOC_ATOMIC(sz) GC_debug_malloc_atomic(sz, GC_EXTRAS)
|
# define GC_MALLOC_ATOMIC(sz) GC_debug_malloc_atomic(sz, GC_EXTRAS)
|
||||||
|
# define GC_STRDUP(s) GC_debug_strdup((s), GC_EXTRAS)
|
||||||
# define GC_MALLOC_UNCOLLECTABLE(sz) \
|
# define GC_MALLOC_UNCOLLECTABLE(sz) \
|
||||||
GC_debug_malloc_uncollectable(sz, GC_EXTRAS)
|
GC_debug_malloc_uncollectable(sz, GC_EXTRAS)
|
||||||
# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
|
# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
|
||||||
|
@ -577,6 +584,7 @@ GC_API GC_PTR GC_debug_realloc_replacement
|
||||||
# else
|
# else
|
||||||
# define GC_MALLOC(sz) GC_malloc(sz)
|
# define GC_MALLOC(sz) GC_malloc(sz)
|
||||||
# define GC_MALLOC_ATOMIC(sz) GC_malloc_atomic(sz)
|
# define GC_MALLOC_ATOMIC(sz) GC_malloc_atomic(sz)
|
||||||
|
# define GC_STRDUP(s) GC_strdup(s)
|
||||||
# define GC_MALLOC_UNCOLLECTABLE(sz) GC_malloc_uncollectable(sz)
|
# define GC_MALLOC_UNCOLLECTABLE(sz) GC_malloc_uncollectable(sz)
|
||||||
# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
|
# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
|
||||||
GC_malloc_ignore_off_page(sz)
|
GC_malloc_ignore_off_page(sz)
|
||||||
|
@ -855,7 +863,7 @@ GC_API GC_PTR GC_is_valid_displacement GC_PROTO((GC_PTR p));
|
||||||
|
|
||||||
/* Safer assignment of a pointer to a nonstack location. */
|
/* Safer assignment of a pointer to a nonstack location. */
|
||||||
#ifdef GC_DEBUG
|
#ifdef GC_DEBUG
|
||||||
# ifdef __STDC__
|
# if defined(__STDC__) || defined(_AIX)
|
||||||
# define GC_PTR_STORE(p, q) \
|
# define GC_PTR_STORE(p, q) \
|
||||||
(*(void **)GC_is_visible(p) = GC_is_valid_displacement(q))
|
(*(void **)GC_is_visible(p) = GC_is_valid_displacement(q))
|
||||||
# else
|
# else
|
||||||
|
@ -896,7 +904,7 @@ GC_API void (*GC_is_visible_print_proc)
|
||||||
GC_PTR GC_malloc_many(size_t lb);
|
GC_PTR GC_malloc_many(size_t lb);
|
||||||
#define GC_NEXT(p) (*(GC_PTR *)(p)) /* Retrieve the next element */
|
#define GC_NEXT(p) (*(GC_PTR *)(p)) /* Retrieve the next element */
|
||||||
/* in returned list. */
|
/* in returned list. */
|
||||||
extern void GC_thr_init(); /* Needed for Solaris/X86 */
|
extern void GC_thr_init GC_PROTO((void));/* Needed for Solaris/X86 */
|
||||||
|
|
||||||
#endif /* THREADS && !SRC_M3 */
|
#endif /* THREADS && !SRC_M3 */
|
||||||
|
|
||||||
|
@ -947,17 +955,43 @@ extern void GC_thr_init(); /* Needed for Solaris/X86 */
|
||||||
* from the statically loaded program section.
|
* from the statically loaded program section.
|
||||||
* This circumvents a Solaris 2.X (X<=4) linker bug.
|
* This circumvents a Solaris 2.X (X<=4) linker bug.
|
||||||
*/
|
*/
|
||||||
/* PLTSCHEME: "extern" provided by Matthew.R.Wette@jpl.nasa.gov: */
|
# ifdef __cplusplus
|
||||||
extern void GC_noop(void *p, ...);
|
# define GC_INIT() { extern int _end[], _etext[]; \
|
||||||
# define GC_INIT() { extern end, etext; \
|
extern "C" void GC_noop1(GC_word); \
|
||||||
GC_noop(&end, &etext); }
|
GC_noop1((GC_word)_end); \
|
||||||
|
GC_noop1((GC_word)_etext); }
|
||||||
|
# else
|
||||||
|
# define GC_INIT() { extern int _end[], _etext[]; \
|
||||||
|
extern void GC_noop(); \
|
||||||
|
GC_noop(_end, _etext); }
|
||||||
|
# endif /* !__cplusplus */
|
||||||
#else
|
#else
|
||||||
# if defined(__CYGWIN32__) && defined(GC_DLL) || defined (_AIX)
|
# if defined(__CYGWIN32__) || defined (_AIX)
|
||||||
/*
|
/*
|
||||||
* Similarly gnu-win32 DLLs need explicit initialization from
|
* Similarly gnu-win32 DLLs need explicit initialization from
|
||||||
* the main program, as does AIX.
|
* the main program, as does AIX.
|
||||||
*/
|
*/
|
||||||
# define GC_INIT() { GC_add_roots(DATASTART, DATAEND); }
|
# ifdef __CYGWIN32__
|
||||||
|
extern int _data_start__[];
|
||||||
|
extern int _data_end__[];
|
||||||
|
extern int _bss_start__[];
|
||||||
|
extern int _bss_end__[];
|
||||||
|
# define GC_MAX(x,y) ((x) > (y) ? (x) : (y))
|
||||||
|
# define GC_MIN(x,y) ((x) < (y) ? (x) : (y))
|
||||||
|
# define GC_DATASTART ((GC_PTR) GC_MIN(_data_start__, _bss_start__))
|
||||||
|
# define GC_DATAEND ((GC_PTR) GC_MAX(_data_end__, _bss_end__))
|
||||||
|
# ifdef GC_DLL
|
||||||
|
# define GC_INIT() { GC_add_roots(GC_DATASTART, GC_DATAEND); }
|
||||||
|
# else
|
||||||
|
# define GC_INIT()
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# if defined(_AIX)
|
||||||
|
extern int _data[], _end[];
|
||||||
|
# define GC_DATASTART ((GC_PTR)((ulong)_data))
|
||||||
|
# define GC_DATAEND ((GC_PTR)((ulong)_end))
|
||||||
|
# define GC_INIT() { GC_add_roots(GC_DATASTART, GC_DATAEND); }
|
||||||
|
# endif
|
||||||
# else
|
# else
|
||||||
# if defined(__APPLE__) && defined(__MACH__) || defined(GC_WIN32_THREADS)
|
# if defined(__APPLE__) && defined(__MACH__) || defined(GC_WIN32_THREADS)
|
||||||
# define GC_INIT() { GC_init(); }
|
# define GC_INIT() { GC_init(); }
|
||||||
|
|
|
@ -42,12 +42,17 @@
|
||||||
|| defined(GC_SOLARIS_PTHREADS) \
|
|| defined(GC_SOLARIS_PTHREADS) \
|
||||||
|| defined(GC_HPUX_THREADS) \
|
|| defined(GC_HPUX_THREADS) \
|
||||||
|| defined(GC_AIX_THREADS) \
|
|| defined(GC_AIX_THREADS) \
|
||||||
|| defined(GC_LINUX_THREADS))
|
|| defined(GC_LINUX_THREADS) \
|
||||||
|
|| defined(GC_NETBSD_THREADS))
|
||||||
# define _REENTRANT
|
# define _REENTRANT
|
||||||
/* Better late than never. This fails if system headers that */
|
/* Better late than never. This fails if system headers that */
|
||||||
/* depend on this were previously included. */
|
/* depend on this were previously included. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(_PTHREADS) && defined(GC_NETBSD_THREADS)
|
||||||
|
# define _PTHREADS
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
|
#if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
|
||||||
# define _POSIX4A_DRAFT10_SOURCE 1
|
# define _POSIX4A_DRAFT10_SOURCE 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,7 +61,7 @@
|
||||||
defined(GC_IRIX_THREADS) || defined(GC_LINUX_THREADS) || \
|
defined(GC_IRIX_THREADS) || defined(GC_LINUX_THREADS) || \
|
||||||
defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || \
|
defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || \
|
||||||
defined(GC_DGUX386_THREADS) || defined(GC_DARWIN_THREADS) || \
|
defined(GC_DGUX386_THREADS) || defined(GC_DARWIN_THREADS) || \
|
||||||
defined(GC_AIX_THREADS) || \
|
defined(GC_AIX_THREADS) || defined(GC_NETBSD_THREADS) || \
|
||||||
(defined(GC_WIN32_THREADS) && defined(__CYGWIN32__))
|
(defined(GC_WIN32_THREADS) && defined(__CYGWIN32__))
|
||||||
# define GC_PTHREADS
|
# define GC_PTHREADS
|
||||||
# endif
|
# endif
|
||||||
|
@ -66,7 +71,7 @@
|
||||||
# define GC_LINUX_THREADS
|
# define GC_LINUX_THREADS
|
||||||
# define GC_PTHREADS
|
# define GC_PTHREADS
|
||||||
# endif
|
# endif
|
||||||
# if !defined(LINUX) && (defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
|
# if !defined(__linux__) && (defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
|
||||||
|| defined(hppa) || defined(__HPPA))
|
|| defined(hppa) || defined(__HPPA))
|
||||||
# define GC_HPUX_THREADS
|
# define GC_HPUX_THREADS
|
||||||
# define GC_PTHREADS
|
# define GC_PTHREADS
|
||||||
|
@ -91,10 +96,18 @@
|
||||||
# define GC_FREEBSD_THREADS
|
# define GC_FREEBSD_THREADS
|
||||||
# define GC_PTHREADS
|
# define GC_PTHREADS
|
||||||
# endif
|
# endif
|
||||||
|
# if !defined(GC_PTHREADS) && defined(__NetBSD__)
|
||||||
|
# define GC_NETBSD_THREADS
|
||||||
|
# define GC_PTHREADS
|
||||||
|
# endif
|
||||||
# if defined(DGUX) && (defined(i386) || defined(__i386__))
|
# if defined(DGUX) && (defined(i386) || defined(__i386__))
|
||||||
# define GC_DGUX386_THREADS
|
# define GC_DGUX386_THREADS
|
||||||
# define GC_PTHREADS
|
# define GC_PTHREADS
|
||||||
# endif
|
# endif
|
||||||
|
# if defined(_AIX)
|
||||||
|
# define GC_AIX_THREADS
|
||||||
|
# define GC_PTHREADS
|
||||||
|
# endif
|
||||||
#endif /* GC_THREADS */
|
#endif /* GC_THREADS */
|
||||||
|
|
||||||
#if defined(GC_THREADS) && !defined(GC_PTHREADS) && \
|
#if defined(GC_THREADS) && !defined(GC_PTHREADS) && \
|
||||||
|
|
164
src/mzscheme/gc/include/gc_config_macros.h~
Normal file
164
src/mzscheme/gc/include/gc_config_macros.h~
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* This should never be included directly. It is included only from gc.h.
|
||||||
|
* We separate it only to make gc.h more suitable as documentation.
|
||||||
|
*
|
||||||
|
* Some tests for old macros. These violate our namespace rules and will
|
||||||
|
* disappear shortly. Use the GC_ names.
|
||||||
|
*/
|
||||||
|
#if defined(SOLARIS_THREADS) || defined(_SOLARIS_THREADS)
|
||||||
|
# define GC_SOLARIS_THREADS
|
||||||
|
#endif
|
||||||
|
#if defined(_SOLARIS_PTHREADS)
|
||||||
|
# define GC_SOLARIS_PTHREADS
|
||||||
|
#endif
|
||||||
|
#if defined(IRIX_THREADS)
|
||||||
|
# define GC_IRIX_THREADS
|
||||||
|
#endif
|
||||||
|
#if defined(DGUX_THREADS)
|
||||||
|
# if !defined(GC_DGUX386_THREADS)
|
||||||
|
# define GC_DGUX386_THREADS
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if defined(AIX_THREADS)
|
||||||
|
# define GC_AIX_THREADS
|
||||||
|
#endif
|
||||||
|
#if defined(HPUX_THREADS)
|
||||||
|
# define GC_HPUX_THREADS
|
||||||
|
#endif
|
||||||
|
#if defined(OSF1_THREADS)
|
||||||
|
# define GC_OSF1_THREADS
|
||||||
|
#endif
|
||||||
|
#if defined(LINUX_THREADS)
|
||||||
|
# define GC_LINUX_THREADS
|
||||||
|
#endif
|
||||||
|
#if defined(WIN32_THREADS)
|
||||||
|
# define GC_WIN32_THREADS
|
||||||
|
#endif
|
||||||
|
#if defined(USE_LD_WRAP)
|
||||||
|
# define GC_USE_LD_WRAP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(_REENTRANT) && (defined(GC_SOLARIS_THREADS) \
|
||||||
|
|| defined(GC_SOLARIS_PTHREADS) \
|
||||||
|
|| defined(GC_HPUX_THREADS) \
|
||||||
|
|| defined(GC_AIX_THREADS) \
|
||||||
|
|| defined(GC_LINUX_THREADS) \
|
||||||
|
|| defined(GC_NETBSD_THREADS))
|
||||||
|
# define _REENTRANT
|
||||||
|
/* Better late than never. This fails if system headers that */
|
||||||
|
/* depend on this were previously included. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(_PTHREADS) && defined(GC_NETBSD_THREADS)
|
||||||
|
# define _PTHREADS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
|
||||||
|
# define _POSIX4A_DRAFT10_SOURCE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# if defined(GC_SOLARIS_PTHREADS) || defined(GC_FREEBSD_THREADS) || \
|
||||||
|
defined(GC_IRIX_THREADS) || defined(GC_LINUX_THREADS) || \
|
||||||
|
defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || \
|
||||||
|
defined(GC_DGUX386_THREADS) || defined(GC_DARWIN_THREADS) || \
|
||||||
|
defined(GC_AIX_THREADS) || defined(GC_NETBSD_THREADS) || \
|
||||||
|
(defined(GC_WIN32_THREADS) && defined(__CYGWIN32__))
|
||||||
|
# define GC_PTHREADS
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#if defined(GC_THREADS) && !defined(GC_PTHREADS)
|
||||||
|
# if defined(__linux__)
|
||||||
|
# define GC_LINUX_THREADS
|
||||||
|
# define GC_PTHREADS
|
||||||
|
# endif
|
||||||
|
# if !defined(__linux__) && (defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
|
||||||
|
|| defined(hppa) || defined(__HPPA))
|
||||||
|
# define GC_HPUX_THREADS
|
||||||
|
# define GC_PTHREADS
|
||||||
|
# endif
|
||||||
|
# if !defined(__linux__) && (defined(__alpha) || defined(__alpha__))
|
||||||
|
# define GC_OSF1_THREADS
|
||||||
|
# define GC_PTHREADS
|
||||||
|
# endif
|
||||||
|
# if defined(__mips) && !defined(__linux__)
|
||||||
|
# define GC_IRIX_THREADS
|
||||||
|
# define GC_PTHREADS
|
||||||
|
# endif
|
||||||
|
# if defined(__sparc) && !defined(__linux__)
|
||||||
|
# define GC_SOLARIS_PTHREADS
|
||||||
|
# define GC_PTHREADS
|
||||||
|
# endif
|
||||||
|
# if defined(__APPLE__) && defined(__MACH__) && defined(__ppc__)
|
||||||
|
# define GC_DARWIN_THREADS
|
||||||
|
# define GC_PTHREADS
|
||||||
|
# endif
|
||||||
|
# if !defined(GC_PTHREADS) && defined(__FreeBSD__)
|
||||||
|
# define GC_FREEBSD_THREADS
|
||||||
|
# define GC_PTHREADS
|
||||||
|
# endif
|
||||||
|
# if !defined(GC_PTHREADS) && defined(__NetBSD__)
|
||||||
|
# define GC_NETBSD_THREADS
|
||||||
|
# define GC_PTHREADS
|
||||||
|
# endif
|
||||||
|
# if defined(DGUX) && (defined(i386) || defined(__i386__))
|
||||||
|
# define GC_DGUX386_THREADS
|
||||||
|
# define GC_PTHREADS
|
||||||
|
# endif
|
||||||
|
# if defined(_AIX)
|
||||||
|
# define GC_AIX_THREADS
|
||||||
|
# define GC_PTHREADS
|
||||||
|
# endif
|
||||||
|
#endif /* GC_THREADS */
|
||||||
|
|
||||||
|
#if defined(GC_THREADS) && !defined(GC_PTHREADS) && \
|
||||||
|
(defined(_WIN32) || defined(_MSC_VER) || defined(__CYGWIN__) \
|
||||||
|
|| defined(__MINGW32__) || defined(__BORLANDC__) \
|
||||||
|
|| defined(_WIN32_WCE))
|
||||||
|
# define GC_WIN32_THREADS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GC_SOLARIS_PTHREADS) && !defined(GC_SOLARIS_THREADS)
|
||||||
|
# define GC_SOLARIS_THREADS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# define __GC
|
||||||
|
# ifndef _WIN32_WCE
|
||||||
|
# include <stddef.h>
|
||||||
|
# else /* ! _WIN32_WCE */
|
||||||
|
/* Yet more kluges for WinCE */
|
||||||
|
# include <stdlib.h> /* size_t is defined here */
|
||||||
|
typedef long ptrdiff_t; /* ptrdiff_t is not defined */
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#if defined(_DLL) && !defined(GC_NOT_DLL) && !defined(GC_DLL)
|
||||||
|
# define GC_DLL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__MINGW32__) && defined(GC_DLL)
|
||||||
|
# ifdef GC_BUILD
|
||||||
|
# define GC_API __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
# define GC_API __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__DMC__) || defined(_MSC_VER)) && defined(GC_DLL)
|
||||||
|
# ifdef GC_BUILD
|
||||||
|
# define GC_API extern __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
# define GC_API __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__WATCOMC__) && defined(GC_DLL)
|
||||||
|
# ifdef GC_BUILD
|
||||||
|
# define GC_API extern __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
# define GC_API extern __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GC_API
|
||||||
|
#define GC_API extern
|
||||||
|
#endif
|
||||||
|
|
|
@ -74,7 +74,7 @@ cycle, then that's considered a storage leak, and neither will be
|
||||||
collectable. See the interface gc.h for low-level facilities for
|
collectable. See the interface gc.h for low-level facilities for
|
||||||
handling such cycles of objects with clean-up.
|
handling such cycles of objects with clean-up.
|
||||||
|
|
||||||
The collector cannot guarrantee that it will find all inaccessible
|
The collector cannot guarantee that it will find all inaccessible
|
||||||
objects. In practice, it finds almost all of them.
|
objects. In practice, it finds almost all of them.
|
||||||
|
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ class gc {public:
|
||||||
inline void* operator new[]( size_t size, void *p );
|
inline void* operator new[]( size_t size, void *p );
|
||||||
inline void operator delete[]( void* obj );
|
inline void operator delete[]( void* obj );
|
||||||
# ifdef GC_PLACEMENT_DELETE
|
# ifdef GC_PLACEMENT_DELETE
|
||||||
inline void gc::operator delete[]( void*, void* );
|
inline void operator delete[]( void*, void* );
|
||||||
# endif
|
# endif
|
||||||
#endif /* GC_OPERATOR_NEW_ARRAY */
|
#endif /* GC_OPERATOR_NEW_ARRAY */
|
||||||
};
|
};
|
||||||
|
|
|
@ -73,6 +73,9 @@
|
||||||
# define pthread_detach GC_pthread_detach
|
# define pthread_detach GC_pthread_detach
|
||||||
|
|
||||||
#ifndef GC_DARWIN_THREADS
|
#ifndef GC_DARWIN_THREADS
|
||||||
|
# ifdef pthread_sigmask
|
||||||
|
# undef pthread_sigmask
|
||||||
|
# endif /* pthread_sigmask */
|
||||||
# define pthread_sigmask GC_pthread_sigmask
|
# define pthread_sigmask GC_pthread_sigmask
|
||||||
# define dlopen GC_dlopen
|
# define dlopen GC_dlopen
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,4 +4,6 @@
|
||||||
#define calloc(m,n) GC_MALLOC((m)*(n))
|
#define calloc(m,n) GC_MALLOC((m)*(n))
|
||||||
#define free(p) GC_FREE(p)
|
#define free(p) GC_FREE(p)
|
||||||
#define realloc(p,n) GC_REALLOC((p),(n))
|
#define realloc(p,n) GC_REALLOC((p),(n))
|
||||||
|
#undef strdup
|
||||||
|
#define strdup(s) GC_STRDUP((s))
|
||||||
#define CHECK_LEAKS() GC_gcollect()
|
#define CHECK_LEAKS() GC_gcollect()
|
||||||
|
|
|
@ -109,7 +109,7 @@ enum { GC_byte_alignment = 8 };
|
||||||
enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word };
|
enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word };
|
||||||
|
|
||||||
inline void * &GC_obj_link(void * p)
|
inline void * &GC_obj_link(void * p)
|
||||||
{ return *(void **)p; }
|
{ return *reinterpret_cast<void **>(p); }
|
||||||
|
|
||||||
// Compute a number of words >= n+1 bytes.
|
// Compute a number of words >= n+1 bytes.
|
||||||
// The +1 allows for pointers one past the end.
|
// The +1 allows for pointers one past the end.
|
||||||
|
@ -228,7 +228,7 @@ class single_client_gc_alloc_template {
|
||||||
} else {
|
} else {
|
||||||
flh = GC_objfreelist_ptr + nwords;
|
flh = GC_objfreelist_ptr + nwords;
|
||||||
GC_obj_link(p) = *flh;
|
GC_obj_link(p) = *flh;
|
||||||
memset((char *)p + GC_bytes_per_word, 0,
|
memset(reinterpret_cast<char *>(p) + GC_bytes_per_word, 0,
|
||||||
GC_bytes_per_word * (nwords - 1));
|
GC_bytes_per_word * (nwords - 1));
|
||||||
*flh = p;
|
*flh = p;
|
||||||
GC_aux::GC_mem_recently_freed += nwords;
|
GC_aux::GC_mem_recently_freed += nwords;
|
||||||
|
@ -352,9 +352,9 @@ class simple_alloc<T, alloc> { \
|
||||||
public: \
|
public: \
|
||||||
static T *allocate(size_t n) \
|
static T *allocate(size_t n) \
|
||||||
{ return 0 == n? 0 : \
|
{ return 0 == n? 0 : \
|
||||||
(T*) alloc::ptr_free_allocate(n * sizeof (T)); } \
|
reinterpret_cast<T*>(alloc::ptr_free_allocate(n * sizeof (T))); } \
|
||||||
static T *allocate(void) \
|
static T *allocate(void) \
|
||||||
{ return (T*) alloc::ptr_free_allocate(sizeof (T)); } \
|
{ return reinterpret_cast<T*>(alloc::ptr_free_allocate(sizeof (T))); } \
|
||||||
static void deallocate(T *p, size_t n) \
|
static void deallocate(T *p, size_t n) \
|
||||||
{ if (0 != n) alloc::ptr_free_deallocate(p, n * sizeof (T)); } \
|
{ if (0 != n) alloc::ptr_free_deallocate(p, n * sizeof (T)); } \
|
||||||
static void deallocate(T *p) \
|
static void deallocate(T *p) \
|
||||||
|
|
|
@ -108,7 +108,7 @@ extern hdr * GC_invalid_header; /* header for an imaginary block */
|
||||||
|
|
||||||
/* Analogous to GET_HDR, except that in the case of large objects, it */
|
/* Analogous to GET_HDR, except that in the case of large objects, it */
|
||||||
/* Returns the header for the object beginning, and updates p. */
|
/* Returns the header for the object beginning, and updates p. */
|
||||||
/* Returns &GC_bad_header instead of 0. All of this saves a branch */
|
/* Returns GC_invalid_header instead of 0. All of this saves a branch */
|
||||||
/* in the fast path. */
|
/* in the fast path. */
|
||||||
# define HC_GET_HDR(p, hhdr, source) \
|
# define HC_GET_HDR(p, hhdr, source) \
|
||||||
{ \
|
{ \
|
||||||
|
|
|
@ -172,12 +172,12 @@
|
||||||
: "cr0","memory");
|
: "cr0","memory");
|
||||||
return oldval;
|
return oldval;
|
||||||
}
|
}
|
||||||
# define GC_TEST_AND_SET_DEFINED
|
# define GC_TEST_AND_SET_DEFINED
|
||||||
inline static void GC_clear(volatile unsigned int *addr) {
|
inline static void GC_clear(volatile unsigned int *addr) {
|
||||||
__asm__ __volatile__("eieio" : : : "memory");
|
__asm__ __volatile__("lwsync" : : : "memory");
|
||||||
*(addr) = 0;
|
*(addr) = 0;
|
||||||
}
|
}
|
||||||
# define GC_CLEAR_DEFINED
|
# define GC_CLEAR_DEFINED
|
||||||
# endif
|
# endif
|
||||||
# if defined(ALPHA)
|
# if defined(ALPHA)
|
||||||
inline static int GC_test_and_set(volatile unsigned int * addr)
|
inline static int GC_test_and_set(volatile unsigned int * addr)
|
||||||
|
@ -219,18 +219,45 @@
|
||||||
# ifdef ARM32
|
# ifdef ARM32
|
||||||
inline static int GC_test_and_set(volatile unsigned int *addr) {
|
inline static int GC_test_and_set(volatile unsigned int *addr) {
|
||||||
int oldval;
|
int oldval;
|
||||||
/* SWP on ARM is very similar to XCHG on x86. Doesn't lock the
|
/* SWP on ARM is very similar to XCHG on x86. */
|
||||||
* bus because there are no SMP ARM machines. If/when there are,
|
/* The first operand is the result, the second the value */
|
||||||
* this code will likely need to be updated. */
|
/* to be stored. Both registers must be different from addr. */
|
||||||
/* See linuxthreads/sysdeps/arm/pt-machine.h in glibc-2.1 */
|
/* Make the address operand an early clobber output so it */
|
||||||
__asm__ __volatile__("swp %0, %1, [%2]"
|
/* doesn't overlap with the other operands. The early clobber*/
|
||||||
: "=r"(oldval)
|
/* on oldval is neccessary to prevent the compiler allocating */
|
||||||
: "r"(1), "r"(addr)
|
/* them to the same register if they are both unused. */
|
||||||
: "memory");
|
__asm__ __volatile__("swp %0, %2, [%3]"
|
||||||
|
: "=&r"(oldval), "=&r"(addr)
|
||||||
|
: "r"(1), "1"(addr)
|
||||||
|
: "memory");
|
||||||
return oldval;
|
return oldval;
|
||||||
}
|
}
|
||||||
# define GC_TEST_AND_SET_DEFINED
|
# define GC_TEST_AND_SET_DEFINED
|
||||||
# endif /* ARM32 */
|
# endif /* ARM32 */
|
||||||
|
# ifdef CRIS
|
||||||
|
inline static int GC_test_and_set(volatile unsigned int *addr) {
|
||||||
|
/* Ripped from linuxthreads/sysdeps/cris/pt-machine.h. */
|
||||||
|
/* Included with Hans-Peter Nilsson's permission. */
|
||||||
|
register unsigned long int ret;
|
||||||
|
|
||||||
|
/* Note the use of a dummy output of *addr to expose the write.
|
||||||
|
* The memory barrier is to stop *other* writes being moved past
|
||||||
|
* this code.
|
||||||
|
*/
|
||||||
|
__asm__ __volatile__("clearf\n"
|
||||||
|
"0:\n\t"
|
||||||
|
"movu.b [%2],%0\n\t"
|
||||||
|
"ax\n\t"
|
||||||
|
"move.b %3,[%2]\n\t"
|
||||||
|
"bwf 0b\n\t"
|
||||||
|
"clearf"
|
||||||
|
: "=&r" (ret), "=m" (*addr)
|
||||||
|
: "r" (addr), "r" ((int) 1), "m" (*addr)
|
||||||
|
: "memory");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
# define GC_TEST_AND_SET_DEFINED
|
||||||
|
# endif /* CRIS */
|
||||||
# ifdef S390
|
# ifdef S390
|
||||||
inline static int GC_test_and_set(volatile unsigned int *addr) {
|
inline static int GC_test_and_set(volatile unsigned int *addr) {
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -274,6 +301,8 @@
|
||||||
# define GC_test_and_set(addr) test_and_set((void *)addr,1)
|
# define GC_test_and_set(addr) test_and_set((void *)addr,1)
|
||||||
# endif
|
# endif
|
||||||
# else
|
# else
|
||||||
|
# include <sgidefs.h>
|
||||||
|
# include <mutex.h>
|
||||||
# define GC_test_and_set(addr) __test_and_set32((void *)addr,1)
|
# define GC_test_and_set(addr) __test_and_set32((void *)addr,1)
|
||||||
# define GC_clear(addr) __lock_release(addr);
|
# define GC_clear(addr) __lock_release(addr);
|
||||||
# define GC_CLEAR_DEFINED
|
# define GC_CLEAR_DEFINED
|
||||||
|
@ -346,7 +375,7 @@
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
|
# if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
|
||||||
&& !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS)
|
&& !defined(GC_WIN32_THREADS)
|
||||||
# define NO_THREAD (pthread_t)(-1)
|
# define NO_THREAD (pthread_t)(-1)
|
||||||
# include <pthread.h>
|
# include <pthread.h>
|
||||||
# if defined(PARALLEL_MARK)
|
# if defined(PARALLEL_MARK)
|
||||||
|
@ -393,6 +422,29 @@
|
||||||
|
|
||||||
# if defined(POWERPC)
|
# if defined(POWERPC)
|
||||||
# if !defined(GENERIC_COMPARE_AND_SWAP)
|
# if !defined(GENERIC_COMPARE_AND_SWAP)
|
||||||
|
# if CPP_WORDSZ == 64
|
||||||
|
/* Returns TRUE if the comparison succeeded. */
|
||||||
|
inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,
|
||||||
|
GC_word old, GC_word new_val)
|
||||||
|
{
|
||||||
|
unsigned long result, dummy;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"1:\tldarx %0,0,%5\n"
|
||||||
|
"\tcmpd %0,%4\n"
|
||||||
|
"\tbne 2f\n"
|
||||||
|
"\tstdcx. %3,0,%2\n"
|
||||||
|
"\tbne- 1b\n"
|
||||||
|
"\tsync\n"
|
||||||
|
"\tli %1, 1\n"
|
||||||
|
"\tb 3f\n"
|
||||||
|
"2:\tli %1, 0\n"
|
||||||
|
"3:\t\n"
|
||||||
|
: "=&r" (dummy), "=r" (result), "=p" (addr)
|
||||||
|
: "r" (new_val), "r" (old), "2"(addr)
|
||||||
|
: "cr0","memory");
|
||||||
|
return (GC_bool) result;
|
||||||
|
}
|
||||||
|
# else
|
||||||
/* Returns TRUE if the comparison succeeded. */
|
/* Returns TRUE if the comparison succeeded. */
|
||||||
inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,
|
inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,
|
||||||
GC_word old, GC_word new_val)
|
GC_word old, GC_word new_val)
|
||||||
|
@ -414,6 +466,7 @@
|
||||||
: "cr0","memory");
|
: "cr0","memory");
|
||||||
return (GC_bool) result;
|
return (GC_bool) result;
|
||||||
}
|
}
|
||||||
|
# endif
|
||||||
# endif /* !GENERIC_COMPARE_AND_SWAP */
|
# endif /* !GENERIC_COMPARE_AND_SWAP */
|
||||||
inline static void GC_memory_barrier()
|
inline static void GC_memory_barrier()
|
||||||
{
|
{
|
||||||
|
@ -427,9 +480,18 @@
|
||||||
GC_word old, GC_word new_val)
|
GC_word old, GC_word new_val)
|
||||||
{
|
{
|
||||||
unsigned long oldval;
|
unsigned long oldval;
|
||||||
__asm__ __volatile__("mov ar.ccv=%4 ;; cmpxchg8.rel %0=%1,%2,ar.ccv"
|
# if CPP_WORDSZ == 32
|
||||||
: "=r"(oldval), "=m"(*addr)
|
__asm__ __volatile__(
|
||||||
: "r"(new_val), "1"(*addr), "r"(old) : "memory");
|
"addp4 %0=0,%1\n"
|
||||||
|
"mov ar.ccv=%3 ;; cmpxchg4.rel %0=[%0],%2,ar.ccv"
|
||||||
|
: "=&r"(oldval)
|
||||||
|
: "r"(addr), "r"(new_val), "r"(old) : "memory");
|
||||||
|
# else
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"mov ar.ccv=%3 ;; cmpxchg8.rel %0=[%1],%2,ar.ccv"
|
||||||
|
: "=r"(oldval)
|
||||||
|
: "r"(addr), "r"(new_val), "r"(old) : "memory");
|
||||||
|
# endif
|
||||||
return (oldval == old);
|
return (oldval == old);
|
||||||
}
|
}
|
||||||
# endif /* !GENERIC_COMPARE_AND_SWAP */
|
# endif /* !GENERIC_COMPARE_AND_SWAP */
|
||||||
|
@ -593,33 +655,6 @@
|
||||||
extern pthread_t GC_mark_lock_holder;
|
extern pthread_t GC_mark_lock_holder;
|
||||||
# endif
|
# endif
|
||||||
# endif /* GC_PTHREADS with linux_threads.c implementation */
|
# endif /* GC_PTHREADS with linux_threads.c implementation */
|
||||||
# if defined(GC_IRIX_THREADS)
|
|
||||||
# include <pthread.h>
|
|
||||||
/* This probably should never be included, but I can't test */
|
|
||||||
/* on Irix anymore. */
|
|
||||||
# include <mutex.h>
|
|
||||||
|
|
||||||
extern volatile unsigned int GC_allocate_lock;
|
|
||||||
/* This is not a mutex because mutexes that obey the (optional) */
|
|
||||||
/* POSIX scheduling rules are subject to convoys in high contention */
|
|
||||||
/* applications. This is basically a spin lock. */
|
|
||||||
extern pthread_t GC_lock_holder;
|
|
||||||
extern void GC_lock(void);
|
|
||||||
/* Allocation lock holder. Only set if acquired by client through */
|
|
||||||
/* GC_call_with_alloc_lock. */
|
|
||||||
# define SET_LOCK_HOLDER() GC_lock_holder = pthread_self()
|
|
||||||
# define NO_THREAD (pthread_t)(-1)
|
|
||||||
# define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD
|
|
||||||
# define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self()))
|
|
||||||
# define LOCK() { if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); }
|
|
||||||
# define UNLOCK() GC_clear(&GC_allocate_lock);
|
|
||||||
extern VOLATILE GC_bool GC_collecting;
|
|
||||||
# define ENTER_GC() \
|
|
||||||
{ \
|
|
||||||
GC_collecting = 1; \
|
|
||||||
}
|
|
||||||
# define EXIT_GC() GC_collecting = 0;
|
|
||||||
# endif /* GC_IRIX_THREADS */
|
|
||||||
# if defined(GC_WIN32_THREADS)
|
# if defined(GC_WIN32_THREADS)
|
||||||
# if defined(GC_PTHREADS)
|
# if defined(GC_PTHREADS)
|
||||||
# include <pthread.h>
|
# include <pthread.h>
|
||||||
|
|
|
@ -248,7 +248,8 @@ exit_label: ; \
|
||||||
if (map_entry == OFFSET_TOO_BIG) { \
|
if (map_entry == OFFSET_TOO_BIG) { \
|
||||||
map_entry = displ % (hhdr -> hb_sz); \
|
map_entry = displ % (hhdr -> hb_sz); \
|
||||||
displ -= map_entry; \
|
displ -= map_entry; \
|
||||||
if (displ + (hhdr -> hb_sz) > BYTES_TO_WORDS(HBLKSIZE)) { \
|
if (displ + (hhdr -> hb_sz) > BYTES_TO_WORDS(HBLKSIZE) \
|
||||||
|
&& displ != 0) { \
|
||||||
GC_ADD_TO_BLACK_LIST_NORMAL((word)current, source); \
|
GC_ADD_TO_BLACK_LIST_NORMAL((word)current, source); \
|
||||||
goto exit_label; \
|
goto exit_label; \
|
||||||
} \
|
} \
|
||||||
|
|
|
@ -107,8 +107,7 @@ typedef char * ptr_t; /* A generic pointer to which we can add */
|
||||||
# define MAKE_HOTTER(x,y) (x) += (y)
|
# define MAKE_HOTTER(x,y) (x) += (y)
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
/* PLTSCHEME: Always put GC_FAR as far data for Mac 68k */
|
#if defined(AMIGA) && defined(__SASC)
|
||||||
#if defined(__MC68K__) || (defined(AMIGA) && defined(__SASC))
|
|
||||||
# define GC_FAR __far
|
# define GC_FAR __far
|
||||||
#else
|
#else
|
||||||
# define GC_FAR
|
# define GC_FAR
|
||||||
|
@ -259,17 +258,6 @@ typedef char * ptr_t; /* A generic pointer to which we can add */
|
||||||
/* */
|
/* */
|
||||||
/*********************************/
|
/*********************************/
|
||||||
|
|
||||||
#ifdef SAVE_CALL_CHAIN
|
|
||||||
|
|
||||||
/* Fill in the pc and argument information for up to NFRAMES of my */
|
|
||||||
/* callers. Ignore my frame and my callers frame. */
|
|
||||||
struct callinfo;
|
|
||||||
void GC_save_callers GC_PROTO((struct callinfo info[NFRAMES]));
|
|
||||||
|
|
||||||
void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES]));
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef NEED_CALLINFO
|
#ifdef NEED_CALLINFO
|
||||||
struct callinfo {
|
struct callinfo {
|
||||||
word ci_pc; /* Caller, not callee, pc */
|
word ci_pc; /* Caller, not callee, pc */
|
||||||
|
@ -283,6 +271,16 @@ void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES]));
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SAVE_CALL_CHAIN
|
||||||
|
|
||||||
|
/* Fill in the pc and argument information for up to NFRAMES of my */
|
||||||
|
/* callers. Ignore my frame and my callers frame. */
|
||||||
|
void GC_save_callers GC_PROTO((struct callinfo info[NFRAMES]));
|
||||||
|
|
||||||
|
void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES]));
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*********************************/
|
/*********************************/
|
||||||
/* */
|
/* */
|
||||||
|
@ -757,17 +755,9 @@ struct hblk {
|
||||||
# ifdef LARGE_CONFIG
|
# ifdef LARGE_CONFIG
|
||||||
# define MAX_ROOT_SETS 4096
|
# define MAX_ROOT_SETS 4096
|
||||||
# else
|
# else
|
||||||
# ifdef PCR
|
/* GCJ LOCAL: MAX_ROOT_SETS increased to permit more shared */
|
||||||
# define MAX_ROOT_SETS 1024
|
/* libraries to be loaded. */
|
||||||
# else
|
# define MAX_ROOT_SETS 1024
|
||||||
# if defined(MSWIN32) || defined(MSWINCE)
|
|
||||||
# define MAX_ROOT_SETS 1024
|
|
||||||
/* Under NT, we add only written pages, which can result */
|
|
||||||
/* in many small root sets. */
|
|
||||||
# else
|
|
||||||
# define MAX_ROOT_SETS 256
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# define MAX_EXCLUSIONS (MAX_ROOT_SETS/4)
|
# define MAX_EXCLUSIONS (MAX_ROOT_SETS/4)
|
||||||
|
@ -1637,6 +1627,10 @@ ptr_t GC_generic_malloc_ignore_off_page GC_PROTO((size_t b, int k));
|
||||||
/* are ignored. */
|
/* are ignored. */
|
||||||
ptr_t GC_generic_malloc_inner GC_PROTO((word lb, int k));
|
ptr_t GC_generic_malloc_inner GC_PROTO((word lb, int k));
|
||||||
/* Ditto, but I already hold lock, etc. */
|
/* Ditto, but I already hold lock, etc. */
|
||||||
|
ptr_t GC_generic_malloc_words_small_inner GC_PROTO((word lw, int k));
|
||||||
|
/* Analogous to the above, but assumes */
|
||||||
|
/* a small object size, and bypasses */
|
||||||
|
/* MERGE_SIZES mechanism. */
|
||||||
ptr_t GC_generic_malloc_words_small GC_PROTO((size_t lw, int k));
|
ptr_t GC_generic_malloc_words_small GC_PROTO((size_t lw, int k));
|
||||||
/* As above, but size in units of words */
|
/* As above, but size in units of words */
|
||||||
/* Bypasses MERGE_SIZES. Assumes */
|
/* Bypasses MERGE_SIZES. Assumes */
|
||||||
|
@ -1722,7 +1716,7 @@ extern GC_bool GC_print_stats; /* Produce at least some logging output */
|
||||||
/* Set from environment variable. */
|
/* Set from environment variable. */
|
||||||
|
|
||||||
#ifndef NO_DEBUGGING
|
#ifndef NO_DEBUGGING
|
||||||
extern GC_bool GC_dump_regularly; /* Generate regular debugging dumps. */
|
extern GC_bool GC_dump_regularly; /* Generate regular debugging dumps. */
|
||||||
# define COND_DUMP if (GC_dump_regularly) GC_dump();
|
# define COND_DUMP if (GC_dump_regularly) GC_dump();
|
||||||
#else
|
#else
|
||||||
# define COND_DUMP
|
# define COND_DUMP
|
||||||
|
@ -1730,6 +1724,13 @@ extern GC_bool GC_dump_regularly; /* Generate regular debugging dumps. */
|
||||||
|
|
||||||
#ifdef KEEP_BACK_PTRS
|
#ifdef KEEP_BACK_PTRS
|
||||||
extern long GC_backtraces;
|
extern long GC_backtraces;
|
||||||
|
void GC_generate_random_backtrace_no_gc(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern GC_bool GC_print_back_height;
|
||||||
|
|
||||||
|
#ifdef MAKE_BACK_GRAPH
|
||||||
|
void GC_print_back_graph_stats(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Macros used for collector internal allocation. */
|
/* Macros used for collector internal allocation. */
|
||||||
|
@ -1817,6 +1818,17 @@ GC_API void GC_dump GC_PROTO((void));
|
||||||
# define GC_MARKED_FOR_FINALIZATION(dest)
|
# define GC_MARKED_FOR_FINALIZATION(dest)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Make arguments appear live to compiler */
|
||||||
|
# ifdef __WATCOMC__
|
||||||
|
void GC_noop(void*, ...);
|
||||||
|
# else
|
||||||
|
# ifdef __DMC__
|
||||||
|
GC_API void GC_noop(...);
|
||||||
|
# else
|
||||||
|
GC_API void GC_noop();
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
void GC_noop1 GC_PROTO((word));
|
void GC_noop1 GC_PROTO((word));
|
||||||
|
|
||||||
/* Logging and diagnostic output: */
|
/* Logging and diagnostic output: */
|
||||||
|
|
1960
src/mzscheme/gc/include/private/gc_priv.h~
Normal file
1960
src/mzscheme/gc/include/private/gc_priv.h~
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -55,7 +55,7 @@
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
/* And one for FreeBSD: */
|
/* And one for FreeBSD: */
|
||||||
# if defined(__FreeBSD__)
|
# if defined(__FreeBSD__) && !defined(FREEBSD)
|
||||||
# define FREEBSD
|
# define FREEBSD
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
@ -97,6 +97,10 @@
|
||||||
# define ARM32
|
# define ARM32
|
||||||
# define mach_type_known
|
# define mach_type_known
|
||||||
# endif
|
# endif
|
||||||
|
# if defined(NETBSD) && defined(__sh__)
|
||||||
|
# define SH
|
||||||
|
# define mach_type_known
|
||||||
|
# endif
|
||||||
# if defined(vax)
|
# if defined(vax)
|
||||||
# define VAX
|
# define VAX
|
||||||
# ifdef ultrix
|
# ifdef ultrix
|
||||||
|
@ -115,8 +119,8 @@
|
||||||
# if defined(nec_ews) || defined(_nec_ews)
|
# if defined(nec_ews) || defined(_nec_ews)
|
||||||
# define EWS4800
|
# define EWS4800
|
||||||
# endif
|
# endif
|
||||||
# if !defined(LINUX) && !defined(EWS4800)
|
# if !defined(LINUX) && !defined(EWS4800) && !defined(NETBSD)
|
||||||
# if defined(ultrix) || defined(__ultrix) || defined(__NetBSD__)
|
# if defined(ultrix) || defined(__ultrix)
|
||||||
# define ULTRIX
|
# define ULTRIX
|
||||||
# else
|
# else
|
||||||
# if defined(_SYSTYPE_SVR4) || defined(SYSTYPE_SVR4) \
|
# if defined(_SYSTYPE_SVR4) || defined(SYSTYPE_SVR4) \
|
||||||
|
@ -170,7 +174,7 @@
|
||||||
# define mach_type_known
|
# define mach_type_known
|
||||||
# endif
|
# endif
|
||||||
# if defined(sparc) && defined(unix) && !defined(sun) && !defined(linux) \
|
# if defined(sparc) && defined(unix) && !defined(sun) && !defined(linux) \
|
||||||
&& !defined(__OpenBSD__) && !(__NetBSD__)
|
&& !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__FreeBSD__)
|
||||||
# define SPARC
|
# define SPARC
|
||||||
# define DRSNX
|
# define DRSNX
|
||||||
# define mach_type_known
|
# define mach_type_known
|
||||||
|
@ -201,14 +205,16 @@
|
||||||
# if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
|
# if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
|
||||||
|| defined(hppa) || defined(__hppa__)
|
|| defined(hppa) || defined(__hppa__)
|
||||||
# define HP_PA
|
# define HP_PA
|
||||||
# ifndef LINUX
|
# if !defined(LINUX) && !defined(HPUX)
|
||||||
# define HPUX
|
# define HPUX
|
||||||
# endif
|
# endif
|
||||||
# define mach_type_known
|
# define mach_type_known
|
||||||
# endif
|
# endif
|
||||||
# if defined(__ia64) && defined(_HPUX_SOURCE)
|
# if defined(__ia64) && defined(_HPUX_SOURCE)
|
||||||
# define IA64
|
# define IA64
|
||||||
# define HPUX
|
# ifndef HPUX
|
||||||
|
# define HPUX
|
||||||
|
# endif
|
||||||
# define mach_type_known
|
# define mach_type_known
|
||||||
# endif
|
# endif
|
||||||
# if defined(__BEOS__) && defined(_X86_)
|
# if defined(__BEOS__) && defined(_X86_)
|
||||||
|
@ -232,7 +238,18 @@
|
||||||
# define ARM32
|
# define ARM32
|
||||||
# define mach_type_known
|
# define mach_type_known
|
||||||
# endif
|
# endif
|
||||||
# if defined(LINUX) && (defined(powerpc) || defined(__powerpc__) || defined(powerpc64) || defined(__powerpc64__))
|
# if defined(LINUX) && defined(__cris__)
|
||||||
|
# ifndef CRIS
|
||||||
|
# define CRIS
|
||||||
|
# endif
|
||||||
|
# define mach_type_known
|
||||||
|
# endif
|
||||||
|
# if defined(LINUX) && (defined(powerpc) || defined(__powerpc__) || \
|
||||||
|
defined(powerpc64) || defined(__powerpc64__))
|
||||||
|
# define POWERPC
|
||||||
|
# define mach_type_known
|
||||||
|
# endif
|
||||||
|
# if defined(FREEBSD) && (defined(powerpc) || defined(__powerpc__))
|
||||||
# define POWERPC
|
# define POWERPC
|
||||||
# define mach_type_known
|
# define mach_type_known
|
||||||
# endif
|
# endif
|
||||||
|
@ -252,6 +269,10 @@
|
||||||
# define SH
|
# define SH
|
||||||
# define mach_type_known
|
# define mach_type_known
|
||||||
# endif
|
# endif
|
||||||
|
# if defined(LINUX) && defined(__m32r__)
|
||||||
|
# define M32R
|
||||||
|
# define mach_type_known
|
||||||
|
# endif
|
||||||
# if defined(__alpha) || defined(__alpha__)
|
# if defined(__alpha) || defined(__alpha__)
|
||||||
# define ALPHA
|
# define ALPHA
|
||||||
# if !defined(LINUX) && !defined(NETBSD) && !defined(OPENBSD) && !defined(FREEBSD)
|
# if !defined(LINUX) && !defined(NETBSD) && !defined(OPENBSD) && !defined(FREEBSD)
|
||||||
|
@ -271,23 +292,21 @@
|
||||||
# define MACOS
|
# define MACOS
|
||||||
# define mach_type_known
|
# define mach_type_known
|
||||||
# endif
|
# endif
|
||||||
/* PLTSCHEME: added MPW_C */
|
# if defined(__MWERKS__) && defined(__powerc) && !defined(__MACH__)
|
||||||
# if (defined(__MWERKS__) || defined(MPW_C)) && defined(__powerc) && !defined(__MACH__)
|
|
||||||
# define POWERPC
|
# define POWERPC
|
||||||
# define MACOS
|
# define MACOS
|
||||||
# define mach_type_known
|
# define mach_type_known
|
||||||
# endif
|
# endif
|
||||||
# if defined(macosx) || \
|
# if defined(macosx) || (defined(__APPLE__) && defined(__MACH__))
|
||||||
defined(__APPLE__) && defined(__MACH__) && defined(__ppc__)
|
# define DARWIN
|
||||||
# define DARWIN
|
# if defined(__ppc__) || defined(__ppc64__)
|
||||||
# define POWERPC
|
# define POWERPC
|
||||||
# define mach_type_known
|
# define mach_type_known
|
||||||
# endif
|
# endif
|
||||||
# if defined(__APPLE__) && defined(__MACH__) && defined(__i386__)
|
# if defined(__i386__)
|
||||||
# define DARWIN
|
|
||||||
# define I386
|
# define I386
|
||||||
/* PLTSCHEME: support x86 Darwin... */
|
|
||||||
# define mach_type_known
|
# define mach_type_known
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
# if defined(NeXT) && defined(mc68000)
|
# if defined(NeXT) && defined(mc68000)
|
||||||
# define M68K
|
# define M68K
|
||||||
|
@ -316,6 +335,10 @@
|
||||||
# define X86_64
|
# define X86_64
|
||||||
# define mach_type_known
|
# define mach_type_known
|
||||||
# endif
|
# endif
|
||||||
|
# if defined(FREEBSD) && defined(__sparc__)
|
||||||
|
# define SPARC
|
||||||
|
# define mach_type_known
|
||||||
|
#endif
|
||||||
# if defined(bsdi) && (defined(i386) || defined(__i386__))
|
# if defined(bsdi) && (defined(i386) || defined(__i386__))
|
||||||
# define I386
|
# define I386
|
||||||
# define BSDI
|
# define BSDI
|
||||||
|
@ -426,6 +449,13 @@
|
||||||
# define mach_type_known
|
# define mach_type_known
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
# if defined(__TANDEM)
|
||||||
|
/* Nonstop S-series */
|
||||||
|
/* FIXME: Should recognize Integrity series? */
|
||||||
|
# define MIPS
|
||||||
|
# define NONSTOP
|
||||||
|
# define mach_type_known
|
||||||
|
# endif
|
||||||
|
|
||||||
/* Feel free to add more clauses here */
|
/* Feel free to add more clauses here */
|
||||||
|
|
||||||
|
@ -447,8 +477,8 @@
|
||||||
/* FREEBSD, THREE86BSD, MSWIN32, */
|
/* FREEBSD, THREE86BSD, MSWIN32, */
|
||||||
/* BSDI,SUNOS5, NEXT, other variants) */
|
/* BSDI,SUNOS5, NEXT, other variants) */
|
||||||
/* NS32K ==> Encore Multimax */
|
/* NS32K ==> Encore Multimax */
|
||||||
/* MIPS ==> R2000 or R3000 */
|
/* MIPS ==> R2000 through R14K */
|
||||||
/* (RISCOS, ULTRIX variants) */
|
/* (many variants) */
|
||||||
/* VAX ==> DEC VAX */
|
/* VAX ==> DEC VAX */
|
||||||
/* (BSD, ULTRIX variants) */
|
/* (BSD, ULTRIX variants) */
|
||||||
/* RS6000 ==> IBM RS/6000 AIX3.X */
|
/* RS6000 ==> IBM RS/6000 AIX3.X */
|
||||||
|
@ -476,17 +506,22 @@
|
||||||
/* POWERPC ==> IBM/Apple PowerPC */
|
/* POWERPC ==> IBM/Apple PowerPC */
|
||||||
/* (MACOS(<=9),DARWIN(incl.MACOSX),*/
|
/* (MACOS(<=9),DARWIN(incl.MACOSX),*/
|
||||||
/* LINUX, NETBSD, NOSYS variants) */
|
/* LINUX, NETBSD, NOSYS variants) */
|
||||||
|
/* Handles 32 and 64-bit variants. */
|
||||||
|
/* AIX should be handled here, but */
|
||||||
|
/* that's called an RS6000. */
|
||||||
|
/* CRIS ==> Axis Etrax */
|
||||||
|
/* M32R ==> Renesas M32R */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For each architecture and OS, the following need to be defined:
|
* For each architecture and OS, the following need to be defined:
|
||||||
*
|
*
|
||||||
* CPP_WORD_SZ is a simple integer constant representing the word size.
|
* CPP_WORDSZ is a simple integer constant representing the word size.
|
||||||
* in bits. We assume byte addressibility, where a byte has 8 bits.
|
* in bits. We assume byte addressibility, where a byte has 8 bits.
|
||||||
* We also assume CPP_WORD_SZ is either 32 or 64.
|
* We also assume CPP_WORDSZ is either 32 or 64.
|
||||||
* (We care about the length of pointers, not hardware
|
* (We care about the length of pointers, not hardware
|
||||||
* bus widths. Thus a 64 bit processor with a C compiler that uses
|
* bus widths. Thus a 64 bit processor with a C compiler that uses
|
||||||
* 32 bit pointers should use CPP_WORD_SZ of 32, not 64. Default is 32.)
|
* 32 bit pointers should use CPP_WORDSZ of 32, not 64. Default is 32.)
|
||||||
*
|
*
|
||||||
* MACH_TYPE is a string representation of the machine type.
|
* MACH_TYPE is a string representation of the machine type.
|
||||||
* OS_TYPE is analogous for the OS.
|
* OS_TYPE is analogous for the OS.
|
||||||
|
@ -507,6 +542,9 @@
|
||||||
* DATAEND, if not `end' where `end' is defined as ``extern int end[];''.
|
* DATAEND, if not `end' where `end' is defined as ``extern int end[];''.
|
||||||
* RTH suggests gaining access to linker script synth'd values with
|
* RTH suggests gaining access to linker script synth'd values with
|
||||||
* this idiom instead of `&end' where `end' is defined as ``extern int end;'' .
|
* this idiom instead of `&end' where `end' is defined as ``extern int end;'' .
|
||||||
|
* Otherwise, ``GCC will assume these are in .sdata/.sbss'' and it will, e.g.,
|
||||||
|
* cause failures on alpha*-*-* with ``-msmall-data or -fpic'' or mips-*-*
|
||||||
|
* without any special options.
|
||||||
*
|
*
|
||||||
* ALIGN_DOUBLE of GC_malloc should return blocks aligned to twice
|
* ALIGN_DOUBLE of GC_malloc should return blocks aligned to twice
|
||||||
* the pointer size.
|
* the pointer size.
|
||||||
|
@ -600,7 +638,8 @@
|
||||||
*/
|
*/
|
||||||
# if defined(__GNUC__) && ((__GNUC__ >= 3) || \
|
# if defined(__GNUC__) && ((__GNUC__ >= 3) || \
|
||||||
(__GNUC__ == 2 && __GNUC_MINOR__ >= 8)) \
|
(__GNUC__ == 2 && __GNUC_MINOR__ >= 8)) \
|
||||||
&& !defined(__INTEL_COMPILER)
|
&& !defined(__INTEL_COMPILER) \
|
||||||
|
&& !defined(__PATHCC__)
|
||||||
# define HAVE_BUILTIN_UNWIND_INIT
|
# define HAVE_BUILTIN_UNWIND_INIT
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
@ -707,12 +746,6 @@
|
||||||
# define GETPAGESIZE() 4096
|
# define GETPAGESIZE() 4096
|
||||||
# endif
|
# endif
|
||||||
# ifdef MACOS
|
# ifdef MACOS
|
||||||
/* PLTSCHEME: 4-byte alignment */
|
|
||||||
# ifdef USE_POWERPC_FOUR_BYTE_ALIGN
|
|
||||||
# define ALIGNMENT 4
|
|
||||||
# else
|
|
||||||
# define ALIGNMENT 2
|
|
||||||
# endif
|
|
||||||
# ifndef __LOWMEM__
|
# ifndef __LOWMEM__
|
||||||
# include <LowMem.h>
|
# include <LowMem.h>
|
||||||
# endif
|
# endif
|
||||||
|
@ -730,7 +763,7 @@
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifdef POWERPC
|
# if defined(POWERPC)
|
||||||
# define MACH_TYPE "POWERPC"
|
# define MACH_TYPE "POWERPC"
|
||||||
# ifdef MACOS
|
# ifdef MACOS
|
||||||
# define ALIGNMENT 2 /* Still necessary? Could it be 4? */
|
# define ALIGNMENT 2 /* Still necessary? Could it be 4? */
|
||||||
|
@ -743,12 +776,14 @@
|
||||||
# define DATAEND /* not needed */
|
# define DATAEND /* not needed */
|
||||||
# endif
|
# endif
|
||||||
# ifdef LINUX
|
# ifdef LINUX
|
||||||
# if (defined (powerpc64) || defined(__powerpc64__))
|
# if defined(__powerpc64__)
|
||||||
# define ALIGNMENT 8
|
# define ALIGNMENT 8
|
||||||
# define CPP_WORDSZ 64
|
# define CPP_WORDSZ 64
|
||||||
|
# ifndef HBLKSIZE
|
||||||
|
# define HBLKSIZE 4096
|
||||||
|
# endif
|
||||||
# else
|
# else
|
||||||
# define ALIGNMENT 4 /* Guess. Can someone verify? */
|
# define ALIGNMENT 4
|
||||||
/* This was 2, but that didn't sound right. */
|
|
||||||
# endif
|
# endif
|
||||||
# define OS_TYPE "LINUX"
|
# define OS_TYPE "LINUX"
|
||||||
/* HEURISTIC1 has been reliably reported to fail for a 32-bit */
|
/* HEURISTIC1 has been reliably reported to fail for a 32-bit */
|
||||||
|
@ -760,7 +795,12 @@
|
||||||
# define DATAEND (_end)
|
# define DATAEND (_end)
|
||||||
# endif
|
# endif
|
||||||
# ifdef DARWIN
|
# ifdef DARWIN
|
||||||
# define ALIGNMENT 4
|
# ifdef __ppc64__
|
||||||
|
# define ALIGNMENT 8
|
||||||
|
# define CPP_WORDSZ 64
|
||||||
|
# else
|
||||||
|
# define ALIGNMENT 4
|
||||||
|
# endif
|
||||||
# define OS_TYPE "DARWIN"
|
# define OS_TYPE "DARWIN"
|
||||||
# define DYNAMIC_LOADING
|
# define DYNAMIC_LOADING
|
||||||
/* XXX: see get_end(3), get_etext() and get_end() should not be used.
|
/* XXX: see get_end(3), get_etext() and get_end() should not be used.
|
||||||
|
@ -772,8 +812,10 @@
|
||||||
# define USE_MMAP_ANON
|
# define USE_MMAP_ANON
|
||||||
# define USE_ASM_PUSH_REGS
|
# define USE_ASM_PUSH_REGS
|
||||||
/* This is potentially buggy. It needs more testing. See the comments in
|
/* This is potentially buggy. It needs more testing. See the comments in
|
||||||
os_dep.c */
|
os_dep.c. It relies on threads to track writes. */
|
||||||
# define MPROTECT_VDB
|
# ifdef GC_DARWIN_THREADS
|
||||||
|
/* # define MPROTECT_VDB -- diabled for now. May work for some apps. */
|
||||||
|
# endif
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
# define GETPAGESIZE() getpagesize()
|
# define GETPAGESIZE() getpagesize()
|
||||||
# if defined(USE_PPC_PREFETCH) && defined(__GNUC__)
|
# if defined(USE_PPC_PREFETCH) && defined(__GNUC__)
|
||||||
|
@ -787,6 +829,22 @@
|
||||||
should be looked into some more */
|
should be looked into some more */
|
||||||
# define NO_PTHREAD_TRYLOCK
|
# define NO_PTHREAD_TRYLOCK
|
||||||
# endif
|
# endif
|
||||||
|
# ifdef FREEBSD
|
||||||
|
# define ALIGNMENT 4
|
||||||
|
# define OS_TYPE "FREEBSD"
|
||||||
|
# ifndef GC_FREEBSD_THREADS
|
||||||
|
# define MPROTECT_VDB
|
||||||
|
# endif
|
||||||
|
# define SIG_SUSPEND SIGUSR1
|
||||||
|
# define SIG_THR_RESTART SIGUSR2
|
||||||
|
# define FREEBSD_STACKBOTTOM
|
||||||
|
# ifdef __ELF__
|
||||||
|
# define DYNAMIC_LOADING
|
||||||
|
# endif
|
||||||
|
extern char etext[];
|
||||||
|
extern char * GC_FreeBSDGetDataStart();
|
||||||
|
# define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext)
|
||||||
|
# endif
|
||||||
# ifdef NETBSD
|
# ifdef NETBSD
|
||||||
# define ALIGNMENT 4
|
# define ALIGNMENT 4
|
||||||
# define OS_TYPE "NETBSD"
|
# define OS_TYPE "NETBSD"
|
||||||
|
@ -922,12 +980,10 @@
|
||||||
extern ptr_t GC_SysVGetDataStart();
|
extern ptr_t GC_SysVGetDataStart();
|
||||||
# ifdef __arch64__
|
# ifdef __arch64__
|
||||||
# define DATASTART GC_SysVGetDataStart(0x100000, _etext)
|
# define DATASTART GC_SysVGetDataStart(0x100000, _etext)
|
||||||
/* libc_stack_end is not set reliably for sparc64 */
|
|
||||||
# define STACKBOTTOM ((ptr_t) 0x80000000000ULL)
|
|
||||||
# else
|
# else
|
||||||
# define DATASTART GC_SysVGetDataStart(0x10000, _etext)
|
# define DATASTART GC_SysVGetDataStart(0x10000, _etext)
|
||||||
# define LINUX_STACKBOTTOM
|
|
||||||
# endif
|
# endif
|
||||||
|
# define LINUX_STACKBOTTOM
|
||||||
# endif
|
# endif
|
||||||
# ifdef OPENBSD
|
# ifdef OPENBSD
|
||||||
# define OS_TYPE "OPENBSD"
|
# define OS_TYPE "OPENBSD"
|
||||||
|
@ -946,6 +1002,23 @@
|
||||||
# define DATASTART ((ptr_t)(etext))
|
# define DATASTART ((ptr_t)(etext))
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
# ifdef FREEBSD
|
||||||
|
# define OS_TYPE "FREEBSD"
|
||||||
|
# define SIG_SUSPEND SIGUSR1
|
||||||
|
# define SIG_THR_RESTART SIGUSR2
|
||||||
|
# define FREEBSD_STACKBOTTOM
|
||||||
|
# ifdef __ELF__
|
||||||
|
# define DYNAMIC_LOADING
|
||||||
|
# endif
|
||||||
|
extern char etext[];
|
||||||
|
extern char edata[];
|
||||||
|
extern char end[];
|
||||||
|
# define NEED_FIND_LIMIT
|
||||||
|
# define DATASTART ((ptr_t)(&etext))
|
||||||
|
# define DATAEND (GC_find_limit (DATASTART, TRUE))
|
||||||
|
# define DATASTART2 ((ptr_t)(&edata))
|
||||||
|
# define DATAEND2 ((ptr_t)(&end))
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifdef I386
|
# ifdef I386
|
||||||
|
@ -968,18 +1041,6 @@
|
||||||
# ifdef HAVE_BUILTIN_UNWIND_INIT
|
# ifdef HAVE_BUILTIN_UNWIND_INIT
|
||||||
# define USE_GENERIC_PUSH_REGS
|
# define USE_GENERIC_PUSH_REGS
|
||||||
# endif
|
# endif
|
||||||
/* PLTSCHEME: I386 Darwin: */
|
|
||||||
# ifdef DARWIN
|
|
||||||
# define OS_TYPE "DARWIN"
|
|
||||||
# define DYNAMIC_LOADING
|
|
||||||
/* XXX: see get_end(3), get_etext() and get_end() should not be used.
|
|
||||||
These aren't used when dyld support is enabled (it is by default) */
|
|
||||||
# define DATASTART ((ptr_t) get_etext())
|
|
||||||
# define DATAEND ((ptr_t) get_end())
|
|
||||||
# define STACKBOTTOM ((ptr_t) 0xc0000000)
|
|
||||||
# define USE_MMAP
|
|
||||||
# define USE_MMAP_ANON
|
|
||||||
# endif
|
|
||||||
# ifdef SEQUENT
|
# ifdef SEQUENT
|
||||||
# define OS_TYPE "SEQUENT"
|
# define OS_TYPE "SEQUENT"
|
||||||
extern int etext[];
|
extern int etext[];
|
||||||
|
@ -1141,26 +1202,8 @@
|
||||||
# endif
|
# endif
|
||||||
# ifdef CYGWIN32
|
# ifdef CYGWIN32
|
||||||
# define OS_TYPE "CYGWIN32"
|
# define OS_TYPE "CYGWIN32"
|
||||||
extern int _data_start__[];
|
# define DATASTART ((ptr_t)GC_DATASTART) /* From gc.h */
|
||||||
extern int _data_end__[];
|
# define DATAEND ((ptr_t)GC_DATAEND)
|
||||||
extern int _bss_start__[];
|
|
||||||
extern int _bss_end__[];
|
|
||||||
/* For binutils 2.9.1, we have */
|
|
||||||
/* DATASTART = _data_start__ */
|
|
||||||
/* DATAEND = _bss_end__ */
|
|
||||||
/* whereas for some earlier versions it was */
|
|
||||||
/* DATASTART = _bss_start__ */
|
|
||||||
/* DATAEND = _data_end__ */
|
|
||||||
/* To get it right for both, we take the */
|
|
||||||
/* minumum/maximum of the two. */
|
|
||||||
# ifndef MAX
|
|
||||||
# define MAX(x,y) ((x) > (y) ? (x) : (y))
|
|
||||||
# endif
|
|
||||||
# ifndef MIN
|
|
||||||
# define MIN(x,y) ((x) < (y) ? (x) : (y))
|
|
||||||
# endif
|
|
||||||
# define DATASTART ((ptr_t) MIN(_data_start__, _bss_start__))
|
|
||||||
# define DATAEND ((ptr_t) MAX(_data_end__, _bss_end__))
|
|
||||||
# undef STACK_GRAN
|
# undef STACK_GRAN
|
||||||
# define STACK_GRAN 0x10000
|
# define STACK_GRAN 0x10000
|
||||||
# define HEURISTIC1
|
# define HEURISTIC1
|
||||||
|
@ -1266,6 +1309,29 @@
|
||||||
/* # define MPROTECT_VDB Not quite working yet? */
|
/* # define MPROTECT_VDB Not quite working yet? */
|
||||||
# define DYNAMIC_LOADING
|
# define DYNAMIC_LOADING
|
||||||
# endif
|
# endif
|
||||||
|
# ifdef DARWIN
|
||||||
|
# define OS_TYPE "DARWIN"
|
||||||
|
# define DARWIN_DONT_PARSE_STACK
|
||||||
|
# define DYNAMIC_LOADING
|
||||||
|
/* XXX: see get_end(3), get_etext() and get_end() should not be used.
|
||||||
|
These aren't used when dyld support is enabled (it is by default) */
|
||||||
|
# define DATASTART ((ptr_t) get_etext())
|
||||||
|
# define DATAEND ((ptr_t) get_end())
|
||||||
|
# define STACKBOTTOM ((ptr_t) 0xc0000000)
|
||||||
|
# define USE_MMAP
|
||||||
|
# define USE_MMAP_ANON
|
||||||
|
# define USE_ASM_PUSH_REGS
|
||||||
|
/* This is potentially buggy. It needs more testing. See the comments in
|
||||||
|
os_dep.c. It relies on threads to track writes. */
|
||||||
|
# ifdef GC_DARWIN_THREADS
|
||||||
|
/* # define MPROTECT_VDB -- disabled for now. May work for some apps. */
|
||||||
|
# endif
|
||||||
|
# include <unistd.h>
|
||||||
|
# define GETPAGESIZE() getpagesize()
|
||||||
|
/* There seems to be some issues with trylock hanging on darwin. This
|
||||||
|
should be looked into some more */
|
||||||
|
# define NO_PTHREAD_TRYLOCK
|
||||||
|
# endif /* DARWIN */
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifdef NS32K
|
# ifdef NS32K
|
||||||
|
@ -1371,10 +1437,8 @@
|
||||||
# define DATAEND /* not needed */
|
# define DATAEND /* not needed */
|
||||||
# endif
|
# endif
|
||||||
# if defined(NETBSD)
|
# if defined(NETBSD)
|
||||||
/* This also checked for __MIPSEL__ . Why? NETBSD recognition */
|
|
||||||
/* should be handled at the top of the file. */
|
|
||||||
# define ALIGNMENT 4
|
|
||||||
# define OS_TYPE "NETBSD"
|
# define OS_TYPE "NETBSD"
|
||||||
|
# define ALIGNMENT 4
|
||||||
# define HEURISTIC2
|
# define HEURISTIC2
|
||||||
# define USE_GENERIC_PUSH_REGS
|
# define USE_GENERIC_PUSH_REGS
|
||||||
# ifdef __ELF__
|
# ifdef __ELF__
|
||||||
|
@ -1387,6 +1451,16 @@
|
||||||
# define STACKBOTTOM ((ptr_t) 0x7ffff000)
|
# define STACKBOTTOM ((ptr_t) 0x7ffff000)
|
||||||
# endif /* _ELF_ */
|
# endif /* _ELF_ */
|
||||||
# endif
|
# endif
|
||||||
|
# if defined(NONSTOP)
|
||||||
|
# define CPP_WORDSZ 32
|
||||||
|
# define OS_TYPE "NONSTOP"
|
||||||
|
# define ALIGNMENT 4
|
||||||
|
# define DATASTART ((ptr_t) 0x08000000)
|
||||||
|
extern int _end[];
|
||||||
|
# define DATAEND (_end)
|
||||||
|
# define STACKBOTTOM ((ptr_t) 0x4fffffff)
|
||||||
|
# define USE_GENERIC_PUSH_REGS
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifdef RS6000
|
# ifdef RS6000
|
||||||
|
@ -1406,6 +1480,8 @@
|
||||||
# define CPP_WORDSZ 32
|
# define CPP_WORDSZ 32
|
||||||
# define STACKBOTTOM ((ptr_t)((ulong)&errno))
|
# define STACKBOTTOM ((ptr_t)((ulong)&errno))
|
||||||
# endif
|
# endif
|
||||||
|
# define USE_MMAP
|
||||||
|
# define USE_MMAP_ANON
|
||||||
/* From AIX linker man page:
|
/* From AIX linker man page:
|
||||||
_text Specifies the first location of the program.
|
_text Specifies the first location of the program.
|
||||||
_etext Specifies the first location after the program.
|
_etext Specifies the first location after the program.
|
||||||
|
@ -1562,7 +1638,7 @@
|
||||||
# endif
|
# endif
|
||||||
# ifdef LINUX
|
# ifdef LINUX
|
||||||
# define OS_TYPE "LINUX"
|
# define OS_TYPE "LINUX"
|
||||||
# define STACKBOTTOM ((ptr_t) 0x120000000)
|
# define LINUX_STACKBOTTOM
|
||||||
# ifdef __ELF__
|
# ifdef __ELF__
|
||||||
# define SEARCH_FOR_DATA_START
|
# define SEARCH_FOR_DATA_START
|
||||||
# define DYNAMIC_LOADING
|
# define DYNAMIC_LOADING
|
||||||
|
@ -1713,7 +1789,7 @@
|
||||||
# define USE_GENERIC_PUSH_REGS
|
# define USE_GENERIC_PUSH_REGS
|
||||||
# ifdef UTS4
|
# ifdef UTS4
|
||||||
# define OS_TYPE "UTS4"
|
# define OS_TYPE "UTS4"
|
||||||
extern int etext[];
|
extern int etext[];
|
||||||
extern int _etext[];
|
extern int _etext[];
|
||||||
extern int _end[];
|
extern int _end[];
|
||||||
extern ptr_t GC_SysVGetDataStart();
|
extern ptr_t GC_SysVGetDataStart();
|
||||||
|
@ -1727,18 +1803,20 @@
|
||||||
# define MACH_TYPE "S390"
|
# define MACH_TYPE "S390"
|
||||||
# define USE_GENERIC_PUSH_REGS
|
# define USE_GENERIC_PUSH_REGS
|
||||||
# ifndef __s390x__
|
# ifndef __s390x__
|
||||||
# define ALIGNMENT 4
|
# define ALIGNMENT 4
|
||||||
# define CPP_WORDSZ 32
|
# define CPP_WORDSZ 32
|
||||||
# else
|
# else
|
||||||
# define ALIGNMENT 8
|
# define ALIGNMENT 8
|
||||||
# define CPP_WORDSZ 64
|
# define CPP_WORDSZ 64
|
||||||
# define HBLKSIZE 4096
|
# endif
|
||||||
|
# ifndef HBLKSIZE
|
||||||
|
# define HBLKSIZE 4096
|
||||||
# endif
|
# endif
|
||||||
# ifdef LINUX
|
# ifdef LINUX
|
||||||
# define OS_TYPE "LINUX"
|
# define OS_TYPE "LINUX"
|
||||||
# define LINUX_STACKBOTTOM
|
# define LINUX_STACKBOTTOM
|
||||||
# define DYNAMIC_LOADING
|
# define DYNAMIC_LOADING
|
||||||
extern int __data_start[];
|
extern int __data_start[];
|
||||||
# define DATASTART ((ptr_t)(__data_start))
|
# define DATASTART ((ptr_t)(__data_start))
|
||||||
extern int _end[];
|
extern int _end[];
|
||||||
# define DATAEND (_end)
|
# define DATAEND (_end)
|
||||||
|
@ -1772,7 +1850,7 @@
|
||||||
# endif
|
# endif
|
||||||
# ifdef LINUX
|
# ifdef LINUX
|
||||||
# define OS_TYPE "LINUX"
|
# define OS_TYPE "LINUX"
|
||||||
# define HEURISTIC1
|
# define LINUX_STACKBOTTOM
|
||||||
# undef STACK_GRAN
|
# undef STACK_GRAN
|
||||||
# define STACK_GRAN 0x10000000
|
# define STACK_GRAN 0x10000000
|
||||||
# define USE_GENERIC_PUSH_REGS
|
# define USE_GENERIC_PUSH_REGS
|
||||||
|
@ -1815,6 +1893,19 @@
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
# ifdef CRIS
|
||||||
|
# define MACH_TYPE "CRIS"
|
||||||
|
# define CPP_WORDSZ 32
|
||||||
|
# define ALIGNMENT 1
|
||||||
|
# define OS_TYPE "LINUX"
|
||||||
|
# define DYNAMIC_LOADING
|
||||||
|
# define LINUX_STACKBOTTOM
|
||||||
|
# define USE_GENERIC_PUSH_REGS
|
||||||
|
# define SEARCH_FOR_DATA_START
|
||||||
|
extern int _end[];
|
||||||
|
# define DATAEND (_end)
|
||||||
|
# endif
|
||||||
|
|
||||||
# ifdef SH
|
# ifdef SH
|
||||||
# define MACH_TYPE "SH"
|
# define MACH_TYPE "SH"
|
||||||
# define ALIGNMENT 4
|
# define ALIGNMENT 4
|
||||||
|
@ -1824,13 +1915,20 @@
|
||||||
# endif
|
# endif
|
||||||
# ifdef LINUX
|
# ifdef LINUX
|
||||||
# define OS_TYPE "LINUX"
|
# define OS_TYPE "LINUX"
|
||||||
# define STACKBOTTOM ((ptr_t) 0x7c000000)
|
# define LINUX_STACKBOTTOM
|
||||||
# define USE_GENERIC_PUSH_REGS
|
# define USE_GENERIC_PUSH_REGS
|
||||||
# define DYNAMIC_LOADING
|
# define DYNAMIC_LOADING
|
||||||
# define SEARCH_FOR_DATA_START
|
# define SEARCH_FOR_DATA_START
|
||||||
extern int _end[];
|
extern int _end[];
|
||||||
# define DATAEND (_end)
|
# define DATAEND (_end)
|
||||||
# endif
|
# endif
|
||||||
|
# ifdef NETBSD
|
||||||
|
# define OS_TYPE "NETBSD"
|
||||||
|
# define HEURISTIC2
|
||||||
|
# define DATASTART GC_data_start
|
||||||
|
# define USE_GENERIC_PUSH_REGS
|
||||||
|
# define DYNAMIC_LOADING
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifdef SH4
|
# ifdef SH4
|
||||||
|
@ -1840,6 +1938,23 @@
|
||||||
# define DATAEND /* not needed */
|
# define DATAEND /* not needed */
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# ifdef M32R
|
||||||
|
# define CPP_WORDSZ 32
|
||||||
|
# define MACH_TYPE "M32R"
|
||||||
|
# define ALIGNMENT 4
|
||||||
|
# ifdef LINUX
|
||||||
|
# define OS_TYPE "LINUX"
|
||||||
|
# define LINUX_STACKBOTTOM
|
||||||
|
# undef STACK_GRAN
|
||||||
|
# define STACK_GRAN 0x10000000
|
||||||
|
# define USE_GENERIC_PUSH_REGS
|
||||||
|
# define DYNAMIC_LOADING
|
||||||
|
# define SEARCH_FOR_DATA_START
|
||||||
|
extern int _end[];
|
||||||
|
# define DATAEND (_end)
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
# ifdef X86_64
|
# ifdef X86_64
|
||||||
# define MACH_TYPE "X86_64"
|
# define MACH_TYPE "X86_64"
|
||||||
# define ALIGNMENT 8
|
# define ALIGNMENT 8
|
||||||
|
@ -1953,6 +2068,11 @@
|
||||||
# define SUNOS5SIGS
|
# define SUNOS5SIGS
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# ifdef GC_NETBSD_THREADS
|
||||||
|
# define SIGRTMIN 33
|
||||||
|
# define SIGRTMAX 63
|
||||||
|
# endif
|
||||||
|
|
||||||
# if defined(SVR4) || defined(LINUX) || defined(IRIX5) || defined(HPUX) \
|
# if defined(SVR4) || defined(LINUX) || defined(IRIX5) || defined(HPUX) \
|
||||||
|| defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \
|
|| defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \
|
||||||
|| defined(DGUX) || defined(BSD) || defined(SUNOS4) \
|
|| defined(DGUX) || defined(BSD) || defined(SUNOS4) \
|
||||||
|
@ -2043,6 +2163,9 @@
|
||||||
# if defined(GC_LINUX_THREADS) && !defined(LINUX)
|
# if defined(GC_LINUX_THREADS) && !defined(LINUX)
|
||||||
--> inconsistent configuration
|
--> inconsistent configuration
|
||||||
# endif
|
# endif
|
||||||
|
# if defined(GC_NETBSD_THREADS) && !defined(NETBSD)
|
||||||
|
--> inconsistent configuration
|
||||||
|
# endif
|
||||||
# if defined(GC_SOLARIS_THREADS) && !defined(SUNOS5)
|
# if defined(GC_SOLARIS_THREADS) && !defined(SUNOS5)
|
||||||
--> inconsistent configuration
|
--> inconsistent configuration
|
||||||
# endif
|
# endif
|
||||||
|
@ -2062,8 +2185,9 @@
|
||||||
# define THREADS
|
# define THREADS
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if defined(HP_PA) || defined(M88K) || defined(POWERPC) && !defined(DARWIN) \
|
# if defined(HP_PA) || defined(M88K) \
|
||||||
|| defined(LINT) || defined(MSWINCE) || defined(ARM32) \
|
|| defined(POWERPC) && !defined(DARWIN) \
|
||||||
|
|| defined(LINT) || defined(MSWINCE) || defined(ARM32) || defined(CRIS) \
|
||||||
|| (defined(I386) && defined(__LCC__))
|
|| (defined(I386) && defined(__LCC__))
|
||||||
/* Use setjmp based hack to mark from callee-save registers. */
|
/* Use setjmp based hack to mark from callee-save registers. */
|
||||||
/* The define should move to the individual platform */
|
/* The define should move to the individual platform */
|
||||||
|
@ -2175,7 +2299,7 @@
|
||||||
+ GC_page_size) \
|
+ GC_page_size) \
|
||||||
+ GC_page_size-1)
|
+ GC_page_size-1)
|
||||||
# else
|
# else
|
||||||
# if defined(NEXT) || defined(DOS4GW) || \
|
# if defined(NEXT) || defined(DOS4GW) || defined(NONSTOP) || \
|
||||||
(defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) || \
|
(defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) || \
|
||||||
(defined(SUNOS5) && !defined(USE_MMAP))
|
(defined(SUNOS5) && !defined(USE_MMAP))
|
||||||
# define GET_MEM(bytes) HBLKPTR((size_t) \
|
# define GET_MEM(bytes) HBLKPTR((size_t) \
|
||||||
|
@ -2204,7 +2328,7 @@
|
||||||
# else
|
# else
|
||||||
# if defined(AMIGA) && defined(GC_AMIGA_FASTALLOC)
|
# if defined(AMIGA) && defined(GC_AMIGA_FASTALLOC)
|
||||||
extern void *GC_amiga_get_mem(size_t size);
|
extern void *GC_amiga_get_mem(size_t size);
|
||||||
define GET_MEM(bytes) HBLKPTR((size_t) \
|
# define GET_MEM(bytes) HBLKPTR((size_t) \
|
||||||
GC_amiga_get_mem((size_t)bytes + GC_page_size) \
|
GC_amiga_get_mem((size_t)bytes + GC_page_size) \
|
||||||
+ GC_page_size-1)
|
+ GC_page_size-1)
|
||||||
# else
|
# else
|
||||||
|
@ -2220,4 +2344,10 @@
|
||||||
|
|
||||||
#endif /* GC_PRIVATE_H */
|
#endif /* GC_PRIVATE_H */
|
||||||
|
|
||||||
|
#if defined(_AIX) && !defined(__GNUC__) && !defined(__STDC__)
|
||||||
|
/* IBMs xlc compiler doesn't appear to follow the convention of */
|
||||||
|
/* defining __STDC__ to be zero in extended mode. */
|
||||||
|
# define __STDC__ 0
|
||||||
|
#endif
|
||||||
|
|
||||||
# endif /* GCCONFIG_H */
|
# endif /* GCCONFIG_H */
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#define GC_PTHREAD_STOP_WORLD_H
|
#define GC_PTHREAD_STOP_WORLD_H
|
||||||
|
|
||||||
struct thread_stop_info {
|
struct thread_stop_info {
|
||||||
int signal;
|
|
||||||
word last_stop_count; /* GC_last_stop_count value when thread */
|
word last_stop_count; /* GC_last_stop_count value when thread */
|
||||||
/* last successfully handled a suspend */
|
/* last successfully handled a suspend */
|
||||||
/* signal. */
|
/* signal. */
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
# include "private/gc_priv.h"
|
# include "private/gc_priv.h"
|
||||||
|
|
||||||
# if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
|
# if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
|
||||||
&& !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS)
|
&& !defined(GC_WIN32_THREADS)
|
||||||
|
|
||||||
#if defined(GC_DARWIN_THREADS)
|
#if defined(GC_DARWIN_THREADS)
|
||||||
# include "private/darwin_stop_world.h"
|
# include "private/darwin_stop_world.h"
|
||||||
|
|
|
@ -27,6 +27,10 @@
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
#if defined(RS6000) || defined(POWERPC)
|
||||||
|
# include <ucontext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__MWERKS__) && !defined(POWERPC)
|
#if defined(__MWERKS__) && !defined(POWERPC)
|
||||||
|
|
||||||
asm static void PushMacRegisters()
|
asm static void PushMacRegisters()
|
||||||
|
@ -400,64 +404,87 @@ void GC_push_regs()
|
||||||
}
|
}
|
||||||
#endif /* !USE_GENERIC_PUSH_REGS && !USE_ASM_PUSH_REGS */
|
#endif /* !USE_GENERIC_PUSH_REGS && !USE_ASM_PUSH_REGS */
|
||||||
|
|
||||||
|
void GC_with_callee_saves_pushed(fn, arg)
|
||||||
|
void (*fn)();
|
||||||
|
ptr_t arg;
|
||||||
|
{
|
||||||
|
word dummy;
|
||||||
|
|
||||||
|
# if defined(USE_GENERIC_PUSH_REGS)
|
||||||
|
# ifdef HAVE_BUILTIN_UNWIND_INIT
|
||||||
|
/* This was suggested by Richard Henderson as the way to */
|
||||||
|
/* force callee-save registers and register windows onto */
|
||||||
|
/* the stack. */
|
||||||
|
__builtin_unwind_init();
|
||||||
|
# else /* !HAVE_BUILTIN_UNWIND_INIT */
|
||||||
|
# if defined(RS6000) || defined(POWERPC)
|
||||||
|
/* FIXME: RS6000 means AIX. */
|
||||||
|
/* This should probably be used in all Posix/non-gcc */
|
||||||
|
/* settings. We defer that change to minimize risk. */
|
||||||
|
ucontext_t ctxt;
|
||||||
|
getcontext(&ctxt);
|
||||||
|
# else
|
||||||
|
/* Generic code */
|
||||||
|
/* The idea is due to Parag Patel at HP. */
|
||||||
|
/* We're not sure whether he would like */
|
||||||
|
/* to be he acknowledged for it or not. */
|
||||||
|
jmp_buf regs;
|
||||||
|
register word * i = (word *) regs;
|
||||||
|
register ptr_t lim = (ptr_t)(regs) + (sizeof regs);
|
||||||
|
|
||||||
|
/* Setjmp doesn't always clear all of the buffer. */
|
||||||
|
/* That tends to preserve garbage. Clear it. */
|
||||||
|
for (; (char *)i < lim; i++) {
|
||||||
|
*i = 0;
|
||||||
|
}
|
||||||
|
# if defined(MSWIN32) || defined(MSWINCE) \
|
||||||
|
|| defined(UTS4) || defined(LINUX) || defined(EWS4800)
|
||||||
|
(void) setjmp(regs);
|
||||||
|
# else
|
||||||
|
(void) _setjmp(regs);
|
||||||
|
/* We don't want to mess with signals. According to */
|
||||||
|
/* SUSV3, setjmp() may or may not save signal mask. */
|
||||||
|
/* _setjmp won't, but is less portable. */
|
||||||
|
# endif
|
||||||
|
# endif /* !AIX ... */
|
||||||
|
# endif /* !HAVE_BUILTIN_UNWIND_INIT */
|
||||||
|
# else
|
||||||
|
# if defined(PTHREADS) && !defined(MSWIN32) /* !USE_GENERIC_PUSH_REGS */
|
||||||
|
/* We may still need this to save thread contexts. */
|
||||||
|
ucontext_t ctxt;
|
||||||
|
getcontext(&ctxt);
|
||||||
|
# else /* Shouldn't be needed */
|
||||||
|
ABORT("Unexpected call to GC_with_callee_saves_pushed");
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# if (defined(SPARC) && !defined(HAVE_BUILTIN_UNWIND_INIT)) \
|
||||||
|
|| defined(IA64)
|
||||||
|
/* On a register window machine, we need to save register */
|
||||||
|
/* contents on the stack for this to work. The setjmp */
|
||||||
|
/* is probably not needed on SPARC, since pointers are */
|
||||||
|
/* only stored in windowed or scratch registers. It is */
|
||||||
|
/* needed on IA64, since some non-windowed registers are */
|
||||||
|
/* preserved. */
|
||||||
|
{
|
||||||
|
GC_save_regs_ret_val = GC_save_regs_in_stack();
|
||||||
|
/* On IA64 gcc, could use __builtin_ia64_flushrs() and */
|
||||||
|
/* __builtin_ia64_flushrs(). The latter will be done */
|
||||||
|
/* implicitly by __builtin_unwind_init() for gcc3.0.1 */
|
||||||
|
/* and later. */
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
fn(arg);
|
||||||
|
/* Strongly discourage the compiler from treating the above */
|
||||||
|
/* as a tail-call, since that would pop the register */
|
||||||
|
/* contents before we get a chance to look at them. */
|
||||||
|
GC_noop1((word)(&dummy));
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(USE_GENERIC_PUSH_REGS)
|
#if defined(USE_GENERIC_PUSH_REGS)
|
||||||
void GC_generic_push_regs(cold_gc_frame)
|
void GC_generic_push_regs(cold_gc_frame)
|
||||||
ptr_t cold_gc_frame;
|
ptr_t cold_gc_frame;
|
||||||
{
|
{
|
||||||
{
|
GC_with_callee_saves_pushed(GC_push_current_stack, cold_gc_frame);
|
||||||
word dummy;
|
|
||||||
|
|
||||||
# ifdef HAVE_BUILTIN_UNWIND_INIT
|
|
||||||
/* This was suggested by Richard Henderson as the way to */
|
|
||||||
/* force callee-save registers and register windows onto */
|
|
||||||
/* the stack. */
|
|
||||||
__builtin_unwind_init();
|
|
||||||
# else /* !HAVE_BUILTIN_UNWIND_INIT */
|
|
||||||
/* Generic code */
|
|
||||||
/* The idea is due to Parag Patel at HP. */
|
|
||||||
/* We're not sure whether he would like */
|
|
||||||
/* to be he acknowledged for it or not. */
|
|
||||||
jmp_buf regs;
|
|
||||||
register word * i = (word *) regs;
|
|
||||||
register ptr_t lim = (ptr_t)(regs) + (sizeof regs);
|
|
||||||
|
|
||||||
/* Setjmp doesn't always clear all of the buffer. */
|
|
||||||
/* That tends to preserve garbage. Clear it. */
|
|
||||||
for (; (char *)i < lim; i++) {
|
|
||||||
*i = 0;
|
|
||||||
}
|
|
||||||
# if defined(POWERPC) || defined(MSWIN32) || defined(MSWINCE) \
|
|
||||||
|| defined(UTS4) || defined(LINUX) || defined(EWS4800)
|
|
||||||
(void) setjmp(regs);
|
|
||||||
# else
|
|
||||||
(void) _setjmp(regs);
|
|
||||||
/* We don't want to mess with signals. According to */
|
|
||||||
/* SUSV3, setjmp() may or may not save signal mask. */
|
|
||||||
/* _setjmp won't, but is less portable. */
|
|
||||||
# endif
|
|
||||||
# endif /* !HAVE_BUILTIN_UNWIND_INIT */
|
|
||||||
# if (defined(SPARC) && !defined(HAVE_BUILTIN_UNWIND_INIT)) \
|
|
||||||
|| defined(IA64)
|
|
||||||
/* On a register window machine, we need to save register */
|
|
||||||
/* contents on the stack for this to work. The setjmp */
|
|
||||||
/* is probably not needed on SPARC, since pointers are */
|
|
||||||
/* only stored in windowed or scratch registers. It is */
|
|
||||||
/* needed on IA64, since some non-windowed registers are */
|
|
||||||
/* preserved. */
|
|
||||||
{
|
|
||||||
GC_save_regs_ret_val = GC_save_regs_in_stack();
|
|
||||||
/* On IA64 gcc, could use __builtin_ia64_flushrs() and */
|
|
||||||
/* __builtin_ia64_flushrs(). The latter will be done */
|
|
||||||
/* implicitly by __builtin_unwind_init() for gcc3.0.1 */
|
|
||||||
/* and later. */
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
GC_push_current_stack(cold_gc_frame);
|
|
||||||
/* Strongly discourage the compiler from treating the above */
|
|
||||||
/* as a tail-call, since that would pop the register */
|
|
||||||
/* contents before we get a chance to look at them. */
|
|
||||||
GC_noop1((word)(&dummy));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* USE_GENERIC_PUSH_REGS */
|
#endif /* USE_GENERIC_PUSH_REGS */
|
||||||
|
|
||||||
|
@ -465,7 +492,7 @@ ptr_t cold_gc_frame;
|
||||||
/* the stack. Return sp. */
|
/* the stack. Return sp. */
|
||||||
# ifdef SPARC
|
# ifdef SPARC
|
||||||
asm(" .seg \"text\"");
|
asm(" .seg \"text\"");
|
||||||
# if defined(SVR4) || defined(NETBSD)
|
# if defined(SVR4) || defined(NETBSD) || defined(FREEBSD)
|
||||||
asm(" .globl GC_save_regs_in_stack");
|
asm(" .globl GC_save_regs_in_stack");
|
||||||
asm("GC_save_regs_in_stack:");
|
asm("GC_save_regs_in_stack:");
|
||||||
asm(" .type GC_save_regs_in_stack,#function");
|
asm(" .type GC_save_regs_in_stack,#function");
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
/* Boehm, February 7, 1996 4:32 pm PST */
|
/* Boehm, February 7, 1996 4:32 pm PST */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
#include "private/gc_priv.h"
|
#include "private/gc_priv.h"
|
||||||
|
|
||||||
extern ptr_t GC_clear_stack(); /* in misc.c, behaves like identity */
|
extern ptr_t GC_clear_stack(); /* in misc.c, behaves like identity */
|
||||||
|
@ -271,6 +273,26 @@ DCL_LOCK_STATE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* provide a version of strdup() that uses the collector to allocate the
|
||||||
|
copy of the string */
|
||||||
|
# ifdef __STDC__
|
||||||
|
char *GC_strdup(const char *s)
|
||||||
|
# else
|
||||||
|
char *GC_strdup(s)
|
||||||
|
char *s;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
char *copy;
|
||||||
|
|
||||||
|
if (s == NULL) return NULL;
|
||||||
|
if ((copy = GC_malloc_atomic(strlen(s) + 1)) == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
strcpy(copy, s);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate lb bytes of composite (pointerful) data */
|
/* Allocate lb bytes of composite (pointerful) data */
|
||||||
# ifdef __STDC__
|
# ifdef __STDC__
|
||||||
GC_PTR GC_malloc(size_t lb)
|
GC_PTR GC_malloc(size_t lb)
|
||||||
|
@ -370,6 +392,10 @@ DCL_LOCK_STATE;
|
||||||
{
|
{
|
||||||
size_t len = strlen(s) + 1;
|
size_t len = strlen(s) + 1;
|
||||||
char * result = ((char *)REDIRECT_MALLOC(len+1));
|
char * result = ((char *)REDIRECT_MALLOC(len+1));
|
||||||
|
if (result == 0) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BCOPY(s, result, len+1);
|
BCOPY(s, result, len+1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,6 @@ extern ptr_t GC_clear_stack(); /* in misc.c, behaves like identity */
|
||||||
void GC_extend_size_map(); /* in misc.c. */
|
void GC_extend_size_map(); /* in misc.c. */
|
||||||
GC_bool GC_alloc_reclaim_list(); /* in malloc.c */
|
GC_bool GC_alloc_reclaim_list(); /* in malloc.c */
|
||||||
|
|
||||||
/* PLTSCHEME: For MSVC /MD Compilation */
|
|
||||||
#ifndef USE_MSVC_MD_LIBRARY
|
|
||||||
|
|
||||||
/* Some externally visible but unadvertised variables to allow access to */
|
/* Some externally visible but unadvertised variables to allow access to */
|
||||||
/* free lists from inlined allocators without including gc_priv.h */
|
/* free lists from inlined allocators without including gc_priv.h */
|
||||||
/* or introducing dependencies on internal data structure layouts. */
|
/* or introducing dependencies on internal data structure layouts. */
|
||||||
|
@ -41,7 +38,6 @@ ptr_t * GC_CONST GC_uobjfreelist_ptr = GC_uobjfreelist;
|
||||||
ptr_t * GC_CONST GC_auobjfreelist_ptr = GC_auobjfreelist;
|
ptr_t * GC_CONST GC_auobjfreelist_ptr = GC_auobjfreelist;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#endif /* PLTSCHEME: GC_MSVC_MD_LIBRARY */
|
|
||||||
|
|
||||||
GC_PTR GC_generic_or_special_malloc(lb,knd)
|
GC_PTR GC_generic_or_special_malloc(lb,knd)
|
||||||
word lb;
|
word lb;
|
||||||
|
@ -176,7 +172,8 @@ int obj_kind;
|
||||||
# endif /* REDIRECT_REALLOC */
|
# endif /* REDIRECT_REALLOC */
|
||||||
|
|
||||||
|
|
||||||
/* The same thing, except caller does not hold allocation lock. */
|
/* Allocate memory such that only pointers to near the */
|
||||||
|
/* beginning of the object are considered. */
|
||||||
/* We avoid holding allocation lock while we clear memory. */
|
/* We avoid holding allocation lock while we clear memory. */
|
||||||
ptr_t GC_generic_malloc_ignore_off_page(lb, k)
|
ptr_t GC_generic_malloc_ignore_off_page(lb, k)
|
||||||
register size_t lb;
|
register size_t lb;
|
||||||
|
|
|
@ -25,7 +25,11 @@
|
||||||
|
|
||||||
/* We put this here to minimize the risk of inlining. */
|
/* We put this here to minimize the risk of inlining. */
|
||||||
/*VARARGS*/
|
/*VARARGS*/
|
||||||
void GC_noop(void *p, ...) {}
|
#ifdef __WATCOMC__
|
||||||
|
void GC_noop(void *p, ...) {}
|
||||||
|
#else
|
||||||
|
void GC_noop() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Single argument version, robust against whole program analysis. */
|
/* Single argument version, robust against whole program analysis. */
|
||||||
void GC_noop1(x)
|
void GC_noop1(x)
|
||||||
|
@ -40,66 +44,30 @@ word x;
|
||||||
|
|
||||||
word GC_n_mark_procs = GC_RESERVED_MARK_PROCS;
|
word GC_n_mark_procs = GC_RESERVED_MARK_PROCS;
|
||||||
|
|
||||||
/* PLTSCHEME: To work with MSVC /MD flag. Client must call GC_pre_init(). */
|
|
||||||
#ifdef USE_MSVC_MD_LIBRARY
|
|
||||||
# define INIT_FLD(x) 0
|
|
||||||
#else
|
|
||||||
# define INIT_FLD(x) x
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Initialize GC_obj_kinds properly and standard free lists properly. */
|
/* Initialize GC_obj_kinds properly and standard free lists properly. */
|
||||||
/* This must be done statically since they may be accessed before */
|
/* This must be done statically since they may be accessed before */
|
||||||
/* GC_init is called. */
|
/* GC_init is called. */
|
||||||
/* It's done here, since we need to deal with mark descriptors. */
|
/* It's done here, since we need to deal with mark descriptors. */
|
||||||
struct obj_kind GC_obj_kinds[MAXOBJKINDS] = {
|
struct obj_kind GC_obj_kinds[MAXOBJKINDS] = {
|
||||||
/* PTRFREE */ { INIT_FLD(&GC_aobjfreelist[0]), 0 /* filled in dynamically */,
|
/* PTRFREE */ { &GC_aobjfreelist[0], 0 /* filled in dynamically */,
|
||||||
0 | GC_DS_LENGTH, FALSE, FALSE },
|
0 | GC_DS_LENGTH, FALSE, FALSE },
|
||||||
/* NORMAL */ { INIT_FLD(&GC_objfreelist[0]), 0,
|
/* NORMAL */ { &GC_objfreelist[0], 0,
|
||||||
0 | GC_DS_LENGTH, /* Adjusted in GC_init_inner for EXTRA_BYTES */
|
0 | GC_DS_LENGTH, /* Adjusted in GC_init_inner for EXTRA_BYTES */
|
||||||
TRUE /* add length to descr */, TRUE },
|
TRUE /* add length to descr */, TRUE },
|
||||||
/* UNCOLLECTABLE */
|
/* UNCOLLECTABLE */
|
||||||
{ INIT_FLD(&GC_uobjfreelist[0]), 0,
|
{ &GC_uobjfreelist[0], 0,
|
||||||
0 | GC_DS_LENGTH, TRUE /* add length to descr */, TRUE },
|
0 | GC_DS_LENGTH, TRUE /* add length to descr */, TRUE },
|
||||||
# ifdef ATOMIC_UNCOLLECTABLE
|
# ifdef ATOMIC_UNCOLLECTABLE
|
||||||
/* AUNCOLLECTABLE */
|
/* AUNCOLLECTABLE */
|
||||||
{ INIT_FLD(&GC_auobjfreelist[0]), 0,
|
{ &GC_auobjfreelist[0], 0,
|
||||||
0 | GC_DS_LENGTH, FALSE /* add length to descr */, FALSE },
|
0 | GC_DS_LENGTH, FALSE /* add length to descr */, FALSE },
|
||||||
# endif
|
# endif
|
||||||
# ifdef STUBBORN_ALLOC
|
# ifdef STUBBORN_ALLOC
|
||||||
/*STUBBORN*/ { INIT_FLD(&GC_sobjfreelist[0]), 0,
|
/*STUBBORN*/ { &GC_sobjfreelist[0], 0,
|
||||||
0 | GC_DS_LENGTH, TRUE /* add length to descr */, TRUE },
|
0 | GC_DS_LENGTH, TRUE /* add length to descr */, TRUE },
|
||||||
# endif
|
# endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* PLTSCHEME: explicit init proc */
|
|
||||||
#ifdef USE_MSVC_MD_LIBRARY
|
|
||||||
# ifdef __CYGWIN32__
|
|
||||||
# include <windows.h>
|
|
||||||
# endif
|
|
||||||
void GC_pre_init(void)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
GC_obj_kinds[i++].ok_freelist = &GC_aobjfreelist[0];
|
|
||||||
GC_obj_kinds[i++].ok_freelist = &GC_objfreelist[0];
|
|
||||||
GC_obj_kinds[i++].ok_freelist = &GC_uobjfreelist[0];
|
|
||||||
# ifdef ATOMIC_UNCOLLECTABLE
|
|
||||||
GC_obj_kinds[i++].ok_freelist = &GC_auobjfreelist[0];
|
|
||||||
# endif
|
|
||||||
# ifdef STUBBORN_ALLOC
|
|
||||||
GC_obj_kinds[i++].ok_freelist = &GC_sobjfreelist[0];
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
# ifdef MD_LIB_MAIN
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)
|
|
||||||
{
|
|
||||||
if (reason == DLL_PROCESS_ATTACH)
|
|
||||||
GC_pre_init();
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# ifdef ATOMIC_UNCOLLECTABLE
|
# ifdef ATOMIC_UNCOLLECTABLE
|
||||||
# ifdef STUBBORN_ALLOC
|
# ifdef STUBBORN_ALLOC
|
||||||
int GC_n_kinds = 5;
|
int GC_n_kinds = 5;
|
||||||
|
@ -901,9 +869,9 @@ mse * GC_steal_mark_stack(mse * low, mse * high, mse * local,
|
||||||
++top;
|
++top;
|
||||||
top -> mse_descr = descr;
|
top -> mse_descr = descr;
|
||||||
top -> mse_start = p -> mse_start;
|
top -> mse_start = p -> mse_start;
|
||||||
GC_ASSERT( top -> mse_descr & GC_DS_TAGS != GC_DS_LENGTH ||
|
GC_ASSERT( (top -> mse_descr & GC_DS_TAGS) != GC_DS_LENGTH ||
|
||||||
top -> mse_descr < GC_greatest_plausible_heap_addr
|
top -> mse_descr < (ptr_t)GC_greatest_plausible_heap_addr
|
||||||
- GC_least_plausible_heap_addr);
|
- (ptr_t)GC_least_plausible_heap_addr);
|
||||||
/* If this is a big object, count it as */
|
/* If this is a big object, count it as */
|
||||||
/* size/256 + 1 objects. */
|
/* size/256 + 1 objects. */
|
||||||
++i;
|
++i;
|
||||||
|
@ -1493,8 +1461,8 @@ void GC_push_all_eager(bottom, top)
|
||||||
ptr_t bottom;
|
ptr_t bottom;
|
||||||
ptr_t top;
|
ptr_t top;
|
||||||
{
|
{
|
||||||
word * b = (word *)(((long) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
|
word * b = (word *)(((word) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
|
||||||
word * t = (word *)(((long) top) & ~(ALIGNMENT-1));
|
word * t = (word *)(((word) top) & ~(ALIGNMENT-1));
|
||||||
register word *p;
|
register word *p;
|
||||||
register word q;
|
register word q;
|
||||||
register word *lim;
|
register word *lim;
|
||||||
|
@ -1529,7 +1497,6 @@ ptr_t top;
|
||||||
ptr_t cold_gc_frame;
|
ptr_t cold_gc_frame;
|
||||||
{
|
{
|
||||||
if (!NEED_FIXUP_POINTER && GC_all_interior_pointers) {
|
if (!NEED_FIXUP_POINTER && GC_all_interior_pointers) {
|
||||||
# define EAGER_BYTES 1024
|
|
||||||
/* Push the hot end of the stack eagerly, so that register values */
|
/* Push the hot end of the stack eagerly, so that register values */
|
||||||
/* saved inside GC frames are marked before they disappear. */
|
/* saved inside GC frames are marked before they disappear. */
|
||||||
/* The rest of the marking can be deferred until later. */
|
/* The rest of the marking can be deferred until later. */
|
||||||
|
|
|
@ -375,8 +375,11 @@ ptr_t p;
|
||||||
|
|
||||||
ptr_t GC_approx_sp()
|
ptr_t GC_approx_sp()
|
||||||
{
|
{
|
||||||
word dummy;
|
VOLATILE word dummy;
|
||||||
|
|
||||||
|
dummy = 42; /* Force stack to grow if necessary. Otherwise the */
|
||||||
|
/* later accesses might cause the kernel to think we're */
|
||||||
|
/* doing something wrong. */
|
||||||
# ifdef _MSC_VER
|
# ifdef _MSC_VER
|
||||||
# pragma warning(disable:4172)
|
# pragma warning(disable:4172)
|
||||||
# endif
|
# endif
|
||||||
|
@ -662,3 +665,4 @@ void GC_flush_mark_stack()
|
||||||
{
|
{
|
||||||
while (!GC_mark_stack_empty()) GC_mark_from_mark_stack();
|
while (!GC_mark_stack_empty()) GC_mark_from_mark_stack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,10 @@
|
||||||
# include <tchar.h>
|
# include <tchar.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef NONSTOP
|
||||||
|
# include <floss.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
# ifdef THREADS
|
# ifdef THREADS
|
||||||
# ifdef PCR
|
# ifdef PCR
|
||||||
# include "il/PCR_IL.h"
|
# include "il/PCR_IL.h"
|
||||||
|
@ -246,7 +250,7 @@ void *arg2;
|
||||||
byte_sz = WORDS_TO_BYTES(word_sz);
|
byte_sz = WORDS_TO_BYTES(word_sz);
|
||||||
if (GC_all_interior_pointers) {
|
if (GC_all_interior_pointers) {
|
||||||
/* We need one extra byte; don't fill in GC_size_map[byte_sz] */
|
/* We need one extra byte; don't fill in GC_size_map[byte_sz] */
|
||||||
byte_sz--;
|
byte_sz -= EXTRA_BYTES;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = low_limit; j <= byte_sz; j++) GC_size_map[j] = word_sz;
|
for (j = low_limit; j <= byte_sz; j++) GC_size_map[j] = word_sz;
|
||||||
|
@ -477,10 +481,11 @@ void GC_init()
|
||||||
#if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
|
#if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
|
||||||
if (!GC_is_initialized) {
|
if (!GC_is_initialized) {
|
||||||
BOOL (WINAPI *pfn) (LPCRITICAL_SECTION, DWORD) = NULL;
|
BOOL (WINAPI *pfn) (LPCRITICAL_SECTION, DWORD) = NULL;
|
||||||
HMODULE hK32 = GetModuleHandle("kernel32.dll");
|
HMODULE hK32 = GetModuleHandleA("kernel32.dll");
|
||||||
if (hK32)
|
if (hK32)
|
||||||
(FARPROC) pfn = GetProcAddress(hK32,
|
pfn = (BOOL (WINAPI *) (LPCRITICAL_SECTION, DWORD))
|
||||||
"InitializeCriticalSectionAndSpinCount");
|
GetProcAddress (hK32,
|
||||||
|
"InitializeCriticalSectionAndSpinCount");
|
||||||
if (pfn)
|
if (pfn)
|
||||||
pfn(&GC_allocate_ml, 4000);
|
pfn(&GC_allocate_ml, 4000);
|
||||||
else
|
else
|
||||||
|
@ -714,13 +719,6 @@ void GC_init_inner()
|
||||||
# endif
|
# endif
|
||||||
GC_ASSERT((signed_word)(-1) < (signed_word)0);
|
GC_ASSERT((signed_word)(-1) < (signed_word)0);
|
||||||
|
|
||||||
/* PLTSCHEME: In case we use near data for 68k Mac, this array is declared FAR */
|
|
||||||
#ifdef __MC68K__
|
|
||||||
GC_add_roots_inner((ptr_t)&GC_arrays,
|
|
||||||
(ptr_t)(((char *)&GC_arrays) + sizeof(GC_arrays)),
|
|
||||||
FALSE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Add initial guess of root sets. Do this first, since sbrk(0) */
|
/* Add initial guess of root sets. Do this first, since sbrk(0) */
|
||||||
/* might be used. */
|
/* might be used. */
|
||||||
if (!GC_no_dls) /* PLTSCHEME: hack */
|
if (!GC_no_dls) /* PLTSCHEME: hack */
|
||||||
|
@ -813,7 +811,10 @@ void GC_init_inner()
|
||||||
|
|
||||||
void GC_enable_incremental GC_PROTO(())
|
void GC_enable_incremental GC_PROTO(())
|
||||||
{
|
{
|
||||||
# if !defined(SMALL_CONFIG)
|
# if !defined(SMALL_CONFIG) && !defined(KEEP_BACK_PTRS)
|
||||||
|
/* If we are keeping back pointers, the GC itself dirties all */
|
||||||
|
/* pages on which objects have been marked, making */
|
||||||
|
/* incremental GC pointless. */
|
||||||
if (!GC_find_leak) {
|
if (!GC_find_leak) {
|
||||||
DCL_LOCK_STATE;
|
DCL_LOCK_STATE;
|
||||||
|
|
||||||
|
@ -1063,7 +1064,7 @@ void GC_abort(msg)
|
||||||
GC_CONST char * msg;
|
GC_CONST char * msg;
|
||||||
{
|
{
|
||||||
# if defined(MSWIN32)
|
# if defined(MSWIN32)
|
||||||
//(void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK);
|
(void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK);
|
||||||
# else
|
# else
|
||||||
GC_err_printf1("%s\n", msg);
|
GC_err_printf1("%s\n", msg);
|
||||||
# endif
|
# endif
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
# Created: 1993-05-16
|
# Created: 1993-05-16
|
||||||
# Public domain
|
# Public domain
|
||||||
|
|
||||||
# $Id: mkinstalldirs,v 1.2 2004/07/21 13:07:55 mflatt Exp $
|
# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $
|
||||||
|
|
||||||
errstatus=0
|
errstatus=0
|
||||||
dirmode=""
|
dirmode=""
|
||||||
|
|
|
@ -60,6 +60,10 @@
|
||||||
# include <signal.h>
|
# include <signal.h>
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
#if defined(LINUX) || defined(LINUX_STACKBOTTOM)
|
||||||
|
# include <ctype.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Blatantly OS dependent routines, except for those that are related */
|
/* Blatantly OS dependent routines, except for those that are related */
|
||||||
/* to dynamic loading. */
|
/* to dynamic loading. */
|
||||||
|
|
||||||
|
@ -80,7 +84,7 @@
|
||||||
# define NEED_FIND_LIMIT
|
# define NEED_FIND_LIMIT
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#if defined(FREEBSD) && defined(I386)
|
#if defined(FREEBSD) && (defined(I386) || defined(powerpc) || defined(__powerpc__))
|
||||||
# include <machine/trap.h>
|
# include <machine/trap.h>
|
||||||
# if !defined(PCR)
|
# if !defined(PCR)
|
||||||
# define NEED_FIND_LIMIT
|
# define NEED_FIND_LIMIT
|
||||||
|
@ -245,30 +249,11 @@ word GC_apply_to_maps(word (*fn)(char *))
|
||||||
// XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537 name of mapping...\n
|
// XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537 name of mapping...\n
|
||||||
// ^^^^^^^^ ^^^^^^^^ ^^^^ ^^
|
// ^^^^^^^^ ^^^^^^^^ ^^^^ ^^
|
||||||
// start end prot maj_dev
|
// start end prot maj_dev
|
||||||
// 0 9 18 32
|
|
||||||
//
|
|
||||||
// For 64 bit ABIs:
|
|
||||||
// 0 17 34 56
|
|
||||||
//
|
//
|
||||||
// The parser is called with a pointer to the entry and the return value
|
// Note that since about auguat 2003 kernels, the columns no longer have
|
||||||
// is either NULL or is advanced to the next entry(the byte after the
|
// fixed offsets on 64-bit kernels. Hence we no longer rely on fixed offsets
|
||||||
// trailing '\n'.)
|
// anywhere, which is safer anyway.
|
||||||
//
|
//
|
||||||
#if CPP_WORDSZ == 32
|
|
||||||
# define OFFSET_MAP_START 0
|
|
||||||
# define OFFSET_MAP_END 9
|
|
||||||
# define OFFSET_MAP_PROT 18
|
|
||||||
# define OFFSET_MAP_MAJDEV 32
|
|
||||||
# define ADDR_WIDTH 8
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CPP_WORDSZ == 64
|
|
||||||
# define OFFSET_MAP_START 0
|
|
||||||
# define OFFSET_MAP_END 17
|
|
||||||
# define OFFSET_MAP_PROT 34
|
|
||||||
# define OFFSET_MAP_MAJDEV 56
|
|
||||||
# define ADDR_WIDTH 16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Assign various fields of the first line in buf_ptr to *start, *end,
|
* Assign various fields of the first line in buf_ptr to *start, *end,
|
||||||
|
@ -277,37 +262,46 @@ word GC_apply_to_maps(word (*fn)(char *))
|
||||||
char *GC_parse_map_entry(char *buf_ptr, word *start, word *end,
|
char *GC_parse_map_entry(char *buf_ptr, word *start, word *end,
|
||||||
char *prot_buf, unsigned int *maj_dev)
|
char *prot_buf, unsigned int *maj_dev)
|
||||||
{
|
{
|
||||||
int i;
|
char *start_start, *end_start, *prot_start, *maj_dev_start;
|
||||||
char *tok;
|
char *p;
|
||||||
|
char *endp;
|
||||||
|
|
||||||
if (buf_ptr == NULL || *buf_ptr == '\0') {
|
if (buf_ptr == NULL || *buf_ptr == '\0') {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(prot_buf, buf_ptr+OFFSET_MAP_PROT, 4);
|
p = buf_ptr;
|
||||||
/* do the protections first. */
|
while (isspace(*p)) ++p;
|
||||||
|
start_start = p;
|
||||||
|
GC_ASSERT(isxdigit(*start_start));
|
||||||
|
*start = strtoul(start_start, &endp, 16); p = endp;
|
||||||
|
GC_ASSERT(*p=='-');
|
||||||
|
|
||||||
|
++p;
|
||||||
|
end_start = p;
|
||||||
|
GC_ASSERT(isxdigit(*end_start));
|
||||||
|
*end = strtoul(end_start, &endp, 16); p = endp;
|
||||||
|
GC_ASSERT(isspace(*p));
|
||||||
|
|
||||||
|
while (isspace(*p)) ++p;
|
||||||
|
prot_start = p;
|
||||||
|
GC_ASSERT(*prot_start == 'r' || *prot_start == '-');
|
||||||
|
memcpy(prot_buf, prot_start, 4);
|
||||||
prot_buf[4] = '\0';
|
prot_buf[4] = '\0';
|
||||||
|
if (prot_buf[1] == 'w') {/* we can skip the rest if it's not writable. */
|
||||||
if (prot_buf[1] == 'w') {/* we can skip all of this if it's not writable. */
|
/* Skip past protection field to offset field */
|
||||||
|
while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
|
||||||
tok = buf_ptr;
|
GC_ASSERT(isxdigit(*p));
|
||||||
buf_ptr[OFFSET_MAP_START+ADDR_WIDTH] = '\0';
|
/* Skip past offset field, which we ignore */
|
||||||
*start = strtoul(tok, NULL, 16);
|
while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
|
||||||
|
maj_dev_start = p;
|
||||||
tok = buf_ptr+OFFSET_MAP_END;
|
GC_ASSERT(isxdigit(*maj_dev_start));
|
||||||
buf_ptr[OFFSET_MAP_END+ADDR_WIDTH] = '\0';
|
*maj_dev = strtoul(maj_dev_start, NULL, 16);
|
||||||
*end = strtoul(tok, NULL, 16);
|
|
||||||
|
|
||||||
buf_ptr += OFFSET_MAP_MAJDEV;
|
|
||||||
tok = buf_ptr;
|
|
||||||
while (*buf_ptr != ':') buf_ptr++;
|
|
||||||
*buf_ptr++ = '\0';
|
|
||||||
*maj_dev = strtoul(tok, NULL, 16);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (*buf_ptr && *buf_ptr++ != '\n');
|
while (*p && *p++ != '\n');
|
||||||
|
|
||||||
return buf_ptr;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Need to parse /proc/self/maps. */
|
#endif /* Need to parse /proc/self/maps. */
|
||||||
|
@ -706,7 +700,7 @@ ptr_t GC_get_stack_base()
|
||||||
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \
|
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \
|
||||||
|| defined(HURD) || defined(NETBSD)
|
|| defined(HURD) || defined(NETBSD)
|
||||||
static struct sigaction old_segv_act;
|
static struct sigaction old_segv_act;
|
||||||
# if defined(_sigargs) /* !Irix6.x */ || defined(HPUX) \
|
# if defined(IRIX5) || defined(HPUX) \
|
||||||
|| defined(HURD) || defined(NETBSD)
|
|| defined(HURD) || defined(NETBSD)
|
||||||
static struct sigaction old_bus_act;
|
static struct sigaction old_bus_act;
|
||||||
# endif
|
# endif
|
||||||
|
@ -739,9 +733,11 @@ ptr_t GC_get_stack_base()
|
||||||
/* and setting a handler at the same time. */
|
/* and setting a handler at the same time. */
|
||||||
(void) sigaction(SIGSEGV, 0, &old_segv_act);
|
(void) sigaction(SIGSEGV, 0, &old_segv_act);
|
||||||
(void) sigaction(SIGSEGV, &act, 0);
|
(void) sigaction(SIGSEGV, &act, 0);
|
||||||
|
(void) sigaction(SIGBUS, 0, &old_bus_act);
|
||||||
|
(void) sigaction(SIGBUS, &act, 0);
|
||||||
# else
|
# else
|
||||||
(void) sigaction(SIGSEGV, &act, &old_segv_act);
|
(void) sigaction(SIGSEGV, &act, &old_segv_act);
|
||||||
# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
|
# if defined(IRIX5) \
|
||||||
|| defined(HPUX) || defined(HURD) || defined(NETBSD)
|
|| defined(HPUX) || defined(HURD) || defined(NETBSD)
|
||||||
/* Under Irix 5.x or HP/UX, we may get SIGBUS. */
|
/* Under Irix 5.x or HP/UX, we may get SIGBUS. */
|
||||||
/* Pthreads doesn't exist under Irix 5.x, so we */
|
/* Pthreads doesn't exist under Irix 5.x, so we */
|
||||||
|
@ -780,7 +776,7 @@ ptr_t GC_get_stack_base()
|
||||||
# if defined(SUNOS5SIGS) || defined(IRIX5) \
|
# if defined(SUNOS5SIGS) || defined(IRIX5) \
|
||||||
|| defined(OSF1) || defined(HURD) || defined(NETBSD)
|
|| defined(OSF1) || defined(HURD) || defined(NETBSD)
|
||||||
(void) sigaction(SIGSEGV, &old_segv_act, 0);
|
(void) sigaction(SIGSEGV, &old_segv_act, 0);
|
||||||
# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
|
# if defined(IRIX5) \
|
||||||
|| defined(HPUX) || defined(HURD) || defined(NETBSD)
|
|| defined(HPUX) || defined(HURD) || defined(NETBSD)
|
||||||
(void) sigaction(SIGBUS, &old_bus_act, 0);
|
(void) sigaction(SIGBUS, &old_bus_act, 0);
|
||||||
# endif
|
# endif
|
||||||
|
@ -861,13 +857,14 @@ ptr_t GC_get_stack_base()
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
# define STAT_SKIP 27 /* Number of fields preceding startstack */
|
# define STAT_SKIP 27 /* Number of fields preceding startstack */
|
||||||
/* field in /proc/self/stat */
|
/* field in /proc/self/stat */
|
||||||
|
|
||||||
|
#ifdef USE_LIBC_PRIVATES
|
||||||
# pragma weak __libc_stack_end
|
# pragma weak __libc_stack_end
|
||||||
extern ptr_t __libc_stack_end;
|
extern ptr_t __libc_stack_end;
|
||||||
|
#endif
|
||||||
|
|
||||||
# ifdef IA64
|
# ifdef IA64
|
||||||
/* Try to read the backing store base from /proc/self/maps. */
|
/* Try to read the backing store base from /proc/self/maps. */
|
||||||
|
@ -897,30 +894,33 @@ ptr_t GC_get_stack_base()
|
||||||
return GC_apply_to_maps(backing_store_base_from_maps);
|
return GC_apply_to_maps(backing_store_base_from_maps);
|
||||||
}
|
}
|
||||||
|
|
||||||
# pragma weak __libc_ia64_register_backing_store_base
|
# ifdef USE_LIBC_PRIVATES
|
||||||
extern ptr_t __libc_ia64_register_backing_store_base;
|
# pragma weak __libc_ia64_register_backing_store_base
|
||||||
|
extern ptr_t __libc_ia64_register_backing_store_base;
|
||||||
|
# endif
|
||||||
|
|
||||||
ptr_t GC_get_register_stack_base(void)
|
ptr_t GC_get_register_stack_base(void)
|
||||||
{
|
{
|
||||||
if (0 != &__libc_ia64_register_backing_store_base
|
# ifdef USE_LIBC_PRIVATES
|
||||||
&& 0 != __libc_ia64_register_backing_store_base) {
|
if (0 != &__libc_ia64_register_backing_store_base
|
||||||
/* Glibc 2.2.4 has a bug such that for dynamically linked */
|
&& 0 != __libc_ia64_register_backing_store_base) {
|
||||||
/* executables __libc_ia64_register_backing_store_base is */
|
/* Glibc 2.2.4 has a bug such that for dynamically linked */
|
||||||
/* defined but uninitialized during constructor calls. */
|
/* executables __libc_ia64_register_backing_store_base is */
|
||||||
/* Hence we check for both nonzero address and value. */
|
/* defined but uninitialized during constructor calls. */
|
||||||
return __libc_ia64_register_backing_store_base;
|
/* Hence we check for both nonzero address and value. */
|
||||||
} else {
|
return __libc_ia64_register_backing_store_base;
|
||||||
word result = backing_store_base_from_proc();
|
}
|
||||||
if (0 == result) {
|
# endif
|
||||||
|
word result = backing_store_base_from_proc();
|
||||||
|
if (0 == result) {
|
||||||
/* Use dumb heuristics. Works only for default configuration. */
|
/* Use dumb heuristics. Works only for default configuration. */
|
||||||
result = (word)GC_stackbottom - BACKING_STORE_DISPLACEMENT;
|
result = (word)GC_stackbottom - BACKING_STORE_DISPLACEMENT;
|
||||||
result += BACKING_STORE_ALIGNMENT - 1;
|
result += BACKING_STORE_ALIGNMENT - 1;
|
||||||
result &= ~(BACKING_STORE_ALIGNMENT - 1);
|
result &= ~(BACKING_STORE_ALIGNMENT - 1);
|
||||||
/* Verify that it's at least readable. If not, we goofed. */
|
/* Verify that it's at least readable. If not, we goofed. */
|
||||||
GC_noop1(*(word *)result);
|
GC_noop1(*(word *)result);
|
||||||
}
|
|
||||||
return (ptr_t)result;
|
|
||||||
}
|
}
|
||||||
|
return (ptr_t)result;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
@ -943,6 +943,7 @@ ptr_t GC_get_stack_base()
|
||||||
/* since the correct value of __libc_stack_end never */
|
/* since the correct value of __libc_stack_end never */
|
||||||
/* becomes visible to us. The second test works around */
|
/* becomes visible to us. The second test works around */
|
||||||
/* this. */
|
/* this. */
|
||||||
|
# ifdef USE_LIBC_PRIVATES
|
||||||
if (0 != &__libc_stack_end && 0 != __libc_stack_end ) {
|
if (0 != &__libc_stack_end && 0 != __libc_stack_end ) {
|
||||||
# ifdef IA64
|
# ifdef IA64
|
||||||
/* Some versions of glibc set the address 16 bytes too */
|
/* Some versions of glibc set the address 16 bytes too */
|
||||||
|
@ -952,9 +953,19 @@ ptr_t GC_get_stack_base()
|
||||||
} /* Otherwise it's not safe to add 16 bytes and we fall */
|
} /* Otherwise it's not safe to add 16 bytes and we fall */
|
||||||
/* back to using /proc. */
|
/* back to using /proc. */
|
||||||
# else
|
# else
|
||||||
|
# ifdef SPARC
|
||||||
|
/* Older versions of glibc for 64-bit Sparc do not set
|
||||||
|
* this variable correctly, it gets set to either zero
|
||||||
|
* or one.
|
||||||
|
*/
|
||||||
|
if (__libc_stack_end != (ptr_t) (unsigned long)0x1)
|
||||||
|
return __libc_stack_end;
|
||||||
|
# else
|
||||||
return __libc_stack_end;
|
return __libc_stack_end;
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
# endif
|
||||||
f = open("/proc/self/stat", O_RDONLY);
|
f = open("/proc/self/stat", O_RDONLY);
|
||||||
if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) {
|
if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) {
|
||||||
ABORT("Couldn't read /proc/self/stat");
|
ABORT("Couldn't read /proc/self/stat");
|
||||||
|
@ -1177,12 +1188,15 @@ void GC_register_data_segments()
|
||||||
/* This used to be set for gcc, to avoid dealing with */
|
/* This used to be set for gcc, to avoid dealing with */
|
||||||
/* the structured exception handling issues. But we now have */
|
/* the structured exception handling issues. But we now have */
|
||||||
/* assembly code to do that right. */
|
/* assembly code to do that right. */
|
||||||
|
GC_bool GC_wnt = FALSE;
|
||||||
|
/* This is a Windows NT derivative, i.e. NT, W2K, XP or later. */
|
||||||
|
|
||||||
void GC_init_win32()
|
void GC_init_win32()
|
||||||
{
|
{
|
||||||
/* if we're running under win32s, assume that no DLLs will be loaded */
|
/* if we're running under win32s, assume that no DLLs will be loaded */
|
||||||
DWORD v = GetVersion();
|
DWORD v = GetVersion();
|
||||||
GC_no_win32_dlls |= ((v & 0x80000000) && (v & 0xff) <= 3);
|
GC_wnt = !(v & 0x80000000);
|
||||||
|
GC_no_win32_dlls |= ((!GC_wnt) && (v & 0xff) <= 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the smallest address a such that VirtualQuery */
|
/* Return the smallest address a such that VirtualQuery */
|
||||||
|
@ -1385,7 +1399,7 @@ int * etext_addr;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if defined(FREEBSD) && defined(I386) && !defined(PCR)
|
# if defined(FREEBSD) && (defined(I386) || defined(powerpc) || defined(__powerpc__)) && !defined(PCR)
|
||||||
/* Its unclear whether this should be identical to the above, or */
|
/* Its unclear whether this should be identical to the above, or */
|
||||||
/* whether it should apply to non-X86 architectures. */
|
/* whether it should apply to non-X86 architectures. */
|
||||||
/* For now we don't assume that there is always an empty page after */
|
/* For now we don't assume that there is always an empty page after */
|
||||||
|
@ -1494,7 +1508,7 @@ void GC_register_data_segments()
|
||||||
|
|
||||||
# if !defined(OS2) && !defined(PCR) && !defined(AMIGA) \
|
# if !defined(OS2) && !defined(PCR) && !defined(AMIGA) \
|
||||||
&& !defined(MSWIN32) && !defined(MSWINCE) \
|
&& !defined(MSWIN32) && !defined(MSWINCE) \
|
||||||
&& !defined(MACOS) && !defined(DOS4GW)
|
&& !defined(MACOS) && !defined(DOS4GW) && !defined(NONSTOP)
|
||||||
|
|
||||||
# ifdef SUNOS4
|
# ifdef SUNOS4
|
||||||
extern caddr_t sbrk();
|
extern caddr_t sbrk();
|
||||||
|
@ -1506,7 +1520,7 @@ void GC_register_data_segments()
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
|
||||||
# ifdef RS6000
|
# if 0 && defined(RS6000) /* We now use mmap */
|
||||||
/* The compiler seems to generate speculative reads one past the end of */
|
/* The compiler seems to generate speculative reads one past the end of */
|
||||||
/* an allocated object. Hence we need to make sure that the page */
|
/* an allocated object. Hence we need to make sure that the page */
|
||||||
/* following the last heap page is also mapped. */
|
/* following the last heap page is also mapped. */
|
||||||
|
@ -1572,13 +1586,6 @@ ptr_t GC_unix_get_mem(bytes)
|
||||||
word bytes;
|
word bytes;
|
||||||
{
|
{
|
||||||
void *result;
|
void *result;
|
||||||
/* PLTSCHEME: make sure HEAP_START and MAP_FAILED are defined: */
|
|
||||||
#if !defined(HEAP_START)
|
|
||||||
# define HEAP_START 0
|
|
||||||
#endif
|
|
||||||
#if !defined(MAP_FAILED)
|
|
||||||
# define MAP_FAILED ((void *)-1)
|
|
||||||
#endif
|
|
||||||
static ptr_t last_addr = HEAP_START;
|
static ptr_t last_addr = HEAP_START;
|
||||||
|
|
||||||
# ifndef USE_MMAP_ANON
|
# ifndef USE_MMAP_ANON
|
||||||
|
@ -1616,18 +1623,6 @@ word bytes;
|
||||||
ptr_t GC_unix_get_mem(bytes)
|
ptr_t GC_unix_get_mem(bytes)
|
||||||
word bytes;
|
word bytes;
|
||||||
{
|
{
|
||||||
/* PLTSCHEME: The SunOS4 man page says not use to sbrk() with malloc().
|
|
||||||
Xt definitely breaks in SunOS 4.x if I use sbrk. */
|
|
||||||
#if defined(sun)
|
|
||||||
ptr_t mem;
|
|
||||||
|
|
||||||
mem = malloc(bytes + HBLKSIZE - 1);
|
|
||||||
|
|
||||||
if ((long)mem % HBLKSIZE)
|
|
||||||
return mem + (HBLKSIZE - ((long)mem % HBLKSIZE));
|
|
||||||
else
|
|
||||||
return mem;
|
|
||||||
#else /* PLTSCHEME: end malloc() */
|
|
||||||
ptr_t result;
|
ptr_t result;
|
||||||
# ifdef IRIX5
|
# ifdef IRIX5
|
||||||
/* Bare sbrk isn't thread safe. Play by malloc rules. */
|
/* Bare sbrk isn't thread safe. Play by malloc rules. */
|
||||||
|
@ -1649,7 +1644,6 @@ word bytes;
|
||||||
__UNLOCK_MALLOC();
|
__UNLOCK_MALLOC();
|
||||||
# endif
|
# endif
|
||||||
return(result);
|
return(result);
|
||||||
#endif /* PLTSCHEME: close */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Not USE_MMAP */
|
#endif /* Not USE_MMAP */
|
||||||
|
@ -1709,7 +1703,7 @@ word bytes;
|
||||||
/* This wastes a small amount of memory, and risks */
|
/* This wastes a small amount of memory, and risks */
|
||||||
/* increased fragmentation. But better alternatives */
|
/* increased fragmentation. But better alternatives */
|
||||||
/* would require effort. */
|
/* would require effort. */
|
||||||
/* PLTSCHEME: PAGE_READWRITE works better for MrEd (because I don't need execute?) */
|
/* PLTSCHEME: use more conservative PAGE_READWRITE */
|
||||||
result = (ptr_t) VirtualAlloc(NULL, bytes + 1,
|
result = (ptr_t) VirtualAlloc(NULL, bytes + 1,
|
||||||
MEM_COMMIT | MEM_RESERVE,
|
MEM_COMMIT | MEM_RESERVE,
|
||||||
PAGE_READWRITE);
|
PAGE_READWRITE);
|
||||||
|
@ -2400,7 +2394,7 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
|
||||||
# endif
|
# endif
|
||||||
# ifdef FREEBSD
|
# ifdef FREEBSD
|
||||||
# define SIG_OK (sig == SIGBUS)
|
# define SIG_OK (sig == SIGBUS)
|
||||||
# define CODE_OK (code == BUS_PAGE_FAULT)
|
# define CODE_OK TRUE
|
||||||
# endif
|
# endif
|
||||||
# endif /* SUNOS4 || (FREEBSD && !SUNOS5SIGS) */
|
# endif /* SUNOS4 || (FREEBSD && !SUNOS5SIGS) */
|
||||||
|
|
||||||
|
@ -2538,7 +2532,11 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
|
||||||
# if defined(ARM32)
|
# if defined(ARM32)
|
||||||
char * addr = (char *)sc.fault_address;
|
char * addr = (char *)sc.fault_address;
|
||||||
# else
|
# else
|
||||||
--> architecture not supported
|
# if defined(CRIS)
|
||||||
|
char * addr = (char *)sc.regs.csraddr;
|
||||||
|
# else
|
||||||
|
--> architecture not supported
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
@ -2961,8 +2959,7 @@ word len;
|
||||||
/* to the write-protected heap with a system call. */
|
/* to the write-protected heap with a system call. */
|
||||||
/* This still serves as sample code if you do want to wrap system calls.*/
|
/* This still serves as sample code if you do want to wrap system calls.*/
|
||||||
|
|
||||||
/* PLTSCHEME: no read() redefinition for MacOS X */
|
#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(GC_USE_LD_WRAP)
|
||||||
#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(GC_USE_LD_WRAP) && !defined(DARWIN)
|
|
||||||
/* Replacement for UNIX system call. */
|
/* Replacement for UNIX system call. */
|
||||||
/* Other calls that write to the heap should be handled similarly. */
|
/* Other calls that write to the heap should be handled similarly. */
|
||||||
/* Note that this doesn't work well for blocking reads: It will hold */
|
/* Note that this doesn't work well for blocking reads: It will hold */
|
||||||
|
@ -3745,7 +3742,7 @@ static kern_return_t GC_forward_exception(
|
||||||
exception_behavior_t behavior;
|
exception_behavior_t behavior;
|
||||||
thread_state_flavor_t flavor;
|
thread_state_flavor_t flavor;
|
||||||
|
|
||||||
thread_state_data_t thread_state;
|
thread_state_t thread_state;
|
||||||
mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;
|
mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;
|
||||||
|
|
||||||
for(i=0;i<GC_old_exc_ports.count;i++)
|
for(i=0;i<GC_old_exc_ports.count;i++)
|
||||||
|
@ -3806,13 +3803,23 @@ catch_exception_raise(
|
||||||
char *addr;
|
char *addr;
|
||||||
struct hblk *h;
|
struct hblk *h;
|
||||||
int i;
|
int i;
|
||||||
#ifdef POWERPC
|
# if defined(POWERPC)
|
||||||
thread_state_flavor_t flavor = PPC_EXCEPTION_STATE;
|
# if CPP_WORDSZ == 32
|
||||||
mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE_COUNT;
|
thread_state_flavor_t flavor = PPC_EXCEPTION_STATE;
|
||||||
ppc_exception_state_t exc_state;
|
mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE_COUNT;
|
||||||
#else
|
ppc_exception_state_t exc_state;
|
||||||
# error FIXME for non-ppc darwin
|
# else
|
||||||
#endif
|
thread_state_flavor_t flavor = PPC_EXCEPTION_STATE64;
|
||||||
|
mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE64_COUNT;
|
||||||
|
ppc_exception_state64_t exc_state;
|
||||||
|
# endif
|
||||||
|
# elif defined(I386)
|
||||||
|
thread_state_flavor_t flavor = i386_EXCEPTION_STATE;
|
||||||
|
mach_msg_type_number_t exc_state_count = i386_EXCEPTION_STATE_COUNT;
|
||||||
|
i386_exception_state_t exc_state;
|
||||||
|
# else
|
||||||
|
# error FIXME for non-ppc/x86 darwin
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
if(exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) {
|
if(exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) {
|
||||||
|
@ -3841,7 +3848,13 @@ catch_exception_raise(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the address that caused the fault */
|
/* This is the address that caused the fault */
|
||||||
|
#if defined(POWERPC)
|
||||||
addr = (char*) exc_state.dar;
|
addr = (char*) exc_state.dar;
|
||||||
|
#elif defined (I386)
|
||||||
|
addr = (char*) exc_state.faultvaddr;
|
||||||
|
#else
|
||||||
|
# error FIXME for non POWERPC/I386
|
||||||
|
#endif
|
||||||
|
|
||||||
if((HDR(addr)) == 0) {
|
if((HDR(addr)) == 0) {
|
||||||
/* Ugh... just like the SIGBUS problem above, it seems we get a bogus
|
/* Ugh... just like the SIGBUS problem above, it seems we get a bogus
|
||||||
|
@ -3972,10 +3985,14 @@ kern_return_t catch_exception_raise_state_identity(
|
||||||
# if defined (DRSNX)
|
# if defined (DRSNX)
|
||||||
# include <sys/sparc/frame.h>
|
# include <sys/sparc/frame.h>
|
||||||
# else
|
# else
|
||||||
# if defined(OPENBSD) || defined(NETBSD)
|
# if defined(OPENBSD)
|
||||||
# include <frame.h>
|
# include <frame.h>
|
||||||
# else
|
# else
|
||||||
# include <sys/frame.h>
|
# if defined(FREEBSD) || defined(NETBSD)
|
||||||
|
# include <machine/frame.h>
|
||||||
|
# else
|
||||||
|
# include <sys/frame.h>
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
@ -4004,6 +4021,16 @@ kern_return_t catch_exception_raise_state_identity(
|
||||||
#if NARGS == 0 && NFRAMES % 2 == 0 /* No padding */ \
|
#if NARGS == 0 && NFRAMES % 2 == 0 /* No padding */ \
|
||||||
&& defined(GC_HAVE_BUILTIN_BACKTRACE)
|
&& defined(GC_HAVE_BUILTIN_BACKTRACE)
|
||||||
|
|
||||||
|
#ifdef REDIRECT_MALLOC
|
||||||
|
/* Deal with possible malloc calls in backtrace by omitting */
|
||||||
|
/* the infinitely recursing backtrace. */
|
||||||
|
# ifdef THREADS
|
||||||
|
__thread /* If your compiler doesn't understand this */
|
||||||
|
/* you could use something like pthread_getspecific. */
|
||||||
|
# endif
|
||||||
|
GC_in_save_callers = FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
void GC_save_callers (info)
|
void GC_save_callers (info)
|
||||||
struct callinfo info[NFRAMES];
|
struct callinfo info[NFRAMES];
|
||||||
{
|
{
|
||||||
|
@ -4013,15 +4040,26 @@ struct callinfo info[NFRAMES];
|
||||||
|
|
||||||
/* We retrieve NFRAMES+1 pc values, but discard the first, since it */
|
/* We retrieve NFRAMES+1 pc values, but discard the first, since it */
|
||||||
/* points to our own frame. */
|
/* points to our own frame. */
|
||||||
|
# ifdef REDIRECT_MALLOC
|
||||||
|
if (GC_in_save_callers) {
|
||||||
|
info[0].ci_pc = (word)(&GC_save_callers);
|
||||||
|
for (i = 1; i < NFRAMES; ++i) info[i].ci_pc = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GC_in_save_callers = TRUE;
|
||||||
|
# endif
|
||||||
GC_ASSERT(sizeof(struct callinfo) == sizeof(void *));
|
GC_ASSERT(sizeof(struct callinfo) == sizeof(void *));
|
||||||
npcs = backtrace((void **)tmp_info, NFRAMES + IGNORE_FRAMES);
|
npcs = backtrace((void **)tmp_info, NFRAMES + IGNORE_FRAMES);
|
||||||
BCOPY(tmp_info+IGNORE_FRAMES, info, (npcs - IGNORE_FRAMES) * sizeof(void *));
|
BCOPY(tmp_info+IGNORE_FRAMES, info, (npcs - IGNORE_FRAMES) * sizeof(void *));
|
||||||
for (i = npcs - IGNORE_FRAMES; i < NFRAMES; ++i) info[i].ci_pc = 0;
|
for (i = npcs - IGNORE_FRAMES; i < NFRAMES; ++i) info[i].ci_pc = 0;
|
||||||
|
# ifdef REDIRECT_MALLOC
|
||||||
|
GC_in_save_callers = FALSE;
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* No builtin backtrace; do it ourselves */
|
#else /* No builtin backtrace; do it ourselves */
|
||||||
|
|
||||||
#if (defined(OPENBSD) || defined(NETBSD)) && defined(SPARC)
|
#if (defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD)) && defined(SPARC)
|
||||||
# define FR_SAVFP fr_fp
|
# define FR_SAVFP fr_fp
|
||||||
# define FR_SAVPC fr_pc
|
# define FR_SAVPC fr_pc
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -1,10 +1,21 @@
|
||||||
|
#if defined(__ppc64__)
|
||||||
|
#define MODE_CHOICE(x, y) y
|
||||||
|
#else
|
||||||
|
#define MODE_CHOICE(x, y) x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define lgu MODE_CHOICE(lwzu, ldu)
|
||||||
|
|
||||||
|
#define g_long MODE_CHOICE(long, quad) /* usage is ".g_long" */
|
||||||
|
|
||||||
|
#define LOG2_GPR_BYTES MODE_CHOICE(2,3) /* log2(GPR_BYTES) */
|
||||||
|
|
||||||
; GC_push_regs function. Under some optimization levels GCC will clobber
|
; GC_push_regs function. Under some optimization levels GCC will clobber
|
||||||
; some of the non-volatile registers before we get a chance to save them
|
; some of the non-volatile registers before we get a chance to save them
|
||||||
; therefore, this can't be inline asm.
|
; therefore, this cannot be inline asm.
|
||||||
|
|
||||||
.text
|
.text
|
||||||
.align 2
|
.align LOG2_GPR_BYTES
|
||||||
.globl _GC_push_regs
|
.globl _GC_push_regs
|
||||||
_GC_push_regs:
|
_GC_push_regs:
|
||||||
|
|
||||||
|
@ -64,7 +75,8 @@ _GC_push_regs:
|
||||||
; PIC stuff, generated by GCC
|
; PIC stuff, generated by GCC
|
||||||
|
|
||||||
.data
|
.data
|
||||||
.picsymbol_stub
|
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||||
|
.align LOG2_GPR_BYTES
|
||||||
L_GC_push_one$stub:
|
L_GC_push_one$stub:
|
||||||
.indirect_symbol _GC_push_one
|
.indirect_symbol _GC_push_one
|
||||||
mflr r0
|
mflr r0
|
||||||
|
@ -73,12 +85,11 @@ L0$_GC_push_one:
|
||||||
mflr r11
|
mflr r11
|
||||||
addis r11,r11,ha16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)
|
addis r11,r11,ha16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)
|
||||||
mtlr r0
|
mtlr r0
|
||||||
lwz r12,lo16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)(r11)
|
lgu r12,lo16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)(r11)
|
||||||
mtctr r12
|
mtctr r12
|
||||||
addi r11,r11,lo16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)
|
|
||||||
bctr
|
bctr
|
||||||
.data
|
.data
|
||||||
.lazy_symbol_pointer
|
.lazy_symbol_pointer
|
||||||
L_GC_push_one$lazy_ptr:
|
L_GC_push_one$lazy_ptr:
|
||||||
.indirect_symbol _GC_push_one
|
.indirect_symbol _GC_push_one
|
||||||
.long dyld_stub_binding_helper
|
.g_long dyld_stub_binding_helper
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
#include "private/pthread_support.h"
|
#include "private/pthread_support.h"
|
||||||
|
|
||||||
#if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
|
#if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
|
||||||
&& !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS) \
|
&& !defined(GC_WIN32_THREADS) && !defined(GC_DARWIN_THREADS)
|
||||||
&& !defined(GC_DARWIN_THREADS) && !defined(GC_AIX_THREADS)
|
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#ifndef HPUX
|
||||||
|
# include <sys/select.h>
|
||||||
|
/* Doesn't exist on HP/UX 11.11. */
|
||||||
|
#endif
|
||||||
|
|
||||||
#if DEBUG_THREADS
|
#if DEBUG_THREADS
|
||||||
|
|
||||||
|
@ -67,7 +71,22 @@ void GC_remove_allowed_signals(sigset_t *set)
|
||||||
|
|
||||||
static sigset_t suspend_handler_mask;
|
static sigset_t suspend_handler_mask;
|
||||||
|
|
||||||
word GC_stop_count; /* Incremented at the beginning of GC_stop_world. */
|
volatile sig_atomic_t GC_stop_count;
|
||||||
|
/* Incremented at the beginning of GC_stop_world. */
|
||||||
|
|
||||||
|
volatile sig_atomic_t GC_world_is_stopped = FALSE;
|
||||||
|
/* FALSE ==> it is safe for threads to restart, i.e. */
|
||||||
|
/* they will see another suspend signal before they */
|
||||||
|
/* are expected to stop (unless they have voluntarily */
|
||||||
|
/* stopped). */
|
||||||
|
|
||||||
|
void GC_brief_async_signal_safe_sleep()
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 1000 * TIME_LIMIT / 2;
|
||||||
|
select(0, 0, 0, 0, &tv);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef GC_OSF1_THREADS
|
#ifdef GC_OSF1_THREADS
|
||||||
GC_bool GC_retry_signals = TRUE;
|
GC_bool GC_retry_signals = TRUE;
|
||||||
|
@ -88,7 +107,7 @@ word GC_stop_count; /* Incremented at the beginning of GC_stop_world. */
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SIG_THR_RESTART
|
#ifndef SIG_THR_RESTART
|
||||||
# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS)
|
# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || defined(GC_NETBSD_THREADS)
|
||||||
# ifdef _SIGRTMIN
|
# ifdef _SIGRTMIN
|
||||||
# define SIG_THR_RESTART _SIGRTMIN + 5
|
# define SIG_THR_RESTART _SIGRTMIN + 5
|
||||||
# else
|
# else
|
||||||
|
@ -101,8 +120,39 @@ word GC_stop_count; /* Incremented at the beginning of GC_stop_world. */
|
||||||
|
|
||||||
sem_t GC_suspend_ack_sem;
|
sem_t GC_suspend_ack_sem;
|
||||||
|
|
||||||
|
#ifdef GC_NETBSD_THREADS
|
||||||
|
# define GC_NETBSD_THREADS_WORKAROUND
|
||||||
|
/* It seems to be necessary to wait until threads have restarted. */
|
||||||
|
/* But it is unclear why that is the case. */
|
||||||
|
sem_t GC_restart_ack_sem;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void GC_suspend_handler_inner(ptr_t sig_arg);
|
||||||
|
|
||||||
|
#if defined(IA64) || defined(HP_PA)
|
||||||
|
extern void GC_with_callee_saves_pushed();
|
||||||
|
|
||||||
void GC_suspend_handler(int sig)
|
void GC_suspend_handler(int sig)
|
||||||
{
|
{
|
||||||
|
int old_errno = errno;
|
||||||
|
GC_with_callee_saves_pushed(GC_suspend_handler_inner, (ptr_t)(word)sig);
|
||||||
|
errno = old_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
/* We believe that in all other cases the full context is already */
|
||||||
|
/* in the signal handler frame. */
|
||||||
|
void GC_suspend_handler(int sig)
|
||||||
|
{
|
||||||
|
int old_errno = errno;
|
||||||
|
GC_suspend_handler_inner((ptr_t)(word)sig);
|
||||||
|
errno = old_errno;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void GC_suspend_handler_inner(ptr_t sig_arg)
|
||||||
|
{
|
||||||
|
int sig = (int)(word)sig_arg;
|
||||||
int dummy;
|
int dummy;
|
||||||
pthread_t my_thread = pthread_self();
|
pthread_t my_thread = pthread_self();
|
||||||
GC_thread me;
|
GC_thread me;
|
||||||
|
@ -152,16 +202,26 @@ void GC_suspend_handler(int sig)
|
||||||
/* this thread a SIG_THR_RESTART signal. */
|
/* this thread a SIG_THR_RESTART signal. */
|
||||||
/* SIG_THR_RESTART should be masked at this point. Thus there */
|
/* SIG_THR_RESTART should be masked at this point. Thus there */
|
||||||
/* is no race. */
|
/* is no race. */
|
||||||
do {
|
/* We do not continue until we receive a SIG_THR_RESTART, */
|
||||||
me->stop_info.signal = 0;
|
/* but we do not take that as authoritative. (We may be */
|
||||||
sigsuspend(&suspend_handler_mask); /* Wait for signal */
|
/* accidentally restarted by one of the user signals we */
|
||||||
} while (me->stop_info.signal != SIG_THR_RESTART);
|
/* don't block.) After we receive the signal, we use a */
|
||||||
|
/* primitive and expensive mechanism to wait until it's */
|
||||||
|
/* really safe to proceed. Under normal circumstances, */
|
||||||
|
/* this code should not be executed. */
|
||||||
|
sigsuspend(&suspend_handler_mask); /* Wait for signal */
|
||||||
|
while (GC_world_is_stopped && GC_stop_count == my_stop_count) {
|
||||||
|
GC_brief_async_signal_safe_sleep();
|
||||||
|
# if DEBUG_THREADS
|
||||||
|
GC_err_printf0("Sleeping in signal handler");
|
||||||
|
# endif
|
||||||
|
}
|
||||||
/* If the RESTART signal gets lost, we can still lose. That should be */
|
/* If the RESTART signal gets lost, we can still lose. That should be */
|
||||||
/* less likely than losing the SUSPEND signal, since we don't do much */
|
/* less likely than losing the SUSPEND signal, since we don't do much */
|
||||||
/* between the sem_post and sigsuspend. */
|
/* between the sem_post and sigsuspend. */
|
||||||
/* We'd need more handshaking to work around that, since we don't want */
|
/* We'd need more handshaking to work around that. */
|
||||||
/* to accidentally leave a RESTART signal pending, thus causing us to */
|
/* Simply dropping the sigsuspend call should be safe, but is unlikely */
|
||||||
/* continue prematurely in a future round. */
|
/* to be efficient. */
|
||||||
|
|
||||||
#if DEBUG_THREADS
|
#if DEBUG_THREADS
|
||||||
GC_printf1("Continuing 0x%lx\n", my_thread);
|
GC_printf1("Continuing 0x%lx\n", my_thread);
|
||||||
|
@ -171,20 +231,15 @@ void GC_suspend_handler(int sig)
|
||||||
void GC_restart_handler(int sig)
|
void GC_restart_handler(int sig)
|
||||||
{
|
{
|
||||||
pthread_t my_thread = pthread_self();
|
pthread_t my_thread = pthread_self();
|
||||||
GC_thread me;
|
|
||||||
|
|
||||||
if (sig != SIG_THR_RESTART) ABORT("Bad signal in suspend_handler");
|
if (sig != SIG_THR_RESTART) ABORT("Bad signal in suspend_handler");
|
||||||
|
|
||||||
/* Let the GC_suspend_handler() know that we got a SIG_THR_RESTART. */
|
#ifdef GC_NETBSD_THREADS_WORKAROUND
|
||||||
/* The lookup here is safe, since I'm doing this on behalf */
|
sem_post(&GC_restart_ack_sem);
|
||||||
/* of a thread which holds the allocation lock in order */
|
#endif
|
||||||
/* to stop the world. Thus concurrent modification of the */
|
|
||||||
/* data structure is impossible. */
|
|
||||||
me = GC_lookup_thread(my_thread);
|
|
||||||
me->stop_info.signal = SIG_THR_RESTART;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Note: even if we didn't do anything useful here,
|
** Note: even if we don't do anything useful here,
|
||||||
** it would still be necessary to have a signal handler,
|
** it would still be necessary to have a signal handler,
|
||||||
** rather than ignoring the signals, otherwise
|
** rather than ignoring the signals, otherwise
|
||||||
** the signals will not be delivered at all, and
|
** the signals will not be delivered at all, and
|
||||||
|
@ -259,6 +314,8 @@ void GC_push_all_stacks()
|
||||||
(unsigned long) bs_lo, (unsigned long) bs_hi);
|
(unsigned long) bs_lo, (unsigned long) bs_hi);
|
||||||
# endif
|
# endif
|
||||||
if (pthread_equal(p -> id, me)) {
|
if (pthread_equal(p -> id, me)) {
|
||||||
|
/* FIXME: This may add an unbounded number of entries, */
|
||||||
|
/* and hence overflow the mark stack, which is bad. */
|
||||||
GC_push_all_eager(bs_lo, bs_hi);
|
GC_push_all_eager(bs_lo, bs_hi);
|
||||||
} else {
|
} else {
|
||||||
GC_push_all_stack(bs_lo, bs_hi);
|
GC_push_all_stack(bs_lo, bs_hi);
|
||||||
|
@ -337,6 +394,7 @@ void GC_stop_world()
|
||||||
/* We should have previously waited for it to become zero. */
|
/* We should have previously waited for it to become zero. */
|
||||||
# endif /* PARALLEL_MARK */
|
# endif /* PARALLEL_MARK */
|
||||||
++GC_stop_count;
|
++GC_stop_count;
|
||||||
|
GC_world_is_stopped = TRUE;
|
||||||
n_live_threads = GC_suspend_all();
|
n_live_threads = GC_suspend_all();
|
||||||
|
|
||||||
if (GC_retry_signals) {
|
if (GC_retry_signals) {
|
||||||
|
@ -369,9 +427,11 @@ void GC_stop_world()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < n_live_threads; i++) {
|
for (i = 0; i < n_live_threads; i++) {
|
||||||
if (0 != (code = sem_wait(&GC_suspend_ack_sem))) {
|
while (0 != (code = sem_wait(&GC_suspend_ack_sem))) {
|
||||||
GC_err_printf1("Sem_wait returned %ld\n", (unsigned long)code);
|
if (errno != EINTR) {
|
||||||
ABORT("sem_wait for handler failed");
|
GC_err_printf1("Sem_wait returned %ld\n", (unsigned long)code);
|
||||||
|
ABORT("sem_wait for handler failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# ifdef PARALLEL_MARK
|
# ifdef PARALLEL_MARK
|
||||||
|
@ -392,11 +452,15 @@ void GC_start_world()
|
||||||
register GC_thread p;
|
register GC_thread p;
|
||||||
register int n_live_threads = 0;
|
register int n_live_threads = 0;
|
||||||
register int result;
|
register int result;
|
||||||
|
#ifdef GC_NETBSD_THREADS_WORKAROUND
|
||||||
|
int code;
|
||||||
|
#endif
|
||||||
|
|
||||||
# if DEBUG_THREADS
|
# if DEBUG_THREADS
|
||||||
GC_printf0("World starting\n");
|
GC_printf0("World starting\n");
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
GC_world_is_stopped = FALSE;
|
||||||
for (i = 0; i < THREAD_TABLE_SZ; i++) {
|
for (i = 0; i < THREAD_TABLE_SZ; i++) {
|
||||||
for (p = GC_threads[i]; p != 0; p = p -> next) {
|
for (p = GC_threads[i]; p != 0; p = p -> next) {
|
||||||
if (p -> id != my_thread) {
|
if (p -> id != my_thread) {
|
||||||
|
@ -406,8 +470,7 @@ void GC_start_world()
|
||||||
#if DEBUG_THREADS
|
#if DEBUG_THREADS
|
||||||
GC_printf1("Sending restart signal to 0x%lx\n", p -> id);
|
GC_printf1("Sending restart signal to 0x%lx\n", p -> id);
|
||||||
#endif
|
#endif
|
||||||
|
result = pthread_kill(p -> id, SIG_THR_RESTART);
|
||||||
result = pthread_kill(p -> id, SIG_THR_RESTART);
|
|
||||||
switch(result) {
|
switch(result) {
|
||||||
case ESRCH:
|
case ESRCH:
|
||||||
/* Not really there anymore. Possible? */
|
/* Not really there anymore. Possible? */
|
||||||
|
@ -421,6 +484,14 @@ void GC_start_world()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef GC_NETBSD_THREADS_WORKAROUND
|
||||||
|
for (i = 0; i < n_live_threads; i++)
|
||||||
|
while (0 != (code = sem_wait(&GC_restart_ack_sem)))
|
||||||
|
if (errno != EINTR) {
|
||||||
|
GC_err_printf1("sem_wait() returned %ld\n", (unsigned long)code);
|
||||||
|
ABORT("sem_wait() for restart handler failed");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#if DEBUG_THREADS
|
#if DEBUG_THREADS
|
||||||
GC_printf0("World started\n");
|
GC_printf0("World started\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -431,6 +502,10 @@ void GC_stop_init() {
|
||||||
|
|
||||||
if (sem_init(&GC_suspend_ack_sem, 0, 0) != 0)
|
if (sem_init(&GC_suspend_ack_sem, 0, 0) != 0)
|
||||||
ABORT("sem_init failed");
|
ABORT("sem_init failed");
|
||||||
|
#ifdef GC_NETBSD_THREADS_WORKAROUND
|
||||||
|
if (sem_init(&GC_restart_ack_sem, 0, 0) != 0)
|
||||||
|
ABORT("sem_init failed");
|
||||||
|
#endif
|
||||||
|
|
||||||
act.sa_flags = SA_RESTART;
|
act.sa_flags = SA_RESTART;
|
||||||
if (sigfillset(&act.sa_mask) != 0) {
|
if (sigfillset(&act.sa_mask) != 0) {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* Copyright (c) 1994 by Xerox Corporation. All rights reserved.
|
* Copyright (c) 1994 by Xerox Corporation. All rights reserved.
|
||||||
* Copyright (c) 1996 by Silicon Graphics. All rights reserved.
|
* Copyright (c) 1996 by Silicon Graphics. All rights reserved.
|
||||||
* Copyright (c) 1998 by Fergus Henderson. All rights reserved.
|
* Copyright (c) 1998 by Fergus Henderson. All rights reserved.
|
||||||
* Copyright (c) 2000-2001 by Hewlett-Packard Company. All rights reserved.
|
* Copyright (c) 2000-2004 by Hewlett-Packard Company. All rights reserved.
|
||||||
*
|
*
|
||||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||||
|
@ -50,8 +50,7 @@
|
||||||
# include "private/pthread_support.h"
|
# include "private/pthread_support.h"
|
||||||
|
|
||||||
# if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
|
# if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
|
||||||
&& !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS) \
|
&& !defined(GC_WIN32_THREADS)
|
||||||
&& !defined(GC_AIX_THREADS)
|
|
||||||
|
|
||||||
# if defined(GC_HPUX_THREADS) && !defined(USE_PTHREAD_SPECIFIC) \
|
# if defined(GC_HPUX_THREADS) && !defined(USE_PTHREAD_SPECIFIC) \
|
||||||
&& !defined(USE_COMPILER_TLS)
|
&& !defined(USE_COMPILER_TLS)
|
||||||
|
@ -68,7 +67,9 @@
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \
|
# if (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \
|
||||||
defined(GC_DARWIN_THREADS)) && !defined(USE_PTHREAD_SPECIFIC)
|
defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS) || \
|
||||||
|
defined(GC_NETBSD_THREADS)) \
|
||||||
|
&& !defined(USE_PTHREAD_SPECIFIC)
|
||||||
# define USE_PTHREAD_SPECIFIC
|
# define USE_PTHREAD_SPECIFIC
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
@ -116,11 +117,14 @@
|
||||||
# include <semaphore.h>
|
# include <semaphore.h>
|
||||||
#endif /* !GC_DARWIN_THREADS */
|
#endif /* !GC_DARWIN_THREADS */
|
||||||
|
|
||||||
#if defined(GC_DARWIN_THREADS)
|
#if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
|
||||||
# include <sys/sysctl.h>
|
# include <sys/sysctl.h>
|
||||||
#endif /* GC_DARWIN_THREADS */
|
#endif /* GC_DARWIN_THREADS */
|
||||||
|
|
||||||
|
#if defined(GC_NETBSD_THREADS)
|
||||||
|
# include <sys/param.h>
|
||||||
|
# include <sys/sysctl.h>
|
||||||
|
#endif /* GC_NETBSD_THREADS */
|
||||||
|
|
||||||
#if defined(GC_DGUX386_THREADS)
|
#if defined(GC_DGUX386_THREADS)
|
||||||
# include <sys/dg_sys_info.h>
|
# include <sys/dg_sys_info.h>
|
||||||
|
@ -836,12 +840,24 @@ int GC_get_nprocs()
|
||||||
}
|
}
|
||||||
#endif /* GC_DGUX386_THREADS */
|
#endif /* GC_DGUX386_THREADS */
|
||||||
|
|
||||||
|
#if defined(GC_NETBSD_THREADS)
|
||||||
|
static int get_ncpu(void)
|
||||||
|
{
|
||||||
|
int mib[] = {CTL_HW,HW_NCPU};
|
||||||
|
int res;
|
||||||
|
size_t len = sizeof(res);
|
||||||
|
|
||||||
|
sysctl(mib, sizeof(mib)/sizeof(int), &res, &len, NULL, 0);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif /* GC_NETBSD_THREADS */
|
||||||
|
|
||||||
/* We hold the allocation lock. */
|
/* We hold the allocation lock. */
|
||||||
void GC_thr_init()
|
void GC_thr_init()
|
||||||
{
|
{
|
||||||
# ifndef GC_DARWIN_THREADS
|
# ifndef GC_DARWIN_THREADS
|
||||||
int dummy;
|
int dummy;
|
||||||
# endif
|
# endif
|
||||||
GC_thread t;
|
GC_thread t;
|
||||||
|
|
||||||
if (GC_thr_initialized) return;
|
if (GC_thr_initialized) return;
|
||||||
|
@ -873,14 +889,18 @@ void GC_thr_init()
|
||||||
# if defined(GC_HPUX_THREADS)
|
# if defined(GC_HPUX_THREADS)
|
||||||
GC_nprocs = pthread_num_processors_np();
|
GC_nprocs = pthread_num_processors_np();
|
||||||
# endif
|
# endif
|
||||||
# if defined(GC_OSF1_THREADS)
|
# if defined(GC_OSF1_THREADS) || defined(GC_AIX_THREADS)
|
||||||
GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN);
|
GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
if (GC_nprocs <= 0) GC_nprocs = 1;
|
if (GC_nprocs <= 0) GC_nprocs = 1;
|
||||||
# endif
|
# endif
|
||||||
# if defined(GC_FREEBSD_THREADS)
|
# if defined(GC_IRIX_THREADS)
|
||||||
GC_nprocs = 1;
|
GC_nprocs = sysconf(_SC_NPROC_ONLN);
|
||||||
|
if (GC_nprocs <= 0) GC_nprocs = 1;
|
||||||
# endif
|
# endif
|
||||||
# if defined(GC_DARWIN_THREADS)
|
# if defined(GC_NETBSD_THREADS)
|
||||||
|
GC_nprocs = get_ncpu();
|
||||||
|
# endif
|
||||||
|
# if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
|
||||||
int ncpus = 1;
|
int ncpus = 1;
|
||||||
size_t len = sizeof(ncpus);
|
size_t len = sizeof(ncpus);
|
||||||
sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0);
|
sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0);
|
||||||
|
@ -927,6 +947,8 @@ void GC_thr_init()
|
||||||
/* Disable true incremental collection, but generational is OK. */
|
/* Disable true incremental collection, but generational is OK. */
|
||||||
GC_time_limit = GC_TIME_UNLIMITED;
|
GC_time_limit = GC_TIME_UNLIMITED;
|
||||||
}
|
}
|
||||||
|
/* If we are using a parallel marker, actually start helper threads. */
|
||||||
|
if (GC_parallel) start_mark_threads();
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -943,10 +965,6 @@ void GC_init_parallel()
|
||||||
|
|
||||||
/* GC_init() calls us back, so set flag first. */
|
/* GC_init() calls us back, so set flag first. */
|
||||||
if (!GC_is_initialized) GC_init();
|
if (!GC_is_initialized) GC_init();
|
||||||
/* If we are using a parallel marker, start the helper threads. */
|
|
||||||
# ifdef PARALLEL_MARK
|
|
||||||
if (GC_parallel) start_mark_threads();
|
|
||||||
# endif
|
|
||||||
/* Initialize thread local free lists if used. */
|
/* Initialize thread local free lists if used. */
|
||||||
# if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
|
# if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
|
||||||
LOCK();
|
LOCK();
|
||||||
|
@ -1222,7 +1240,7 @@ WRAP_FUNC(pthread_create)(pthread_t *new_thread,
|
||||||
if (!GC_thr_initialized) GC_thr_init();
|
if (!GC_thr_initialized) GC_thr_init();
|
||||||
# ifdef GC_ASSERTIONS
|
# ifdef GC_ASSERTIONS
|
||||||
{
|
{
|
||||||
int stack_size;
|
size_t stack_size;
|
||||||
if (NULL == attr) {
|
if (NULL == attr) {
|
||||||
pthread_attr_t my_attr;
|
pthread_attr_t my_attr;
|
||||||
pthread_attr_init(&my_attr);
|
pthread_attr_init(&my_attr);
|
||||||
|
@ -1230,7 +1248,13 @@ WRAP_FUNC(pthread_create)(pthread_t *new_thread,
|
||||||
} else {
|
} else {
|
||||||
pthread_attr_getstacksize(attr, &stack_size);
|
pthread_attr_getstacksize(attr, &stack_size);
|
||||||
}
|
}
|
||||||
GC_ASSERT(stack_size >= (8*HBLKSIZE*sizeof(word)));
|
# ifdef PARALLEL_MARK
|
||||||
|
GC_ASSERT(stack_size >= (8*HBLKSIZE*sizeof(word)));
|
||||||
|
# else
|
||||||
|
/* FreeBSD-5.3/Alpha: default pthread stack is 64K, */
|
||||||
|
/* HBLKSIZE=8192, sizeof(word)=8 */
|
||||||
|
GC_ASSERT(stack_size >= 65536);
|
||||||
|
# endif
|
||||||
/* Our threads may need to do some work for the GC. */
|
/* Our threads may need to do some work for the GC. */
|
||||||
/* Ridiculously small threads won't work, and they */
|
/* Ridiculously small threads won't work, and they */
|
||||||
/* probably wouldn't work anyway. */
|
/* probably wouldn't work anyway. */
|
||||||
|
|
|
@ -888,7 +888,7 @@ void GC_print_block_list()
|
||||||
{
|
{
|
||||||
struct Print_stats pstats;
|
struct Print_stats pstats;
|
||||||
|
|
||||||
GC_printf0("(kind(0=ptrfree,1=normal,2=unc.,3=stubborn):size_in_bytes, #_marks_set)\n");
|
GC_printf1("(kind(0=ptrfree,1=normal,2=unc.,%lu=stubborn):size_in_bytes, #_marks_set)\n", STUBBORN);
|
||||||
pstats.number_of_blocks = 0;
|
pstats.number_of_blocks = 0;
|
||||||
pstats.total_bytes = 0;
|
pstats.total_bytes = 0;
|
||||||
GC_apply_to_all_blocks(GC_print_block_descr, (word)&pstats);
|
GC_apply_to_all_blocks(GC_print_block_descr, (word)&pstats);
|
||||||
|
|
|
@ -16,9 +16,8 @@
|
||||||
* Modified by Peter C. for Solaris Posix Threads.
|
* Modified by Peter C. for Solaris Posix Threads.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
# if defined(GC_SOLARIS_PTHREADS) || defined(GC_THREADS)
|
|
||||||
# include "private/gc_priv.h"
|
# include "private/gc_priv.h"
|
||||||
# endif
|
|
||||||
# if defined(GC_SOLARIS_PTHREADS)
|
# if defined(GC_SOLARIS_PTHREADS)
|
||||||
# include <pthread.h>
|
# include <pthread.h>
|
||||||
# include <thread.h>
|
# include <thread.h>
|
||||||
|
|
|
@ -16,10 +16,7 @@
|
||||||
*/
|
*/
|
||||||
/* Boehm, September 14, 1994 4:44 pm PDT */
|
/* Boehm, September 14, 1994 4:44 pm PDT */
|
||||||
|
|
||||||
# if defined(GC_SOLARIS_THREADS) || defined(GC_SOLARIS_PTHREADS) \
|
# include "private/gc_priv.h"
|
||||||
|| defined(GC_THREADS)
|
|
||||||
# include "private/gc_priv.h"
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if defined(GC_SOLARIS_THREADS) || defined(GC_SOLARIS_PTHREADS)
|
# if defined(GC_SOLARIS_THREADS) || defined(GC_SOLARIS_PTHREADS)
|
||||||
# include "private/solaris_threads.h"
|
# include "private/solaris_threads.h"
|
||||||
|
@ -251,8 +248,8 @@ static void stop_all_lwps()
|
||||||
for (i = 0; i < max_lwps; i++)
|
for (i = 0; i < max_lwps; i++)
|
||||||
last_ids[i] = 0;
|
last_ids[i] = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (syscall(SYS_ioctl, GC_main_proc_fd, PIOCSTATUS, &status) < 0)
|
if (syscall(SYS_ioctl, GC_main_proc_fd, PIOCSTATUS, &status) < 0)
|
||||||
ABORT("Main PIOCSTATUS failed");
|
ABORT("Main PIOCSTATUS failed");
|
||||||
if (status.pr_nlwp < 1)
|
if (status.pr_nlwp < 1)
|
||||||
ABORT("Invalid number of lwps returned by PIOCSTATUS");
|
ABORT("Invalid number of lwps returned by PIOCSTATUS");
|
||||||
if (status.pr_nlwp >= max_lwps) {
|
if (status.pr_nlwp >= max_lwps) {
|
||||||
|
@ -265,7 +262,7 @@ static void stop_all_lwps()
|
||||||
for (i = 0; i < max_lwps; i++)
|
for (i = 0; i < max_lwps; i++)
|
||||||
last_ids[i] = 0;
|
last_ids[i] = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (syscall(SYS_ioctl, GC_main_proc_fd, PIOCLWPIDS, GC_current_ids) < 0)
|
if (syscall(SYS_ioctl, GC_main_proc_fd, PIOCLWPIDS, GC_current_ids) < 0)
|
||||||
ABORT("PIOCLWPIDS failed");
|
ABORT("PIOCLWPIDS failed");
|
||||||
changed = FALSE;
|
changed = FALSE;
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
* modified is included with the above copyright notice.
|
* modified is included with the above copyright notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "private/gc_priv.h" /* For GC_compare_and_exchange, GC_memory_barrier */
|
||||||
|
|
||||||
#if defined(GC_LINUX_THREADS)
|
#if defined(GC_LINUX_THREADS)
|
||||||
|
|
||||||
#include "private/gc_priv.h" /* For GC_compare_and_exchange, GC_memory_barrier */
|
|
||||||
#include "private/specific.h"
|
#include "private/specific.h"
|
||||||
|
|
||||||
static tse invalid_tse = {INVALID_QTID, 0, 0, INVALID_THREADID};
|
static tse invalid_tse = {INVALID_QTID, 0, 0, INVALID_THREADID};
|
||||||
|
|
|
@ -1367,6 +1367,10 @@ void check_heap_stats()
|
||||||
max_heap_sz = 11000000;
|
max_heap_sz = 11000000;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
# ifndef ALIGN_DOUBLE
|
||||||
|
/* We end up needing more small object pages. */
|
||||||
|
max_heap_sz += 2000000;
|
||||||
|
# endif
|
||||||
# ifdef GC_DEBUG
|
# ifdef GC_DEBUG
|
||||||
max_heap_sz *= 2;
|
max_heap_sz *= 2;
|
||||||
# ifdef SAVE_CALL_CHAIN
|
# ifdef SAVE_CALL_CHAIN
|
||||||
|
|
|
@ -11,10 +11,21 @@ int main()
|
||||||
"-Wl,--wrap -Wl,pthread_sigmask -Wl,--wrap -Wl,sleep\n");
|
"-Wl,--wrap -Wl,pthread_sigmask -Wl,--wrap -Wl,sleep\n");
|
||||||
# endif
|
# endif
|
||||||
# if defined(GC_LINUX_THREADS) || defined(GC_IRIX_THREADS) \
|
# if defined(GC_LINUX_THREADS) || defined(GC_IRIX_THREADS) \
|
||||||
|| defined(GC_FREEBSD_THREADS) || defined(GC_SOLARIS_PTHREADS) \
|
|| defined(GC_SOLARIS_PTHREADS) \
|
||||||
|| defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)
|
|| defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)
|
||||||
printf("-lpthread\n");
|
printf("-lpthread\n");
|
||||||
# endif
|
# endif
|
||||||
|
# if defined(GC_FREEBSD_THREADS)
|
||||||
|
# if (__FREEBSD_version >= 500000)
|
||||||
|
printf("-lpthread\n");
|
||||||
|
# else
|
||||||
|
printf("-pthread\n");
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# if defined(GC_NETBSD_THREADS)
|
||||||
|
printf("-lpthread -lrt\n");
|
||||||
|
# endif
|
||||||
|
|
||||||
# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS)
|
# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS)
|
||||||
printf("-lpthread -lrt\n");
|
printf("-lpthread -lrt\n");
|
||||||
# endif
|
# endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
(define old-dir (current-directory))
|
(define old-dir (current-directory))
|
||||||
(define new-dir "~/tmp/gc6.3")
|
(define new-dir "~/Desktop/gc6.7")
|
||||||
(define really-svn? #t)
|
(define really-svn? #t)
|
||||||
|
|
||||||
(require (lib "file.ss")
|
(require (lib "file.ss")
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
/* Eventually this one may become unnecessary. For now we need */
|
/* Eventually this one may become unnecessary. For now we need */
|
||||||
/* it to keep the old-style build process working. */
|
/* it to keep the old-style build process working. */
|
||||||
#define GC_TMP_VERSION_MAJOR 6
|
#define GC_TMP_VERSION_MAJOR 6
|
||||||
#define GC_TMP_VERSION_MINOR 3
|
#define GC_TMP_VERSION_MINOR 7
|
||||||
#define GC_TMP_ALPHA_VERSION GC_NOT_ALPHA
|
#define GC_TMP_ALPHA_VERSION GC_NOT_ALPHA
|
||||||
|
|
||||||
#ifndef GC_NOT_ALPHA
|
#ifndef GC_NOT_ALPHA
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
#include "private/gc_priv.h"
|
||||||
|
|
||||||
#if defined(GC_WIN32_THREADS)
|
#if defined(GC_WIN32_THREADS)
|
||||||
|
|
||||||
#include "private/gc_priv.h"
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#ifdef CYGWIN32
|
#ifdef CYGWIN32
|
||||||
|
@ -10,6 +11,7 @@
|
||||||
# undef pthread_create
|
# undef pthread_create
|
||||||
# undef pthread_sigmask
|
# undef pthread_sigmask
|
||||||
# undef pthread_join
|
# undef pthread_join
|
||||||
|
# undef pthread_detach
|
||||||
# undef dlopen
|
# undef dlopen
|
||||||
|
|
||||||
# define DEBUG_CYGWIN_THREADS 0
|
# define DEBUG_CYGWIN_THREADS 0
|
||||||
|
@ -184,7 +186,7 @@ static void GC_delete_thread(DWORD thread_id) {
|
||||||
/* Must still be in_use, since nobody else can store our thread_id. */
|
/* Must still be in_use, since nobody else can store our thread_id. */
|
||||||
i++) {}
|
i++) {}
|
||||||
if (i > my_max) {
|
if (i > my_max) {
|
||||||
WARN("Removing nonexisiting thread %ld\n", (GC_word)thread_id);
|
WARN("Removing nonexistent thread %ld\n", (GC_word)thread_id);
|
||||||
} else {
|
} else {
|
||||||
GC_delete_gc_thread(thread_table+i);
|
GC_delete_gc_thread(thread_table+i);
|
||||||
}
|
}
|
||||||
|
@ -231,6 +233,9 @@ void GC_push_thread_structures GC_PROTO((void))
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Defined in misc.c */
|
||||||
|
extern CRITICAL_SECTION GC_write_cs;
|
||||||
|
|
||||||
void GC_stop_world()
|
void GC_stop_world()
|
||||||
{
|
{
|
||||||
DWORD thread_id = GetCurrentThreadId();
|
DWORD thread_id = GetCurrentThreadId();
|
||||||
|
@ -239,6 +244,9 @@ void GC_stop_world()
|
||||||
if (!GC_thr_initialized) ABORT("GC_stop_world() called before GC_thr_init()");
|
if (!GC_thr_initialized) ABORT("GC_stop_world() called before GC_thr_init()");
|
||||||
|
|
||||||
GC_please_stop = TRUE;
|
GC_please_stop = TRUE;
|
||||||
|
# ifndef CYGWIN32
|
||||||
|
EnterCriticalSection(&GC_write_cs);
|
||||||
|
# endif /* !CYGWIN32 */
|
||||||
for (i = 0; i <= GC_get_max_thread_index(); i++)
|
for (i = 0; i <= GC_get_max_thread_index(); i++)
|
||||||
if (thread_table[i].stack_base != 0
|
if (thread_table[i].stack_base != 0
|
||||||
&& thread_table[i].id != thread_id) {
|
&& thread_table[i].id != thread_id) {
|
||||||
|
@ -269,6 +277,9 @@ void GC_stop_world()
|
||||||
# endif
|
# endif
|
||||||
thread_table[i].suspended = TRUE;
|
thread_table[i].suspended = TRUE;
|
||||||
}
|
}
|
||||||
|
# ifndef CYGWIN32
|
||||||
|
LeaveCriticalSection(&GC_write_cs);
|
||||||
|
# endif /* !CYGWIN32 */
|
||||||
}
|
}
|
||||||
|
|
||||||
void GC_start_world()
|
void GC_start_world()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user