summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile33
-rw-r--r--[l---------]NT_THREADS_MAKEFILE2088
-rw-r--r--README37
-rw-r--r--README.QUICK4
-rw-r--r--README.hp7
-rw-r--r--allchblk.c3
-rw-r--r--alloc.c35
-rw-r--r--blacklst.c7
-rw-r--r--cord/cord.h2
-rw-r--r--cord/gc.h20
-rw-r--r--dbg_mlc.c10
-rw-r--r--dyn_load.c12
-rw-r--r--gc.h20
-rw-r--r--gc_priv.h120
-rw-r--r--gcconfig.h92
-rw-r--r--hpux_irix_threads.c (renamed from irix_threads.c)121
-rw-r--r--hpux_test_and_clear.s21
-rw-r--r--include/gc.h20
-rw-r--r--include/gc_copy_descr.h (renamed from gc_copy_descr.h)0
-rwxr-xr-xinclude/gc_nursery.h (renamed from nursery.h)0
-rw-r--r--include/new_gc_alloc.h6
-rw-r--r--include/private/gc_priv.h120
-rw-r--r--mach_dep.c43
-rw-r--r--mark.c19
-rw-r--r--mark_rts.c28
-rw-r--r--misc.c22
-rw-r--r--nursery.c181
-rw-r--r--os_dep.c163
-rw-r--r--reclaim.c174
-rw-r--r--test.c34
-rw-r--r--threadlibs.c3
-rw-r--r--version.h2
32 files changed, 3226 insertions, 221 deletions
diff --git a/Makefile b/Makefile
index cfbfc452..d6eab33f 100644
--- a/Makefile
+++ b/Makefile
@@ -7,9 +7,9 @@
# and runs some tests of collector and cords. Does not add cords or
# c++ interface to gc.a
# cord/de - builds dumb editor based on cords.
-ABI_FLAG=
+ABI_FLAG=
CC=cc $(ABI_FLAG)
-CXX=CC $(ABI_FLAG)
+CXX=g++ $(ABI_FLAG)
AS=as $(ABI_FLAG)
# The above doesn't work with gas, which doesn't run cpp.
# Define AS as `gcc -c -x assembler-with-cpp' instead.
@@ -35,6 +35,8 @@ CFLAGS= -O -DATOMIC_UNCOLLECTABLE -DNO_SIGNALS -DNO_EXECUTE_PERMISSION -DALL_INT
# -D_SOLARIS_PTHREADS enables support for Solaris pthreads.
# Define SOLARIS_THREADS as well.
# -DIRIX_THREADS enables support for Irix pthreads. See README.irix.
+# -DHPUX_THREADS enables support for HP/UX 11 pthreads.
+# Also requires -D_REENTRANT. See README.hp.
# -DLINUX_THREADS enables support for Xavier Leroy's Linux threads.
# see README.linux. -D_REENTRANT may also be required.
# -DALL_INTERIOR_POINTERS allows all pointers to the interior
@@ -149,9 +151,9 @@ RANLIB= ranlib
srcdir = .
VPATH = $(srcdir)
-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 irix_threads.o linux_threads.o typd_mlc.o ptr_chck.o mallocx.o solaris_pthreads.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 hpux_irix_threads.o linux_threads.o typd_mlc.o ptr_chck.o mallocx.o solaris_pthreads.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 irix_threads.c linux_threads.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.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 hpux_irix_threads.c linux_threads.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.c
CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordtest.c cord/cord.h cord/ec.h cord/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/SCOPTIONS.amiga cord/SMakefile.amiga
@@ -163,7 +165,7 @@ SRCS= $(CSRCS) mips_sgi_mach_dep.s rs6000_mach_dep.s alpha_mach_dep.s \
threadlibs.c if_mach.c if_not_there.c gc_cpp.cc gc_cpp.h weakpointer.h \
gcc_support.c mips_ultrix_mach_dep.s include/gc_alloc.h gc_alloc.h \
include/new_gc_alloc.h include/javaxfc.h sparc_sunos4_mach_dep.s \
- solaris_threads.h backptr.h $(CORD_SRCS)
+ solaris_threads.h backptr.h hpux_test_and_clear.s $(CORD_SRCS)
OTHER_FILES= Makefile PCR-Makefile OS2_MAKEFILE NT_MAKEFILE BCC_MAKEFILE \
README test.c test_cpp.cc setjmp_t.c SMakefile.amiga \
@@ -180,7 +182,7 @@ OTHER_FILES= Makefile PCR-Makefile OS2_MAKEFILE NT_MAKEFILE BCC_MAKEFILE \
add_gc_prefix.c README.solaris2 README.sgi README.hp README.uts \
win32_threads.c NT_THREADS_MAKEFILE gc.mak README.dj Makefile.dj \
README.alpha README.linux version.h Makefile.DLLs \
- WCC_MAKEFILE nursery.c nursery.h gc_copy_descr.h \
+ WCC_MAKEFILE nursery.c include/gc_nursery.h include/gc_copy_descr.h \
include/leak_detector.h
CORD_INCLUDE_FILES= $(srcdir)/gc.h $(srcdir)/cord/cord.h $(srcdir)/cord/ec.h \
@@ -242,7 +244,7 @@ gc_cpp.o: $(srcdir)/gc_cpp.cc $(srcdir)/gc_cpp.h $(srcdir)/gc.h Makefile
test_cpp: $(srcdir)/test_cpp.cc $(srcdir)/gc_cpp.h gc_cpp.o $(srcdir)/gc.h \
base_lib $(UTILS)
rm -f test_cpp
- ./if_mach HP_PA "" $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/test_cpp.cc gc_cpp.o gc.a -ldld
+ ./if_mach HP_PA HPUX $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/test_cpp.cc gc_cpp.o gc.a -ldld `./threadlibs`
./if_not_there test_cpp $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/test_cpp.cc gc_cpp.o gc.a `./threadlibs`
c++: gc_cpp.o $(srcdir)/gc_cpp.h test_cpp
@@ -302,9 +304,12 @@ mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/mips_sgi_mach_dep.s $(srcdir)/mips_ul
./if_mach SPARC SUNOS5 $(AS) -o mach_dep.o $(srcdir)/sparc_mach_dep.s
./if_mach SPARC SUNOS4 $(AS) -o mach_dep.o $(srcdir)/sparc_sunos4_mach_dep.s
./if_mach SPARC OPENBSD $(AS) -o mach_dep.o $(srcdir)/sparc_sunos4_mach_dep.s
+ ./if_mach HP_PA HPUX $(AS) -o hpux_test_and_clear.o $(srcdir)/hpux_test_and_clear.s
+ ./if_mach HP_PA HPUX $(CC) -c -o md_tmp.o $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
+ ./if_mach HP_PA HPUX ld -r -o mach_dep.o md_tmp.o hpux_test_and_clear.o
./if_not_there mach_dep.o $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
-mark_rts.o: $(srcdir)/mark_rts.c if_mach if_not_there $(UTILS)
+mark_rts.o: $(srcdir)/mark_rts.c $(UTILS)
rm -f mark_rts.o
-./if_mach ALPHA OSF1 $(CC) -c $(CFLAGS) -Wo,-notail $(srcdir)/mark_rts.c
./if_not_there mark_rts.o $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c
@@ -329,13 +334,13 @@ cord/cordprnt.o: $(srcdir)/cord/cordprnt.c $(CORD_INCLUDE_FILES)
cord/cordtest: $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a $(UTILS)
rm -f cord/cordtest
./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a -lucb
- ./if_mach HP_PA "" $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a -ldld
+ ./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a -ldld `./threadlibs`
./if_not_there cord/cordtest $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a `./threadlibs`
cord/de: $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(UTILS)
rm -f cord/de
./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) -lucb `./threadlibs`
- ./if_mach HP_PA "" $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) -ldld
+ ./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) -ldld `./threadlibs`
./if_mach RS6000 "" $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses
./if_mach I386 LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs`
./if_mach ALPHA LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses
@@ -357,16 +362,16 @@ clean:
threadlibs $(CORD_OBJS) cord/cordtest cord/de
-rm -f *~
-gctest: test.o gc.a if_mach if_not_there
+gctest: test.o gc.a $(UTILS)
rm -f gctest
./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o gctest test.o gc.a -lucb
- ./if_mach HP_PA "" $(CC) $(CFLAGS) -o gctest test.o gc.a -ldld
+ ./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o gctest test.o gc.a -ldld `./threadlibs`
./if_not_there gctest $(CC) $(CFLAGS) -o gctest test.o gc.a `./threadlibs`
# If an optimized setjmp_test generates a segmentation fault,
# odds are your compiler is broken. Gctest may still work.
# Try compiling setjmp_t.c unoptimized.
-setjmp_test: $(srcdir)/setjmp_t.c $(srcdir)/gc.h if_mach if_not_there
+setjmp_test: $(srcdir)/setjmp_t.c $(srcdir)/gc.h $(UTILS)
$(CC) $(CFLAGS) -o setjmp_test $(srcdir)/setjmp_t.c
test: KandRtest cord/cordtest
@@ -382,7 +387,7 @@ add_gc_prefix: add_gc_prefix.c
gc.tar: $(SRCS) $(OTHER_FILES) add_gc_prefix
./add_gc_prefix $(SRCS) $(OTHER_FILES) > /tmp/gc.tar-files
- (cd $(srcdir)/.. ; tar cvfh - `cat /tmp/gc.tar-files`) > gc.tar
+ tar cvfh gc.tar `cat /tmp/gc.tar-files`
pc_gc.tar: $(SRCS) $(OTHER_FILES)
tar cvfX pc_gc.tar pc_excludes $(SRCS) $(OTHER_FILES)
diff --git a/NT_THREADS_MAKEFILE b/NT_THREADS_MAKEFILE
index 1f801cff..0fd22b70 120000..100644
--- a/NT_THREADS_MAKEFILE
+++ b/NT_THREADS_MAKEFILE
@@ -1 +1,2087 @@
-gc.mak \ No newline at end of file
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.10
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+!IF "$(CFG)" == ""
+CFG=gctest - Win32 Release
+!MESSAGE No configuration specified. Defaulting to cord - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "gc - Win32 Release" && "$(CFG)" != "gc - Win32 Debug" &&\
+ "$(CFG)" != "gctest - Win32 Release" && "$(CFG)" != "gctest - Win32 Debug" &&\
+ "$(CFG)" != "cord - Win32 Release" && "$(CFG)" != "cord - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gc.mak" CFG="cord - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "gc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "gctest - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "gctest - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "cord - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "cord - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "gctest - Win32 Debug"
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : ".\Release\gc.dll" ".\Release\gc.bsc"
+
+CLEAN :
+ -@erase ".\Release\allchblk.obj"
+ -@erase ".\Release\allchblk.sbr"
+ -@erase ".\Release\alloc.obj"
+ -@erase ".\Release\alloc.sbr"
+ -@erase ".\Release\blacklst.obj"
+ -@erase ".\Release\blacklst.sbr"
+ -@erase ".\Release\checksums.obj"
+ -@erase ".\Release\checksums.sbr"
+ -@erase ".\Release\dbg_mlc.obj"
+ -@erase ".\Release\dbg_mlc.sbr"
+ -@erase ".\Release\dyn_load.obj"
+ -@erase ".\Release\dyn_load.sbr"
+ -@erase ".\Release\finalize.obj"
+ -@erase ".\Release\finalize.sbr"
+ -@erase ".\Release\gc.bsc"
+ -@erase ".\Release\gc.dll"
+ -@erase ".\Release\gc.exp"
+ -@erase ".\Release\gc.lib"
+ -@erase ".\Release\headers.obj"
+ -@erase ".\Release\headers.sbr"
+ -@erase ".\Release\mach_dep.obj"
+ -@erase ".\Release\mach_dep.sbr"
+ -@erase ".\Release\malloc.obj"
+ -@erase ".\Release\malloc.sbr"
+ -@erase ".\Release\mallocx.obj"
+ -@erase ".\Release\mallocx.sbr"
+ -@erase ".\Release\mark.obj"
+ -@erase ".\Release\mark.sbr"
+ -@erase ".\Release\mark_rts.obj"
+ -@erase ".\Release\mark_rts.sbr"
+ -@erase ".\Release\misc.obj"
+ -@erase ".\Release\misc.sbr"
+ -@erase ".\Release\new_hblk.obj"
+ -@erase ".\Release\new_hblk.sbr"
+ -@erase ".\Release\obj_map.obj"
+ -@erase ".\Release\obj_map.sbr"
+ -@erase ".\Release\os_dep.obj"
+ -@erase ".\Release\os_dep.sbr"
+ -@erase ".\Release\ptr_chck.obj"
+ -@erase ".\Release\ptr_chck.sbr"
+ -@erase ".\Release\reclaim.obj"
+ -@erase ".\Release\reclaim.sbr"
+ -@erase ".\Release\stubborn.obj"
+ -@erase ".\Release\stubborn.sbr"
+ -@erase ".\Release\typd_mlc.obj"
+ -@erase ".\Release\typd_mlc.sbr"
+ -@erase ".\Release\win32_threads.obj"
+ -@erase ".\Release\win32_threads.sbr"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "SILENT" /D "GC_BUILD" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "WIN32_THREADS" /FR /YX /c
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "SILENT" /D "GC_BUILD" /D\
+ "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D\
+ "WIN32_THREADS" /FR"$(INTDIR)/" /Fp"$(INTDIR)/gc.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\Release/
+CPP_SBRS=.\Release/
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/gc.bsc"
+BSC32_SBRS= \
+ ".\Release\allchblk.sbr" \
+ ".\Release\alloc.sbr" \
+ ".\Release\blacklst.sbr" \
+ ".\Release\checksums.sbr" \
+ ".\Release\dbg_mlc.sbr" \
+ ".\Release\dyn_load.sbr" \
+ ".\Release\finalize.sbr" \
+ ".\Release\headers.sbr" \
+ ".\Release\mach_dep.sbr" \
+ ".\Release\malloc.sbr" \
+ ".\Release\mallocx.sbr" \
+ ".\Release\mark.sbr" \
+ ".\Release\mark_rts.sbr" \
+ ".\Release\misc.sbr" \
+ ".\Release\new_hblk.sbr" \
+ ".\Release\obj_map.sbr" \
+ ".\Release\os_dep.sbr" \
+ ".\Release\ptr_chck.sbr" \
+ ".\Release\reclaim.sbr" \
+ ".\Release\stubborn.sbr" \
+ ".\Release\typd_mlc.sbr" \
+ ".\Release\win32_threads.sbr"
+
+".\Release\gc.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /dll /incremental:no\
+ /pdb:"$(OUTDIR)/gc.pdb" /machine:I386 /out:"$(OUTDIR)/gc.dll"\
+ /implib:"$(OUTDIR)/gc.lib"
+LINK32_OBJS= \
+ ".\Release\allchblk.obj" \
+ ".\Release\alloc.obj" \
+ ".\Release\blacklst.obj" \
+ ".\Release\checksums.obj" \
+ ".\Release\dbg_mlc.obj" \
+ ".\Release\dyn_load.obj" \
+ ".\Release\finalize.obj" \
+ ".\Release\headers.obj" \
+ ".\Release\mach_dep.obj" \
+ ".\Release\malloc.obj" \
+ ".\Release\mallocx.obj" \
+ ".\Release\mark.obj" \
+ ".\Release\mark_rts.obj" \
+ ".\Release\misc.obj" \
+ ".\Release\new_hblk.obj" \
+ ".\Release\obj_map.obj" \
+ ".\Release\os_dep.obj" \
+ ".\Release\ptr_chck.obj" \
+ ".\Release\reclaim.obj" \
+ ".\Release\stubborn.obj" \
+ ".\Release\typd_mlc.obj" \
+ ".\Release\win32_threads.obj"
+
+".\Release\gc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+OUTDIR=.\Debug
+INTDIR=.\Debug
+
+ALL : ".\Debug\gc.dll" ".\Debug\gc.bsc"
+
+CLEAN :
+ -@erase ".\Debug\allchblk.obj"
+ -@erase ".\Debug\allchblk.sbr"
+ -@erase ".\Debug\alloc.obj"
+ -@erase ".\Debug\alloc.sbr"
+ -@erase ".\Debug\blacklst.obj"
+ -@erase ".\Debug\blacklst.sbr"
+ -@erase ".\Debug\checksums.obj"
+ -@erase ".\Debug\checksums.sbr"
+ -@erase ".\Debug\dbg_mlc.obj"
+ -@erase ".\Debug\dbg_mlc.sbr"
+ -@erase ".\Debug\dyn_load.obj"
+ -@erase ".\Debug\dyn_load.sbr"
+ -@erase ".\Debug\finalize.obj"
+ -@erase ".\Debug\finalize.sbr"
+ -@erase ".\Debug\gc.bsc"
+ -@erase ".\Debug\gc.dll"
+ -@erase ".\Debug\gc.exp"
+ -@erase ".\Debug\gc.lib"
+ -@erase ".\Debug\gc.map"
+ -@erase ".\Debug\gc.pdb"
+ -@erase ".\Debug\headers.obj"
+ -@erase ".\Debug\headers.sbr"
+ -@erase ".\Debug\mach_dep.obj"
+ -@erase ".\Debug\mach_dep.sbr"
+ -@erase ".\Debug\malloc.obj"
+ -@erase ".\Debug\malloc.sbr"
+ -@erase ".\Debug\mallocx.obj"
+ -@erase ".\Debug\mallocx.sbr"
+ -@erase ".\Debug\mark.obj"
+ -@erase ".\Debug\mark.sbr"
+ -@erase ".\Debug\mark_rts.obj"
+ -@erase ".\Debug\mark_rts.sbr"
+ -@erase ".\Debug\misc.obj"
+ -@erase ".\Debug\misc.sbr"
+ -@erase ".\Debug\new_hblk.obj"
+ -@erase ".\Debug\new_hblk.sbr"
+ -@erase ".\Debug\obj_map.obj"
+ -@erase ".\Debug\obj_map.sbr"
+ -@erase ".\Debug\os_dep.obj"
+ -@erase ".\Debug\os_dep.sbr"
+ -@erase ".\Debug\ptr_chck.obj"
+ -@erase ".\Debug\ptr_chck.sbr"
+ -@erase ".\Debug\reclaim.obj"
+ -@erase ".\Debug\reclaim.sbr"
+ -@erase ".\Debug\stubborn.obj"
+ -@erase ".\Debug\stubborn.sbr"
+ -@erase ".\Debug\typd_mlc.obj"
+ -@erase ".\Debug\typd_mlc.sbr"
+ -@erase ".\Debug\vc40.idb"
+ -@erase ".\Debug\vc40.pdb"
+ -@erase ".\Debug\win32_threads.obj"
+ -@erase ".\Debug\win32_threads.sbr"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "SILENT" /D "GC_BUILD" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "WIN32_THREADS" /FR /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "SILENT" /D "GC_BUILD"\
+ /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D\
+ "WIN32_THREADS" /FR"$(INTDIR)/" /Fp"$(INTDIR)/gc.pch" /YX /Fo"$(INTDIR)/"\
+ /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\Debug/
+CPP_SBRS=.\Debug/
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/gc.bsc"
+BSC32_SBRS= \
+ ".\Debug\allchblk.sbr" \
+ ".\Debug\alloc.sbr" \
+ ".\Debug\blacklst.sbr" \
+ ".\Debug\checksums.sbr" \
+ ".\Debug\dbg_mlc.sbr" \
+ ".\Debug\dyn_load.sbr" \
+ ".\Debug\finalize.sbr" \
+ ".\Debug\headers.sbr" \
+ ".\Debug\mach_dep.sbr" \
+ ".\Debug\malloc.sbr" \
+ ".\Debug\mallocx.sbr" \
+ ".\Debug\mark.sbr" \
+ ".\Debug\mark_rts.sbr" \
+ ".\Debug\misc.sbr" \
+ ".\Debug\new_hblk.sbr" \
+ ".\Debug\obj_map.sbr" \
+ ".\Debug\os_dep.sbr" \
+ ".\Debug\ptr_chck.sbr" \
+ ".\Debug\reclaim.sbr" \
+ ".\Debug\stubborn.sbr" \
+ ".\Debug\typd_mlc.sbr" \
+ ".\Debug\win32_threads.sbr"
+
+".\Debug\gc.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /dll /incremental:no\
+ /pdb:"$(OUTDIR)/gc.pdb" /map:"$(INTDIR)/gc.map" /debug /machine:I386\
+ /out:"$(OUTDIR)/gc.dll" /implib:"$(OUTDIR)/gc.lib"
+LINK32_OBJS= \
+ ".\Debug\allchblk.obj" \
+ ".\Debug\alloc.obj" \
+ ".\Debug\blacklst.obj" \
+ ".\Debug\checksums.obj" \
+ ".\Debug\dbg_mlc.obj" \
+ ".\Debug\dyn_load.obj" \
+ ".\Debug\finalize.obj" \
+ ".\Debug\headers.obj" \
+ ".\Debug\mach_dep.obj" \
+ ".\Debug\malloc.obj" \
+ ".\Debug\mallocx.obj" \
+ ".\Debug\mark.obj" \
+ ".\Debug\mark_rts.obj" \
+ ".\Debug\misc.obj" \
+ ".\Debug\new_hblk.obj" \
+ ".\Debug\obj_map.obj" \
+ ".\Debug\os_dep.obj" \
+ ".\Debug\ptr_chck.obj" \
+ ".\Debug\reclaim.obj" \
+ ".\Debug\stubborn.obj" \
+ ".\Debug\typd_mlc.obj" \
+ ".\Debug\win32_threads.obj"
+
+".\Debug\gc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "gctest\Release"
+# PROP BASE Intermediate_Dir "gctest\Release"
+# PROP BASE Target_Dir "gctest"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "gctest\Release"
+# PROP Intermediate_Dir "gctest\Release"
+# PROP Target_Dir "gctest"
+OUTDIR=.\gctest\Release
+INTDIR=.\gctest\Release
+
+ALL : "gc - Win32 Release" ".\Release\gctest.exe"
+
+CLEAN :
+ -@erase ".\gctest\Release\test.obj"
+ -@erase ".\Release\gctest.exe"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "WIN32_THREADS" /YX /c
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\
+ "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "WIN32_THREADS"\
+ /Fp"$(INTDIR)/gctest.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\gctest\Release/
+CPP_SBRS=.\.
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/gctest.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"Release/gctest.exe"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /incremental:no\
+ /pdb:"$(OUTDIR)/gctest.pdb" /machine:I386 /out:"Release/gctest.exe"
+LINK32_OBJS= \
+ ".\gctest\Release\test.obj" \
+ ".\Release\gc.lib"
+
+".\Release\gctest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "gctest\Debug"
+# PROP BASE Intermediate_Dir "gctest\Debug"
+# PROP BASE Target_Dir "gctest"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "gctest\Debug"
+# PROP Intermediate_Dir "gctest\Debug"
+# PROP Target_Dir "gctest"
+OUTDIR=.\gctest\Debug
+INTDIR=.\gctest\Debug
+
+ALL : "gc - Win32 Debug" ".\Debug\gctest.exe" ".\gctest\Debug\gctest.bsc"
+
+CLEAN :
+ -@erase ".\Debug\gctest.exe"
+ -@erase ".\gctest\Debug\gctest.bsc"
+ -@erase ".\gctest\Debug\gctest.map"
+ -@erase ".\gctest\Debug\gctest.pdb"
+ -@erase ".\gctest\Debug\test.obj"
+ -@erase ".\gctest\Debug\test.sbr"
+ -@erase ".\gctest\Debug\vc40.idb"
+ -@erase ".\gctest\Debug\vc40.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "WIN32_THREADS" /FR /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS"\
+ /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "WIN32_THREADS" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/gctest.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\gctest\Debug/
+CPP_SBRS=.\gctest\Debug/
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/gctest.bsc"
+BSC32_SBRS= \
+ ".\gctest\Debug\test.sbr"
+
+".\gctest\Debug\gctest.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /incremental:no /map /debug /machine:I386 /out:"Debug/gctest.exe"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /incremental:no\
+ /pdb:"$(OUTDIR)/gctest.pdb" /map:"$(INTDIR)/gctest.map" /debug /machine:I386\
+ /out:"Debug/gctest.exe"
+LINK32_OBJS= \
+ ".\Debug\gc.lib" \
+ ".\gctest\Debug\test.obj"
+
+".\Debug\gctest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "cord - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "cord\Release"
+# PROP BASE Intermediate_Dir "cord\Release"
+# PROP BASE Target_Dir "cord"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "cord\Release"
+# PROP Intermediate_Dir "cord\Release"
+# PROP Target_Dir "cord"
+OUTDIR=.\cord\Release
+INTDIR=.\cord\Release
+
+ALL : "gc - Win32 Release" ".\Release\de.exe"
+
+CLEAN :
+ -@erase ".\cord\Release\cordbscs.obj"
+ -@erase ".\cord\Release\cordxtra.obj"
+ -@erase ".\cord\Release\de.obj"
+ -@erase ".\cord\Release\de_win.obj"
+ -@erase ".\cord\Release\de_win.res"
+ -@erase ".\Release\de.exe"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /YX /c
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "." /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\
+ "ALL_INTERIOR_POINTERS" /Fp"$(INTDIR)/cord.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\cord\Release/
+CPP_SBRS=.\.
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)/de_win.res" /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/cord.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"Release/de.exe"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /incremental:no /pdb:"$(OUTDIR)/de.pdb"\
+ /machine:I386 /out:"Release/de.exe"
+LINK32_OBJS= \
+ ".\cord\Release\cordbscs.obj" \
+ ".\cord\Release\cordxtra.obj" \
+ ".\cord\Release\de.obj" \
+ ".\cord\Release\de_win.obj" \
+ ".\cord\Release\de_win.res" \
+ ".\Release\gc.lib"
+
+".\Release\de.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "cord\Debug"
+# PROP BASE Intermediate_Dir "cord\Debug"
+# PROP BASE Target_Dir "cord"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "cord\Debug"
+# PROP Intermediate_Dir "cord\Debug"
+# PROP Target_Dir "cord"
+OUTDIR=.\cord\Debug
+INTDIR=.\cord\Debug
+
+ALL : "gc - Win32 Debug" ".\Debug\de.exe"
+
+CLEAN :
+ -@erase ".\cord\Debug\cordbscs.obj"
+ -@erase ".\cord\Debug\cordxtra.obj"
+ -@erase ".\cord\Debug\de.obj"
+ -@erase ".\cord\Debug\de.pdb"
+ -@erase ".\cord\Debug\de_win.obj"
+ -@erase ".\cord\Debug\de_win.res"
+ -@erase ".\cord\Debug\vc40.idb"
+ -@erase ".\cord\Debug\vc40.pdb"
+ -@erase ".\Debug\de.exe"
+ -@erase ".\Debug\de.ilk"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "." /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /YX /c
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "." /D "_DEBUG" /D "WIN32" /D\
+ "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /Fp"$(INTDIR)/cord.pch" /YX\
+ /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\cord\Debug/
+CPP_SBRS=.\.
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)/de_win.res" /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/cord.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/de.exe"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
+ odbccp32.lib /nologo /subsystem:windows /incremental:yes\
+ /pdb:"$(OUTDIR)/de.pdb" /debug /machine:I386 /out:"Debug/de.exe"
+LINK32_OBJS= \
+ ".\cord\Debug\cordbscs.obj" \
+ ".\cord\Debug\cordxtra.obj" \
+ ".\cord\Debug\de.obj" \
+ ".\cord\Debug\de_win.obj" \
+ ".\cord\Debug\de_win.res" \
+ ".\Debug\gc.lib"
+
+".\Debug\de.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+################################################################################
+# Begin Target
+
+# Name "gc - Win32 Release"
+# Name "gc - Win32 Debug"
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\reclaim.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_RECLA=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_RECLA=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\reclaim.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+".\Release\reclaim.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_RECLA=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_RECLA=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\reclaim.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+".\Debug\reclaim.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\os_dep.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_OS_DE=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_OS_DE=\
+ ".\il\PCR_IL.h"\
+ ".\mm\PCR_MM.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+ ".\vd\PCR_VD.h"\
+
+
+".\Release\os_dep.obj" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
+
+".\Release\os_dep.sbr" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_OS_DE=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_OS_DE=\
+ ".\il\PCR_IL.h"\
+ ".\mm\PCR_MM.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+ ".\vd\PCR_VD.h"\
+
+
+".\Debug\os_dep.obj" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
+
+".\Debug\os_dep.sbr" : $(SOURCE) $(DEP_CPP_OS_DE) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\misc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MISC_=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MISC_=\
+ ".\il\PCR_IL.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\misc.obj" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
+
+".\Release\misc.sbr" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MISC_=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MISC_=\
+ ".\il\PCR_IL.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\misc.obj" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
+
+".\Debug\misc.sbr" : $(SOURCE) $(DEP_CPP_MISC_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\mark_rts.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MARK_=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MARK_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\mark_rts.obj" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
+
+".\Release\mark_rts.sbr" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MARK_=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MARK_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\mark_rts.obj" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
+
+".\Debug\mark_rts.sbr" : $(SOURCE) $(DEP_CPP_MARK_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\mach_dep.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MACH_=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MACH_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\mach_dep.obj" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
+
+".\Release\mach_dep.sbr" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MACH_=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MACH_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\mach_dep.obj" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
+
+".\Debug\mach_dep.sbr" : $(SOURCE) $(DEP_CPP_MACH_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\headers.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_HEADE=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_HEADE=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\headers.obj" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
+
+".\Release\headers.sbr" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_HEADE=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_HEADE=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\headers.obj" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
+
+".\Debug\headers.sbr" : $(SOURCE) $(DEP_CPP_HEADE) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\alloc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_ALLOC=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_ALLOC=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\alloc.obj" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
+
+".\Release\alloc.sbr" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_ALLOC=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_ALLOC=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\alloc.obj" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
+
+".\Debug\alloc.sbr" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\allchblk.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_ALLCH=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_ALLCH=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\allchblk.obj" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
+
+".\Release\allchblk.sbr" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_ALLCH=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_ALLCH=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\allchblk.obj" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
+
+".\Debug\allchblk.sbr" : $(SOURCE) $(DEP_CPP_ALLCH) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\stubborn.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_STUBB=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_STUBB=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\stubborn.obj" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
+
+".\Release\stubborn.sbr" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_STUBB=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_STUBB=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\stubborn.obj" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
+
+".\Debug\stubborn.sbr" : $(SOURCE) $(DEP_CPP_STUBB) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\obj_map.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_OBJ_M=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_OBJ_M=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\obj_map.obj" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
+
+".\Release\obj_map.sbr" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_OBJ_M=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_OBJ_M=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\obj_map.obj" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
+
+".\Debug\obj_map.sbr" : $(SOURCE) $(DEP_CPP_OBJ_M) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\new_hblk.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_NEW_H=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_NEW_H=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\new_hblk.obj" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
+
+".\Release\new_hblk.sbr" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_NEW_H=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_NEW_H=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\new_hblk.obj" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
+
+".\Debug\new_hblk.sbr" : $(SOURCE) $(DEP_CPP_NEW_H) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\mark.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MARK_C=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_mark.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MARK_C=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\mark.obj" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
+
+".\Release\mark.sbr" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MARK_C=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_mark.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MARK_C=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\mark.obj" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
+
+".\Debug\mark.sbr" : $(SOURCE) $(DEP_CPP_MARK_C) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\malloc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MALLO=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MALLO=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\malloc.obj" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
+
+".\Release\malloc.sbr" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MALLO=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MALLO=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\malloc.obj" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
+
+".\Debug\malloc.sbr" : $(SOURCE) $(DEP_CPP_MALLO) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\mallocx.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_MALLX=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MALLX=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\mallocx.obj" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
+
+".\Release\mallocx.sbr" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_MALLX=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_MALLX=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\mallocx.obj" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
+
+".\Debug\mallocx.sbr" : $(SOURCE) $(DEP_CPP_MALLX) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\finalize.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_FINAL=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_mark.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_FINAL=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\finalize.obj" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
+
+".\Release\finalize.sbr" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_FINAL=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_mark.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_FINAL=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\finalize.obj" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
+
+".\Debug\finalize.sbr" : $(SOURCE) $(DEP_CPP_FINAL) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\dbg_mlc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_DBG_M=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_DBG_M=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\dbg_mlc.obj" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
+
+".\Release\dbg_mlc.sbr" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_DBG_M=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_DBG_M=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\dbg_mlc.obj" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
+
+".\Debug\dbg_mlc.sbr" : $(SOURCE) $(DEP_CPP_DBG_M) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\blacklst.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_BLACK=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_BLACK=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\blacklst.obj" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
+
+".\Release\blacklst.sbr" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_BLACK=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_BLACK=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\blacklst.obj" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
+
+".\Debug\blacklst.sbr" : $(SOURCE) $(DEP_CPP_BLACK) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\typd_mlc.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_TYPD_=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_mark.h"\
+ ".\gc_priv.h"\
+ ".\gc_typed.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_TYPD_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\typd_mlc.obj" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
+
+".\Release\typd_mlc.sbr" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_TYPD_=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_mark.h"\
+ ".\gc_priv.h"\
+ ".\gc_typed.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_TYPD_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\typd_mlc.obj" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
+
+".\Debug\typd_mlc.sbr" : $(SOURCE) $(DEP_CPP_TYPD_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\ptr_chck.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_PTR_C=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_mark.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_PTR_C=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\ptr_chck.obj" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
+
+".\Release\ptr_chck.sbr" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_PTR_C=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_mark.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_PTR_C=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\ptr_chck.obj" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
+
+".\Debug\ptr_chck.sbr" : $(SOURCE) $(DEP_CPP_PTR_C) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\dyn_load.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_DYN_L=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_DYN_L=\
+ ".\il\PCR_IL.h"\
+ ".\mm\PCR_MM.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\dyn_load.obj" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
+
+".\Release\dyn_load.sbr" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_DYN_L=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\STAT.H"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_DYN_L=\
+ ".\il\PCR_IL.h"\
+ ".\mm\PCR_MM.h"\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\dyn_load.obj" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
+
+".\Debug\dyn_load.sbr" : $(SOURCE) $(DEP_CPP_DYN_L) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\win32_threads.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_WIN32=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_WIN32=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\win32_threads.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+".\Release\win32_threads.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_WIN32=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_WIN32=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\win32_threads.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+".\Debug\win32_threads.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\checksums.c
+
+!IF "$(CFG)" == "gc - Win32 Release"
+
+DEP_CPP_CHECK=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_CHECK=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Release\checksums.obj" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
+
+".\Release\checksums.sbr" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gc - Win32 Debug"
+
+DEP_CPP_CHECK=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_CHECK=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+".\Debug\checksums.obj" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
+
+".\Debug\checksums.sbr" : $(SOURCE) $(DEP_CPP_CHECK) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+# End Target
+################################################################################
+# Begin Target
+
+# Name "gctest - Win32 Release"
+# Name "gctest - Win32 Debug"
+
+!IF "$(CFG)" == "gctest - Win32 Release"
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Project Dependency
+
+# Project_Dep_Name "gc"
+
+!IF "$(CFG)" == "gctest - Win32 Release"
+
+"gc - Win32 Release" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Debug"
+
+"gc - Win32 Debug" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Debug"
+
+!ENDIF
+
+# End Project Dependency
+################################################################################
+# Begin Source File
+
+SOURCE=.\test.c
+DEP_CPP_TEST_=\
+ ".\gcconfig.h"\
+ ".\gc.h"\
+ ".\gc_hdrs.h"\
+ ".\gc_priv.h"\
+ ".\gc_typed.h"\
+ {$(INCLUDE)}"\sys\TYPES.H"\
+
+NODEP_CPP_TEST_=\
+ ".\th\PCR_Th.h"\
+ ".\th\PCR_ThCrSec.h"\
+ ".\th\PCR_ThCtl.h"\
+
+
+!IF "$(CFG)" == "gctest - Win32 Release"
+
+
+".\gctest\Release\test.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "gctest - Win32 Debug"
+
+
+".\gctest\Debug\test.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
+
+".\gctest\Debug\test.sbr" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)"
+
+
+!ENDIF
+
+# End Source File
+# End Target
+################################################################################
+# Begin Target
+
+# Name "cord - Win32 Release"
+# Name "cord - Win32 Debug"
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Project Dependency
+
+# Project_Dep_Name "gc"
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+"gc - Win32 Release" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Release"
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+"gc - Win32 Debug" :
+ $(MAKE) /$(MAKEFLAGS) /F ".\gc.mak" CFG="gc - Win32 Debug"
+
+!ENDIF
+
+# End Project Dependency
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\de_win.c
+DEP_CPP_DE_WI=\
+ ".\cord\cord.h"\
+ ".\cord\de_cmds.h"\
+ ".\cord\de_win.h"\
+ ".\cord\private\cord_pos.h"\
+
+NODEP_CPP_DE_WI=\
+ ".\cord\gc.h"\
+
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\de_win.obj" : $(SOURCE) $(DEP_CPP_DE_WI) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\de_win.obj" : $(SOURCE) $(DEP_CPP_DE_WI) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\de.c
+DEP_CPP_DE_C2e=\
+ ".\cord\cord.h"\
+ ".\cord\de_cmds.h"\
+ ".\cord\de_win.h"\
+ ".\cord\private\cord_pos.h"\
+
+NODEP_CPP_DE_C2e=\
+ ".\cord\gc.h"\
+
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\de.obj" : $(SOURCE) $(DEP_CPP_DE_C2e) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\de.obj" : $(SOURCE) $(DEP_CPP_DE_C2e) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\cordxtra.c
+DEP_CPP_CORDX=\
+ ".\cord\cord.h"\
+ ".\cord\ec.h"\
+ ".\cord\private\cord_pos.h"\
+
+NODEP_CPP_CORDX=\
+ ".\cord\gc.h"\
+
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\cordxtra.obj" : $(SOURCE) $(DEP_CPP_CORDX) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\cordxtra.obj" : $(SOURCE) $(DEP_CPP_CORDX) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\cordbscs.c
+DEP_CPP_CORDB=\
+ ".\cord\cord.h"\
+ ".\cord\private\cord_pos.h"\
+
+NODEP_CPP_CORDB=\
+ ".\cord\gc.h"\
+
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\cordbscs.obj" : $(SOURCE) $(DEP_CPP_CORDB) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\cordbscs.obj" : $(SOURCE) $(DEP_CPP_CORDB) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cord\de_win.RC
+
+!IF "$(CFG)" == "cord - Win32 Release"
+
+
+".\cord\Release\de_win.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x809 /fo"$(INTDIR)/de_win.res" /i "cord" /d "NDEBUG" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "cord - Win32 Debug"
+
+
+".\cord\Debug\de_win.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) /l 0x809 /fo"$(INTDIR)/de_win.res" /i "cord" /d "_DEBUG" $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
+################################################################################
diff --git a/README b/README
index 80cb26ab..957ddbaf 100644
--- a/README
+++ b/README
@@ -1,6 +1,7 @@
Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+Copyright (c) 1999 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.
@@ -11,7 +12,7 @@ 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.
-This is version 5.0alpha3 of a conservative garbage collector for C and C++.
+This is version 5.0alpha4 of a conservative garbage collector for C and C++.
You might find a more recent version of this at
@@ -1497,6 +1498,32 @@ Since 5.0alpha2
- Significantly changed the way leak detection is handled, as a consequence
of the above.
+Since 5.0 alpha3
+ - Added protection fault handling patch for Linux/M68K from Fergus
+ Henderson and Roman Hodek.
+ - Removed the tests for SGI_SOURCE in new_gc_alloc.h. This was causing that
+ interface to fail on nonSGI platforms.
+ - Changed the Linux stack finding code to use /proc, after chnging it
+ to use HEURISTIC1. (Thanks to David Mossberger for pointing out the
+ /proc hook.)
+ - Added HP/UX incremental GC support and HP/UX 11 thread support.
+ - Added basic Linux/IA64 support.
+ - Integrated Anthony Green's PicoJava support.
+ - Integrated Scott Ananian's StrongARM/NetBSD support.
+ - Fixed some fairly serious performance bugs in the incremental
+ collector. These have probably been there essentially forever.
+ (Mark bits were sometimes set before scanning dirty pages.
+ The reclaim phase unnecessarily dirtied full small object pages.)
+ - Changed the reclaim phase to ignore nearly full pages to avoid
+ touching them.
+ - Limited GC_black_list_spacing to roughly the heap growth increment.
+ - Changed full collection triggering heuristic to decrease full GC
+ frequency by default, but to explicitly trigger full GCs during
+ heap growth. This doesn't always improve things, but on average it's
+ probably a win.
+ - GC_debug_free(0, ...) failed. Thanks to Fergus Henderson for the
+ bug report and fix.
+
To do:
- Very large root set sizes (> 16 MB or so) could cause the collector
to abort with an unexpected mark stack overflow. (Thanks again to
@@ -1510,8 +1537,6 @@ To do:
be possible to conditionally intercept mmap and use GC_exclude_static_roots.
The real fix is to walk rld data structures, which looks possible.
- Integrate MIT and DEC pthreads ports.
- - Deal with very uneven black-listing distributions. If all the black listed
- blocks reside in the newly allocated heap section, the heuristic for
- temporarily ignoring black-listing fails, and the heap grows too much.
- (This was observed in only one case, and could be worked around, but ...)
- - Some platform specific updates are waiting for 4.15alpha1.
+ - Incremental collector should handle large objects better. Currently,
+ it looks like the whole object is treated as dirty if any part of it
+ is.
diff --git a/README.QUICK b/README.QUICK
index 3273c8ba..ddebf82c 100644
--- a/README.QUICK
+++ b/README.QUICK
@@ -1,5 +1,7 @@
Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
-Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
+Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+Copyright (c) 1999 by Hewlett-Packard. All rights reserved.
THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
diff --git a/README.hp b/README.hp
index b290590d..072ba538 100644
--- a/README.hp
+++ b/README.hp
@@ -8,4 +8,9 @@ The collector should compile with either plain cc or cc -Ae. CC -Aa
fails to define _HPUX_SOURCE and thus will not configure the collector
correctly.
-There is currently no thread support.
+Incremental collection support was reccently added, and should now work.
+
+Thread support for HP/UX 11 Pthreads was also recently added. It is still
+flakey in this release. (It has only been tested on a uniprocessor. Even
+there some fraction of thread creation calls fail with a not-yet-understood
+error return from sem_wait.)
diff --git a/allchblk.c b/allchblk.c
index d8d0afdf..189b9421 100644
--- a/allchblk.c
+++ b/allchblk.c
@@ -2,6 +2,7 @@
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
* Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
* Copyright (c) 1998-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 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.
@@ -122,7 +123,7 @@ hdr * wanted;
void GC_dump_regions()
{
- int i;
+ unsigned i;
ptr_t start, end;
ptr_t p;
size_t bytes;
diff --git a/alloc.c b/alloc.c
index 1c57951f..65bb602b 100644
--- a/alloc.c
+++ b/alloc.c
@@ -1,7 +1,8 @@
/*
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
- * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
* Copyright (c) 1998 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 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.
@@ -62,8 +63,16 @@ word GC_gc_no = 0;
int GC_incremental = 0; /* By default, stop the world. */
#endif
-int GC_full_freq = 4; /* Every 5th collection is a full */
- /* collection. */
+int GC_full_freq = 19; /* Every 20th collection is a full */
+ /* collection, whether we need it */
+ /* or not. */
+
+GC_bool GC_need_full_gc = FALSE;
+ /* Need full GC do to heap growth. */
+
+#define USED_HEAP_SIZE (GC_heapsize - GC_large_free_bytes)
+
+word GC_used_heap_size_after_full = 0;
char * GC_copyright[] =
{"Copyright 1988,1989 Hans-J. Boehm and Alan J. Demers ",
@@ -210,6 +219,7 @@ GC_bool GC_should_collect()
return(GC_adj_words_allocd() >= min_words_allocd());
}
+
void GC_notify_full_gc()
{
if (GC_start_call_back != (void (*)())0) {
@@ -217,6 +227,8 @@ void GC_notify_full_gc()
}
}
+GC_bool GC_is_full_gc = FALSE;
+
/*
* Initiate a garbage collection if appropriate.
* Choose judiciously
@@ -226,7 +238,6 @@ void GC_notify_full_gc()
void GC_maybe_gc()
{
static int n_partial_gcs = 0;
- GC_bool is_full_gc = FALSE;
if (GC_should_collect()) {
if (!GC_incremental) {
@@ -234,7 +245,7 @@ void GC_maybe_gc()
GC_gcollect_inner();
n_partial_gcs = 0;
return;
- } else if (n_partial_gcs >= GC_full_freq) {
+ } else if (GC_need_full_gc || n_partial_gcs >= GC_full_freq) {
# ifdef PRINTSTATS
GC_printf2(
"***>Full mark for collection %lu after %ld allocd bytes\n",
@@ -246,7 +257,7 @@ void GC_maybe_gc()
GC_clear_marks();
n_partial_gcs = 0;
GC_notify_full_gc();
- is_full_gc = TRUE;
+ GC_is_full_gc = TRUE;
} else {
n_partial_gcs++;
}
@@ -260,7 +271,7 @@ void GC_maybe_gc()
# endif
GC_finish_collection();
} else {
- if (!is_full_gc) {
+ if (!GC_is_full_gc) {
/* Count this as the first attempt */
GC_n_attempts++;
}
@@ -307,6 +318,7 @@ GC_stop_func stop_func;
# ifdef SAVE_CALL_CHAIN
GC_save_callers(GC_last_stack);
# endif
+ GC_is_full_gc = TRUE;
if (!GC_stopped_mark(stop_func)) {
if (!GC_incremental) {
/* We're partially done and have no way to complete or use */
@@ -548,6 +560,14 @@ void GC_finish_collection()
# endif
/* Reconstruct free lists to contain everything not marked */
GC_start_reclaim(FALSE);
+ if (GC_is_full_gc) {
+ GC_used_heap_size_after_full = USED_HEAP_SIZE;
+ GC_need_full_gc = FALSE;
+ } else {
+ GC_need_full_gc =
+ BYTES_TO_WORDS(USED_HEAP_SIZE - GC_used_heap_size_after_full)
+ > min_words_allocd();
+ }
# ifdef PRINTSTATS
GC_printf2(
@@ -564,6 +584,7 @@ void GC_finish_collection()
# endif
GC_n_attempts = 0;
+ GC_is_full_gc = FALSE;
/* Reset or increment counters for next cycle */
GC_words_allocd_before_gc += GC_words_allocd;
GC_non_gc_bytes_at_gc = GC_non_gc_bytes;
diff --git a/blacklst.c b/blacklst.c
index 0d623c0f..e5a3a26a 100644
--- a/blacklst.c
+++ b/blacklst.c
@@ -145,6 +145,13 @@ void GC_promote_black_lists()
if (GC_black_list_spacing < 3 * HBLKSIZE) {
GC_black_list_spacing = 3 * HBLKSIZE;
}
+ if (GC_black_list_spacing > MAXHINCR * HBLKSIZE) {
+ GC_black_list_spacing = MAXHINCR * HBLKSIZE;
+ /* Makes it easier to allocate really huge blocks, which otherwise */
+ /* may have problems with nonuniform blacklist distributions. */
+ /* This way we should always succeed immediately after growing the */
+ /* heap. */
+ }
}
void GC_unpromote_black_lists()
diff --git a/cord/cord.h b/cord/cord.h
index 584112fd..926089e8 100644
--- a/cord/cord.h
+++ b/cord/cord.h
@@ -41,7 +41,7 @@
* This interface is fairly big, largely for performance reasons.
* The most basic constants and functions:
*
- * CORD - the type fo a cord;
+ * CORD - the type of a cord;
* CORD_EMPTY - empty cord;
* CORD_len(cord) - length of a cord;
* CORD_cat(cord1,cord2) - concatenation of two cords;
diff --git a/cord/gc.h b/cord/gc.h
index 30614095..cc74765d 100644
--- a/cord/gc.h
+++ b/cord/gc.h
@@ -58,9 +58,11 @@
# if defined(__STDC__) || defined(__cplusplus)
# define GC_PROTO(args) args
typedef void * GC_PTR;
+# define GC_CONST const
# else
# define GC_PROTO(args) ()
typedef char * GC_PTR;
+# define GC_CONST
# endif
# ifdef __cplusplus
@@ -131,6 +133,12 @@ GC_API int GC_dont_expand;
GC_API int GC_full_freq; /* Number of partial collections between */
/* full collections. Matters only if */
/* GC_incremental is set. */
+ /* Full collections are also triggered if */
+ /* the collector detects a substantial */
+ /* increase in the number of in-use heap */
+ /* blocks. Values in the tens are now */
+ /* perfectly reasonable, unlike for */
+ /* earlier GC versions. */
GC_API GC_word GC_non_gc_bytes;
/* Bytes not considered candidates for collection. */
@@ -297,6 +305,9 @@ GC_API int GC_try_to_collect GC_PROTO((GC_stop_func stop_func));
/* Includes some pages that were allocated but never written. */
GC_API size_t GC_get_heap_size GC_PROTO((void));
+/* Return a lower bound on the number of free bytes in the heap. */
+GC_API size_t GC_get_free_bytes GC_PROTO((void));
+
/* Return the number of bytes allocated since the last collection. */
GC_API size_t GC_get_bytes_since_gc GC_PROTO((void));
@@ -341,10 +352,11 @@ GC_API GC_PTR GC_malloc_atomic_ignore_off_page GC_PROTO((size_t lb));
#ifdef GC_ADD_CALLER
# define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__
-# define GC_EXTRA_PARAMS GC_word ra, char * descr_string, int descr_int
+# define GC_EXTRA_PARAMS GC_word ra, GC_CONST char * descr_string,
+ int descr_int
#else
# define GC_EXTRAS __FILE__, __LINE__
-# define GC_EXTRA_PARAMS char * descr_string, int descr_int
+# define GC_EXTRA_PARAMS GC_CONST char * descr_string, int descr_int
#endif
/* Debugging (annotated) allocation. GC_gcollect will check */
@@ -688,7 +700,7 @@ GC_API void (*GC_is_visible_print_proc)
# endif /* SOLARIS_THREADS */
-#if defined(IRIX_THREADS) || defined(LINUX_THREADS)
+#if defined(IRIX_THREADS) || defined(LINUX_THREADS) || defined(HPUX_THREADS)
/* We treat these similarly. */
# include <pthread.h>
# include <signal.h>
@@ -707,7 +719,7 @@ GC_API void (*GC_is_visible_print_proc)
# if defined(PCR) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || \
defined(IRIX_THREADS) || defined(LINUX_THREADS) || \
- defined(IRIX_JDK_THREADS)
+ defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS)
/* Any flavor of threads except SRC_M3. */
/* This returns a list of objects, linked through their first */
/* word. Its use can greatly reduce lock contention problems, since */
diff --git a/dbg_mlc.c b/dbg_mlc.c
index 64832567..41843be1 100644
--- a/dbg_mlc.c
+++ b/dbg_mlc.c
@@ -343,10 +343,10 @@ void GC_start_debugging()
}
# ifdef GC_ADD_CALLER
-# define EXTRA_ARGS word ra, char * s, int i
+# define EXTRA_ARGS word ra, CONST char * s, int i
# define OPT_RA ra,
# else
-# define EXTRA_ARGS char * s, int i
+# define EXTRA_ARGS CONST char * s, int i
# define OPT_RA
# endif
@@ -531,13 +531,15 @@ GC_PTR p;
GC_PTR p;
# endif
{
- register GC_PTR base = GC_base(p);
+ register GC_PTR base;
register ptr_t clobbered;
+ if (0 == p) return;
+ base = GC_base(p);
if (base == 0) {
GC_err_printf1("Attempt to free invalid pointer %lx\n",
(unsigned long)p);
- if (p != 0) ABORT("free(invalid pointer)");
+ ABORT("free(invalid pointer)");
}
if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
GC_err_printf1(
diff --git a/dyn_load.c b/dyn_load.c
index d3df0a08..8c3ec418 100644
--- a/dyn_load.c
+++ b/dyn_load.c
@@ -47,7 +47,7 @@
#if (defined(DYNAMIC_LOADING) || defined(MSWIN32)) && !defined(PCR)
#if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && \
!defined(MSWIN32) && !(defined(ALPHA) && defined(OSF1)) && \
- !defined(HP_PA) && !(defined(LINUX) && defined(__ELF__)) && \
+ !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \
!defined(RS6000) && !defined(SCO_ELF)
--> We only know how to find data segments of dynamic libraries for the
--> above. Additional SVR4 variants might not be too
@@ -658,7 +658,7 @@ void GC_register_dynamic_libraries()
}
#endif
-#if defined(HP_PA)
+#if defined(HPUX)
#include <errno.h>
#include <dl.h>
@@ -681,6 +681,11 @@ void GC_register_dynamic_libraries()
/* Check if this is the end of the list or if some error occured */
if (status != 0) {
+# ifdef HPUX_THREADS
+ /* I've seen errno values of 0. The man page is not clear */
+ /* as to whether errno should get set on a -1 return. */
+ break;
+# else
if (errno == EINVAL) {
break; /* Moved past end of shared library list --> finished */
} else {
@@ -691,6 +696,7 @@ void GC_register_dynamic_libraries()
}
ABORT("shl_get failed");
}
+# endif
}
# ifdef VERBOSE
@@ -713,7 +719,7 @@ void GC_register_dynamic_libraries()
index++;
}
}
-#endif /* HP_PA */
+#endif /* HPUX */
#ifdef RS6000
#pragma alloca
diff --git a/gc.h b/gc.h
index 30614095..cc74765d 100644
--- a/gc.h
+++ b/gc.h
@@ -58,9 +58,11 @@
# if defined(__STDC__) || defined(__cplusplus)
# define GC_PROTO(args) args
typedef void * GC_PTR;
+# define GC_CONST const
# else
# define GC_PROTO(args) ()
typedef char * GC_PTR;
+# define GC_CONST
# endif
# ifdef __cplusplus
@@ -131,6 +133,12 @@ GC_API int GC_dont_expand;
GC_API int GC_full_freq; /* Number of partial collections between */
/* full collections. Matters only if */
/* GC_incremental is set. */
+ /* Full collections are also triggered if */
+ /* the collector detects a substantial */
+ /* increase in the number of in-use heap */
+ /* blocks. Values in the tens are now */
+ /* perfectly reasonable, unlike for */
+ /* earlier GC versions. */
GC_API GC_word GC_non_gc_bytes;
/* Bytes not considered candidates for collection. */
@@ -297,6 +305,9 @@ GC_API int GC_try_to_collect GC_PROTO((GC_stop_func stop_func));
/* Includes some pages that were allocated but never written. */
GC_API size_t GC_get_heap_size GC_PROTO((void));
+/* Return a lower bound on the number of free bytes in the heap. */
+GC_API size_t GC_get_free_bytes GC_PROTO((void));
+
/* Return the number of bytes allocated since the last collection. */
GC_API size_t GC_get_bytes_since_gc GC_PROTO((void));
@@ -341,10 +352,11 @@ GC_API GC_PTR GC_malloc_atomic_ignore_off_page GC_PROTO((size_t lb));
#ifdef GC_ADD_CALLER
# define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__
-# define GC_EXTRA_PARAMS GC_word ra, char * descr_string, int descr_int
+# define GC_EXTRA_PARAMS GC_word ra, GC_CONST char * descr_string,
+ int descr_int
#else
# define GC_EXTRAS __FILE__, __LINE__
-# define GC_EXTRA_PARAMS char * descr_string, int descr_int
+# define GC_EXTRA_PARAMS GC_CONST char * descr_string, int descr_int
#endif
/* Debugging (annotated) allocation. GC_gcollect will check */
@@ -688,7 +700,7 @@ GC_API void (*GC_is_visible_print_proc)
# endif /* SOLARIS_THREADS */
-#if defined(IRIX_THREADS) || defined(LINUX_THREADS)
+#if defined(IRIX_THREADS) || defined(LINUX_THREADS) || defined(HPUX_THREADS)
/* We treat these similarly. */
# include <pthread.h>
# include <signal.h>
@@ -707,7 +719,7 @@ GC_API void (*GC_is_visible_print_proc)
# if defined(PCR) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || \
defined(IRIX_THREADS) || defined(LINUX_THREADS) || \
- defined(IRIX_JDK_THREADS)
+ defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS)
/* Any flavor of threads except SRC_M3. */
/* This returns a list of objects, linked through their first */
/* word. Its use can greatly reduce lock contention problems, since */
diff --git a/gc_priv.h b/gc_priv.h
index 5ce52a7a..ac4d63a0 100644
--- a/gc_priv.h
+++ b/gc_priv.h
@@ -1,6 +1,9 @@
/*
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
* Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 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.
@@ -64,15 +67,15 @@ typedef char * ptr_t; /* A generic pointer to which we can add */
# include <stddef.h>
# endif
# define VOLATILE volatile
-# define CONST const
#else
# ifdef MSWIN32
# include <stdlib.h>
# endif
# define VOLATILE
-# define CONST
#endif
+#define CONST GC_CONST
+
#if 0 /* was once defined for AMIGA */
# define GC_FAR __far
#else
@@ -436,7 +439,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
# endif
# ifdef LINUX_THREADS
# include <pthread.h>
-# ifdef __i386__
+# if defined(I386)
inline static int GC_test_and_set(volatile unsigned int *addr) {
int oldval;
/* Note: the "xchg" instruction does not need a "lock" prefix */
@@ -446,9 +449,57 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
return oldval;
}
# else
- -- > Need implementation of GC_test_and_set()
+# if defined(POWERPC)
+ inline static int GC_test_and_set(volatile unsigned int *addr) {
+ int oldval;
+ int temp = 1; // locked value
+
+ __asm__ __volatile__(
+ "1:\tlwarx %0,0,%3\n" // load and reserve
+ "\tcmpwi %0, 0\n" // if load is
+ "\tbne 2f\n" // non-zero, return already set
+ "\tstwcx. %2,0,%1\n" // else store conditional
+ "\tbne- 1b\n" // retry if lost reservation
+ "2:\t\n" // oldval is zero if we set
+ : "=&r"(oldval), "=p"(addr)
+ : "r"(temp), "1"(addr)
+ : "memory");
+ return (int)oldval;
+ }
+# else
+# ifdef ALPHA
+ inline static int GC_test_and_set(volatile unsigned int *
+addr)
+ {
+ unsigned long oldvalue;
+ unsigned long temp;
+
+ __asm__ __volatile__(
+ "1: ldl_l %0,%1\n"
+ " and %0,%3,%2\n"
+ " bne %2,2f\n"
+ " xor %0,%3,%0\n"
+ " stl_c %0,%1\n"
+ " beq %0,3f\n"
+ " mb\n"
+ "2:\n"
+ ".section .text2,\"ax\"\n"
+ "3: br 1b\n"
+ ".previous"
+ :"=&r" (temp), "=m" (*addr), "=&r"
+(oldvalue)
+ :"Ir" (1), "m" (*addr));
+
+ return oldvalue;
+ }
+# else
+ -- > Need implementation of GC_test_and_set()
+# endif
+# endif
# endif
-# define GC_clear(addr) (*(addr) = 0)
+ inline static void GC_clear(volatile unsigned int *addr) {
+ *(addr) = 0;
+ }
extern volatile unsigned int GC_allocate_lock;
/* This is not a mutex because mutexes that obey the (optional) */
@@ -462,15 +513,10 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
# 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()))
-# ifdef UNDEFINED
-# define LOCK() pthread_mutex_lock(&GC_allocate_ml)
-# define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
-# else
-# define LOCK() \
+# define LOCK() \
{ if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); }
-# define UNLOCK() \
+# define UNLOCK() \
GC_clear(&GC_allocate_lock)
-# endif
extern GC_bool GC_collecting;
# define ENTER_GC() \
{ \
@@ -478,15 +524,30 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
}
# define EXIT_GC() GC_collecting = 0;
# endif /* LINUX_THREADS */
-# if defined(IRIX_THREADS) || defined(IRIX_JDK_THREADS)
+# if defined(HPUX_THREADS)
# include <pthread.h>
-# include <mutex.h>
+ extern pthread_mutex_t GC_allocate_ml;
+# define LOCK() pthread_mutex_lock(&GC_allocate_ml)
+# define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
+# endif
+# if defined(IRIX_THREADS) || defined(IRIX_JDK_THREADS)
+ /* This may also eventually be appropriate for HPUX_THREADS */
+# include <pthread.h>
+# ifndef HPUX_THREADS
+ /* This probably should never be included, but I can't test */
+ /* on Irix anymore. */
+# include <mutex.h>
+# endif
-# if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \
+# ifndef HPUX_THREADS
+# if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \
|| !defined(_COMPILER_VERSION) || _COMPILER_VERSION < 700
# define GC_test_and_set(addr, v) test_and_set(addr,v)
-# else
+# else
# define GC_test_and_set(addr, v) __test_and_set(addr,v)
+# endif
+# else
+ /* I couldn't find a way to do this inline on HP/UX */
# endif
extern unsigned long GC_allocate_lock;
/* This is not a mutex because mutexes that obey the (optional) */
@@ -500,15 +561,17 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
# 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()))
-# ifdef UNDEFINED
-# define LOCK() pthread_mutex_lock(&GC_allocate_ml)
-# define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
+# ifdef HPUX_THREADS
+# define LOCK() { if (!GC_test_and_clear(&GC_allocate_lock)) GC_lock(); }
+ /* The following is INCORRECT, since the memory model is too weak. */
+# define UNLOCK() { GC_noop1(&GC_allocate_lock); \
+ *(volatile unsigned long *)(&GC_allocate_lock) = 1; }
# else
-# define LOCK() { if (GC_test_and_set(&GC_allocate_lock, 1)) GC_lock(); }
-# if __mips >= 3 && (defined (_ABIN32) || defined(_ABI64)) \
+# define LOCK() { if (GC_test_and_set(&GC_allocate_lock, 1)) GC_lock(); }
+# if __mips >= 3 && (defined (_ABIN32) || defined(_ABI64)) \
&& defined(_COMPILER_VERSION) && _COMPILER_VERSION >= 700
# define UNLOCK() __lock_release(&GC_allocate_lock)
-# else
+# else
/* The function call in the following should prevent the */
/* compiler from moving assignments to below the UNLOCK. */
/* This is probably not necessary for ucode or gcc 2.8. */
@@ -516,7 +579,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
/* versions. */
# define UNLOCK() { GC_noop1(&GC_allocate_lock); \
*(volatile unsigned long *)(&GC_allocate_lock) = 0; }
-# endif
+# endif
# endif
extern GC_bool GC_collecting;
# define ENTER_GC() \
@@ -607,7 +670,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
# else
# if defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \
|| defined(IRIX_THREADS) || defined(LINUX_THREADS) \
- || defined(IRIX_JDK_THREADS)
+ || defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS)
void GC_stop_world();
void GC_start_world();
# define STOP_WORLD() GC_stop_world()
@@ -857,6 +920,9 @@ struct hblkhdr {
/* object starting at the ith word (header */
/* INCLUDED) in the heap block. */
/* The lsb of word 0 is numbered 0. */
+ /* Unused bits are invalid, and are */
+ /* occasionally set, e.g for uncollectable */
+ /* objects. */
};
/* heap block body */
@@ -1411,8 +1477,14 @@ extern void (*GC_start_call_back)(/* void */);
/* lock held. */
/* 0 by default. */
void GC_push_regs(); /* Push register contents onto mark stack. */
+ /* If NURSERY is defined, the default push */
+ /* action can be overridden with GC_push_proc */
void GC_remark(); /* Mark from all marked objects. Used */
/* only if we had to drop something. */
+
+# ifdef NURSERY
+ extern void (*GC_push_proc)(ptr_t);
+# endif
# if defined(MSWIN32)
void __cdecl GC_push_one();
# else
diff --git a/gcconfig.h b/gcconfig.h
index c9017d37..a7001089 100644
--- a/gcconfig.h
+++ b/gcconfig.h
@@ -53,6 +53,11 @@
# define NETBSD
# define mach_type_known
# endif
+# if defined(__NetBSD__) && defined(arm32)
+# define ARM32
+# define NETBSD
+# define mach_type_known
+# endif
# if defined(vax)
# define VAX
# ifdef ultrix
@@ -130,15 +135,22 @@
# define SYSV
# define mach_type_known
# endif
-# if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) \
+# if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
|| defined(hppa) || defined(__hppa__)
# define HP_PA
+# ifndef LINUX
+# define HPUX
+# endif
# define mach_type_known
# endif
# if defined(LINUX) && (defined(i386) || defined(__i386__))
# define I386
# define mach_type_known
# endif
+# if defined(LINUX) && (defined(__ia64__) || defined(__ia64))
+# define IA64
+# define mach_type_known
+# endif
# if defined(LINUX) && defined(powerpc)
# define POWERPC
# define mach_type_known
@@ -253,6 +265,10 @@
# define UTS4
# define mach_type_known
# endif
+# if defined(__pj__)
+# define PJ
+# define mach_type_known
+# endif
/* Ivan Demakov */
# if defined(__WATCOMC__) && defined(__386__)
# define I386
@@ -517,6 +533,11 @@
# define STACK_GRAN 0x10000000
/* Stack usually starts at 0x80000000 */
# define DATASTART GC_data_start
+ /* Others have reported better success with */
+ /* extern int __data_start; */
+ /*# define DATASTART (&__data_start) */
+ /* and disabling the GC_data_start */
+ /* initialization code. */
extern int _end;
# define DATAEND (&_end)
# endif
@@ -892,9 +913,17 @@
# endif
# ifdef HP_PA
+ /* OS is assumed to be HP/UX */
# define MACH_TYPE "HP_PA"
-# define ALIGNMENT 4
-# define ALIGN_DOUBLE
+# define OS_TYPE "HPUX"
+# ifdef __LP64__
+# define CPP_WORDSZ 64
+# define ALIGNMENT 8
+# else
+# define CPP_WORDSZ 32
+# define ALIGNMENT 4
+# define ALIGN_DOUBLE
+# endif
extern int __data_start;
# define DATASTART ((ptr_t)(&__data_start))
# if 0
@@ -911,6 +940,9 @@
# endif
# define STACK_GROWS_UP
# define DYNAMIC_LOADING
+# ifndef HPUX_THREADS
+# define MPROTECT_VDB
+# endif
# include <unistd.h>
# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE)
/* They misspelled the Posix macro? */
@@ -957,6 +989,31 @@
# endif
# endif
+# ifdef IA64
+# define MACH_TYPE "IA64"
+# define ALIGN_DOUBLE
+ /* Requires 16 byte alignment for malloc */
+# define ALIGNMENT 8
+# ifdef HPUX
+ --> needs work
+# endif
+# ifdef LINUX
+# define OS_TYPE "LINUX"
+# define CPP_WORDSZ 64
+ /* This should really be done through /proc, but that */
+ /* requires we run on an IA64 kernel. */
+# define STACKBOTTOM ((ptr_t) 0xa000000000000000l)
+ /* We also need the base address of the register stack */
+ /* backing store. There is probably a better way to */
+ /* get that, too ... */
+# define BACKING_STORE_BASE ((ptr_t) 0x9fffffff80000000l)
+# define DATASTART GC_data_start
+# define DYNAMIC_LOADING
+ extern int _end;
+# define DATAEND (&_end)
+# endif
+# endif
+
# ifdef M88K
# define MACH_TYPE "M88K"
# define ALIGNMENT 4
@@ -987,6 +1044,26 @@
# define HEURISTIC2
# endif
+# if defined(PJ)
+# define ALIGNMENT 4
+ extern int _etext;
+# define DATASTART ((ptr_t)(&_etext))
+# define HEURISTIC1
+# endif
+
+# ifdef ARM32
+# define CPP_WORDSZ 32
+# define MACH_TYPE "ARM32"
+# define ALIGNMENT 4
+# ifdef NETBSD
+# define OS_TYPE "NETBSD"
+# define HEURISTIC2
+ extern char etext;
+# define DATASTART ((ptr_t)(&etext))
+# define USE_GENERIC_PUSH_REGS
+# endif
+#endif
+
# ifndef STACK_GROWS_UP
# define STACK_GROWS_DOWN
# endif
@@ -1029,6 +1106,10 @@
# define SUNOS5SIGS
# endif
+# if defined(HPUX)
+# define SUNOS5SIGS
+# endif
+
# if CPP_WORDSZ != 32 && CPP_WORDSZ != 64
-> bad word size
# endif
@@ -1078,10 +1159,13 @@
# if defined(SOLARIS_THREADS) && !defined(SUNOS5)
--> inconsistent configuration
# endif
+# if defined(HPUX_THREADS) && !defined(HPUX)
+--> inconsistent configuration
+# endif
# if defined(PCR) || defined(SRC_M3) || \
defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || \
defined(IRIX_THREADS) || defined(LINUX_THREADS) || \
- defined(IRIX_JDK_THREADS)
+ defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS)
# define THREADS
# endif
diff --git a/irix_threads.c b/hpux_irix_threads.c
index 5efca211..a5b2cce5 100644
--- a/irix_threads.c
+++ b/hpux_irix_threads.c
@@ -1,6 +1,7 @@
/*
- * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
- * Copyright (c) 1996 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 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.
@@ -16,12 +17,19 @@
* not guaranteed by the Pthread standard. It may or may not be portable
* to other implementations.
*
+ * This now also includes an initial attempt at thread support for
+ * HP/UX 11.
+ *
* Note that there is a lot of code duplication between linux_threads.c
- * and irix_threads.c; any changes made here may need to be reflected
+ * and hpux_irix_threads.c; any changes made here may need to be reflected
* there too.
*/
-# if defined(IRIX_THREADS)
+# if defined(IRIX_THREADS) || defined(HPUX_THREADS)
+
+# if defined(HPUX_THREADS)
+# include <sys/semaphore.h>
+# endif
# include "gc_priv.h"
# include <pthread.h>
@@ -169,8 +177,12 @@ ptr_t GC_stack_alloc(size_t * stack_size)
result = (ptr_t) GC_scratch_alloc(search_sz + 2*GC_page_sz);
result = (ptr_t)(((word)result + GC_page_sz) & ~(GC_page_sz - 1));
/* Protect hottest page to detect overflow. */
- /* mprotect(result, GC_page_sz, PROT_NONE); */
- result += GC_page_sz;
+# ifdef STACK_GROWS_UP
+ /* mprotect(result + search_sz, GC_page_sz, PROT_NONE); */
+# else
+ /* mprotect(result, GC_page_sz, PROT_NONE); */
+ result += GC_page_sz;
+# endif
}
*stack_size = search_sz;
return(result);
@@ -381,7 +393,7 @@ void GC_push_all_stacks()
register int i;
register GC_thread p;
register ptr_t sp = GC_approx_sp();
- register ptr_t lo, hi;
+ register ptr_t hot, cold;
pthread_t me = pthread_self();
if (!GC_thr_initialized) GC_thr_init();
@@ -390,17 +402,25 @@ void GC_push_all_stacks()
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();
+ hot = GC_approx_sp();
} else {
- lo = p -> stack_ptr;
+ hot = p -> stack_ptr;
}
if (p -> stack_size != 0) {
- hi = p -> stack + p -> stack_size;
+# ifdef STACK_GROWS_UP
+ cold = p -> stack;
+# else
+ cold = p -> stack + p -> stack_size;
+# endif
} else {
/* The original stack. */
- hi = GC_stackbottom;
+ cold = GC_stackbottom;
}
- GC_push_all_stack(lo, hi);
+# ifdef STACK_GROWS_UP
+ GC_push_all_stack(cold, hot);
+# else
+ GC_push_all_stack(hot, cold);
+# endif
}
}
}
@@ -531,6 +551,40 @@ void * GC_start_routine(void * arg)
return(result);
}
+# ifdef HPUX_THREADS
+ /* pthread_attr_t is not a structure, thus a simple structure copy */
+ /* won't work. */
+ static void copy_attr(pthread_attr_t * pa_ptr,
+ const pthread_attr_t * source) {
+ int tmp;
+ size_t stmp;
+ void * vtmp;
+ struct sched_param sp_tmp;
+ pthread_spu_t ps_tmp;
+ (void) pthread_attr_init(pa_ptr);
+ (void) pthread_attr_getdetachstate(source, &tmp);
+ (void) pthread_attr_setdetachstate(pa_ptr, tmp);
+ (void) pthread_attr_getinheritsched(source, &tmp);
+ (void) pthread_attr_setinheritsched(pa_ptr, tmp);
+ (void) pthread_attr_getschedpolicy(source, &tmp);
+ (void) pthread_attr_setschedpolicy(pa_ptr, tmp);
+ (void) pthread_attr_getstacksize(source, &stmp);
+ (void) pthread_attr_setstacksize(pa_ptr, stmp);
+ (void) pthread_attr_getguardsize(source, &stmp);
+ (void) pthread_attr_setguardsize(pa_ptr, stmp);
+ (void) pthread_attr_getstackaddr(source, &vtmp);
+ (void) pthread_attr_setstackaddr(pa_ptr, vtmp);
+ (void) pthread_attr_getscope(source, &tmp);
+ (void) pthread_attr_setscope(pa_ptr, tmp);
+ (void) pthread_attr_getschedparam(source, &sp_tmp);
+ (void) pthread_attr_setschedparam(pa_ptr, &sp_tmp);
+ (void) pthread_attr_getprocessor_np(source, &ps_tmp, &tmp);
+ (void) pthread_attr_setprocessor_np(pa_ptr, ps_tmp, tmp);
+ }
+# else
+# define copy_attr(pa_ptr, source) *(pa_ptr) = *(source)
+# endif
+
int
GC_pthread_create(pthread_t *new_thread,
const pthread_attr_t *attr,
@@ -548,7 +602,9 @@ GC_pthread_create(pthread_t *new_thread,
/* library, which isn't visible to the collector. */
if (0 == si) return(ENOMEM);
- sem_init(&(si -> registered), 0, 0);
+ if (0 != sem_init(&(si -> registered), 0, 0)) {
+ ABORT("sem_init failed");
+ }
si -> start_routine = start_routine;
si -> arg = arg;
LOCK();
@@ -557,7 +613,7 @@ GC_pthread_create(pthread_t *new_thread,
stack = 0;
(void) pthread_attr_init(&new_attr);
} else {
- new_attr = *attr;
+ copy_attr(&new_attr, attr);
pthread_attr_getstackaddr(&new_attr, &stack);
}
pthread_attr_getstacksize(&new_attr, &stacksize);
@@ -586,24 +642,39 @@ GC_pthread_create(pthread_t *new_thread,
/* 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 != sem_wait(&(si -> registered))) ABORT("sem_wait failed");
+ while (0 != sem_wait(&(si -> registered))) {
+ if (errno != EINTR) {
+ GC_printf1("Sem_wait: errno = %ld\n", (unsigned long) errno);
+ ABORT("sem_wait failed");
+ }
+ }
sem_destroy(&(si -> registered));
- /* pthread_attr_destroy(&new_attr); */
+ pthread_attr_destroy(&new_attr); /* Not a no-op under HPUX */
return(result);
}
+#ifndef HPUX_THREADS
+/* For now we use the pthreads locking primitives on HP/UX */
+
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. This isn't really the right way to do this. */
-/* but until the POSIX scheduling mess gets straightened out ... */
-
-unsigned long GC_allocate_lock = 0;
+/* as STL alloc.h. */
#define SLEEP_THRESHOLD 3
+#ifdef HPUX
+ unsigned long GC_allocate_lock = 1;
+# define GC_TRY_LOCK() GC_test_and_clear(&GC_allocate_lock)
+# define GC_LOCK_TAKEN !GC_allocate_lock
+#else
+ unsigned long GC_allocate_lock = 0;
+# define GC_TRY_LOCK() !GC_test_and_set(&GC_allocate_lock,1)
+# define GC_LOCK_TAKEN GC_allocate_lock
+#endif
+
void GC_lock()
{
# define low_spin_max 30 /* spin cycles if we suspect uniprocessor */
@@ -616,7 +687,7 @@ void GC_lock()
# define PAUSE junk *= junk; junk *= junk; junk *= junk; junk *= junk
int i;
- if (!GC_test_and_set(&GC_allocate_lock, 1)) {
+ if (GC_TRY_LOCK()) {
return;
}
junk = 0;
@@ -624,11 +695,11 @@ void GC_lock()
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_allocate_lock) {
+ if (i < my_last_spins/2 || GC_LOCK_TAKEN) {
PAUSE;
continue;
}
- if (!GC_test_and_set(&GC_allocate_lock, 1)) {
+ if (GC_TRY_LOCK()) {
/*
* got it!
* Spinning worked. Thus we're probably not being scheduled
@@ -644,7 +715,7 @@ void GC_lock()
spin_max = low_spin_max;
yield:
for (i = 0;; ++i) {
- if (!GC_test_and_set(&GC_allocate_lock, 1)) {
+ if (GC_TRY_LOCK()) {
return;
}
if (i < SLEEP_THRESHOLD) {
@@ -662,7 +733,7 @@ yield:
}
}
-
+#endif /* !HPUX_THREADS */
# else
diff --git a/hpux_test_and_clear.s b/hpux_test_and_clear.s
new file mode 100644
index 00000000..f09b2114
--- /dev/null
+++ b/hpux_test_and_clear.s
@@ -0,0 +1,21 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT GC_test_and_clear,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+GC_test_and_clear
+ .PROC
+ .CALLINFO FRAME=0,NO_CALLS
+ .ENTRY
+ ldcw,co (%r26),%r28
+ bv,n 0(%r2)
+ .EXIT
+ .PROCEND
diff --git a/include/gc.h b/include/gc.h
index 30614095..cc74765d 100644
--- a/include/gc.h
+++ b/include/gc.h
@@ -58,9 +58,11 @@
# if defined(__STDC__) || defined(__cplusplus)
# define GC_PROTO(args) args
typedef void * GC_PTR;
+# define GC_CONST const
# else
# define GC_PROTO(args) ()
typedef char * GC_PTR;
+# define GC_CONST
# endif
# ifdef __cplusplus
@@ -131,6 +133,12 @@ GC_API int GC_dont_expand;
GC_API int GC_full_freq; /* Number of partial collections between */
/* full collections. Matters only if */
/* GC_incremental is set. */
+ /* Full collections are also triggered if */
+ /* the collector detects a substantial */
+ /* increase in the number of in-use heap */
+ /* blocks. Values in the tens are now */
+ /* perfectly reasonable, unlike for */
+ /* earlier GC versions. */
GC_API GC_word GC_non_gc_bytes;
/* Bytes not considered candidates for collection. */
@@ -297,6 +305,9 @@ GC_API int GC_try_to_collect GC_PROTO((GC_stop_func stop_func));
/* Includes some pages that were allocated but never written. */
GC_API size_t GC_get_heap_size GC_PROTO((void));
+/* Return a lower bound on the number of free bytes in the heap. */
+GC_API size_t GC_get_free_bytes GC_PROTO((void));
+
/* Return the number of bytes allocated since the last collection. */
GC_API size_t GC_get_bytes_since_gc GC_PROTO((void));
@@ -341,10 +352,11 @@ GC_API GC_PTR GC_malloc_atomic_ignore_off_page GC_PROTO((size_t lb));
#ifdef GC_ADD_CALLER
# define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__
-# define GC_EXTRA_PARAMS GC_word ra, char * descr_string, int descr_int
+# define GC_EXTRA_PARAMS GC_word ra, GC_CONST char * descr_string,
+ int descr_int
#else
# define GC_EXTRAS __FILE__, __LINE__
-# define GC_EXTRA_PARAMS char * descr_string, int descr_int
+# define GC_EXTRA_PARAMS GC_CONST char * descr_string, int descr_int
#endif
/* Debugging (annotated) allocation. GC_gcollect will check */
@@ -688,7 +700,7 @@ GC_API void (*GC_is_visible_print_proc)
# endif /* SOLARIS_THREADS */
-#if defined(IRIX_THREADS) || defined(LINUX_THREADS)
+#if defined(IRIX_THREADS) || defined(LINUX_THREADS) || defined(HPUX_THREADS)
/* We treat these similarly. */
# include <pthread.h>
# include <signal.h>
@@ -707,7 +719,7 @@ GC_API void (*GC_is_visible_print_proc)
# if defined(PCR) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || \
defined(IRIX_THREADS) || defined(LINUX_THREADS) || \
- defined(IRIX_JDK_THREADS)
+ defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS)
/* Any flavor of threads except SRC_M3. */
/* This returns a list of objects, linked through their first */
/* word. Its use can greatly reduce lock contention problems, since */
diff --git a/gc_copy_descr.h b/include/gc_copy_descr.h
index 212c99e2..212c99e2 100644
--- a/gc_copy_descr.h
+++ b/include/gc_copy_descr.h
diff --git a/nursery.h b/include/gc_nursery.h
index d109ff09..d109ff09 100755
--- a/nursery.h
+++ b/include/gc_nursery.h
diff --git a/include/new_gc_alloc.h b/include/new_gc_alloc.h
index 57713883..54b7bd44 100644
--- a/include/new_gc_alloc.h
+++ b/include/new_gc_alloc.h
@@ -318,12 +318,10 @@ class traceable_alloc_template {
typedef traceable_alloc_template < 0 > traceable_alloc;
-#ifdef _SGI_SOURCE
-
// We want to specialize simple_alloc so that it does the right thing
// for all pointerfree types. At the moment there is no portable way to
// even approximate that. The following approximation should work for
-// SGI compilers, and perhaps some others.
+// SGI compilers, and recent versions of g++.
# define __GC_SPECIALIZE(T,alloc) \
class simple_alloc<T, alloc> { \
@@ -451,6 +449,4 @@ __STL_END_NAMESPACE
#endif /* __STL_USE_STD_ALLOCATORS */
-#endif /* _SGI_SOURCE */
-
#endif /* GC_ALLOC_H */
diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h
index 5ce52a7a..ac4d63a0 100644
--- a/include/private/gc_priv.h
+++ b/include/private/gc_priv.h
@@ -1,6 +1,9 @@
/*
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
* Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 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.
@@ -64,15 +67,15 @@ typedef char * ptr_t; /* A generic pointer to which we can add */
# include <stddef.h>
# endif
# define VOLATILE volatile
-# define CONST const
#else
# ifdef MSWIN32
# include <stdlib.h>
# endif
# define VOLATILE
-# define CONST
#endif
+#define CONST GC_CONST
+
#if 0 /* was once defined for AMIGA */
# define GC_FAR __far
#else
@@ -436,7 +439,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
# endif
# ifdef LINUX_THREADS
# include <pthread.h>
-# ifdef __i386__
+# if defined(I386)
inline static int GC_test_and_set(volatile unsigned int *addr) {
int oldval;
/* Note: the "xchg" instruction does not need a "lock" prefix */
@@ -446,9 +449,57 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
return oldval;
}
# else
- -- > Need implementation of GC_test_and_set()
+# if defined(POWERPC)
+ inline static int GC_test_and_set(volatile unsigned int *addr) {
+ int oldval;
+ int temp = 1; // locked value
+
+ __asm__ __volatile__(
+ "1:\tlwarx %0,0,%3\n" // load and reserve
+ "\tcmpwi %0, 0\n" // if load is
+ "\tbne 2f\n" // non-zero, return already set
+ "\tstwcx. %2,0,%1\n" // else store conditional
+ "\tbne- 1b\n" // retry if lost reservation
+ "2:\t\n" // oldval is zero if we set
+ : "=&r"(oldval), "=p"(addr)
+ : "r"(temp), "1"(addr)
+ : "memory");
+ return (int)oldval;
+ }
+# else
+# ifdef ALPHA
+ inline static int GC_test_and_set(volatile unsigned int *
+addr)
+ {
+ unsigned long oldvalue;
+ unsigned long temp;
+
+ __asm__ __volatile__(
+ "1: ldl_l %0,%1\n"
+ " and %0,%3,%2\n"
+ " bne %2,2f\n"
+ " xor %0,%3,%0\n"
+ " stl_c %0,%1\n"
+ " beq %0,3f\n"
+ " mb\n"
+ "2:\n"
+ ".section .text2,\"ax\"\n"
+ "3: br 1b\n"
+ ".previous"
+ :"=&r" (temp), "=m" (*addr), "=&r"
+(oldvalue)
+ :"Ir" (1), "m" (*addr));
+
+ return oldvalue;
+ }
+# else
+ -- > Need implementation of GC_test_and_set()
+# endif
+# endif
# endif
-# define GC_clear(addr) (*(addr) = 0)
+ inline static void GC_clear(volatile unsigned int *addr) {
+ *(addr) = 0;
+ }
extern volatile unsigned int GC_allocate_lock;
/* This is not a mutex because mutexes that obey the (optional) */
@@ -462,15 +513,10 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
# 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()))
-# ifdef UNDEFINED
-# define LOCK() pthread_mutex_lock(&GC_allocate_ml)
-# define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
-# else
-# define LOCK() \
+# define LOCK() \
{ if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); }
-# define UNLOCK() \
+# define UNLOCK() \
GC_clear(&GC_allocate_lock)
-# endif
extern GC_bool GC_collecting;
# define ENTER_GC() \
{ \
@@ -478,15 +524,30 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
}
# define EXIT_GC() GC_collecting = 0;
# endif /* LINUX_THREADS */
-# if defined(IRIX_THREADS) || defined(IRIX_JDK_THREADS)
+# if defined(HPUX_THREADS)
# include <pthread.h>
-# include <mutex.h>
+ extern pthread_mutex_t GC_allocate_ml;
+# define LOCK() pthread_mutex_lock(&GC_allocate_ml)
+# define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
+# endif
+# if defined(IRIX_THREADS) || defined(IRIX_JDK_THREADS)
+ /* This may also eventually be appropriate for HPUX_THREADS */
+# include <pthread.h>
+# ifndef HPUX_THREADS
+ /* This probably should never be included, but I can't test */
+ /* on Irix anymore. */
+# include <mutex.h>
+# endif
-# if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \
+# ifndef HPUX_THREADS
+# if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \
|| !defined(_COMPILER_VERSION) || _COMPILER_VERSION < 700
# define GC_test_and_set(addr, v) test_and_set(addr,v)
-# else
+# else
# define GC_test_and_set(addr, v) __test_and_set(addr,v)
+# endif
+# else
+ /* I couldn't find a way to do this inline on HP/UX */
# endif
extern unsigned long GC_allocate_lock;
/* This is not a mutex because mutexes that obey the (optional) */
@@ -500,15 +561,17 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
# 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()))
-# ifdef UNDEFINED
-# define LOCK() pthread_mutex_lock(&GC_allocate_ml)
-# define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
+# ifdef HPUX_THREADS
+# define LOCK() { if (!GC_test_and_clear(&GC_allocate_lock)) GC_lock(); }
+ /* The following is INCORRECT, since the memory model is too weak. */
+# define UNLOCK() { GC_noop1(&GC_allocate_lock); \
+ *(volatile unsigned long *)(&GC_allocate_lock) = 1; }
# else
-# define LOCK() { if (GC_test_and_set(&GC_allocate_lock, 1)) GC_lock(); }
-# if __mips >= 3 && (defined (_ABIN32) || defined(_ABI64)) \
+# define LOCK() { if (GC_test_and_set(&GC_allocate_lock, 1)) GC_lock(); }
+# if __mips >= 3 && (defined (_ABIN32) || defined(_ABI64)) \
&& defined(_COMPILER_VERSION) && _COMPILER_VERSION >= 700
# define UNLOCK() __lock_release(&GC_allocate_lock)
-# else
+# else
/* The function call in the following should prevent the */
/* compiler from moving assignments to below the UNLOCK. */
/* This is probably not necessary for ucode or gcc 2.8. */
@@ -516,7 +579,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
/* versions. */
# define UNLOCK() { GC_noop1(&GC_allocate_lock); \
*(volatile unsigned long *)(&GC_allocate_lock) = 0; }
-# endif
+# endif
# endif
extern GC_bool GC_collecting;
# define ENTER_GC() \
@@ -607,7 +670,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
# else
# if defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \
|| defined(IRIX_THREADS) || defined(LINUX_THREADS) \
- || defined(IRIX_JDK_THREADS)
+ || defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS)
void GC_stop_world();
void GC_start_world();
# define STOP_WORLD() GC_stop_world()
@@ -857,6 +920,9 @@ struct hblkhdr {
/* object starting at the ith word (header */
/* INCLUDED) in the heap block. */
/* The lsb of word 0 is numbered 0. */
+ /* Unused bits are invalid, and are */
+ /* occasionally set, e.g for uncollectable */
+ /* objects. */
};
/* heap block body */
@@ -1411,8 +1477,14 @@ extern void (*GC_start_call_back)(/* void */);
/* lock held. */
/* 0 by default. */
void GC_push_regs(); /* Push register contents onto mark stack. */
+ /* If NURSERY is defined, the default push */
+ /* action can be overridden with GC_push_proc */
void GC_remark(); /* Mark from all marked objects. Used */
/* only if we had to drop something. */
+
+# ifdef NURSERY
+ extern void (*GC_push_proc)(ptr_t);
+# endif
# if defined(MSWIN32)
void __cdecl GC_push_one();
# else
diff --git a/mach_dep.c b/mach_dep.c
index 53698604..52f86346 100644
--- a/mach_dep.c
+++ b/mach_dep.c
@@ -62,6 +62,12 @@ asm static void PushMacRegisters()
#endif /* __MWERKS__ */
+# if defined(SPARC) || defined(IA64)
+ /* Value returned from register flushing routine; either sp (SPARC) */
+ /* or ar.bsp (IA64) */
+ word GC_save_regs_ret_val;
+# endif
+
/* Routine to mark from registers that are preserved by the C compiler. */
/* This must be ported to every new architecture. There is a generic */
/* version at the end, that is likely, but not guaranteed to work */
@@ -268,12 +274,12 @@ void GC_push_regs()
asm ("movd r7, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
# endif
-# ifdef SPARC
+# if defined(SPARC) || defined(IA64)
{
word GC_save_regs_in_stack();
/* generic code will not work */
- (void)GC_save_regs_in_stack();
+ GC_save_regs_ret_val = GC_save_regs_in_stack();
}
# endif
@@ -333,12 +339,22 @@ void GC_push_regs()
# endif /* !__GNUC__ */
# endif /* M68K/SYSV */
+# if defined(PJ)
+ {
+ register int * sp asm ("optop");
+ extern int *__libc_stack_end;
+
+ GC_push_all_stack (sp, __libc_stack_end);
+ }
+# endif
/* other machines... */
# if !(defined M68K) && !(defined VAX) && !(defined RT)
# if !(defined SPARC) && !(defined I386) && !(defined NS32K)
-# if !defined(POWERPC) && !defined(UTS4)
+# if !defined(POWERPC) && !defined(UTS4) && !defined(IA64)
+# if !defined(PJ)
--> bad news <--
+# endif
# endif
# endif
# endif
@@ -398,6 +414,27 @@ ptr_t cold_gc_frame;
# endif
# endif
+/* On IA64, we also need to flush register windows. But they end */
+/* up on the other side of the stack segment. */
+/* Returns the backing store pointer for the register stack. */
+# ifdef IA64
+ asm(" .text");
+ asm(" .psr abi64");
+ asm(" .psr lsb");
+ asm(" .lsb");
+ asm("");
+ asm(" .text");
+ asm(" .align 16");
+ asm(" .global GC_save_regs_in_stack");
+ asm(" .proc GC_save_regs_in_stack");
+ asm("GC_save_regs_in_stack:");
+ asm(" .body");
+ asm(" flushrs");
+ asm(" ;;");
+ asm(" mov r8=ar.bsp");
+ asm(" br.ret.sptk.few rp");
+ asm(" .endp GC_save_regs_in_stack");
+# endif
/* GC_clear_stack_inner(arg, limit) clears stack area up to limit and */
/* returns arg. Stack clearing is crucial on SPARC, so we supply */
diff --git a/mark.c b/mark.c
index 34db472a..67085fbc 100644
--- a/mark.c
+++ b/mark.c
@@ -87,6 +87,10 @@ struct obj_kind GC_obj_kinds[MAXOBJKINDS] = {
# define INITIAL_MARK_STACK_SIZE (1*HBLKSIZE)
/* INITIAL_MARK_STACK_SIZE * sizeof(mse) should be a */
/* multiple of HBLKSIZE. */
+ /* The incremental collector actually likes a larger */
+ /* size, since it want to push all marked dirty objs */
+ /* before marking anything new. Currently we let it */
+ /* grow dynamically. */
# endif
/*
@@ -254,7 +258,12 @@ ptr_t cold_gc_frame;
case MS_PUSH_RESCUERS:
if (GC_mark_stack_top
- >= GC_mark_stack + INITIAL_MARK_STACK_SIZE/4) {
+ >= GC_mark_stack + GC_mark_stack_size
+ - INITIAL_MARK_STACK_SIZE/2) {
+ /* Go ahead and mark, even though that might cause us to */
+ /* see more marked dirty objects later on. Avoid this */
+ /* in the future. */
+ GC_mark_stack_too_small = TRUE;
GC_mark_from_mark_stack();
return(FALSE);
} else {
@@ -671,6 +680,12 @@ int all;
# endif
word p;
{
+# ifdef NURSERY
+ if (0 != GC_push_proc) {
+ GC_push_proc(p);
+ return;
+ }
+# endif
GC_PUSH_ONE_STACK(p, 0);
}
@@ -1115,7 +1130,7 @@ struct hblk *h;
struct hblk * GC_push_next_marked_dirty(h)
struct hblk *h;
{
- register hdr * hhdr = HDR(h);
+ register hdr * hhdr;
if (!GC_dirty_maintained) { ABORT("dirty bits not set up"); }
for (;;) {
diff --git a/mark_rts.c b/mark_rts.c
index 2f21ed32..0e84f273 100644
--- a/mark_rts.c
+++ b/mark_rts.c
@@ -412,6 +412,9 @@ ptr_t cold_gc_frame;
if (0 == cold_gc_frame) return;
# ifdef STACK_GROWS_DOWN
GC_push_all_eager(GC_approx_sp(), cold_gc_frame);
+# ifdef IA64
+ --> fix this
+# endif
# else
GC_push_all_eager( cold_gc_frame, GC_approx_sp() );
# endif
@@ -419,6 +422,31 @@ ptr_t cold_gc_frame;
# ifdef STACK_GROWS_DOWN
GC_push_all_stack_partially_eager( GC_approx_sp(), GC_stackbottom,
cold_gc_frame );
+# ifdef IA64
+ /* We also need to push the register stack backing store. */
+ /* This should really be done in the same way as the */
+ /* regular stack. For now we fudge it a bit. */
+ /* Note that the backing store grows up, so we can't use */
+ /* GC_push_all_stack_partially_eager. */
+ {
+ extern word GC_save_regs_ret_val;
+ /* Previously set to backing store pointer. */
+ ptr_t bsp = (ptr_t) GC_save_regs_ret_val;
+ ptr_t cold_gc_bs_pointer;
+# ifdef ALL_INTERIOR_POINTERS
+ cold_gc_bs_pointer = bsp - 2048;
+ if (cold_gc_bs_pointer < BACKING_STORE_BASE) {
+ cold_gc_bs_pointer = BACKING_STORE_BASE;
+ }
+ GC_push_all(BACKING_STORE_BASE, cold_gc_bs_pointer);
+# else
+ cold_gc_bs_pointer = BACKING_STORE_BASE;
+# endif
+ GC_push_all_eager(cold_gc_bs_pointer, bsp);
+ /* All values should be sufficiently aligned that we */
+ /* dont have to worry about the boundary. */
+ }
+# endif
# else
GC_push_all_stack_partially_eager( GC_stackbottom, GC_approx_sp(),
cold_gc_frame );
diff --git a/misc.c b/misc.c
index c3fce63d..40cbe97d 100644
--- a/misc.c
+++ b/misc.c
@@ -44,12 +44,13 @@
# else
# if defined(IRIX_THREADS) || defined(LINUX_THREADS) \
|| defined(IRIX_JDK_THREADS)
-# ifdef UNDEFINED
- pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
-# endif
pthread_t GC_lock_holder = NO_THREAD;
# else
- --> declare allocator lock here
+# if defined(HPUX_THREADS)
+ pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
+# else
+ --> declare allocator lock here
+# endif
# endif
# endif
# endif
@@ -391,6 +392,11 @@ size_t GC_get_heap_size GC_PROTO(())
return ((size_t) GC_heapsize);
}
+size_t GC_get_free_bytes GC_PROTO(())
+{
+ return ((size_t) GC_large_free_bytes);
+}
+
size_t GC_get_bytes_since_gc GC_PROTO(())
{
return ((size_t) WORDS_TO_BYTES(GC_words_allocd));
@@ -433,7 +439,8 @@ void GC_init_inner()
# ifdef MSWIN32
GC_init_win32();
# endif
-# if defined(LINUX) && (defined(POWERPC) || defined(ALPHA) || defined(SPARC))
+# if defined(LINUX) && \
+ (defined(POWERPC) || defined(ALPHA) || defined(SPARC) || defined(IA64))
GC_init_linux_data_start();
# endif
# ifdef SOLARIS_THREADS
@@ -442,11 +449,12 @@ void GC_init_inner()
GC_dirty_init();
# endif
# if defined(IRIX_THREADS) || defined(LINUX_THREADS) \
- || defined(IRIX_JDK_THREADS)
+ || defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS)
GC_thr_init();
# endif
# if !defined(THREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \
- || defined(IRIX_THREADS) || defined(LINUX_THREADS)
+ || defined(IRIX_THREADS) || defined(LINUX_THREADS) \
+ || defined(HPUX_THREADS)
if (GC_stackbottom == 0) {
GC_stackbottom = GC_get_stack_base();
}
diff --git a/nursery.c b/nursery.c
index 8bbb1015..ab83afba 100644
--- a/nursery.c
+++ b/nursery.c
@@ -11,12 +11,16 @@
* modified is included with the above copyright notice.
*/
-
+#ifdef NURSERY
??? This implementation is incomplete. If you are trying to
??? compile this you are doing something wrong.
#include "nursery.h"
+#define SCAN_STATICS_FOR_NURSERY
+ /* If this is not defined, the collector will not see */
+ /* references from static data areas to the nursery. */
+
struct copy_obj {
ptr_t forward; /* Forwarding link for copied objects. */
GC_copy_descriptor descr; /* Object descriptor */
@@ -68,6 +72,23 @@ unsigned short *GC_pinned; /* Number of pinned objects in ith */
GC_copy_alloc_state global_alloc_state = (ptr_t)(-1); /* will overflow. */
+/* Array of known rescuing pointers from the heap to the nursery. */
+ ptr_t ** nursery_rescuers;
+ /* Pointer to one past the last slot in rescuer table */
+ ptr_t ** nursery_rescuers_end;
+ /* Maximum number of known rescuing pointers. */
+# define MAX_NURSERY_RESCUERS 32*1024
+ /* Add a rescuer to the list */
+# define ADD_NURSERY_RESCUER(p) \
+ if (nursery_rescuers_end >= nursery_rescuers + MAX_NURSERY_RESCUERS) { \
+ ABORT("Nursery recuers overflow"); /* Fix later !!! */ \
+ } else { \
+ *nursery_rescuers_end++ = p; \
+ }
+ /* Remove rescuer at the given position in the table */
+# define REMOVE_RESCUER(p) \
+ *p = *--nursery_rescuers_end
+
/* Should be called with allocator lock held. */
GC_nursery_init() {
GC_nursery_start = GET_MEM(GC_nursery_size);
@@ -92,44 +113,158 @@ GC_nursery_init() {
GC_nursery_blocks = GC_nursery_size/NURSERY_BLOCK_SIZE;
GC_pinned = GC_scratch_alloc(GC_nursery_blocks * sizeof(unsigned short));
BZERO(GC_pinned, GC_nursery_blocks);
+ nursery_rescuers = GET_MEM(MAX_NURSERY_RESCUERS * sizeof(ptr_t *));
+ nursery_rescuers_end = nursery_rescuers;
+ if (0 == GC_nursery_start || 0 == GC_nursery_map || 0 == nursery_rescuers)
+ ABORT("Insufficient memory for nursery");
+}
+
+#define PIN_OBJ(p) \
+ if (p >= GC_nursery_start && p < GC_nursery_end) { GC_pin_obj_checked(p); }
+
+/* Pin the object at p, if it's in the nursery. */
+void GC_pin_obj(ptr_t p) {
+ PIN_OBJ(p);
+}
+
+void (*GC_push_proc)(ptr_t) = 0;
+
+/* Pin the object at p, which is known to be in the nursery. */
+void GC_pin_obj_checked(ptr_t p) {
+ unsigned offset = p - GC_nursery_start;
+ unsigned word_offset = BYTES_TO_WORDS(offset);
+ unsigned blockno = (current - GC_nursery_start)/NURSERY_BLOCK_SIZE;
+ while (GC_nursery_map[word_offset] == NURSERY_MAP_NOT_START) {
+ --word_offset;
+ }
+ if (GC_nursery_map[word_offset] != NURSERY_MAP_PINNED) {
+ GC_nursery_map[word_offset] = NURSERY_MAP_PINNED;
+ ++GC_pinned[blockno];
+ ??Push object at GC_nursery_start + WORDS_TO_BYTES(word_offset)
+ ??onto mark stack.
+ }
+}
+
+void GC_scan_region_for_nursery(ptr_t low, ptr_t high) {
+# if CPP_WORDSZ/8 != ALIGNMENT
+ --> fix this
+# endif
+ word * l = (word *)((word)low + ALIGNMENT - 1 & ~(ALIGNMENT - 1));
+ word * h = (word *)((word)high & ~(ALIGNMENT - 1));
+ word * p;
+ for (p = l; p < h; ++p) {
+ PIN_OBJ(p);
+ }
}
-/* Pin all nursery objects referenced from mark stack. */
-void GC_pin_mark_stack_objects(void) {
- for each possible pointer current in a mark stack object
- if (current >= GC_nursery_start && current < GC_nursery_end) {
- unsigned offset = current - GC_nursery_start;
- unsigned word_offset = BYTES_TO_WORDS(offset);
- unsigned blockno = (current - GC_nursery_start)/NURSERY_BLOCK_SIZE;
- while (GC_nursery_map[word_offset] == NURSERY_MAP_NOT_START) {
- --word_offset;
- }
- if (GC_nursery_map[word_offset] != NURSERY_MAP_PINNED) {
- GC_nursery_map[word_offset] = NURSERY_MAP_PINNED;
- ++GC_pinned[blockno];
- ??Push object at GC_nursery_start + WORDS_TO_BYTES(word_offset)
- ??onto stack.
- }
+/* Invoke GC_scan_region_for_nursery on ranges that are not excluded. */
+void GC_scan_region_for_nursery_with_exclusions(ptr_t bottom, ptr_t top)
+{
+ struct exclusion * next;
+ ptr_t excl_start;
+
+ while (bottom < top) {
+ next = GC_next_exclusion(bottom);
+ if (0 == next || (excl_start = next -> e_start) >= top) {
+ GC_scan_region_for_nursery(bottom, top);
+ return;
}
+ if (excl_start > bottom)
+ GC_scan_region_for_nursery(bottom, excl_start);
+ bottom = next -> e_end;
}
}
+
+void GC_scan_stacks_for_nursery(void) {
+# ifdef THREADS
+ --> fix this
+# endif
+# ifdef STACK_GROWS_DOWN
+ ptr_t stack_low = GC_approx_sp();
+ ptr_t stack_high = GC_stackbottom;
+# else
+ ptr_t stack_low = GC_stackbottom;
+ ptr_t stack_high = GC_approx_sp();
+# endif
+ GC_scan_region_for_nursery(stack_low, stack_high);
+# ifdef IA64
+ GC_scan_region_for_nursery(BACKING_STORE_BASE,
+ (ptr_t) GC_save_regs_ret_val);
+# endif
+}
+
+void GC_scan_roots_for_nursery(void) {
+ /* Scan registers. */
+ /* Direct GC_push_one to call GC_pin_obj instead of marking */
+ /* and pushing objects. */
+ /* This is a bit ugly, but we don't have to touch the */
+ /* platform-dependent code. */
+
+ void (*old_push_proc)(ptr_t) = GC_push_proc;
+ GC_push_proc = GC_pin_obj;
+ GC_push_regs();
+ GC_push_proc = old_push_proc;
+ GC_scan_stacks_for_nursery();
+# ifdef SCAN_STATICS_FOR_NURSERY
+# if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(PCR)) \
+ && !defined(SRC_M3)
+ GC_remove_tmp_roots();
+ GC_register_dynamic_libraries();
+# endif
+ /* Mark everything in static data areas */
+ for (i = 0; i < n_root_sets; i++) {
+ GC_scan_region_for_nursery_with_exclusions (
+ GC_static_roots[i].r_start,
+ GC_static_roots[i].r_end);
+ }
+# endif
+}
+
+/* Array of known rescuing pointers from the heap to the nursery. */
+ptr_t ** nursery_rescuers;
+
/* Caller holds allocation lock. */
void GC_collect_nursery(void) {
int i;
ptr_t scan_ptr = 0;
- ?? old_mark_stack_top;
STOP_WORLD;
for (i = 0; i < GC_nursery_blocks; ++i) GC_pinned[i] = 0;
- GC_push_all_roots();
- old_mark_stack_top = GC_mark_stack_top();
- GC_pin_mark_stack_objects();
+ GC_scan_roots_for_nursery();
+ /* All objects referenced by roots are now pinned. */
+ /* Their contents are described by */
+ /* mark stack entries. */
+
+ /* Pin blocks corresponding to valid allocation states. */
+ /* that probably happens automagically if the allocation */
+ /* states are kept where we can see them. */
+ /* It will take work if static roots are not scanned. */
+ /* We want to do this both for correctness and to avoid */
+ /* promoting very young objects. */
+
+ /* Somehow capture dirty bits. Update rescuers array to */
+ /* reflect newly valid and invalid references from dirty */
+ /* pages. Other references should remain valid, since the */
+ /* referents should have been pinned. */
+
+ /* Traverse the old object heap. Pin objects in the */
+ /* nursery that are ambiguously referenced, copy those */
+ /* that are unambiguously referenced. */
+
+ /* Traverse objects in mark stack. */
+ /* If referenced object is in pinned block, add contents */
+ /* to mark stack. If referenced object is forwarded, */
+ /* update pointer. Otherwise reallocate the object in the */
+ /* old heap, copy its contents, and then enqueue its */
+ /* contents in the mark stack. */
START_WORLD;
}
/* Initialize an allocation state so that it can be used for */
/* allocation. This implicitly reserves a small section of the */
-/* nursery for use with his allocator. */
+/* nursery for use with this allocator. */
+/* Also called to replenish an allocator that has been */
+/* exhausted. */
void GC_init_copy_alloc_state(GC_copy_alloc_state *)
unsigned next_block;
ptr_t block_addr;
@@ -173,3 +308,5 @@ GC_PTR GC_copying_malloc2(GC_copy_descriptor *d, GC_copy_alloc_state *s) {
GC_PTR GC_copying_malloc(GC_copy_descriptor *d) {
}
+
+#endif /* NURSERY */
diff --git a/os_dep.c b/os_dep.c
index 81f74f3a..e83b5cac 100644
--- a/os_dep.c
+++ b/os_dep.c
@@ -1,6 +1,8 @@
/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
* Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
- * Copyright (c) 1996-1997 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 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.
@@ -31,7 +33,7 @@
/* make sure the former gets defined to be the latter if appropriate. */
# include <features.h>
# if 2 <= __GLIBC__
-# if 0 == __GLIBC_MINOR__
+# if 2 == __GLIBC__ && 0 == __GLIBC_MINOR__
/* glibc 2.1 no longer has sigcontext.h. But signal.h */
/* has the right declaration for glibc 2.1. */
# include <sigcontext.h>
@@ -54,13 +56,13 @@
# include <signal.h>
/* Blatantly OS dependent routines, except for those that are related */
-/* dynamic loading. */
+/* to dynamic loading. */
# if !defined(THREADS) && !defined(STACKBOTTOM) && defined(HEURISTIC2)
# define NEED_FIND_LIMIT
# endif
-# if defined(IRIX_THREADS)
+# if defined(IRIX_THREADS) || defined(HPUX_THREADS)
# define NEED_FIND_LIMIT
# endif
@@ -72,7 +74,8 @@
# define NEED_FIND_LIMIT
# endif
-# if defined(LINUX) && (defined(POWERPC) || defined(SPARC) || defined(ALPHA))
+# if defined(LINUX) && \
+ (defined(POWERPC) || defined(SPARC) || defined(ALPHA) || defined(IA64))
# define NEED_FIND_LIMIT
# endif
@@ -139,7 +142,8 @@
# define OPT_PROT_EXEC 0
#endif
-#if defined(LINUX) && (defined(POWERPC) || defined(SPARC) || defined(ALPHA))
+#if defined(LINUX) && (defined(POWERPC) || defined(SPARC) || defined(ALPHA) \
+ || defined(IA64))
/* The I386 case can be handled without a search. The Alpha case */
/* used to be handled differently as well, but the rules changed */
/* for recent Linux versions. This seems to be the easiest way to */
@@ -497,7 +501,7 @@ ptr_t GC_get_stack_base()
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1)
static struct sigaction old_segv_act;
-# if defined(_sigargs) /* !Irix6.x */
+# if defined(_sigargs) || defined(HPUX) /* !Irix6.x */
static struct sigaction old_bus_act;
# endif
# else
@@ -525,10 +529,11 @@ ptr_t GC_get_stack_base()
(void) sigaction(SIGSEGV, &act, 0);
# else
(void) sigaction(SIGSEGV, &act, &old_segv_act);
-# ifdef _sigargs /* Irix 5.x, not 6.x */
- /* Under 5.x, we may get SIGBUS. */
- /* Pthreads doesn't exist under 5.x, so we don't */
- /* have to worry in the threads case. */
+# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
+ || defined(HPUX)
+ /* Under Irix 5.x or HP/UX, we may get SIGBUS. */
+ /* Pthreads doesn't exist under Irix 5.x, so we */
+ /* don't have to worry in the threads case. */
(void) sigaction(SIGBUS, &act, &old_bus_act);
# endif
# endif /* IRIX_THREADS */
@@ -544,7 +549,8 @@ ptr_t GC_get_stack_base()
{
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1)
(void) sigaction(SIGSEGV, &old_segv_act, 0);
-# ifdef _sigargs /* Irix 5.x, not 6.x */
+# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
+ || defined(HPUX)
(void) sigaction(SIGBUS, &old_bus_act, 0);
# endif
# else
@@ -589,6 +595,40 @@ ptr_t GC_get_stack_base()
}
# endif
+#ifdef LINUX_STACKBOTTOM
+
+# define STAT_SKIP 27 /* Number of fields preceding startstack */
+ /* field in /proc/<pid>/stat */
+
+ ptr_t GC_linux_stack_base(void)
+ {
+ char buf[50];
+ FILE *f;
+ char c;
+ word result = 0;
+ int i;
+
+ sprintf(buf, "/proc/%d/stat", getpid());
+ f = fopen(buf, "r");
+ if (NULL == f) ABORT("Couldn't open /proc/<pid>/stat");
+ c = getc(f);
+ /* Skip the required number of fields. This number is hopefully */
+ /* constant across all Linux implementations. */
+ for (i = 0; i < STAT_SKIP; ++i) {
+ while (isspace(c)) c = getc(f);
+ while (!isspace(c)) c = getc(f);
+ }
+ while (isspace(c)) c = getc(f);
+ while (isdigit(c)) {
+ result *= 10;
+ result += c - '0';
+ c = getc(f);
+ }
+ if (result < 0x10000000) ABORT("Absurd stack bottom value");
+ return (ptr_t)result;
+ }
+
+#endif /* LINUX_STACKBOTTOM */
ptr_t GC_get_stack_base()
{
@@ -610,6 +650,9 @@ ptr_t GC_get_stack_base()
& ~STACKBOTTOM_ALIGNMENT_M1);
# endif
# endif /* HEURISTIC1 */
+# ifdef LINUX_STACKBOTTOM
+ result = GC_linux_stack_base();
+# endif
# ifdef HEURISTIC2
# ifdef STACK_GROWS_DOWN
result = GC_find_limit((ptr_t)(&dummy), TRUE);
@@ -1443,7 +1486,7 @@ void GC_default_push_other_roots()
# if defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \
|| defined(IRIX_THREADS) || defined(LINUX_THREADS) \
- || defined(IRIX_PCR_THREADS)
+ || defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS)
extern void GC_push_all_stacks();
@@ -1570,12 +1613,12 @@ struct hblk *h;
# include <sys/syscall.h>
# define PROTECT(addr, len) \
- if (mprotect((caddr_t)(addr), (int)(len), \
+ if (mprotect((caddr_t)(addr), (size_t)(len), \
PROT_READ | OPT_PROT_EXEC) < 0) { \
ABORT("mprotect failed"); \
}
# define UNPROTECT(addr, len) \
- if (mprotect((caddr_t)(addr), (int)(len), \
+ if (mprotect((caddr_t)(addr), (size_t)(len), \
PROT_WRITE | PROT_READ | OPT_PROT_EXEC ) < 0) { \
ABORT("un-mprotect failed"); \
}
@@ -1604,7 +1647,11 @@ struct hblk *h;
typedef void (* SIG_PF)();
#endif
#if defined(SUNOS5SIGS) || defined(OSF1) || defined(LINUX)
+# ifdef __STDC__
typedef void (* SIG_PF)(int);
+# else
+ typedef void (* SIG_PF)();
+# endif
#endif
#if defined(MSWIN32)
typedef LPTOP_LEVEL_EXCEPTION_FILTER SIG_PF;
@@ -1616,17 +1663,34 @@ struct hblk *h;
typedef void (* REAL_SIG_PF)(int, int, struct sigcontext *);
#endif
#if defined(SUNOS5SIGS)
- typedef void (* REAL_SIG_PF)(int, struct siginfo *, void *);
+# ifdef HPUX
+# define SIGINFO __siginfo
+# else
+# define SIGINFO siginfo
+# endif
+# ifdef __STDC__
+ typedef void (* REAL_SIG_PF)(int, struct SIGINFO *, void *);
+# else
+ typedef void (* REAL_SIG_PF)();
+# endif
#endif
#if defined(LINUX)
# include <linux/version.h>
-# if (LINUX_VERSION_CODE >= 0x20100) && !defined(M68K) || defined(ALPHA)
+# if (LINUX_VERSION_CODE >= 0x20100) && !defined(M68K) || defined(ALPHA) || defined(IA64)
typedef struct sigcontext s_c;
# else
typedef struct sigcontext_struct s_c;
# endif
+# if defined(ALPHA) || defined(M68K)
+ typedef void (* REAL_SIG_PF)(int, int, s_c *);
+# else
+# if defined(IA64)
+ typedef void (* REAL_SIG_PF)(int, siginfo_t *, s_c *);
+# else
+ typedef void (* REAL_SIG_PF)(int, s_c);
+# endif
+# endif
# ifdef ALPHA
- typedef void (* REAL_SIG_PF)(int, int, s_c *);
/* Retrieve fault address from sigcontext structure by decoding */
/* instruction. */
char * get_fault_addr(s_c *sc) {
@@ -1638,8 +1702,6 @@ struct hblk *h;
faultaddr += (word) (((int)instr << 16) >> 16);
return (char *)faultaddr;
}
-# else /* !ALPHA */
- typedef void (* REAL_SIG_PF)(int, s_c);
# endif /* !ALPHA */
# endif
@@ -1675,21 +1737,41 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
# endif
# endif
# if defined(LINUX)
-# ifdef ALPHA
+# if defined(ALPHA) || defined(M68K)
void GC_write_fault_handler(int sig, int code, s_c * sc)
# else
- void GC_write_fault_handler(int sig, s_c sc)
+# if defined(IA64)
+ void GC_write_fault_handler(int sig, siginfo_t * si, s_c * scp)
+# else
+ void GC_write_fault_handler(int sig, s_c sc)
+# endif
# endif
# define SIG_OK (sig == SIGSEGV)
# define CODE_OK TRUE
- /* Empirically c.trapno == 14, but is that useful? */
- /* We assume Intel architecture, so alignment */
- /* faults are not possible. */
+ /* Empirically c.trapno == 14, on IA32, but is that useful? */
+ /* Should probably consider alignment issues on other */
+ /* architectures. */
# endif
# if defined(SUNOS5SIGS)
- void GC_write_fault_handler(int sig, struct siginfo *scp, void * context)
-# define SIG_OK (sig == SIGSEGV)
-# define CODE_OK (scp -> si_code == SEGV_ACCERR)
+# ifdef __STDC__
+ void GC_write_fault_handler(int sig, struct SIGINFO *scp, void * context)
+# else
+ void GC_write_fault_handler(sig, scp, context)
+ int sig;
+ struct SIGINFO *scp;
+ void * context;
+# endif
+# ifdef HPUX
+# define SIG_OK (sig == SIGSEGV || sig == SIGBUS)
+# define CODE_OK (scp -> si_code == SEGV_ACCERR) \
+ || (scp -> si_code == BUS_ADRERR) \
+ || (scp -> si_code == BUS_UNKNOWN) \
+ || (scp -> si_code == SEGV_UNKNOWN) \
+ || (scp -> si_code == BUS_OBJERR)
+# else
+# define SIG_OK (sig == SIGSEGV)
+# define CODE_OK (scp -> si_code == SEGV_ACCERR)
+# endif
# endif
# if defined(MSWIN32)
LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info)
@@ -1741,7 +1823,15 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
# ifdef ALPHA
char * addr = get_fault_addr(sc);
# else
+# ifdef IA64
+ char * addr = si -> si_addr;
+# else
+# if defined(POWERPC)
+ char * addr = (char *) (sc.regs->dar);
+# else
--> architecture not supported
+# endif
+# endif
# endif
# endif
# endif
@@ -1794,10 +1884,14 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
return;
# endif
# if defined (LINUX)
-# ifdef ALPHA
+# if defined(ALPHA) || defined(M68K)
(*(REAL_SIG_PF)old_handler) (sig, code, sc);
# else
+# if defined(IA64)
+ (*(REAL_SIG_PF)old_handler) (sig, si, scp);
+# else
(*(REAL_SIG_PF)old_handler) (sig, sc);
+# endif
# endif
return;
# endif
@@ -1909,7 +2003,7 @@ void GC_dirty_init()
}
# endif
# if defined(SUNOS5SIGS) || defined(IRIX5)
-# if defined(IRIX_THREADS) || defined(IRIX_PCR_THREADS)
+# if defined(IRIX_THREADS) || defined(IRIX_JDK_THREADS)
sigaction(SIGSEGV, 0, &oldact);
sigaction(SIGSEGV, &act, 0);
# else
@@ -1935,6 +2029,15 @@ void GC_dirty_init()
GC_err_printf0("Replaced other SIGSEGV handler\n");
# endif
}
+# ifdef HPUX
+ sigaction(SIGBUS, &act, &oldact);
+ GC_old_bus_handler = oldact.sa_handler;
+ if (GC_old_segv_handler != SIG_DFL) {
+# ifdef PRINTSTATS
+ GC_err_printf0("Replaced other SIGBUS handler\n");
+# endif
+ }
+# endif
# endif
# if defined(MSWIN32)
GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler);
diff --git a/reclaim.c b/reclaim.c
index 30859469..6e0f53bb 100644
--- a/reclaim.c
+++ b/reclaim.c
@@ -1,6 +1,8 @@
/*
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
- * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 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.
@@ -11,7 +13,6 @@
* provided the above notices are retained, and a notice that the code was
* modified is included with the above copyright notice.
*/
-/* Boehm, February 15, 1996 2:41 pm PST */
#include <stdio.h>
#include "gc_priv.h"
@@ -67,6 +68,139 @@ register hdr * hhdr;
return(TRUE);
}
+/* The following functions sometimes return a DONT_KNOW value. */
+#define DONT_KNOW 2
+
+#ifdef SMALL_CONFIG
+# define GC_block_nearly_full1(hhdr, pat1) DONT_KNOW
+# define GC_block_nearly_full3(hhdr, pat1, pat2) DONT_KNOW
+# define GC_block_nearly_full(hhdr) DONT_KNOW
+#else
+
+/*
+ * Test whether nearly all of the mark words consist of the same
+ * repeating pattern.
+ */
+#define FULL_THRESHOLD (MARK_BITS_SZ/16)
+
+GC_bool GC_block_nearly_full1(hhdr, pat1)
+hdr *hhdr;
+word pat1;
+{
+ unsigned i;
+ unsigned misses = 0;
+ GC_ASSERT((MARK_BITS_SZ & 1) == 0);
+ for (i = 0; i < MARK_BITS_SZ; ++i) {
+ if ((hhdr -> hb_marks[i] | ~pat1) != ONES) {
+ if (++misses > FULL_THRESHOLD) return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * Test whether the same repeating 3 word pattern occurs in nearly
+ * all the mark bit slots.
+ * This is used as a heuristic, so we're a bit sloppy and ignore
+ * the last one or two words.
+ */
+GC_bool GC_block_nearly_full3(hhdr, pat1, pat2, pat3)
+hdr *hhdr;
+word pat1, pat2, pat3;
+{
+ unsigned i;
+ unsigned misses = 0;
+
+ if (MARK_BITS_SZ < 4) {
+ return DONT_KNOW;
+ }
+ for (i = 0; i < MARK_BITS_SZ - 2; i += 3) {
+ if ((hhdr -> hb_marks[i] | ~pat1) != ONES) {
+ if (++misses > FULL_THRESHOLD) return FALSE;
+ }
+ if ((hhdr -> hb_marks[i+1] | ~pat2) != ONES) {
+ if (++misses > FULL_THRESHOLD) return FALSE;
+ }
+ if ((hhdr -> hb_marks[i+2] | ~pat3) != ONES) {
+ if (++misses > FULL_THRESHOLD) return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/* Check whether a small object block is nearly full by looking at only */
+/* the mark bits. */
+/* We manually precomputed the mark bit patterns that need to be */
+/* checked for, and we give up on the ones that are unlikely to occur, */
+/* or have period > 3. */
+/* This would be a lot easier with a mark bit per object instead of per */
+/* word, but that would rewuire computing object numbers in the mark */
+/* loop, which would require different data structures ... */
+GC_bool GC_block_nearly_full(hhdr)
+hdr *hhdr;
+{
+ int sz = hhdr -> hb_sz;
+
+# if CPP_WORDSZ != 32 && CPP_WORDSZ != 64
+ return DONT_KNOW; /* Shouldn't be used in any standard config. */
+# endif
+ if (0 != HDR_WORDS) return DONT_KNOW;
+ /* Also shouldn't happen */
+# if CPP_WORDSZ == 32
+ switch(sz) {
+ case 1:
+ return GC_block_nearly_full1(hhdr, 0xffffffffl);
+ case 2:
+ return GC_block_nearly_full1(hhdr, 0x55555555l);
+ case 4:
+ return GC_block_nearly_full1(hhdr, 0x11111111l);
+ case 6:
+ return GC_block_nearly_full3(hhdr, 0x41041041l,
+ 0x10410410l,
+ 0x04104104l);
+ case 8:
+ return GC_block_nearly_full1(hhdr, 0x01010101l);
+ case 12:
+ return GC_block_nearly_full3(hhdr, 0x01001001l,
+ 0x10010010l,
+ 0x00100100l);
+ case 16:
+ return GC_block_nearly_full1(hhdr, 0x00010001l);
+ case 32:
+ return GC_block_nearly_full1(hhdr, 0x00000001l);
+ default:
+ return DONT_KNOW;
+ }
+# endif
+# if CPP_WORDSZ == 64
+ switch(sz) {
+ case 1:
+ return GC_block_nearly_full1(hhdr, 0xffffffffffffffffl);
+ case 2:
+ return GC_block_nearly_full1(hhdr, 0x5555555555555555l);
+ case 4:
+ return GC_block_nearly_full1(hhdr, 0x1111111111111111l);
+ case 6:
+ return GC_block_nearly_full3(hhdr, 0x1041041041041041l,
+ 0x4104104104104104l,
+ 0x0410410410410410l);
+ case 8:
+ return GC_block_nearly_full1(hhdr, 0x0101010101010101l);
+ case 12:
+ return GC_block_nearly_full3(hhdr, 0x1001001001001001l,
+ 0x0100100100100100l,
+ 0x0010010010010010l);
+ case 16:
+ return GC_block_nearly_full1(hhdr, 0x0001000100010001l);
+ case 32:
+ return GC_block_nearly_full1(hhdr, 0x0000000100000001l);
+ default:
+ return DONT_KNOW;
+ }
+# endif
+}
+#endif /* !SMALL_CONFIG */
+
# ifdef GATHERSTATS
# define INCR_WORDS(sz) n_words_found += (sz)
# else
@@ -448,10 +582,11 @@ register struct hblk *hbp; /* ptr to current heap block */
int report_if_found; /* Abort if a reclaimable object is found */
{
hdr * hhdr;
- register word sz; /* size of objects in current block */
- register struct obj_kind * ok;
- register ptr_t * flh;
- register int kind;
+ word sz; /* size of objects in current block */
+ struct obj_kind * ok;
+ ptr_t * flh;
+ int kind;
+ GC_bool full;
hhdr = HDR(hbp);
sz = hhdr -> hb_sz;
@@ -459,7 +594,6 @@ int report_if_found; /* Abort if a reclaimable object is found */
kind = hhdr -> hb_obj_kind;
ok = &GC_obj_kinds[kind];
flh = &(ok -> ok_freelist[sz]);
- GC_write_hint(hbp);
if (report_if_found) {
GC_reclaim_check(hbp, hhdr, sz);
@@ -467,16 +601,29 @@ int report_if_found; /* Abort if a reclaimable object is found */
switch(sz) {
# ifndef SMALL_CONFIG
case 1:
+ full = GC_block_nearly_full1(hhdr, 0xffffffffl);
+ if (TRUE == full) goto out;
+ if (FALSE == full) GC_write_hint(hbp);
+ /* In the DONT_KNOW case, we let reclaim fault. */
*flh = GC_reclaim1(hbp, hhdr, *flh);
break;
case 2:
+ full = GC_block_nearly_full1(hhdr, 0x55555555l);
+ if (TRUE == full) goto out;
+ if (FALSE == full) GC_write_hint(hbp);
*flh = GC_reclaim_clear2(hbp, hhdr, *flh);
break;
case 4:
+ full = GC_block_nearly_full1(hhdr, 0x11111111l);
+ if (TRUE == full) goto out;
+ if (FALSE == full) GC_write_hint(hbp);
*flh = GC_reclaim_clear4(hbp, hhdr, *flh);
break;
# endif
default:
+ full = GC_block_nearly_full(hhdr);
+ if (TRUE == full) goto out;
+ if (FALSE == full) GC_write_hint(hbp);
*flh = GC_reclaim_clear(hbp, hhdr, sz, *flh);
break;
}
@@ -484,20 +631,33 @@ int report_if_found; /* Abort if a reclaimable object is found */
switch(sz) {
# ifndef SMALL_CONFIG
case 1:
+ full = GC_block_nearly_full1(hhdr, 0xffffffffl);
+ if (TRUE == full) goto out;
+ if (FALSE == full) GC_write_hint(hbp);
*flh = GC_reclaim1(hbp, hhdr, *flh);
break;
case 2:
+ full = GC_block_nearly_full1(hhdr, 0x55555555l);
+ if (TRUE == full) goto out;
+ if (FALSE == full) GC_write_hint(hbp);
*flh = GC_reclaim_uninit2(hbp, hhdr, *flh);
break;
case 4:
+ full = GC_block_nearly_full1(hhdr, 0x11111111l);
+ if (TRUE == full) goto out;
+ if (FALSE == full) GC_write_hint(hbp);
*flh = GC_reclaim_uninit4(hbp, hhdr, *flh);
break;
# endif
default:
+ full = GC_block_nearly_full(hhdr);
+ if (TRUE == full) goto out;
+ if (FALSE == full) GC_write_hint(hbp);
*flh = GC_reclaim_uninit(hbp, hhdr, sz, *flh);
break;
}
}
+out:
if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(hhdr);
}
diff --git a/test.c b/test.c
index b65632c9..43b09010 100644
--- a/test.c
+++ b/test.c
@@ -45,7 +45,7 @@
# include <synch.h>
# endif
-# if defined(IRIX_THREADS) || defined(LINUX_THREADS)
+# if defined(IRIX_THREADS) || defined(LINUX_THREADS) || defined(HPUX_THREADS)
# include <pthread.h>
# endif
@@ -53,9 +53,6 @@
# include <process.h>
static CRITICAL_SECTION incr_cs;
# endif
-# if defined(PCR) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS)
-# define THREADS
-# endif
# ifdef AMIGA
long __stack = 200000;
@@ -281,7 +278,7 @@ struct {
}
# if defined(IRIX_THREADS) || defined(LINUX_THREADS) \
- || defined(SOLARIS_PTHREADS)
+ || defined(SOLARIS_PTHREADS) || defined(HPUX_THREADS)
void fork_a_thread()
{
pthread_t t;
@@ -453,7 +450,7 @@ VOLATILE int dropped_something = 0;
static mutex_t incr_lock;
mutex_lock(&incr_lock);
# endif
-# if defined(IRIX_THREADS) || defined(LINUX_THREADS)
+# if defined(IRIX_THREADS) || defined(LINUX_THREADS) || defined(HPUX_THREADS)
static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&incr_lock);
# endif
@@ -471,7 +468,7 @@ VOLATILE int dropped_something = 0;
# ifdef SOLARIS_THREADS
mutex_unlock(&incr_lock);
# endif
-# if defined(IRIX_THREADS) || defined(LINUX_THREADS)
+# if defined(IRIX_THREADS) || defined(LINUX_THREADS) || defined(HPUX_THREADS)
pthread_mutex_unlock(&incr_lock);
# endif
# ifdef WIN32_THREADS
@@ -532,7 +529,8 @@ int n;
static mutex_t incr_lock;
mutex_lock(&incr_lock);
# endif
-# if defined(IRIX_THREADS) || defined(LINUX_THREADS)
+# if defined(IRIX_THREADS) || defined(LINUX_THREADS) \
+ || defined(HPUX_THREADS)
static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&incr_lock);
# endif
@@ -548,7 +546,8 @@ int n;
# ifdef SOLARIS_THREADS
mutex_unlock(&incr_lock);
# endif
-# if defined(IRIX_THREADS) || defined(LINUX_THREADS)
+# if defined(IRIX_THREADS) || defined(LINUX_THREADS) \
+ || defined(HPUX_THREADS)
pthread_mutex_unlock(&incr_lock);
# endif
# ifdef WIN32_THREADS
@@ -644,7 +643,7 @@ void * alloc8bytes()
#else
# if defined(_SOLARIS_PTHREADS) || defined(IRIX_THREADS) \
- || defined(LINUX_THREADS)
+ || defined(LINUX_THREADS) || defined(HPUX_THREADS)
pthread_key_t fl_key;
void * alloc8bytes()
@@ -857,6 +856,7 @@ void run_one_test()
(void)GC_printf0("GC_malloc_uncollectable(0) failed\n");
FAIL;
}
+ GC_FREE(0);
GC_is_valid_displacement_print_proc = fail_proc1;
GC_is_visible_print_proc = fail_proc1;
x = GC_malloc(16);
@@ -879,7 +879,7 @@ void run_one_test()
FAIL;
}
if (!TEST_FAIL_COUNT(1)) {
-# if!(defined(RS6000) || defined(POWERPC))
+# if!(defined(RS6000) || defined(POWERPC) || defined(IA64))
/* ON RS6000s function pointers point to a descriptor in the */
/* data segment, so there should have been no failures. */
(void)GC_printf0("GC_is_visible produced wrong failure indication\n");
@@ -1030,7 +1030,8 @@ void SetMinimumStack(long minSize)
#if !defined(PCR) && !defined(SOLARIS_THREADS) && !defined(WIN32_THREADS) \
- && !defined(IRIX_THREADS) && !defined(LINUX_THREADS) || defined(LINT)
+ && !defined(IRIX_THREADS) && !defined(LINUX_THREADS) \
+ && !defined(HPUX_THREADS) || defined(LINT)
#ifdef MSWIN32
int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int n)
#else
@@ -1161,7 +1162,8 @@ test()
}
#endif
-#if defined(SOLARIS_THREADS) || defined(IRIX_THREADS) || defined(LINUX_THREADS)
+#if defined(SOLARIS_THREADS) || defined(IRIX_THREADS) \
+ || defined(HPUX_THREADS) || defined(LINUX_THREADS)
void * thr_run_one_test(void * arg)
{
run_one_test();
@@ -1222,7 +1224,7 @@ main()
*((volatile char *)&code - 1024*1024) = 0; /* Require 1 Mb */
# endif /* IRIX_THREADS */
pthread_attr_init(&attr);
-# ifdef IRIX_THREADS
+# if defined(IRIX_THREADS) || defined(HPUX_THREADS)
pthread_attr_setstacksize(&attr, 1000000);
# endif
n_tests = 0;
@@ -1232,7 +1234,7 @@ main()
(void) GC_printf0("Emulating dirty bits with mprotect/signals\n");
# endif
(void) GC_set_warn_proc(warn_proc);
- if (pthread_key_create(&fl_key, 0) != 0) {
+ if ((code = pthread_key_create(&fl_key, 0)) != 0) {
(void)GC_printf1("Key creation failed %lu\n", (unsigned long)code);
FAIL;
}
@@ -1260,4 +1262,4 @@ main()
return(0);
}
#endif /* pthreads */
-#endif /* SOLARIS_THREADS || IRIX_THREADS || LINUX_THREADS */
+#endif /* SOLARIS_THREADS || IRIX_THREADS || LINUX_THREADS || HPUX_THREADS */
diff --git a/threadlibs.c b/threadlibs.c
index 4a0a6cfc..df4eb77b 100644
--- a/threadlibs.c
+++ b/threadlibs.c
@@ -6,6 +6,9 @@ int main()
# if defined(IRIX_THREADS) || defined(LINUX_THREADS)
printf("-lpthread\n");
# endif
+# if defined(HPUX_THREADS)
+ printf("-lpthread -lrt\n");
+# endif
# ifdef SOLARIS_THREADS
printf("-lthread -ldl\n");
# endif
diff --git a/version.h b/version.h
index 97ac5f5e..df0770c9 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
#define GC_VERSION_MAJOR 5
#define GC_VERSION_MINOR 0
-#define GC_ALPHA_VERSION 3
+#define GC_ALPHA_VERSION 4
# define GC_NOT_ALPHA 0xff