From: bryce Date: Mon, 21 May 2001 06:39:25 +0000 (+0000) Subject: This commit was generated by cvs2svn to compensate for changes in r42373, X-Git-Tag: upstream/4.9.2~94293 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e46d228c487acde2ac1bdcd445bae97168d80674;p=platform%2Fupstream%2Flinaro-gcc.git This commit was generated by cvs2svn to compensate for changes in r42373, which included commits to RCS files with non-trunk default branches. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@42374 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/boehm-gc/NT_THREADS_MAKEFILE b/boehm-gc/NT_THREADS_MAKEFILE index 0fd22b7..c90584e 100644 --- a/boehm-gc/NT_THREADS_MAKEFILE +++ b/boehm-gc/NT_THREADS_MAKEFILE @@ -1,5 +1,6 @@ # Microsoft Developer Studio Generated NMAKE File, Format Version 4.10 -# ** DO NOT EDIT ** +# This has been hand-edited way too many times. +# A clean, manually generated makefile would be an improvement. # TARGTYPE "Win32 (x86) Application" 0x0101 # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 @@ -72,6 +73,8 @@ CLEAN : -@erase ".\Release\finalize.obj" -@erase ".\Release\finalize.sbr" -@erase ".\Release\gc.bsc" + -@erase ".\Release\gc_cpp.obj" + -@erase ".\Release\gc_cpp.sbr" -@erase ".\Release\gc.dll" -@erase ".\Release\gc.exp" -@erase ".\Release\gc.lib" @@ -111,8 +114,8 @@ CLEAN : 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\ +# ADD CPP /nologo /MD /W3 /GX /O2 /I include /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 /I include /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/ @@ -155,6 +158,7 @@ BSC32_SBRS= \ ".\Release\dbg_mlc.sbr" \ ".\Release\dyn_load.sbr" \ ".\Release\finalize.sbr" \ + ".\Release\gc_cpp.sbr" \ ".\Release\headers.sbr" \ ".\Release\mach_dep.sbr" \ ".\Release\malloc.sbr" \ @@ -192,6 +196,7 @@ LINK32_OBJS= \ ".\Release\dbg_mlc.obj" \ ".\Release\dyn_load.obj" \ ".\Release\finalize.obj" \ + ".\Release\gc_cpp.obj" \ ".\Release\headers.obj" \ ".\Release\mach_dep.obj" \ ".\Release\malloc.obj" \ @@ -245,6 +250,8 @@ CLEAN : -@erase ".\Debug\dyn_load.sbr" -@erase ".\Debug\finalize.obj" -@erase ".\Debug\finalize.sbr" + -@erase ".\Debug\gc_cpp.obj" + -@erase ".\Debug\gc_cpp.sbr" -@erase ".\Debug\gc.bsc" -@erase ".\Debug\gc.dll" -@erase ".\Debug\gc.exp" @@ -289,8 +296,8 @@ CLEAN : 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"\ +# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I include /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 /I include /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 @@ -334,6 +341,7 @@ BSC32_SBRS= \ ".\Debug\dbg_mlc.sbr" \ ".\Debug\dyn_load.sbr" \ ".\Debug\finalize.sbr" \ + ".\Debug\gc_cpp.sbr" \ ".\Debug\headers.sbr" \ ".\Debug\mach_dep.sbr" \ ".\Debug\malloc.sbr" \ @@ -371,6 +379,7 @@ LINK32_OBJS= \ ".\Debug\dbg_mlc.obj" \ ".\Debug\dyn_load.obj" \ ".\Debug\finalize.obj" \ + ".\Debug\gc_cpp.obj" \ ".\Debug\headers.obj" \ ".\Debug\mach_dep.obj" \ ".\Debug\malloc.obj" \ @@ -416,10 +425,13 @@ CLEAN : "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" +test.c : tests\test.c + copy tests\test.c test.c + 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\ +# ADD CPP /nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "__STDC__" /D "WIN32_THREADS" /YX /c +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I include /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/ @@ -505,7 +517,7 @@ CLEAN : 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"\ +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I include /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/ @@ -596,7 +608,7 @@ CLEAN : 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\ +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "." /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\ "ALL_INTERIOR_POINTERS" /Fp"$(INTDIR)/cord.pch" /YX /Fo"$(INTDIR)/" /c CPP_OBJS=.\cord\Release/ CPP_SBRS=.\. @@ -688,7 +700,7 @@ CLEAN : 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\ +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "." /I include /D "_DEBUG" /D "WIN32" /D\ "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /Fp"$(INTDIR)/cord.pch" /YX\ /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c CPP_OBJS=.\cord\Debug/ @@ -763,15 +775,65 @@ LINK32_OBJS= \ ################################################################################ # Begin Source File +SOURCE=.\gc_cpp.cpp + +!IF "$(CFG)" == "gc - Win32 Release" + +DEP_CPP_RECLA=\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ + ".\include\gc_cpp.h"\ + {$(INCLUDE)}"\sys\TYPES.H"\ + +NODEP_CPP_RECLA=\ + ".\th\PCR_Th.h"\ + ".\th\PCR_ThCrSec.h"\ + ".\th\PCR_ThCtl.h"\ + + +".\Release\gc_cpp.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)" + +".\Release\gc_cpp.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "gc - Win32 Debug" + +DEP_CPP_RECLA=\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ + ".\include\gc_cpp.h"\ + {$(INCLUDE)}"\sys\TYPES.H"\ + +NODEP_CPP_RECLA=\ + ".\th\PCR_Th.h"\ + ".\th\PCR_ThCrSec.h"\ + ".\th\PCR_ThCtl.h"\ + + +".\Debug\gc_cpp.obj" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)" + +".\Debug\gc_cpp.sbr" : $(SOURCE) $(DEP_CPP_RECLA) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# 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\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_RECLA=\ @@ -788,10 +850,10 @@ NODEP_CPP_RECLA=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_RECLA=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_RECLA=\ @@ -808,6 +870,7 @@ NODEP_CPP_RECLA=\ !ENDIF # End Source File + ################################################################################ # Begin Source File @@ -816,10 +879,10 @@ SOURCE=.\os_dep.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_OS_DE=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\STAT.H"\ {$(INCLUDE)}"\sys\TYPES.H"\ @@ -840,10 +903,10 @@ NODEP_CPP_OS_DE=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_OS_DE=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\STAT.H"\ {$(INCLUDE)}"\sys\TYPES.H"\ @@ -872,10 +935,10 @@ SOURCE=.\misc.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_MISC_=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_MISC_=\ @@ -893,10 +956,10 @@ NODEP_CPP_MISC_=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_MISC_=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_MISC_=\ @@ -922,10 +985,10 @@ SOURCE=.\mark_rts.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_MARK_=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_MARK_=\ @@ -942,10 +1005,10 @@ NODEP_CPP_MARK_=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_MARK_=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_MARK_=\ @@ -970,10 +1033,10 @@ SOURCE=.\mach_dep.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_MACH_=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_MACH_=\ @@ -990,10 +1053,10 @@ NODEP_CPP_MACH_=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_MACH_=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_MACH_=\ @@ -1018,10 +1081,10 @@ SOURCE=.\headers.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_HEADE=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_HEADE=\ @@ -1038,10 +1101,10 @@ NODEP_CPP_HEADE=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_HEADE=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_HEADE=\ @@ -1066,10 +1129,10 @@ SOURCE=.\alloc.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_ALLOC=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_ALLOC=\ @@ -1086,10 +1149,10 @@ NODEP_CPP_ALLOC=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_ALLOC=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_ALLOC=\ @@ -1114,10 +1177,10 @@ SOURCE=.\allchblk.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_ALLCH=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_ALLCH=\ @@ -1134,10 +1197,10 @@ NODEP_CPP_ALLCH=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_ALLCH=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_ALLCH=\ @@ -1162,10 +1225,10 @@ SOURCE=.\stubborn.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_STUBB=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_STUBB=\ @@ -1182,10 +1245,10 @@ NODEP_CPP_STUBB=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_STUBB=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_STUBB=\ @@ -1210,10 +1273,10 @@ SOURCE=.\obj_map.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_OBJ_M=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_OBJ_M=\ @@ -1230,10 +1293,10 @@ NODEP_CPP_OBJ_M=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_OBJ_M=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_OBJ_M=\ @@ -1258,10 +1321,10 @@ SOURCE=.\new_hblk.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_NEW_H=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_NEW_H=\ @@ -1278,10 +1341,10 @@ NODEP_CPP_NEW_H=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_NEW_H=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_NEW_H=\ @@ -1306,11 +1369,12 @@ 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\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_pmark.h"\ + ".\include\gc_mark.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_MARK_C=\ @@ -1327,11 +1391,12 @@ NODEP_CPP_MARK_C=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_MARK_C=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_mark.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_pmark.h"\ + ".\include\gc_mark.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_MARK_C=\ @@ -1356,10 +1421,10 @@ SOURCE=.\malloc.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_MALLO=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_MALLO=\ @@ -1376,10 +1441,10 @@ NODEP_CPP_MALLO=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_MALLO=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_MALLO=\ @@ -1404,10 +1469,10 @@ SOURCE=.\mallocx.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_MALLX=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_MALLX=\ @@ -1424,10 +1489,10 @@ NODEP_CPP_MALLX=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_MALLX=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_MALLX=\ @@ -1452,11 +1517,12 @@ 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\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_pmark.h"\ + ".\include\gc_mark.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_FINAL=\ @@ -1473,11 +1539,12 @@ NODEP_CPP_FINAL=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_FINAL=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_mark.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_pmark.h"\ + ".\include\gc_mark.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_FINAL=\ @@ -1502,10 +1569,10 @@ SOURCE=.\dbg_mlc.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_DBG_M=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_DBG_M=\ @@ -1522,10 +1589,10 @@ NODEP_CPP_DBG_M=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_DBG_M=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_DBG_M=\ @@ -1550,10 +1617,10 @@ SOURCE=.\blacklst.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_BLACK=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_BLACK=\ @@ -1570,10 +1637,10 @@ NODEP_CPP_BLACK=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_BLACK=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_BLACK=\ @@ -1598,12 +1665,13 @@ 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\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_pmark.h"\ + ".\include\gc_mark.h"\ + ".\include\private\gc_priv.h"\ + ".\include\gc_typed.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_TYPD_=\ @@ -1620,12 +1688,13 @@ NODEP_CPP_TYPD_=\ !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\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_pmark.h"\ + ".\include\gc_mark.h"\ + ".\include\private\gc_priv.h"\ + ".\include\gc_typed.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_TYPD_=\ @@ -1650,11 +1719,12 @@ 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\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_pmark.h"\ + ".\include\gc_mark.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_PTR_C=\ @@ -1671,11 +1741,12 @@ NODEP_CPP_PTR_C=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_PTR_C=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_mark.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_pmark.h"\ + ".\include\gc_mark.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_PTR_C=\ @@ -1700,10 +1771,10 @@ SOURCE=.\dyn_load.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_DYN_L=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\STAT.H"\ {$(INCLUDE)}"\sys\TYPES.H"\ @@ -1723,10 +1794,10 @@ NODEP_CPP_DYN_L=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_DYN_L=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\STAT.H"\ {$(INCLUDE)}"\sys\TYPES.H"\ @@ -1754,10 +1825,10 @@ SOURCE=.\win32_threads.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_WIN32=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_WIN32=\ @@ -1774,10 +1845,10 @@ NODEP_CPP_WIN32=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_WIN32=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_WIN32=\ @@ -1802,10 +1873,10 @@ SOURCE=.\checksums.c !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_CHECK=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_CHECK=\ @@ -1822,10 +1893,10 @@ NODEP_CPP_CHECK=\ !ELSEIF "$(CFG)" == "gc - Win32 Debug" DEP_CPP_CHECK=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_CHECK=\ @@ -1876,13 +1947,13 @@ NODEP_CPP_CHECK=\ ################################################################################ # Begin Source File -SOURCE=.\test.c +SOURCE=.\tests\test.c DEP_CPP_TEST_=\ - ".\gcconfig.h"\ - ".\gc.h"\ - ".\gc_hdrs.h"\ - ".\gc_priv.h"\ - ".\gc_typed.h"\ + ".\include\private\gcconfig.h"\ + ".\include\gc.h"\ + ".\include\private\gc_hdrs.h"\ + ".\include\private\gc_priv.h"\ + ".\include\gc_typed.h"\ {$(INCLUDE)}"\sys\TYPES.H"\ NODEP_CPP_TEST_=\ @@ -1944,13 +2015,13 @@ NODEP_CPP_TEST_=\ SOURCE=.\cord\de_win.c DEP_CPP_DE_WI=\ - ".\cord\cord.h"\ + ".\include\cord.h"\ ".\cord\de_cmds.h"\ ".\cord\de_win.h"\ - ".\cord\private\cord_pos.h"\ + ".\include\private\cord_pos.h"\ NODEP_CPP_DE_WI=\ - ".\cord\gc.h"\ + ".\include\gc.h"\ !IF "$(CFG)" == "cord - Win32 Release" @@ -1975,13 +2046,13 @@ NODEP_CPP_DE_WI=\ SOURCE=.\cord\de.c DEP_CPP_DE_C2e=\ - ".\cord\cord.h"\ + ".\include\cord.h"\ ".\cord\de_cmds.h"\ ".\cord\de_win.h"\ - ".\cord\private\cord_pos.h"\ + ".\include\private\cord_pos.h"\ NODEP_CPP_DE_C2e=\ - ".\cord\gc.h"\ + ".\include\gc.h"\ !IF "$(CFG)" == "cord - Win32 Release" @@ -2006,12 +2077,12 @@ NODEP_CPP_DE_C2e=\ SOURCE=.\cord\cordxtra.c DEP_CPP_CORDX=\ - ".\cord\cord.h"\ - ".\cord\ec.h"\ - ".\cord\private\cord_pos.h"\ + ".\include\cord.h"\ + ".\include\ec.h"\ + ".\include\private\cord_pos.h"\ NODEP_CPP_CORDX=\ - ".\cord\gc.h"\ + ".\include\gc.h"\ !IF "$(CFG)" == "cord - Win32 Release" @@ -2036,11 +2107,11 @@ NODEP_CPP_CORDX=\ SOURCE=.\cord\cordbscs.c DEP_CPP_CORDB=\ - ".\cord\cord.h"\ - ".\cord\private\cord_pos.h"\ + ".\include\cord.h"\ + ".\include\private\cord_pos.h"\ NODEP_CPP_CORDB=\ - ".\cord\gc.h"\ + ".\include\gc.h"\ !IF "$(CFG)" == "cord - Win32 Release" diff --git a/boehm-gc/cord/cordtest.c b/boehm-gc/cord/cordtest.c index d11d7dd..d54c65f 100644 --- a/boehm-gc/cord/cordtest.c +++ b/boehm-gc/cord/cordtest.c @@ -14,6 +14,7 @@ # include "cord.h" # include # include +# include /* This is a very incomplete test of the cord package. It knows about */ /* a few internals of the package (e.g. when C strings are returned) */ /* that real clients shouldn't rely on. */ diff --git a/boehm-gc/include/gc.h b/boehm-gc/include/gc.h index d7cd899..b1449f5 100644 --- a/boehm-gc/include/gc.h +++ b/boehm-gc/include/gc.h @@ -29,8 +29,56 @@ #ifndef _GC_H # define _GC_H + +#if defined(_SOLARIS_PTHREADS) && !defined(SOLARIS_THREADS) +# define SOLARIS_THREADS +#endif + +/* + * Some tests for old macros. These violate our namespace rules and will + * disappear shortly. + */ +#if defined(SOLARIS_THREADS) || defined(_SOLARIS_THREADS) +# define GC_SOLARIS_THREADS +#endif +#if defined(_SOLARIS_PTHREADS) +# define GC_SOLARIS_PTHREADS +#endif +#if defined(IRIX_THREADS) +# define GC_IRIX_THREADS +#endif +#if defined(HPUX_THREADS) +# define GC_HPUX_THREADS +#endif +#if defined(OSF1_THREADS) +# define GC_OSF1_THREADS +#endif +#if defined(LINUX_THREADS) +# define GC_LINUX_THREADS +#endif +#if defined(WIN32_THREADS) +# define GC_WIN32_THREADS +#endif +#if defined(USE_LD_WRAP) +# define GC_USE_LD_WRAP +#endif + +#if !defined(_REENTRANT) && (defined(GC_SOLARIS_THREADS) \ + || defined(GC_SOLARIS_PTHREADS) \ + || defined(GC_HPUX_THREADS) \ + || defined(GC_LINUX_THREADS)) +# define _REENTRANT + /* Better late than never. This fails if system headers that */ + /* depend on this were previously included. */ +#endif + # define __GC # include +# ifdef _WIN32_WCE +/* Yet more kluges for WinCE */ +# include /* size_t is defined here */ + typedef long ptrdiff_t; /* ptrdiff_t is not defined */ +# endif #if defined(__CYGWIN32__) && defined(GC_USE_DLL) #include "libgc_globals.h" @@ -44,9 +92,10 @@ # endif #endif -#if defined(_MSC_VER) && defined(_DLL) +#if defined(_MSC_VER) && (defined(_DLL) && !defined(NOT_GC_DLL) \ + || defined(GC_DLL)) # ifdef GC_BUILD -# define GC_API __declspec(dllexport) +# define GC_API extern __declspec(dllexport) # else # define GC_API __declspec(dllimport) # endif @@ -94,6 +143,16 @@ typedef long GC_signed_word; GC_API GC_word GC_gc_no;/* Counter incremented per collection. */ /* Includes empty GCs at startup. */ + +GC_API int GC_parallel; /* GC is parallelized for performance on */ + /* multiprocessors. Currently set only */ + /* implicitly if collector is built with */ + /* -DPARALLEL_MARK and if either: */ + /* Env variable GC_NPROC is set to > 1, or */ + /* GC_NPROC is not set and this is an MP. */ + /* If GC_parallel is set, incremental */ + /* collection is aonly partially functional, */ + /* and may not be desirable. */ /* Public R/W variables */ @@ -113,6 +172,18 @@ GC_API int GC_find_leak; /* deallocated with GC_free. Initial value */ /* is determined by FIND_LEAK macro. */ +GC_API int GC_all_interior_pointers; + /* Arrange for pointers to object interiors to */ + /* be recognized as valid. May not be changed */ + /* after GC initialization. */ + /* Initial value is determined by */ + /* -DALL_INTERIOR_POINTERS. */ + /* Unless DONT_ADD_BYTE_AT_END is defined, this */ + /* also affects whether sizes are increased by */ + /* at least a byte to allow "off the end" */ + /* pointer recognition. */ + /* MUST BE 0 or 1. */ + GC_API int GC_quiet; /* Disable statistics output. Only matters if */ /* collector has been compiled with statistics */ /* enabled. This involves a performance cost, */ @@ -120,7 +191,7 @@ GC_API int GC_quiet; /* Disable statistics output. Only matters if */ GC_API int GC_finalize_on_demand; /* If nonzero, finalizers will only be run in */ - /* response to an eplit GC_invoke_finalizers */ + /* response to an explicit GC_invoke_finalizers */ /* call. The default is determined by whether */ /* the FINALIZE_ON_DEMAND macro is defined */ /* when the collector is built. */ @@ -132,6 +203,15 @@ GC_API int GC_java_finalization; /* ordered finalization. Default value is */ /* determined by JAVA_FINALIZATION macro. */ +GC_API void (* GC_finalizer_notifier)(); + /* Invoked by the collector when there are */ + /* objects to be finalized. Invoked at most */ + /* once per GC cycle. Never invoked unless */ + /* GC_finalize_on_demand is set. */ + /* Typically this will notify a finalization */ + /* thread, which will call GC_invoke_finalizers */ + /* in response. */ + GC_API int GC_dont_gc; /* Dont collect unless explicitly requested, e.g. */ /* because it's not safe. */ @@ -163,6 +243,16 @@ GC_API int GC_full_freq; /* Number of partial collections between */ GC_API GC_word GC_non_gc_bytes; /* Bytes not considered candidates for collection. */ /* Used only to control scheduling of collections. */ + /* Updated by GC_malloc_uncollectable and GC_free. */ + /* Wizards only. */ + +GC_API int GC_no_dls; + /* Don't register dynamic library data segments. */ + /* Wizards only. Should be used only if the */ + /* application explicitly registers all roots. */ + /* In Microsoft Windows environments, this will */ + /* usually also prevent registration of the */ + /* main data segment as part of the root set. */ GC_API GC_word GC_free_space_divisor; /* We try to make sure that we allocate at */ @@ -193,8 +283,16 @@ GC_API char *GC_stackbottom; /* Cool end of user stack. */ /* automatically. */ /* For multithreaded code, this is the */ /* cold end of the stack for the */ - /* primordial thread. */ + /* primordial thread. */ +GC_API int GC_dont_precollect; /* Don't collect as part of */ + /* initialization. Should be set only */ + /* if the client wants a chance to */ + /* manually initialize the root set */ + /* before the first collection. */ + /* Interferes with blacklisting. */ + /* Wizards only. */ + /* Public procedures */ /* * general purpose allocation routines, with roughly malloc calling conv. @@ -204,8 +302,13 @@ GC_API char *GC_stackbottom; /* Cool end of user stack. */ * will occur after GC_end_stubborn_change has been called on the * result of GC_malloc_stubborn. GC_malloc_uncollectable allocates an object * that is scanned for pointers to collectable objects, but is not itself - * collectable. GC_malloc_uncollectable and GC_free called on the resulting + * collectable. The object is scanned even if it does not appear to + * be reachable. GC_malloc_uncollectable and GC_free called on the resulting * object implicitly update GC_non_gc_bytes appropriately. + * + * Note that the GC_malloc_stubborn support is stubbed out by default + * starting in 6.0. GC_malloc_stubborn is an alias for GC_malloc unless + * the collector is built with STUBBORN_ALLOC defined. */ GC_API GC_PTR GC_malloc GC_PROTO((size_t size_in_bytes)); GC_API GC_PTR GC_malloc_atomic GC_PROTO((size_t size_in_bytes)); @@ -331,12 +434,18 @@ 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)); +/* Return the total number of bytes allocated in this process. */ +/* Never decreases. */ +GC_API size_t GC_get_total_bytes GC_PROTO((void)); + /* Enable incremental/generational collection. */ /* Not advisable unless dirty bits are */ /* available or most heap objects are */ /* pointerfree(atomic) or immutable. */ /* Don't use in leak finding mode. */ /* Ignored if GC_dont_gc is true. */ +/* Only the generational piece of this is */ +/* functional if GC_parallel is TRUE. */ GC_API void GC_enable_incremental GC_PROTO((void)); /* Perform some garbage collection work, if appropriate. */ @@ -497,6 +606,8 @@ GC_API void GC_debug_register_finalizer /* but it's unavoidable for C++, since the compiler may */ /* silently introduce these. It's also benign in that specific */ /* case. */ +/* Note that cd will still be viewed as accessible, even if it */ +/* refers to the object itself. */ GC_API void GC_register_finalizer_ignore_self GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd, GC_finalization_proc *ofn, GC_PTR *ocd)); @@ -505,7 +616,9 @@ GC_API void GC_debug_register_finalizer_ignore_self GC_finalization_proc *ofn, GC_PTR *ocd)); /* Another version of the above. It ignores all cycles. */ -/* It should probably only be used by Java implementations. */ +/* It should probably only be used by Java implementations. */ +/* Note that cd will still be viewed as accessible, even if it */ +/* refers to the object itself. */ GC_API void GC_register_finalizer_no_order GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd, GC_finalization_proc *ofn, GC_PTR *ocd)); @@ -608,6 +721,9 @@ typedef GC_PTR (*GC_fn_type) GC_PROTO((GC_PTR client_data)); GC_API GC_PTR GC_call_with_alloc_lock GC_PROTO((GC_fn_type fn, GC_PTR client_data)); +/* The following routines are primarily intended for use with a */ +/* preprocessor which inserts calls to check C pointer arithmetic. */ + /* Check that p and q point to the same object. */ /* Fail conspicuously if they don't. */ /* Returns the first argument. */ @@ -635,7 +751,7 @@ GC_API GC_PTR GC_is_visible GC_PROTO((GC_PTR p)); /* Check that if p is a pointer to a heap page, then it points to */ /* a valid displacement within a heap object. */ /* Fail conspicuously if this property does not hold. */ -/* Uninteresting with ALL_INTERIOR_POINTERS. */ +/* Uninteresting with GC_all_interior_pointers. */ /* Always returns its argument. */ GC_API GC_PTR GC_is_valid_displacement GC_PROTO((GC_PTR p)); @@ -651,9 +767,9 @@ GC_API GC_PTR GC_is_valid_displacement GC_PROTO((GC_PTR p)); # ifdef __GNUC__ # define GC_PTR_ADD(x, n) \ GC_PTR_ADD3(x, n, typeof(x)) -# define GC_PRE_INCR(x, n) \ +# define GC_PRE_INCR(x, n) \ GC_PRE_INCR3(x, n, typeof(x)) -# define GC_POST_INCR(x, n) \ +# define GC_POST_INCR(x, n) \ GC_POST_INCR3(x, typeof(x)) # else /* We can't do this right without typeof, which ANSI */ @@ -693,76 +809,28 @@ GC_API void (*GC_is_valid_displacement_print_proc) GC_API void (*GC_is_visible_print_proc) GC_PROTO((GC_PTR p)); -#if defined(_SOLARIS_PTHREADS) && !defined(SOLARIS_THREADS) -# define SOLARIS_THREADS -#endif - -#ifdef SOLARIS_THREADS -/* We need to intercept calls to many of the threads primitives, so */ -/* that we can locate thread stacks and stop the world. */ -/* Note also that the collector cannot see thread specific data. */ -/* Thread specific data should generally consist of pointers to */ -/* uncollectable objects, which are deallocated using the destructor */ -/* facility in thr_keycreate. */ -# include -# include - int GC_thr_create(void *stack_base, size_t stack_size, - void *(*start_routine)(void *), void *arg, long flags, - thread_t *new_thread); - int GC_thr_join(thread_t wait_for, thread_t *departed, void **status); - int GC_thr_suspend(thread_t target_thread); - int GC_thr_continue(thread_t target_thread); - void * GC_dlopen(const char *path, int mode); - -# ifdef _SOLARIS_PTHREADS -# include - extern int GC_pthread_create(pthread_t *new_thread, - const pthread_attr_t *attr, - void * (*thread_execp)(void *), void *arg); - extern int GC_pthread_join(pthread_t wait_for, void **status); - -# undef thread_t - -# define pthread_join GC_pthread_join -# define pthread_create GC_pthread_create -#endif - -# define thr_create GC_thr_create -# define thr_join GC_thr_join -# define thr_suspend GC_thr_suspend -# define thr_continue GC_thr_continue -# define dlopen GC_dlopen - -# endif /* SOLARIS_THREADS */ +/* For pthread support, we generally need to intercept a number of */ +/* thread library calls. We do that here by macro defining them. */ -#if !defined(USE_LD_WRAP) && \ - (defined(IRIX_THREADS) || defined(LINUX_THREADS) || defined(HPUX_THREADS)) -/* We treat these similarly. */ -# include -# include - - int GC_pthread_create(pthread_t *new_thread, - const pthread_attr_t *attr, - void *(*start_routine)(void *), void *arg); - int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset); - int GC_pthread_join(pthread_t thread, void **retval); - -# define pthread_create GC_pthread_create -# define pthread_sigmask GC_pthread_sigmask -# define pthread_join GC_pthread_join -# define dlopen GC_dlopen - -#endif /* xxxxx_THREADS */ +#if !defined(GC_USE_LD_WRAP) && \ + (defined(GC_LINUX_THREADS) || defined(GC_HPUX_THREADS) || \ + defined(GC_IRIX_THREADS) || defined(GC_SOLARIS_PTHREADS) || \ + defined(GC_SOLARIS_THREADS) || defined(GC_OSF1_THREADS)) +# include "gc_pthread_redirects.h" +#endif -# if defined(PCR) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || \ - defined(IRIX_THREADS) || defined(LINUX_THREADS) || \ - defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS) +# if defined(PCR) || defined(GC_SOLARIS_THREADS) || \ + defined(GC_SOLARIS_PTHREADS) || defined(GC_WIN32_THREADS) || \ + defined(GC_IRIX_THREADS) || defined(GC_LINUX_THREADS) || \ + defined(GC_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 */ /* the allocation lock can be acquired and released many fewer times. */ /* lb must be large enough to hold the pointer field. */ +/* It is used internally by gc_local_alloc.h, which provides a simpler */ +/* programming interface on Linux. */ GC_PTR GC_malloc_many(size_t lb); #define GC_NEXT(p) (*(GC_PTR *)(p)) /* Retrieve the next element */ /* in returned list. */ @@ -770,6 +838,35 @@ extern void GC_thr_init(); /* Needed for Solaris/X86 */ #endif /* THREADS && !SRC_M3 */ +#if defined(WIN32_THREADS) && defined(_WIN32_WCE) +# include + + /* + * win32_threads.c implements the real WinMain, which will start a new thread + * to call GC_WinMain after initializing the garbage collector. + */ + int WINAPI GC_WinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPWSTR lpCmdLine, + int nCmdShow ); + + /* + * All threads must be created using GC_CreateThread, so that they will be + * recorded in the thread table. + */ + HANDLE WINAPI GC_CreateThread( + LPSECURITY_ATTRIBUTES lpThreadAttributes, + DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ); + +# ifndef GC_BUILD +# define WinMain GC_WinMain +# define CreateThread GC_CreateThread +# endif + +#endif + /* * If you are planning on putting * the collector in a SunOS 5 dynamic library, you need to call GC_INIT() @@ -790,13 +887,23 @@ extern void GC_thr_init(); /* Needed for Solaris/X86 */ # endif #endif -#if (defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \ - || defined(_WIN32) +#if !defined(_WIN32_WCE) \ + && ((defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \ + || defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__)) /* win32S may not free all resources on process exit. */ /* This explicitly deallocates the heap. */ GC_API void GC_win32_free_heap (); #endif +#if ( defined(_AMIGA) && !defined(GC_AMIGA_MAKINGLIB) ) + /* Allocation really goes through GC_amiga_allocwrapper_do */ +# include "gc_amiga_redirects.h" +#endif + +#if defined(GC_REDIRECT_TO_LOCAL) && !defined(GC_LOCAL_ALLOC_H) +# include "gc_local_alloc.h" +#endif + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/boehm-gc/include/gc_alloc.h b/boehm-gc/include/gc_alloc.h index 1f1d54a..c50a758 100644 --- a/boehm-gc/include/gc_alloc.h +++ b/boehm-gc/include/gc_alloc.h @@ -25,6 +25,9 @@ // This uses template classes with static members, and hence does not work // with g++ 2.7.2 and earlier. // +// This code assumes that the collector itself has been compiled with a +// compiler that defines __STDC__ . +// #include "gc.h" diff --git a/boehm-gc/include/gc_cpp.h b/boehm-gc/include/gc_cpp.h index 35686fc..6aacd0a 100644 --- a/boehm-gc/include/gc_cpp.h +++ b/boehm-gc/include/gc_cpp.h @@ -139,7 +139,7 @@ by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined. #if ! defined( OPERATOR_NEW_ARRAY ) \ && (__BORLANDC__ >= 0x450 || (__GNUC__ >= 2 && __GNUC_MINOR__ >= 6) \ - || __WATCOMC__ >= 1050) + || __WATCOMC__ >= 1050 || _MSC_VER >= 1100) # define OPERATOR_NEW_ARRAY #endif @@ -179,6 +179,12 @@ private: extern "C" {typedef void (*GCCleanUpFunc)( void* obj, void* clientData );} +#ifdef _MSC_VER + // Disable warning that "no matching operator delete found; memory will + // not be freed if initialization throws an exception" +# pragma warning(disable:4291) +#endif + inline void* operator new( size_t size, GCPlacement gcp, @@ -200,6 +206,49 @@ inline void* operator new( #ifdef OPERATOR_NEW_ARRAY +#ifdef _MSC_VER + /** This ensures that the system default operator new[] doesn't get + * undefined, which is what seems to happen on VC++ 6 for some reason + * if we define a multi-argument operator new[]. + * There seems to be really redirect new in this environment without + * including this everywhere. + */ + inline void *operator new[]( size_t size ) + { + return GC_MALLOC_UNCOLLECTABLE( size ); + } + + inline void operator delete[](void* obj) + { + GC_FREE(obj); + }; + + inline void* operator new( size_t size) + { + return GC_MALLOC_UNCOLLECTABLE( size); + }; + + inline void operator delete(void* obj) + { + GC_FREE(obj); + }; + + +// This new operator is used by VC++ in case of Debug builds ! + inline void* operator new( size_t size, + int ,//nBlockUse, + const char * szFileName, + int nLine + ) { +# ifndef GC_DEBUG + return GC_malloc_uncollectable( size ); +# else + return GC_debug_malloc_uncollectable(size, szFileName, nLine); +# endif + } + +#endif /* _MSC_VER */ + inline void* operator new[]( size_t size, GCPlacement gcp, diff --git a/boehm-gc/include/gc_gcj.h b/boehm-gc/include/gc_gcj.h index 1dede51..9123a28 100644 --- a/boehm-gc/include/gc_gcj.h +++ b/boehm-gc/include/gc_gcj.h @@ -24,6 +24,10 @@ * may be marked by the mark procedure passed to GC_init_gcj_malloc. */ +#ifndef GC_GCJ_H + +#define GC_GCJ_H + #ifndef MARK_DESCR_OFFSET # define MARK_DESCR_OFFSET sizeof(word) #endif @@ -41,10 +45,7 @@ #endif /* The following allocators signal an out of memory condition with */ -/* return GC_oom_action(); */ -/* The default GC_oom_action returns 0. */ -/* This functionality is currently restricted to the gcj allocators. */ -/* We may want to extend it to the others. */ +/* return GC_oom_fn(bytes); */ extern void * (*GC_oom_action)(void); @@ -58,8 +59,6 @@ extern void * (*GC_oom_action)(void); /* to use the same mark_proc for some of its generated mark descriptors.*/ /* In that case, it should use a different "environment" value to */ /* detect the presence or absence of the debug header. */ - -/* the debugging interface. */ /* Mp is really of type mark_proc, as defined in gc_mark.h. We don't */ /* want to include that here for namespace pollution reasons. */ extern void GC_init_gcj_malloc(int mp_index, void * /* really mark_proc */mp); @@ -77,6 +76,9 @@ extern void * GC_debug_gcj_malloc(size_t lb, /* Similar to the above, but the size is in words, and we don't */ /* adjust it. The size is assumed to be such that it can be */ /* allocated as a small object. */ +/* Unless it is known that the collector is not configured */ +/* with USE_MARK_BYTES and unless it is known that the object */ +/* has weak alignment requirements, lw must be even. */ extern void * GC_gcj_fast_malloc(size_t lw, void * ptr_to_struct_containing_descr); extern void * GC_debug_gcj_fast_malloc(size_t lw, @@ -91,11 +93,12 @@ extern void * GC_gcj_malloc_ignore_off_page(size_t lb, # ifdef GC_DEBUG # define GC_GCJ_MALLOC(s,d) GC_debug_gcj_malloc(s,d,GC_EXTRAS) # define GC_GCJ_FAST_MALLOC(s,d) GC_debug_gcj_fast_malloc(s,d,GC_EXTRAS) -# define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s,d) GC_gcj_debug_malloc(s,d,GC_EXTRAS) +# define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s,d) GC_debug_gcj_malloc(s,d,GC_EXTRAS) # else # define GC_GCJ_MALLOC(s,d) GC_gcj_malloc(s,d) # define GC_GCJ_FAST_MALLOC(s,d) GC_gcj_fast_malloc(s,d) # define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s,d) \ - GC_gcj_debug_malloc_ignore_off_page(s,d) + GC_gcj_malloc_ignore_off_page(s,d) # endif +#endif /* GC_GCJ_H */ diff --git a/boehm-gc/include/gc_inl.h b/boehm-gc/include/gc_inl.h index 700843b..c535cfd 100644 --- a/boehm-gc/include/gc_inl.h +++ b/boehm-gc/include/gc_inl.h @@ -17,18 +17,22 @@ # include "private/gc_priv.h" # endif -/* USE OF THIS FILE IS NOT RECOMMENDED unless the collector has been */ -/* compiled without -DALL_INTERIOR_POINTERS or with */ +/* USE OF THIS FILE IS NOT RECOMMENDED unless GC_all_interior_pointers */ +/* is always set, or the collector has been built with */ /* -DDONT_ADD_BYTE_AT_END, or the specified size includes a pointerfree */ /* word at the end. In the standard collector configuration, */ /* the final word of each object may not be scanned. */ -/* This is most useful for compilers that generate C. */ +/* This iinterface is most useful for compilers that generate C. */ /* Manual use is hereby discouraged. */ /* Allocate n words (NOT BYTES). X is made to point to the result. */ /* It is assumed that n < MAXOBJSZ, and */ /* that n > 0. On machines requiring double word alignment of some */ -/* data, we also assume that n is 1 or even. This bypasses the */ +/* data, we also assume that n is 1 or even. */ +/* If the collector is built with -DUSE_MARK_BYTES or -DPARALLEL_MARK, */ +/* the n = 1 case is also disallowed. */ +/* Effectively this means that portable code should make sure n is even.*/ +/* This bypasses the */ /* MERGE_SIZES mechanism. In order to minimize the number of distinct */ /* free lists that are maintained, the caller should ensure that a */ /* small number of distinct values of n are used. (The MERGE_SIZES */ diff --git a/boehm-gc/include/new_gc_alloc.h b/boehm-gc/include/new_gc_alloc.h index 54b7bd4..1187f0b 100644 --- a/boehm-gc/include/new_gc_alloc.h +++ b/boehm-gc/include/new_gc_alloc.h @@ -20,9 +20,9 @@ // It also doesn't yet understand the new header file names or // namespaces. // -// This assumes the collector has been compiled with -DATOMIC_UNCOLLECTABLE -// and -DALL_INTERIOR_POINTERS. We also recommend -// -DREDIRECT_MALLOC=GC_uncollectable_malloc. +// This assumes the collector has been compiled with -DATOMIC_UNCOLLECTABLE. +// The user should also consider -DREDIRECT_MALLOC=GC_uncollectable_malloc, +// to ensure that object allocated through malloc are traced. // // Some of this could be faster in the explicit deallocation case. // In particular, we spend too much time clearing objects on the @@ -43,11 +43,14 @@ // problems. The argument for changing it is that the usual default // allocator is usually a very bad choice for a garbage collected environment.) // +// This code assumes that the collector itself has been compiled with a +// compiler that defines __STDC__ . +// #ifndef GC_ALLOC_H #include "gc.h" -#include +#include // A more portable way to get stl_alloc.h . #define GC_ALLOC_H @@ -337,6 +340,8 @@ public: \ { alloc::ptr_free_deallocate(p, sizeof (T)); } \ }; +__STL_BEGIN_NAMESPACE + __GC_SPECIALIZE(char, gc_alloc) __GC_SPECIALIZE(int, gc_alloc) __GC_SPECIALIZE(unsigned, gc_alloc) @@ -361,6 +366,8 @@ __GC_SPECIALIZE(unsigned, single_client_traceable_alloc) __GC_SPECIALIZE(float, single_client_traceable_alloc) __GC_SPECIALIZE(double, single_client_traceable_alloc) +__STL_END_NAMESPACE + #ifdef __STL_USE_STD_ALLOCATORS __STL_BEGIN_NAMESPACE diff --git a/boehm-gc/include/private/gc_hdrs.h b/boehm-gc/include/private/gc_hdrs.h index 60dc2ad..6966a9a 100644 --- a/boehm-gc/include/private/gc_hdrs.h +++ b/boehm-gc/include/private/gc_hdrs.h @@ -24,6 +24,17 @@ typedef struct hblkhdr hdr; * The 2 level tree data structure that is used to find block headers. * If there are more than 32 bits in a pointer, the top level is a hash * table. + * + * This defines HDR, GET_HDR, and SET_HDR, the main macros used to + * retrieve and set object headers. We also define some variants to + * retrieve 2 unrelated headers in interleaved fashion. This + * slightly improves scheduling. + * + * Since 5.0 alpha 5, we can also take advantage of a header lookup + * cache. This is a locally declared direct mapped cache, used inside + * the marker. The HC_GET_HDR and HC_GET_HDR2 macros use and maintain this + * cache. Assuming we get reasonable hit rates, this shaves a few + * memory references from each pointer validation. */ # if CPP_WORDSZ > 32 @@ -45,6 +56,127 @@ typedef struct hblkhdr hdr; # define TOP_SZ (1 << LOG_TOP_SZ) # define BOTTOM_SZ (1 << LOG_BOTTOM_SZ) +#ifndef SMALL_CONFIG +# define USE_HDR_CACHE +#endif + +/* #define COUNT_HDR_CACHE_HITS */ + +extern hdr * GC_invalid_header; /* header for an imaginary block */ + /* containing no objects. */ + + +/* Check whether p and corresponding hhdr point to long or invalid */ +/* object. If so, advance them to */ +/* beginning of block, or set hhdr to GC_invalid_header. */ +#define ADVANCE(p, hhdr, source) \ + if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) { \ + p = GC_FIND_START(p, hhdr, (word)source); \ + if (p == 0) { \ + hhdr = GC_invalid_header; \ + } else { \ + hhdr = GC_find_header(p); \ + } \ + } + +#ifdef USE_HDR_CACHE + +# ifdef COUNT_HDR_CACHE_HITS + extern word GC_hdr_cache_hits; + extern word GC_hdr_cache_misses; +# define HC_HIT() ++GC_hdr_cache_hits +# define HC_MISS() ++GC_hdr_cache_misses +# else +# define HC_HIT() +# define HC_MISS() +# endif + + typedef struct hce { + word block_addr; /* right shifted by LOG_HBLKSIZE */ + hdr * hce_hdr; + } hdr_cache_entry; + +# define HDR_CACHE_SIZE 8 /* power of 2 */ + +# define DECLARE_HDR_CACHE \ + hdr_cache_entry hdr_cache[HDR_CACHE_SIZE] + +# define INIT_HDR_CACHE BZERO(hdr_cache, sizeof(hdr_cache)); + +# define HCE(h) hdr_cache + (((word)(h) >> LOG_HBLKSIZE) & (HDR_CACHE_SIZE-1)) + +# define HCE_VALID_FOR(hce,h) ((hce) -> block_addr == \ + ((word)(h) >> LOG_HBLKSIZE)) + +# define HCE_HDR(h) ((hce) -> hce_hdr) + + +/* Analogous to GET_HDR, except that in the case of large objects, it */ +/* Returns the header for the object beginning, and updates p. */ +/* Returns &GC_bad_header instead of 0. All of this saves a branch */ +/* in the fast path. */ +# define HC_GET_HDR(p, hhdr, source) \ + { \ + hdr_cache_entry * hce = HCE(p); \ + if (HCE_VALID_FOR(hce, p)) { \ + HC_HIT(); \ + hhdr = hce -> hce_hdr; \ + } else { \ + HC_MISS(); \ + GET_HDR(p, hhdr); \ + ADVANCE(p, hhdr, source); \ + hce -> block_addr = (word)(p) >> LOG_HBLKSIZE; \ + hce -> hce_hdr = hhdr; \ + } \ + } + +# define HC_GET_HDR2(p1, hhdr1, source1, p2, hhdr2, source2) \ + { \ + hdr_cache_entry * hce1 = HCE(p1); \ + hdr_cache_entry * hce2 = HCE(p2); \ + if (HCE_VALID_FOR(hce1, p1)) { \ + HC_HIT(); \ + hhdr1 = hce1 -> hce_hdr; \ + } else { \ + HC_MISS(); \ + GET_HDR(p1, hhdr1); \ + ADVANCE(p1, hhdr1, source1); \ + hce1 -> block_addr = (word)(p1) >> LOG_HBLKSIZE; \ + hce1 -> hce_hdr = hhdr1; \ + } \ + if (HCE_VALID_FOR(hce2, p2)) { \ + HC_HIT(); \ + hhdr2 = hce2 -> hce_hdr; \ + } else { \ + HC_MISS(); \ + GET_HDR(p2, hhdr2); \ + ADVANCE(p2, hhdr2, source2); \ + hce2 -> block_addr = (word)(p2) >> LOG_HBLKSIZE; \ + hce2 -> hce_hdr = hhdr2; \ + } \ + } + +#else /* !USE_HDR_CACHE */ + +# define DECLARE_HDR_CACHE + +# define INIT_HDR_CACHE + +# define HC_GET_HDR(p, hhdr, source) \ + { \ + GET_HDR(p, hhdr); \ + ADVANCE(p, hhdr, source); \ + } + +# define HC_GET_HDR2(p1, hhdr1, source1, p2, hhdr2, source2) \ + { \ + GET_HDR2(p1, hhdr1, p2, hhdr2); \ + ADVANCE(p1, hhdr1, source1); \ + ADVANCE(p2, hhdr2, source2); \ + } + +#endif + typedef struct bi { hdr * index[BOTTOM_SZ]; /* @@ -97,6 +229,8 @@ typedef struct bi { # define GET_HDR(p, hhdr) (hhdr) = HDR(p) # define SET_HDR(p, hhdr) HDR_INNER(p) = (hhdr) # define GET_HDR_ADDR(p, ha) (ha) = &(HDR_INNER(p)) +# define GET_HDR2(p1, hhdr1, p2, hhdr2) \ + { GET_HDR(p1, hhdr1); GET_HDR(p2, hhdr2); } # else /* hash */ /* Hash function for tree top level */ # define TL_HASH(hi) ((hi) & (TOP_SZ - 1)) @@ -123,6 +257,40 @@ typedef struct bi { # define SET_HDR(p, hhdr) { register hdr ** _ha; GET_HDR_ADDR(p, _ha); \ *_ha = (hhdr); } # define HDR(p) GC_find_header((ptr_t)(p)) + /* And some interleaved versions for two pointers at once. */ + /* This hopefully helps scheduling on processors like IA64. */ +# define GET_BI2(p1, bottom_indx1, p2, bottom_indx2) \ + { \ + register word hi1 = \ + (word)(p1) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE); \ + register word hi2 = \ + (word)(p2) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE); \ + register bottom_index * _bi1 = GC_top_index[TL_HASH(hi1)]; \ + register bottom_index * _bi2 = GC_top_index[TL_HASH(hi2)]; \ + \ + while (_bi1 -> key != hi1 && _bi1 != GC_all_nils) \ + _bi1 = _bi1 -> hash_link; \ + while (_bi2 -> key != hi2 && _bi2 != GC_all_nils) \ + _bi2 = _bi2 -> hash_link; \ + (bottom_indx1) = _bi1; \ + (bottom_indx2) = _bi2; \ + } +# define GET_HDR_ADDR2(p1, ha1, p2, ha2) \ + { \ + register bottom_index * bi1; \ + register bottom_index * bi2; \ + \ + GET_BI2(p1, bi1, p2, bi2); \ + (ha1) = &(HDR_FROM_BI(bi1, p1)); \ + (ha2) = &(HDR_FROM_BI(bi2, p2)); \ + } +# define GET_HDR2(p1, hhdr1, p2, hhdr2) \ + { register hdr ** _ha1; \ + register hdr ** _ha2; \ + GET_HDR_ADDR2(p1, _ha1, p2, _ha2); \ + (hhdr1) = *_ha1; \ + (hhdr2) = *_ha2; \ + } # endif /* Is the result a forwarding address to someplace closer to the */ diff --git a/boehm-gc/include/private/gc_priv.h b/boehm-gc/include/private/gc_priv.h index ce68587..d06cd8b 100644 --- a/boehm-gc/include/private/gc_priv.h +++ b/boehm-gc/include/private/gc_priv.h @@ -2,7 +2,7 @@ * 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. + * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved. * * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED @@ -14,7 +14,6 @@ * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice. */ -/* Boehm, February 16, 1996 2:30 pm PST */ # ifndef GC_PRIVATE_H @@ -41,16 +40,16 @@ # include "gc.h" # endif -typedef GC_word word; -typedef GC_signed_word signed_word; +# ifndef GC_MARK_H +# include "../gc_mark.h" +# endif # ifndef GCCONFIG_H # include "gcconfig.h" # endif -# ifndef HEADERS_H -# include "gc_hdrs.h" -# endif +typedef GC_word word; +typedef GC_signed_word signed_word; typedef int GC_bool; # define TRUE 1 @@ -61,6 +60,10 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ /* Preferably identical to caddr_t, if it */ /* exists. */ +# ifndef HEADERS_H +# include "gc_hdrs.h" +# endif + #if defined(__STDC__) # include # if !(defined( sony_news ) ) @@ -74,9 +77,31 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ # define VOLATILE #endif -#define CONST GC_CONST +#if 0 /* defined(__GNUC__) doesn't work yet */ +# define EXPECT(expr, outcome) __builtin_expect(expr,outcome) + /* Equivalent to (expr), but predict that usually (expr)==outcome. */ +#else +# define EXPECT(expr, outcome) (expr) +#endif /* __GNUC__ */ + +# ifndef GC_LOCKS_H +# include "gc_locks.h" +# endif -#if 0 /* was once defined for AMIGA */ +# ifdef STACK_GROWS_DOWN +# define COOLER_THAN > +# define HOTTER_THAN < +# define MAKE_COOLER(x,y) if ((word)(x)+(y) > (word)(x)) {(x) += (y);} \ + else {(x) = (word)ONES;} +# define MAKE_HOTTER(x,y) (x) -= (y) +# else +# define COOLER_THAN < +# define HOTTER_THAN > +# define MAKE_COOLER(x,y) if ((word)(x)-(y) < (word)(x)) {(x) -= (y);} else {(x) = 0;} +# define MAKE_HOTTER(x,y) (x) += (y) +# endif + +#if defined(AMIGA) && defined(__SASC) # define GC_FAR __far #else # define GC_FAR @@ -96,11 +121,9 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ /* */ /*********************************/ -#define STUBBORN_ALLOC /* Define stubborn allocation primitives */ -#if defined(SRC_M3) || defined(SMALL_CONFIG) -# undef STUBBORN_ALLOC -#endif - +/* #define STUBBORN_ALLOC */ + /* Enable stubborm allocation, and thus a limited */ + /* form of incremental collection w/o dirty bits. */ /* #define ALL_INTERIOR_POINTERS */ /* Forces all pointers into the interior of an */ @@ -127,6 +150,8 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ /* touched. */ /* If you can easily avoid using this option, do. */ /* If not, try to keep individual objects small. */ + /* This is now really controlled at startup, */ + /* through GC_all_interior_pointers. */ #define PRINTSTATS /* Print garbage collection statistics */ /* For less verbose output, undefine in reclaim.c */ @@ -157,12 +182,12 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ # define GATHERSTATS #endif -#ifdef FINALIZE_ON_DEMAND -# define GC_INVOKE_FINALIZERS() -#else -# define GC_INVOKE_FINALIZERS() (void)GC_invoke_finalizers() +#if defined(PRINTSTATS) || !defined(SMALL_CONFIG) +# define CONDPRINT /* Print some things if GC_print_stats is set */ #endif +#define GC_INVOKE_FINALIZERS() GC_notify_or_invoke_finalizers() + #define MERGE_SIZES /* Round up some object sizes, so that fewer distinct */ /* free lists are actually maintained. This applies */ /* only to the top level routines in misc.c, not to */ @@ -174,20 +199,28 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ /* May save significant amounts of space for obj_map */ /* entries. */ +#if defined(USE_MARK_BYTES) && !defined(ALIGN_DOUBLE) +# define ALIGN_DOUBLE + /* We use one byte for every 2 words, which doesn't allow for */ + /* odd numbered words to have mark bits. */ +#endif + /* ALIGN_DOUBLE requires MERGE_SIZES at present. */ # if defined(ALIGN_DOUBLE) && !defined(MERGE_SIZES) # define MERGE_SIZES # endif -#if defined(ALL_INTERIOR_POINTERS) && !defined(DONT_ADD_BYTE_AT_END) -# define ADD_BYTE_AT_END +#if !defined(DONT_ADD_BYTE_AT_END) +# define EXTRA_BYTES GC_all_interior_pointers +#else +# define EXTRA_BYTES 0 #endif # ifndef LARGE_CONFIG -# define MINHINCR 16 /* Minimum heap increment, in blocks of HBLKSIZE */ - /* Must be multiple of largest page size. */ -# define MAXHINCR 512 /* Maximum heap increment, in blocks */ +# define MINHINCR 16 /* Minimum heap increment, in blocks of HBLKSIZE */ + /* Must be multiple of largest page size. */ +# define MAXHINCR 2048 /* Maximum heap increment, in blocks */ # else # define MINHINCR 64 # define MAXHINCR 4096 @@ -220,17 +253,22 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ * Number of frames and arguments to save in objects allocated by * debugging allocator. */ -# define NFRAMES 6 /* Number of frames to save. Even for */ +# ifndef SAVE_CALL_COUNT +# define NFRAMES 6 /* Number of frames to save. Even for */ /* alignment reasons. */ +# else +# define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1) +# endif # define NARGS 2 /* Mumber of arguments to save for each call. */ # define NEED_CALLINFO /* Fill in the pc and argument information for up to NFRAMES of my */ /* callers. Ignore my frame and my callers frame. */ -void GC_save_callers (/* struct callinfo info[NFRAMES] */); - -void GC_print_callers (/* struct callinfo info[NFRAMES] */); +struct callinfo; +void GC_save_callers GC_PROTO((struct callinfo info[NFRAMES])); + +void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES])); #else @@ -244,7 +282,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); #ifdef NEED_CALLINFO struct callinfo { - word ci_pc; + word ci_pc; /* Caller, not callee, pc */ # if NARGS > 0 word ci_arg[NARGS]; /* bit-wise complement to avoid retention */ # endif @@ -273,13 +311,13 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); # define MS_TIME_DIFF(a,b) ((double) (a.tv_sec - b.tv_sec) * 1000.0 \ + (double) (a.tv_usec - b.tv_usec) / 1000.0) #else /* !BSD_TIME */ -# ifdef MSWIN32 +# if defined(MSWIN32) || defined(MSWINCE) # include # include # define CLOCK_TYPE DWORD # define GET_TIME(x) x = GetTickCount() # define MS_TIME_DIFF(a,b) ((long)((a)-(b))) -# else /* !MSWIN32, !BSD_TIME */ +# else /* !MSWIN32, !MSWINCE, !BSD_TIME */ # include # if !defined(__STDC__) && defined(SPARC) && defined(SUNOS4) clock_t clock(); /* Not in time.h, where it belongs */ @@ -325,6 +363,9 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); # include # define BCOPY_EXISTS # endif +# if defined(MACOSX) +# define BCOPY_EXISTS +# endif # ifndef BCOPY_EXISTS # include @@ -342,6 +383,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); /* GET_MEM is currently not assumed to retrieve 0 filled space, */ /* though we should perhaps take advantage of the case in which */ /* does. */ +struct hblk; /* See below. */ # ifdef PCR char * real_malloc(); # define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + GC_page_size) \ @@ -353,7 +395,8 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); + GC_page_size) \ + GC_page_size-1) # else -# if defined(AMIGA) || defined(NEXT) || defined(MACOSX) || defined(DOS4GW) +# if defined(NEXT) || defined(MACOSX) || defined(DOS4GW) || \ + (defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) # define GET_MEM(bytes) HBLKPTR((size_t) \ calloc(1, (size_t)bytes + GC_page_size) \ + GC_page_size-1) @@ -374,312 +417,26 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); NewPtrClear(bytes + GC_page_size) + GC_page_size-1) # endif # else - extern ptr_t GC_unix_get_mem(); -# define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes) +# ifdef MSWINCE + extern ptr_t GC_wince_get_mem(); +# define GET_MEM(bytes) (struct hblk *)GC_wince_get_mem(bytes) +# else +# if defined(AMIGA) && defined(GC_AMIGA_FASTALLOC) + extern void *GC_amiga_get_mem(size_t size); + define GET_MEM(bytes) HBLKPTR((size_t) \ + GC_amiga_get_mem((size_t)bytes + GC_page_size) \ + + GC_page_size-1) +# else + extern ptr_t GC_unix_get_mem(); +# define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes) +# endif +# endif # endif # endif # endif # endif # endif -/* - * Mutual exclusion between allocator/collector routines. - * Needed if there is more than one allocator thread. - * FASTLOCK() is assumed to try to acquire the lock in a cheap and - * dirty way that is acceptable for a few instructions, e.g. by - * inhibiting preemption. This is assumed to have succeeded only - * if a subsequent call to FASTLOCK_SUCCEEDED() returns TRUE. - * FASTUNLOCK() is called whether or not FASTLOCK_SUCCEEDED(). - * If signals cannot be tolerated with the FASTLOCK held, then - * FASTLOCK should disable signals. The code executed under - * FASTLOCK is otherwise immune to interruption, provided it is - * not restarted. - * DCL_LOCK_STATE declares any local variables needed by LOCK and UNLOCK - * and/or DISABLE_SIGNALS and ENABLE_SIGNALS and/or FASTLOCK. - * (There is currently no equivalent for FASTLOCK.) - */ -# ifdef THREADS -# ifdef PCR_OBSOLETE /* Faster, but broken with multiple lwp's */ -# include "th/PCR_Th.h" -# include "th/PCR_ThCrSec.h" - extern struct PCR_Th_MLRep GC_allocate_ml; -# define DCL_LOCK_STATE PCR_sigset_t GC_old_sig_mask -# define LOCK() PCR_Th_ML_Acquire(&GC_allocate_ml) -# define UNLOCK() PCR_Th_ML_Release(&GC_allocate_ml) -# define FASTLOCK() PCR_ThCrSec_EnterSys() - /* Here we cheat (a lot): */ -# define FASTLOCK_SUCCEEDED() (*(int *)(&GC_allocate_ml) == 0) - /* TRUE if nobody currently holds the lock */ -# define FASTUNLOCK() PCR_ThCrSec_ExitSys() -# endif -# ifdef PCR -# include -# include - extern PCR_Th_ML GC_allocate_ml; -# define DCL_LOCK_STATE \ - PCR_ERes GC_fastLockRes; PCR_sigset_t GC_old_sig_mask -# define LOCK() PCR_Th_ML_Acquire(&GC_allocate_ml) -# define UNLOCK() PCR_Th_ML_Release(&GC_allocate_ml) -# define FASTLOCK() (GC_fastLockRes = PCR_Th_ML_Try(&GC_allocate_ml)) -# define FASTLOCK_SUCCEEDED() (GC_fastLockRes == PCR_ERes_okay) -# define FASTUNLOCK() {\ - if( FASTLOCK_SUCCEEDED() ) PCR_Th_ML_Release(&GC_allocate_ml); } -# endif -# ifdef SRC_M3 - extern word RT0u__inCritical; -# define LOCK() RT0u__inCritical++ -# define UNLOCK() RT0u__inCritical-- -# endif -# ifdef SOLARIS_THREADS -# include -# include - extern mutex_t GC_allocate_ml; -# define LOCK() mutex_lock(&GC_allocate_ml); -# define UNLOCK() mutex_unlock(&GC_allocate_ml); -# endif -# if defined(LINUX_THREADS) -# if defined(I386)|| defined(POWERPC) || defined(ALPHA) || defined(IA64) \ - || defined(M68K) -# include -# define USE_SPIN_LOCK -# 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 */ - __asm__ __volatile__("xchgl %0, %1" - : "=r"(oldval), "=m"(*(addr)) - : "0"(1), "m"(*(addr))); - return oldval; - } -# endif -# if defined(IA64) - inline static int GC_test_and_set(volatile unsigned int *addr) { - int oldval; - __asm__ __volatile__("xchg4 %0=%1,%2" - : "=r"(oldval), "=m"(*addr) - : "r"(1), "1"(*addr)); - return oldval; - } - inline static void GC_clear(volatile unsigned int *addr) { - __asm__ __volatile__("st4.rel %0=r0" : "=m" (*addr)); - } -# define GC_CLEAR_DEFINED -# endif -# ifdef M68K - /* Contributed by Tony Mantler. I'm not sure how well it was */ - /* tested. */ - inline static int GC_test_and_set(volatile unsigned int *addr) { - char oldval; /* this must be no longer than 8 bits */ - - /* The return value is semi-phony. */ - /* 'tas' sets bit 7 while the return */ - /* value pretends bit 0 was set */ - __asm__ __volatile__( - "tas %1@; sne %0; negb %0" - : "=d" (oldval) - : "a" (addr)); - return oldval; - } -# endif -# 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; - } - inline static void GC_clear(volatile unsigned int *addr) { - __asm__ __volatile__("eieio"); - *(addr) = 0; - } -# define GC_CLEAR_DEFINED -# endif -# 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; - } - /* Should probably also define GC_clear, since it needs */ - /* a memory barrier ?? */ -# endif /* ALPHA */ -# ifdef ARM32 - inline static int GC_test_and_set(volatile unsigned int *addr) { - int oldval; - /* SWP on ARM is very similar to XCHG on x86. Doesn't lock the - * bus because there are no SMP ARM machines. If/when there are, - * this code will likely need to be updated. */ - /* See linuxthreads/sysdeps/arm/pt-machine.h in glibc-2.1 */ - __asm__ __volatile__("swp %0, %1, [%2]" - : "=r"(oldval) - : "r"(1), "r"(addr)); - return oldval; - } -# endif -# ifndef GC_CLEAR_DEFINED - inline static void GC_clear(volatile unsigned int *addr) { - /* Try to discourage gcc from moving anything past this. */ - __asm__ __volatile__(" "); - *(addr) = 0; - } -# endif - - extern volatile unsigned int GC_allocate_lock; - extern pthread_t GC_lock_holder; - extern void GC_lock(void); - /* Allocation lock holder. Only set if acquired by client through */ - /* GC_call_with_alloc_lock. */ -# define SET_LOCK_HOLDER() GC_lock_holder = pthread_self() -# define NO_THREAD (pthread_t)(-1) -# define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD -# define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self())) -# define LOCK() \ - { if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); } -# define UNLOCK() \ - GC_clear(&GC_allocate_lock) - extern VOLATILE GC_bool GC_collecting; -# define ENTER_GC() \ - { \ - GC_collecting = 1; \ - } -# define EXIT_GC() GC_collecting = 0; -# else /* LINUX_THREADS on hardware for which we don't know how */ - /* to do test and set. */ -# include - extern pthread_mutex_t GC_allocate_ml; -# define LOCK() pthread_mutex_lock(&GC_allocate_ml) -# define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml) -# endif -# endif /* LINUX_THREADS */ -# if defined(HPUX_THREADS) -# include - 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 -# ifndef HPUX_THREADS - /* This probably should never be included, but I can't test */ - /* on Irix anymore. */ -# include -# endif - -# 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 -# 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) */ - /* POSIX scheduling rules are subject to convoys in high contention */ - /* applications. This is basically a spin lock. */ - extern pthread_t GC_lock_holder; - extern void GC_lock(void); - /* Allocation lock holder. Only set if acquired by client through */ - /* GC_call_with_alloc_lock. */ -# define SET_LOCK_HOLDER() GC_lock_holder = pthread_self() -# define NO_THREAD (pthread_t)(-1) -# define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD -# define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self())) -# 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)) \ - && defined(_COMPILER_VERSION) && _COMPILER_VERSION >= 700 -# define UNLOCK() __lock_release(&GC_allocate_lock) -# 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. */ - /* It may be necessary for Ragnarok and future gcc */ - /* versions. */ -# define UNLOCK() { GC_noop1(&GC_allocate_lock); \ - *(volatile unsigned long *)(&GC_allocate_lock) = 0; } -# endif -# endif - extern VOLATILE GC_bool GC_collecting; -# define ENTER_GC() \ - { \ - GC_collecting = 1; \ - } -# define EXIT_GC() GC_collecting = 0; -# endif /* IRIX_THREADS || IRIX_JDK_THREADS */ -# ifdef WIN32_THREADS -# include - GC_API CRITICAL_SECTION GC_allocate_ml; -# define LOCK() EnterCriticalSection(&GC_allocate_ml); -# define UNLOCK() LeaveCriticalSection(&GC_allocate_ml); -# endif -# ifndef SET_LOCK_HOLDER -# define SET_LOCK_HOLDER() -# define UNSET_LOCK_HOLDER() -# define I_HOLD_LOCK() FALSE - /* Used on platforms were locks can be reacquired, */ - /* so it doesn't matter if we lie. */ -# endif -# else -# define LOCK() -# define UNLOCK() -# endif -# ifndef SET_LOCK_HOLDER -# define SET_LOCK_HOLDER() -# define UNSET_LOCK_HOLDER() -# define I_HOLD_LOCK() FALSE - /* Used on platforms were locks can be reacquired, */ - /* so it doesn't matter if we lie. */ -# endif -# ifndef ENTER_GC -# define ENTER_GC() -# define EXIT_GC() -# endif - -# ifndef DCL_LOCK_STATE -# define DCL_LOCK_STATE -# endif -# ifndef FASTLOCK -# define FASTLOCK() LOCK() -# define FASTLOCK_SUCCEEDED() TRUE -# define FASTUNLOCK() UNLOCK() -# endif - /* Delay any interrupts or signals that may abort this thread. Data */ /* structures are in a consistent state outside this pair of calls. */ /* ANSI C allows both to be empty (though the standard isn't very */ @@ -693,9 +450,9 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); PCR_Th_SetSigMask(&GC_old_sig_mask, NIL) # else # if defined(SRC_M3) || defined(AMIGA) || defined(SOLARIS_THREADS) \ - || defined(MSWIN32) || defined(MACOS) || defined(DJGPP) \ - || defined(NO_SIGNALS) || defined(IRIX_THREADS) \ - || defined(IRIX_JDK_THREADS) || defined(LINUX_THREADS) + || defined(MSWIN32) || defined(MSWINCE) || defined(MACOS) \ + || defined(DJGPP) || defined(NO_SIGNALS) || defined(IRIX_THREADS) \ + || defined(LINUX_THREADS) /* Also useful for debugging. */ /* Should probably use thr_sigsetmask for SOLARIS_THREADS. */ # define DISABLE_SIGNALS() @@ -724,7 +481,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(HPUX_THREADS) + || defined(HPUX_THREADS) void GC_stop_world(); void GC_start_world(); # define STOP_WORLD() GC_stop_world() @@ -758,6 +515,13 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */); # define WARN(msg,arg) (*GC_current_warn_proc)(msg, (GC_word)(arg)) extern GC_warn_proc GC_current_warn_proc; +/* Get environment entry */ +#if !defined(NO_GETENV) +# define GETENV(name) getenv(name) +#else +# define GETENV(name) 0 +#endif + /*********************************/ /* */ /* Word-size-dependent defines */ @@ -787,7 +551,7 @@ extern GC_warn_proc GC_current_warn_proc; #define WORDSZ ((word)CPP_WORDSZ) #define SIGNB ((word)1 << (WORDSZ-1)) #define BYTES_PER_WORD ((word)(sizeof (word))) -#define ONES ((word)(-1)) +#define ONES ((word)(signed_word)(-1)) #define divWORDSZ(n) ((n) >> LOGWL) /* divide n by size of word */ /*********************/ @@ -840,6 +604,8 @@ extern GC_warn_proc GC_current_warn_proc; /* max size objects supported by freelist (larger objects may be */ /* allocated, but less efficiently) */ +#define CPP_MAXOBJBYTES (CPP_HBLKSIZE/2) +#define MAXOBJBYTES ((word)CPP_MAXOBJBYTES) #define CPP_MAXOBJSZ BYTES_TO_WORDS(CPP_HBLKSIZE/2) #define MAXOBJSZ ((word)CPP_MAXOBJSZ) @@ -860,25 +626,28 @@ extern GC_warn_proc GC_current_warn_proc; # define HBLKDISPL(objptr) (((word) (objptr)) & (HBLKSIZE-1)) /* Round up byte allocation requests to integral number of words, etc. */ -# ifdef ADD_BYTE_AT_END -# define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1)) -# ifdef ALIGN_DOUBLE -# define ALIGNED_WORDS(n) (BYTES_TO_WORDS((n) + WORDS_TO_BYTES(2)) & ~1) -# else -# define ALIGNED_WORDS(n) ROUNDED_UP_WORDS(n) -# endif -# define SMALL_OBJ(bytes) ((bytes) < WORDS_TO_BYTES(MAXOBJSZ)) -# define ADD_SLOP(bytes) ((bytes)+1) -# else -# define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + (WORDS_TO_BYTES(1) - 1)) -# ifdef ALIGN_DOUBLE +# define ROUNDED_UP_WORDS(n) \ + BYTES_TO_WORDS((n) + (WORDS_TO_BYTES(1) - 1 + EXTRA_BYTES)) +# ifdef ALIGN_DOUBLE # define ALIGNED_WORDS(n) \ - (BYTES_TO_WORDS((n) + WORDS_TO_BYTES(2) - 1) & ~1) -# else + (BYTES_TO_WORDS((n) + WORDS_TO_BYTES(2) - 1 + EXTRA_BYTES) & ~1) +# else # define ALIGNED_WORDS(n) ROUNDED_UP_WORDS(n) +# endif +# define SMALL_OBJ(bytes) ((bytes) < (MAXOBJBYTES -EXTRA_BYTES)) +# define ADD_SLOP(bytes) ((bytes) + EXTRA_BYTES) +# ifndef MIN_WORDS + /* MIN_WORDS is the size of the smallest allocated object. */ + /* 1 and 2 are the only valid values. */ + /* 2 must be used if: */ + /* - GC_gcj_malloc can be used for objects of requested */ + /* size smaller than 2 words, or */ + /* - USE_MARK_BYTES is defined. */ +# if defined(USE_MARK_BYTES) || defined(GC_GCJ_SUPPORT) +# define MIN_WORDS 2 /* Smallest allocated object. */ +# else +# define MIN_WORDS 1 # endif -# define SMALL_OBJ(bytes) ((bytes) <= WORDS_TO_BYTES(MAXOBJSZ)) -# define ADD_SLOP(bytes) (bytes) # endif @@ -889,11 +658,19 @@ extern GC_warn_proc GC_current_warn_proc; */ # ifdef LARGE_CONFIG -# define LOG_PHT_ENTRIES 17 +# define LOG_PHT_ENTRIES 19 /* Collisions likely at 512K blocks, */ + /* which is >= 2GB. Each table takes */ + /* 64KB. */ # else -# define LOG_PHT_ENTRIES 14 /* Collisions are likely if heap grows */ - /* to more than 16K hblks = 64MB. */ - /* Each hash table occupies 2K bytes. */ +# ifdef SMALL_CONFIG +# define LOG_PHT_ENTRIES 14 /* Collisions are likely if heap grows */ + /* to more than 16K hblks = 64MB. */ + /* Each hash table occupies 2K bytes. */ +# else /* default "medium" configuration */ +# define LOG_PHT_ENTRIES 16 /* Collisions are likely if heap grows */ + /* to more than 16K hblks >= 256MB. */ + /* Each hash table occupies 8K bytes. */ +# endif # endif # define PHT_ENTRIES ((word)1 << LOG_PHT_ENTRIES) # define PHT_SIZE (PHT_ENTRIES >> LOGWL) @@ -907,6 +684,10 @@ typedef word page_hash_table[PHT_SIZE]; (bl)[divWORDSZ(index)] |= (word)1 << modWORDSZ(index) # define clear_pht_entry_from_index(bl, index) \ (bl)[divWORDSZ(index)] &= ~((word)1 << modWORDSZ(index)) +/* And a dumb but thread-safe version of set_pht_entry_from_index. */ +/* This sets (many) extra bits. */ +# define set_pht_entry_from_index_safe(bl, index) \ + (bl)[divWORDSZ(index)] = ONES @@ -919,20 +700,28 @@ typedef word page_hash_table[PHT_SIZE]; /* heap block header */ #define HBLKMASK (HBLKSIZE-1) -#define BITS_PER_HBLK (HBLKSIZE * 8) +#define BITS_PER_HBLK (CPP_HBLKSIZE * 8) #define MARK_BITS_PER_HBLK (BITS_PER_HBLK/CPP_WORDSZ) /* upper bound */ - /* We allocate 1 bit/word. Only the first word */ + /* We allocate 1 bit/word, unless USE_MARK_BYTES */ + /* is defined. Only the first word */ /* in each object is actually marked. */ -# ifdef ALIGN_DOUBLE -# define MARK_BITS_SZ (((MARK_BITS_PER_HBLK + 2*CPP_WORDSZ - 1) \ - / (2*CPP_WORDSZ))*2) +# ifdef USE_MARK_BYTES +# define MARK_BITS_SZ (MARK_BITS_PER_HBLK/2) + /* Unlike the other case, this is in units of bytes. */ + /* We actually allocate only every second mark bit, since we */ + /* force all objects to be doubleword aligned. */ + /* However, each mark bit is allocated as a byte. */ # else -# define MARK_BITS_SZ ((MARK_BITS_PER_HBLK + CPP_WORDSZ - 1)/CPP_WORDSZ) +# define MARK_BITS_SZ (MARK_BITS_PER_HBLK/CPP_WORDSZ) # endif - /* Upper bound on number of mark words per heap block */ + +/* We maintain layout maps for heap blocks containing objects of a given */ +/* size. Each entry in this map describes a byte offset and has the */ +/* following type. */ +typedef unsigned char map_entry_type; struct hblkhdr { word hb_sz; /* If in use, size in words, of objects in the block. */ @@ -943,7 +732,8 @@ struct hblkhdr { struct hblk * hb_prev; /* Backwards link for free list. */ word hb_descr; /* object descriptor for marking. See */ /* mark.h. */ - char* hb_map; /* A pointer to a pointer validity map of the block. */ + map_entry_type * hb_map; + /* A pointer to a pointer validity map of the block. */ /* See GC_obj_map. */ /* Valid for all blocks with headers. */ /* Free blocks point to GC_invalid_map. */ @@ -965,11 +755,20 @@ struct hblkhdr { /* Value of GC_gc_no when block was */ /* last allocated or swept. May wrap. */ /* For a free block, this is maintained */ - /* unly for USE_MUNMAP, and indicates */ + /* only for USE_MUNMAP, and indicates */ /* when the header was allocated, or */ /* when the size of the block last */ /* changed. */ - word hb_marks[MARK_BITS_SZ]; +# ifdef USE_MARK_BYTES + union { + char _hb_marks[MARK_BITS_SZ]; + /* The i'th byte is 1 if the object */ + /* starting at word 2i is marked, 0 o.w. */ + word dummy; /* Force word alignment of mark bytes. */ + } _mark_byte_union; +# define hb_marks _mark_byte_union._hb_marks +# else + word hb_marks[MARK_BITS_SZ]; /* Bit i in the array refers to the */ /* object starting at the ith word (header */ /* INCLUDED) in the heap block. */ @@ -977,44 +776,28 @@ struct hblkhdr { /* Unused bits are invalid, and are */ /* occasionally set, e.g for uncollectable */ /* objects. */ +# endif /* !USE_MARK_BYTES */ }; /* heap block body */ -# define DISCARD_WORDS 0 - /* Number of words to be dropped at the beginning of each block */ - /* Must be a multiple of WORDSZ. May reasonably be nonzero */ - /* on machines that don't guarantee longword alignment of */ - /* pointers, so that the number of false hits is minimized. */ - /* 0 and WORDSZ are probably the only reasonable values. */ - -# define BODY_SZ ((HBLKSIZE-WORDS_TO_BYTES(DISCARD_WORDS))/sizeof(word)) +# define BODY_SZ (HBLKSIZE/sizeof(word)) struct hblk { -# if (DISCARD_WORDS != 0) +# if 0 /* DISCARDWORDS no longer supported */ word garbage[DISCARD_WORDS]; # endif word hb_body[BODY_SZ]; }; -# define HDR_WORDS ((word)DISCARD_WORDS) -# define HDR_BYTES ((word)WORDS_TO_BYTES(DISCARD_WORDS)) - # define OBJ_SZ_TO_BLOCKS(sz) \ - divHBLKSZ(HDR_BYTES + WORDS_TO_BYTES(sz) + HBLKSIZE-1) + divHBLKSZ(WORDS_TO_BYTES(sz) + HBLKSIZE-1) /* Size of block (in units of HBLKSIZE) needed to hold objects of */ /* given sz (in words). */ /* Object free list link */ # define obj_link(p) (*(ptr_t *)(p)) -/* The type of mark procedures. This really belongs in gc_mark.h. */ -/* But we put it here, so that we can avoid scanning the mark proc */ -/* table. */ -typedef struct ms_entry * (*mark_proc)(/* word * addr, - struct ms_entry *mark_stack_ptr, - struct ms_entry *mark_stack_limit, - word env */); # define LOG_MAX_MARK_PROCS 6 # define MAX_MARK_PROCS (1 << LOG_MAX_MARK_PROCS) @@ -1028,12 +811,12 @@ typedef struct ms_entry * (*mark_proc)(/* word * addr, # ifdef PCR # define MAX_ROOT_SETS 1024 # else -# ifdef MSWIN32 -# define MAX_ROOT_SETS 512 +# if defined(MSWIN32) || defined(MSWINCE) +# define MAX_ROOT_SETS 1024 /* Under NT, we add only written pages, which can result */ /* in many small root sets. */ # else -# define MAX_ROOT_SETS 64 +# define MAX_ROOT_SETS 256 # endif # endif # endif @@ -1056,14 +839,14 @@ struct exclusion { struct roots { ptr_t r_start; ptr_t r_end; -# ifndef MSWIN32 +# if !defined(MSWIN32) && !defined(MSWINCE) struct roots * r_next; # endif GC_bool r_tmp; /* Delete before registering new dynamic libraries */ }; -#ifndef MSWIN32 +#if !defined(MSWIN32) && !defined(MSWINCE) /* Size of hash table index to roots. */ # define LOG_RT_SIZE 6 # define RT_SIZE (1 << LOG_RT_SIZE) /* Power of 2, may be != MAX_ROOT_SETS */ @@ -1097,11 +880,22 @@ struct _GC_arrays { word _large_free_bytes; /* Total bytes contained in blocks on large object free */ /* list. */ + word _large_allocd_bytes; + /* Total number of bytes in allocated large objects blocks. */ + /* For the purposes of this counter and the next one only, a */ + /* large object is one that occupies a block of at least */ + /* 2*HBLKSIZE. */ + word _max_large_allocd_bytes; + /* Maximum number of bytes that were ever allocated in */ + /* large object blocks. This is used to help decide when it */ + /* is safe to split up a large block. */ word _words_allocd_before_gc; /* Number of words allocated before this */ /* collection cycle. */ - word _words_allocd; +# ifndef SEPARATE_GLOBALS + word _words_allocd; /* Number of words allocated during this collection cycle */ +# endif word _words_wasted; /* Number of words wasted due to internal fragmentation */ /* in large objects, or due to dropping blacklisted */ @@ -1120,14 +914,17 @@ struct _GC_arrays { ptr_t _scratch_last_end_ptr; /* Used by headers.c, and can easily appear to point to */ /* heap. */ - mark_proc _mark_procs[MAX_MARK_PROCS]; + GC_mark_proc _mark_procs[MAX_MARK_PROCS]; /* Table of user-defined mark procedures. There is */ /* a small number of these, which can be referenced */ /* by DS_PROC mark descriptors. See gc_mark.h. */ - ptr_t _objfreelist[MAXOBJSZ+1]; + +# ifndef SEPARATE_GLOBALS + ptr_t _objfreelist[MAXOBJSZ+1]; /* free list for objects */ - ptr_t _aobjfreelist[MAXOBJSZ+1]; + ptr_t _aobjfreelist[MAXOBJSZ+1]; /* free list for atomic objs */ +# endif ptr_t _uobjfreelist[MAXOBJSZ+1]; /* uncollectable but traced objs */ @@ -1160,41 +957,28 @@ struct _GC_arrays { ptr_t _sobjfreelist[MAXOBJSZ+1]; # endif /* free list for immutable objects */ - ptr_t _obj_map[MAXOBJSZ+1]; + map_entry_type * _obj_map[MAXOBJSZ+1]; /* If not NIL, then a pointer to a map of valid */ /* object addresses. _obj_map[sz][i] is j if the */ /* address block_start+i is a valid pointer */ - /* to an object at */ - /* block_start+i&~3 - WORDS_TO_BYTES(j). */ - /* (If ALL_INTERIOR_POINTERS is defined, then */ - /* instead ((short *)(hb_map[sz])[i] is j if */ - /* block_start+WORDS_TO_BYTES(i) is in the */ - /* interior of an object starting at */ - /* block_start+WORDS_TO_BYTES(i-j)). */ - /* It is OBJ_INVALID if */ - /* block_start+WORDS_TO_BYTES(i) is not */ - /* valid as a pointer to an object. */ - /* We assume all values of j <= OBJ_INVALID. */ - /* The zeroth entry corresponds to large objects.*/ -# ifdef ALL_INTERIOR_POINTERS -# define map_entry_type short -# define OBJ_INVALID 0x7fff -# define MAP_ENTRY(map, bytes) \ - (((map_entry_type *)(map))[BYTES_TO_WORDS(bytes)]) -# define MAP_ENTRIES BYTES_TO_WORDS(HBLKSIZE) -# define MAP_SIZE (MAP_ENTRIES * sizeof(map_entry_type)) -# define OFFSET_VALID(displ) TRUE -# define CPP_MAX_OFFSET (HBLKSIZE - HDR_BYTES - 1) -# define MAX_OFFSET ((word)CPP_MAX_OFFSET) -# else -# define map_entry_type char -# define OBJ_INVALID 0x7f -# define MAP_ENTRY(map, bytes) \ - (map)[bytes] -# define MAP_ENTRIES HBLKSIZE -# define MAP_SIZE MAP_ENTRIES -# define CPP_MAX_OFFSET (WORDS_TO_BYTES(OBJ_INVALID) - 1) -# define MAX_OFFSET ((word)CPP_MAX_OFFSET) + /* to an object at block_start + */ + /* WORDS_TO_BYTES(BYTES_TO_WORDS(i) - j) */ + /* I.e. j is a word displacement from the */ + /* object beginning. */ + /* The entry is OBJ_INVALID if the corresponding */ + /* address is not a valid pointer. It is */ + /* OFFSET_TOO_BIG if the value j would be too */ + /* large to fit in the entry. (Note that the */ + /* size of these entries matters, both for */ + /* space consumption and for cache utilization. */ +# define OFFSET_TOO_BIG 0xfe +# define OBJ_INVALID 0xff +# define MAP_ENTRY(map, bytes) (map)[bytes] +# define MAP_ENTRIES HBLKSIZE +# define MAP_SIZE MAP_ENTRIES +# define CPP_MAX_OFFSET (OFFSET_TOO_BIG - 1) +# define MAX_OFFSET ((word)CPP_MAX_OFFSET) + /* The following are used only if GC_all_interior_ptrs != 0 */ # define VALID_OFFSET_SZ \ (CPP_MAX_OFFSET > WORDS_TO_BYTES(CPP_MAXOBJSZ)? \ CPP_MAX_OFFSET+1 \ @@ -1202,11 +986,11 @@ struct _GC_arrays { char _valid_offsets[VALID_OFFSET_SZ]; /* GC_valid_offsets[i] == TRUE ==> i */ /* is registered as a displacement. */ -# define OFFSET_VALID(displ) GC_valid_offsets[displ] +# define OFFSET_VALID(displ) \ + (GC_all_interior_pointers || GC_valid_offsets[displ]) char _modws_valid_offsets[sizeof(word)]; /* GC_valid_offsets[i] ==> */ /* GC_modws_valid_offsets[i%sizeof(word)] */ -# endif # ifdef STUBBORN_ALLOC page_hash_table _changed_pages; /* Stubborn object pages that were changes since last call to */ @@ -1233,17 +1017,25 @@ struct _GC_arrays { # define MAX_HEAP_SECTS 768 /* Separately added heap sections. */ # endif # else -# define MAX_HEAP_SECTS 256 +# ifdef SMALL_CONFIG +# define MAX_HEAP_SECTS 128 /* Roughly 1GB */ +# else +# define MAX_HEAP_SECTS 384 /* Roughly 3GB */ +# endif # endif struct HeapSect { ptr_t hs_start; word hs_bytes; } _heap_sects[MAX_HEAP_SECTS]; -# ifdef MSWIN32 +# if defined(MSWIN32) || defined(MSWINCE) ptr_t _heap_bases[MAX_HEAP_SECTS]; /* Start address of memory regions obtained from kernel. */ # endif +# ifdef MSWINCE + word _heap_lengths[MAX_HEAP_SECTS]; + /* Commited lengths of memory regions obtained from kernel. */ +# endif struct roots _static_roots[MAX_ROOT_SETS]; -# ifndef MSWIN32 +# if !defined(MSWIN32) && !defined(MSWINCE) struct roots * _root_index[RT_SIZE]; # endif struct exclusion _excl_table[MAX_EXCLUSIONS]; @@ -1262,8 +1054,11 @@ struct _GC_arrays { GC_API GC_FAR struct _GC_arrays GC_arrays; -# define GC_objfreelist GC_arrays._objfreelist -# define GC_aobjfreelist GC_arrays._aobjfreelist +# ifndef SEPARATE_GLOBALS +# define GC_objfreelist GC_arrays._objfreelist +# define GC_aobjfreelist GC_arrays._aobjfreelist +# define GC_words_allocd GC_arrays._words_allocd +# endif # define GC_uobjfreelist GC_arrays._uobjfreelist # ifdef ATOMIC_UNCOLLECTABLE # define GC_auobjfreelist GC_arrays._auobjfreelist @@ -1278,9 +1073,10 @@ GC_API GC_FAR struct _GC_arrays GC_arrays; # define GC_obj_map GC_arrays._obj_map # define GC_last_heap_addr GC_arrays._last_heap_addr # define GC_prev_heap_addr GC_arrays._prev_heap_addr -# define GC_words_allocd GC_arrays._words_allocd # define GC_words_wasted GC_arrays._words_wasted # define GC_large_free_bytes GC_arrays._large_free_bytes +# define GC_large_allocd_bytes GC_arrays._large_allocd_bytes +# define GC_max_large_allocd_bytes GC_arrays._max_large_allocd_bytes # define GC_words_finalized GC_arrays._words_finalized # define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc # define GC_mem_freed GC_arrays._mem_freed @@ -1296,9 +1092,12 @@ GC_API GC_FAR struct _GC_arrays GC_arrays; # ifdef USE_MUNMAP # define GC_unmapped_bytes GC_arrays._unmapped_bytes # endif -# ifdef MSWIN32 +# if defined(MSWIN32) || defined(MSWINCE) # define GC_heap_bases GC_arrays._heap_bases # endif +# ifdef MSWINCE +# define GC_heap_lengths GC_arrays._heap_lengths +# endif # define GC_static_roots GC_arrays._static_roots # define GC_root_index GC_arrays._root_index # define GC_excl_table GC_arrays._excl_table @@ -1345,10 +1144,27 @@ extern struct obj_kind { GC_bool ok_init; /* Clear objects before putting them on the free list. */ } GC_obj_kinds[MAXOBJKINDS]; -# define endGC_obj_kinds (((ptr_t)(&GC_obj_kinds)) + (sizeof GC_obj_kinds)) +# define beginGC_obj_kinds ((ptr_t)(&GC_obj_kinds)) +# define endGC_obj_kinds (beginGC_obj_kinds + (sizeof GC_obj_kinds)) -# define end_gc_area ((ptr_t)endGC_arrays == (ptr_t)(&GC_obj_kinds) ? \ - endGC_obj_kinds : endGC_arrays) +/* Variables that used to be in GC_arrays, but need to be accessed by */ +/* inline allocation code. If they were in GC_arrays, the inlined */ +/* allocation code would include GC_arrays offsets (as it did), which */ +/* introduce maintenance problems. */ + +#ifdef SEPARATE_GLOBALS + word GC_words_allocd; + /* Number of words allocated during this collection cycle */ + ptr_t GC_objfreelist[MAXOBJSZ+1]; + /* free list for NORMAL objects */ +# define beginGC_objfreelist ((ptr_t)(&GC_objfreelist)) +# define endGC_objfreelist (beginGC_objfreelist + sizeof(GC_objfreelist)) + + ptr_t GC_aobjfreelist[MAXOBJSZ+1]; + /* free list for atomic (PTRFREE) objs */ +# define beginGC_aobjfreelist ((ptr_t)(&GC_aobjfreelist)) +# define endGC_aobjfreelist (beginGC_aobjfreelist + sizeof(GC_aobjfreelist)) +#endif /* Predefined kinds: */ # define PTRFREE 0 @@ -1372,8 +1188,10 @@ extern word GC_n_heap_sects; /* Number of separately added heap */ extern word GC_page_size; -# ifdef MSWIN32 -extern word GC_n_heap_bases; /* See GC_heap_bases. */ +# if defined(MSWIN32) || defined(MSWINCE) + struct _SYSTEM_INFO; + extern struct _SYSTEM_INFO GC_sysinfo; + extern word GC_n_heap_bases; /* See GC_heap_bases. */ # endif extern word GC_total_stack_black_listed; @@ -1386,7 +1204,7 @@ extern word GC_black_list_spacing; /* "stack-blacklisted", i.e. that are */ /* problematic in the interior of an object. */ -extern char * GC_invalid_map; +extern map_entry_type * GC_invalid_map; /* Pointer to the nowhere valid hblk map */ /* Blocks pointing to this map are free. */ @@ -1418,10 +1236,6 @@ extern word GC_root_size; /* Total size of registered root sections */ extern GC_bool GC_debugging_started; /* GC_debug_malloc has been called. */ -extern ptr_t GC_least_plausible_heap_addr; -extern ptr_t GC_greatest_plausible_heap_addr; - /* Bounds on the heap. Guaranteed valid */ - /* Likely to include future heap expansion. */ /* Operations */ # ifndef abs @@ -1434,6 +1248,33 @@ extern ptr_t GC_greatest_plausible_heap_addr; /* with it. Only those corresponding to the beginning of an */ /* object are used. */ +/* Set mark bit correctly, even if mark bits may be concurrently */ +/* accessed. */ +#ifdef PARALLEL_MARK +# define OR_WORD(addr, bits) \ + { word old; \ + do { \ + old = *((volatile word *)addr); \ + } while (!GC_compare_and_exchange((addr), old, old | (bits))); \ + } +# define OR_WORD_EXIT_IF_SET(addr, bits, exit_label) \ + { word old; \ + word my_bits = (bits); \ + do { \ + old = *((volatile word *)addr); \ + if (old & my_bits) goto exit_label; \ + } while (!GC_compare_and_exchange((addr), old, old | my_bits)); \ + } +#else +# define OR_WORD(addr, bits) *(addr) |= (bits) +# define OR_WORD_EXIT_IF_SET(addr, bits, exit_label) \ + { \ + word old = *(addr); \ + word my_bits = (bits); \ + if (old & my_bits) goto exit_label; \ + *(addr) = (old | my_bits); \ + } +#endif /* Mark bit operations */ @@ -1445,72 +1286,87 @@ extern ptr_t GC_greatest_plausible_heap_addr; * relative to the beginning of the block, including unused words) */ +#ifdef USE_MARK_BYTES +# define mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[(n) >> 1]) +# define set_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[(n)>>1]) = 1 +# define clear_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[(n)>>1]) = 0 +#else /* !USE_MARK_BYTES */ # define mark_bit_from_hdr(hhdr,n) (((hhdr)->hb_marks[divWORDSZ(n)] \ >> (modWORDSZ(n))) & (word)1) -# define set_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \ - |= (word)1 << modWORDSZ(n) - +# define set_mark_bit_from_hdr(hhdr,n) \ + OR_WORD((hhdr)->hb_marks+divWORDSZ(n), \ + (word)1 << modWORDSZ(n)) # define clear_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \ &= ~((word)1 << modWORDSZ(n)) +#endif /* !USE_MARK_BYTES */ /* Important internal collector routines */ -ptr_t GC_approx_sp(); - -GC_bool GC_should_collect(); - -void GC_apply_to_all_blocks(/*fn, client_data*/); - /* Invoke fn(hbp, client_data) for each */ - /* allocated heap block. */ -struct hblk * GC_next_used_block(/* struct hblk * h */); - /* Return first in-use block >= h */ -struct hblk * GC_prev_block(/* struct hblk * h */); - /* Return last block <= h. Returned block */ - /* is managed by GC, but may or may not be in */ +ptr_t GC_approx_sp GC_PROTO((void)); + +GC_bool GC_should_collect GC_PROTO((void)); + +void GC_apply_to_all_blocks GC_PROTO(( \ + void (*fn) GC_PROTO((struct hblk *h, word client_data)), \ + word client_data)); + /* Invoke fn(hbp, client_data) for each */ + /* allocated heap block. */ +struct hblk * GC_next_used_block GC_PROTO((struct hblk * h)); + /* Return first in-use block >= h */ +struct hblk * GC_prev_block GC_PROTO((struct hblk * h)); + /* Return last block <= h. Returned block */ + /* is managed by GC, but may or may not be in */ /* use. */ -void GC_mark_init(); -void GC_clear_marks(); /* Clear mark bits for all heap objects. */ -void GC_invalidate_mark_state(); /* Tell the marker that marked */ - /* objects may point to unmarked */ - /* ones, and roots may point to */ - /* unmarked objects. */ - /* Reset mark stack. */ -void GC_mark_from_mark_stack(); /* Mark from everything on the mark stack. */ - /* Return after about one pages worth of */ - /* work. */ -GC_bool GC_mark_stack_empty(); -GC_bool GC_mark_some(/* cold_gc_frame */); - /* Perform about one pages worth of marking */ - /* work of whatever kind is needed. Returns */ - /* quickly if no collection is in progress. */ - /* Return TRUE if mark phase finished. */ -void GC_initiate_gc(); /* initiate collection. */ - /* If the mark state is invalid, this */ - /* becomes full colleection. Otherwise */ - /* it's partial. */ -void GC_push_all(/*b,t*/); /* Push everything in a range */ - /* onto mark stack. */ -void GC_push_dirty(/*b,t*/); /* Push all possibly changed */ - /* subintervals of [b,t) onto */ - /* mark stack. */ +void GC_mark_init GC_PROTO((void)); +void GC_clear_marks GC_PROTO((void)); /* Clear mark bits for all heap objects. */ +void GC_invalidate_mark_state GC_PROTO((void)); + /* Tell the marker that marked */ + /* objects may point to unmarked */ + /* ones, and roots may point to */ + /* unmarked objects. */ + /* Reset mark stack. */ +GC_bool GC_mark_stack_empty GC_PROTO((void)); +GC_bool GC_mark_some GC_PROTO((ptr_t cold_gc_frame)); + /* Perform about one pages worth of marking */ + /* work of whatever kind is needed. Returns */ + /* quickly if no collection is in progress. */ + /* Return TRUE if mark phase finished. */ +void GC_initiate_gc GC_PROTO((void)); + /* initiate collection. */ + /* If the mark state is invalid, this */ + /* becomes full colleection. Otherwise */ + /* it's partial. */ +void GC_push_all GC_PROTO((ptr_t bottom, ptr_t top)); + /* Push everything in a range */ + /* onto mark stack. */ +void GC_push_selected GC_PROTO(( \ + ptr_t bottom, \ + ptr_t top, \ + int (*dirty_fn) GC_PROTO((struct hblk *h)), \ + void (*push_fn) GC_PROTO((ptr_t bottom, ptr_t top)) )); + /* Push all pages h in [b,t) s.t. */ + /* select_fn(h) != 0 onto mark stack. */ #ifndef SMALL_CONFIG - void GC_push_conditional(/* ptr_t b, ptr_t t, GC_bool all*/); + void GC_push_conditional GC_PROTO((ptr_t b, ptr_t t, GC_bool all)); #else # define GC_push_conditional(b, t, all) GC_push_all(b, t) #endif /* Do either of the above, depending */ /* on the third arg. */ -void GC_push_all_stack(/*b,t*/); /* As above, but consider */ +void GC_push_all_stack GC_PROTO((ptr_t b, ptr_t t)); + /* As above, but consider */ /* interior pointers as valid */ -void GC_push_all_eager(/*b,t*/); /* Same as GC_push_all_stack, but */ +void GC_push_all_eager GC_PROTO((ptr_t b, ptr_t t)); + /* Same as GC_push_all_stack, but */ /* ensures that stack is scanned */ /* immediately, not just scheduled */ /* for scanning. */ #ifndef THREADS - void GC_push_all_stack_partially_eager(/* bottom, top, cold_gc_frame */); + void GC_push_all_stack_partially_eager GC_PROTO(( \ + ptr_t bottom, ptr_t top, ptr_t cold_gc_frame )); /* Similar to GC_push_all_eager, but only the */ /* part hotter than cold_gc_frame is scanned */ - /* immediately. Needed to endure that callee- */ + /* immediately. Needed to ensure that callee- */ /* save registers are not missed. */ #else /* In the threads case, we push part of the current thread stack */ @@ -1519,169 +1375,237 @@ void GC_push_all_eager(/*b,t*/); /* Same as GC_push_all_stack, but */ /* stacks are scheduled for scanning in *GC_push_other_roots, which */ /* is thread-package-specific. */ #endif -void GC_push_current_stack(/* ptr_t cold_gc_frame */); - /* Push enough of the current stack eagerly to */ - /* ensure that callee-save registers saved in */ - /* GC frames are scanned. */ - /* In the non-threads case, schedule entire */ - /* stack for scanning. */ -void GC_push_roots(/* GC_bool all, ptr_t cold_gc_frame */); - /* Push all or dirty roots. */ -extern void (*GC_push_other_roots)(); - /* Push system or application specific roots */ - /* onto the mark stack. In some environments */ - /* (e.g. threads environments) this is */ - /* predfined to be non-zero. A client supplied */ - /* replacement should also call the original */ - /* function. */ -extern void (*GC_start_call_back)(/* void */); - /* Called at start of full collections. */ - /* Not called if 0. Called with allocation */ - /* 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. */ +void GC_push_current_stack GC_PROTO((ptr_t cold_gc_frame)); + /* Push enough of the current stack eagerly to */ + /* ensure that callee-save registers saved in */ + /* GC frames are scanned. */ + /* In the non-threads case, schedule entire */ + /* stack for scanning. */ +void GC_push_roots GC_PROTO((GC_bool all, ptr_t cold_gc_frame)); + /* Push all or dirty roots. */ +extern void (*GC_push_other_roots) GC_PROTO((void)); + /* Push system or application specific roots */ + /* onto the mark stack. In some environments */ + /* (e.g. threads environments) this is */ + /* predfined to be non-zero. A client supplied */ + /* replacement should also call the original */ + /* function. */ +extern void GC_push_gc_structures GC_PROTO((void)); + /* Push GC internal roots. These are normally */ + /* included in the static data segment, and */ + /* Thus implicitly pushed. But we must do this */ + /* explicitly if normal root processing is */ + /* disabled. Calls the following: */ + extern void GC_push_finalizer_structures GC_PROTO((void)); + extern void GC_push_stubborn_structures GC_PROTO((void)); +# ifdef THREADS + extern void GC_push_thread_structures GC_PROTO((void)); +# endif +extern void (*GC_start_call_back) GC_PROTO((void)); + /* Called at start of full collections. */ + /* Not called if 0. Called with allocation */ + /* lock held. */ + /* 0 by default. */ +# if defined(USE_GENERIC_PUSH_REGS) + void GC_generic_push_regs GC_PROTO((ptr_t cold_gc_frame)); +# else + void GC_push_regs GC_PROTO((void)); +# endif + /* Push register contents onto mark stack. */ + /* If NURSERY is defined, the default push */ + /* action can be overridden with GC_push_proc */ # ifdef NURSERY extern void (*GC_push_proc)(ptr_t); # endif -# if defined(MSWIN32) - void __cdecl GC_push_one(); +# if defined(MSWIN32) || defined(MSWINCE) + void __cdecl GC_push_one GC_PROTO((word p)); # else - void GC_push_one(/*p*/); /* If p points to an object, mark it */ + void GC_push_one GC_PROTO((word p)); + /* If p points to an object, mark it */ /* and push contents on the mark stack */ + /* Pointer recognition test always */ + /* accepts interior pointers, i.e. this */ + /* is appropriate for pointers found on */ + /* stack. */ +# endif +# if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS) + void GC_mark_and_push_stack GC_PROTO((word p, ptr_t source)); + /* Ditto, omits plausibility test */ +# else + void GC_mark_and_push_stack GC_PROTO((word p)); # endif -void GC_push_one_checked(/*p*/); /* Ditto, omits plausibility test */ -void GC_push_marked(/* struct hblk h, hdr * hhdr */); +void GC_push_marked GC_PROTO((struct hblk * h, hdr * hhdr)); /* Push contents of all marked objects in h onto */ /* mark stack. */ #ifdef SMALL_CONFIG # define GC_push_next_marked_dirty(h) GC_push_next_marked(h) #else - struct hblk * GC_push_next_marked_dirty(/* h */); + struct hblk * GC_push_next_marked_dirty GC_PROTO((struct hblk * h)); /* Invoke GC_push_marked on next dirty block above h. */ /* Return a pointer just past the end of this block. */ #endif /* !SMALL_CONFIG */ -struct hblk * GC_push_next_marked(/* h */); - /* Ditto, but also mark from clean pages. */ -struct hblk * GC_push_next_marked_uncollectable(/* h */); - /* Ditto, but mark only from uncollectable pages. */ -GC_bool GC_stopped_mark(); /* Stop world and mark from all roots */ - /* and rescuers. */ -void GC_clear_hdr_marks(/* hhdr */); /* Clear the mark bits in a header */ -void GC_set_hdr_marks(/* hhdr */); /* Set the mark bits in a header */ -void GC_add_roots_inner(); -GC_bool GC_is_static_root(/* ptr_t p */); - /* Is the address p in one of the registered static */ +struct hblk * GC_push_next_marked GC_PROTO((struct hblk * h)); + /* Ditto, but also mark from clean pages. */ +struct hblk * GC_push_next_marked_uncollectable GC_PROTO((struct hblk * h)); + /* Ditto, but mark only from uncollectable pages. */ +GC_bool GC_stopped_mark GC_PROTO((GC_stop_func stop_func)); + /* Stop world and mark from all roots */ + /* and rescuers. */ +void GC_clear_hdr_marks GC_PROTO((hdr * hhdr)); + /* Clear the mark bits in a header */ +void GC_set_hdr_marks GC_PROTO((hdr * hhdr)); + /* Set the mark bits in a header */ +void GC_add_roots_inner GC_PROTO((char * b, char * e, GC_bool tmp)); +GC_bool GC_is_static_root GC_PROTO((ptr_t p)); + /* Is the address p in one of the registered static */ + /* root sections? */ +# if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION) +GC_bool GC_is_tmp_root GC_PROTO((ptr_t p)); + /* Is the address p in one of the temporary static */ /* root sections? */ -void GC_register_dynamic_libraries(); - /* Add dynamic library data sections to the root set. */ - +# endif +void GC_register_dynamic_libraries GC_PROTO((void)); + /* Add dynamic library data sections to the root set. */ + /* Machine dependent startup routines */ -ptr_t GC_get_stack_base(); -void GC_register_data_segments(); - +ptr_t GC_get_stack_base GC_PROTO((void)); /* Cold end of stack */ +#ifdef IA64 + ptr_t GC_get_register_stack_base GC_PROTO((void)); + /* Cold end of register stack. */ +#endif +void GC_register_data_segments GC_PROTO((void)); + /* Black listing: */ -void GC_bl_init(); -# ifndef ALL_INTERIOR_POINTERS - void GC_add_to_black_list_normal(/* bits, maybe source */); +void GC_bl_init GC_PROTO((void)); +# ifdef PRINT_BLACK_LIST + void GC_add_to_black_list_normal GC_PROTO((word p, ptr_t source)); /* Register bits as a possible future false */ /* reference from the heap or static data */ -# ifdef PRINT_BLACK_LIST # define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \ - GC_add_to_black_list_normal(bits, source) -# else -# define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \ - GC_add_to_black_list_normal(bits) -# endif + if (GC_all_interior_pointers) { \ + GC_add_to_black_list_stack(bits, source); \ + } else { \ + GC_add_to_black_list_normal(bits, source); \ + } # else -# ifdef PRINT_BLACK_LIST -# define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \ - GC_add_to_black_list_stack(bits, source) -# else + void GC_add_to_black_list_normal GC_PROTO((word p)); # define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \ - GC_add_to_black_list_stack(bits) -# endif + if (GC_all_interior_pointers) { \ + GC_add_to_black_list_stack(bits); \ + } else { \ + GC_add_to_black_list_normal(bits); \ + } # endif -void GC_add_to_black_list_stack(/* bits, maybe source */); -struct hblk * GC_is_black_listed(/* h, len */); - /* If there are likely to be false references */ - /* to a block starting at h of the indicated */ - /* length, then return the next plausible */ - /* starting location for h that might avoid */ - /* these false references. */ -void GC_promote_black_lists(); - /* Declare an end to a black listing phase. */ -void GC_unpromote_black_lists(); - /* Approximately undo the effect of the above. */ - /* This actually loses some information, but */ - /* only in a reasonably safe way. */ -word GC_number_stack_black_listed(/*struct hblk *start, struct hblk *endp1 */); - /* Return the number of (stack) blacklisted */ - /* blocks in the range for statistical */ - /* purposes. */ - -ptr_t GC_scratch_alloc(/*bytes*/); - /* GC internal memory allocation for */ - /* small objects. Deallocation is not */ - /* possible. */ - +# ifdef PRINT_BLACK_LIST + void GC_add_to_black_list_stack GC_PROTO((word p, ptr_t source)); +# else + void GC_add_to_black_list_stack GC_PROTO((word p)); +# endif +struct hblk * GC_is_black_listed GC_PROTO((struct hblk * h, word len)); + /* If there are likely to be false references */ + /* to a block starting at h of the indicated */ + /* length, then return the next plausible */ + /* starting location for h that might avoid */ + /* these false references. */ +void GC_promote_black_lists GC_PROTO((void)); + /* Declare an end to a black listing phase. */ +void GC_unpromote_black_lists GC_PROTO((void)); + /* Approximately undo the effect of the above. */ + /* This actually loses some information, but */ + /* only in a reasonably safe way. */ +word GC_number_stack_black_listed GC_PROTO(( \ + struct hblk *start, struct hblk *endp1)); + /* Return the number of (stack) blacklisted */ + /* blocks in the range for statistical */ + /* purposes. */ + +ptr_t GC_scratch_alloc GC_PROTO((word bytes)); + /* GC internal memory allocation for */ + /* small objects. Deallocation is not */ + /* possible. */ + /* Heap block layout maps: */ -void GC_invalidate_map(/* hdr */); - /* Remove the object map associated */ - /* with the block. This identifies */ - /* the block as invalid to the mark */ - /* routines. */ -GC_bool GC_add_map_entry(/*sz*/); - /* Add a heap block map for objects of */ - /* size sz to obj_map. */ - /* Return FALSE on failure. */ -void GC_register_displacement_inner(/*offset*/); - /* Version of GC_register_displacement */ - /* that assumes lock is already held */ - /* and signals are already disabled. */ - +void GC_invalidate_map GC_PROTO((hdr * hhdr)); + /* Remove the object map associated */ + /* with the block. This identifies */ + /* the block as invalid to the mark */ + /* routines. */ +GC_bool GC_add_map_entry GC_PROTO((word sz)); + /* Add a heap block map for objects of */ + /* size sz to obj_map. */ + /* Return FALSE on failure. */ +void GC_register_displacement_inner GC_PROTO((word offset)); + /* Version of GC_register_displacement */ + /* that assumes lock is already held */ + /* and signals are already disabled. */ + /* hblk allocation: */ -void GC_new_hblk(/*size_in_words, kind*/); - /* Allocate a new heap block, and build */ - /* a free list in it. */ -struct hblk * GC_allochblk(/*size_in_words, kind*/); - /* Allocate a heap block, clear it if */ - /* for composite objects, inform */ +void GC_new_hblk GC_PROTO((word size_in_words, int kind)); + /* Allocate a new heap block, and build */ + /* a free list in it. */ + +ptr_t GC_build_fl GC_PROTO((struct hblk *h, word sz, + GC_bool clear, ptr_t list)); + /* Build a free list for objects of */ + /* size sz in block h. Append list to */ + /* end of the free lists. Possibly */ + /* clear objects on the list. Normally */ + /* called by GC_new_hblk, but also */ + /* called explicitly without GC lock. */ + +struct hblk * GC_allochblk GC_PROTO(( \ + word size_in_words, int kind, unsigned flags)); + /* Allocate a heap block, inform */ /* the marker that block is valid */ /* for objects of indicated size. */ - /* sz < 0 ==> atomic. */ -void GC_freehblk(); /* Deallocate a heap block and mark it */ - /* as invalid. */ - + +ptr_t GC_alloc_large GC_PROTO((word lw, int k, unsigned flags)); + /* Allocate a large block of size lw words. */ + /* The block is not cleared. */ + /* Flags is 0 or IGNORE_OFF_PAGE. */ + /* Calls GC_allchblk to do the actual */ + /* allocation, but also triggers GC and/or */ + /* heap expansion as appropriate. */ + /* Does not update GC_words_allocd, but does */ + /* other accounting. */ + +ptr_t GC_alloc_large_and_clear GC_PROTO((word lw, int k, unsigned flags)); + /* As above, but clear block if appropriate */ + /* for kind k. */ + +void GC_freehblk GC_PROTO((struct hblk * p)); + /* Deallocate a heap block and mark it */ + /* as invalid. */ + /* Misc GC: */ -void GC_init_inner(); -GC_bool GC_expand_hp_inner(); -void GC_start_reclaim(/*abort_if_found*/); - /* Restore unmarked objects to free */ - /* lists, or (if abort_if_found is */ - /* TRUE) report them. */ - /* Sweeping of small object pages is */ - /* largely deferred. */ -void GC_continue_reclaim(/*size, kind*/); - /* Sweep pages of the given size and */ - /* kind, as long as possible, and */ - /* as long as the corr. free list is */ - /* empty. */ -void GC_reclaim_or_delete_all(); - /* Arrange for all reclaim lists to be */ - /* empty. Judiciously choose between */ - /* sweeping and discarding each page. */ -GC_bool GC_reclaim_all(/* GC_stop_func f*/); - /* Reclaim all blocks. Abort (in a */ - /* consistent state) if f returns TRUE. */ -GC_bool GC_block_empty(/* hhdr */); /* Block completely unmarked? */ -GC_bool GC_never_stop_func(); /* Returns FALSE. */ -GC_bool GC_try_to_collect_inner(/* GC_stop_func f */); +void GC_init_inner GC_PROTO((void)); +GC_bool GC_expand_hp_inner GC_PROTO((word n)); +void GC_start_reclaim GC_PROTO((int abort_if_found)); + /* Restore unmarked objects to free */ + /* lists, or (if abort_if_found is */ + /* TRUE) report them. */ + /* Sweeping of small object pages is */ + /* largely deferred. */ +void GC_continue_reclaim GC_PROTO((word sz, int kind)); + /* Sweep pages of the given size and */ + /* kind, as long as possible, and */ + /* as long as the corr. free list is */ + /* empty. */ +void GC_reclaim_or_delete_all GC_PROTO((void)); + /* Arrange for all reclaim lists to be */ + /* empty. Judiciously choose between */ + /* sweeping and discarding each page. */ +GC_bool GC_reclaim_all GC_PROTO((GC_stop_func stop_func, GC_bool ignore_old)); + /* Reclaim all blocks. Abort (in a */ + /* consistent state) if f returns TRUE. */ +GC_bool GC_block_empty GC_PROTO((hdr * hhdr)); + /* Block completely unmarked? */ +GC_bool GC_never_stop_func GC_PROTO((void)); + /* Returns FALSE. */ +GC_bool GC_try_to_collect_inner GC_PROTO((GC_stop_func f)); + /* Collect; caller must have acquired */ /* lock and disabled signals. */ /* Collection is aborted if f returns */ @@ -1689,88 +1613,133 @@ GC_bool GC_try_to_collect_inner(/* GC_stop_func f */); /* successfully. */ # define GC_gcollect_inner() \ (void) GC_try_to_collect_inner(GC_never_stop_func) -void GC_finish_collection(); /* Finish collection. Mark bits are */ - /* consistent and lock is still held. */ -GC_bool GC_collect_or_expand(/* needed_blocks */); - /* Collect or expand heap in an attempt */ - /* make the indicated number of free */ - /* blocks available. Should be called */ - /* until the blocks are available or */ - /* until it fails by returning FALSE. */ -GC_API void GC_init(); /* Initialize collector. */ -void GC_collect_a_little_inner(/* int n */); - /* Do n units worth of garbage */ - /* collection work, if appropriate. */ - /* A unit is an amount appropriate for */ - /* HBLKSIZE bytes of allocation. */ -ptr_t GC_generic_malloc(/* bytes, kind */); - /* Allocate an object of the given */ - /* kind. By default, there are only */ - /* a few kinds: composite(pointerfree), */ +void GC_finish_collection GC_PROTO((void)); + /* Finish collection. Mark bits are */ + /* consistent and lock is still held. */ +GC_bool GC_collect_or_expand GC_PROTO(( \ + word needed_blocks, GC_bool ignore_off_page)); + /* Collect or expand heap in an attempt */ + /* make the indicated number of free */ + /* blocks available. Should be called */ + /* until the blocks are available or */ + /* until it fails by returning FALSE. */ +GC_API void GC_init GC_PROTO((void)); /* Initialize collector. */ + +#if defined(MSWIN32) || defined(MSWINCE) + void GC_deinit GC_PROTO((void)); + /* Free any resources allocated by */ + /* GC_init */ +#endif + +void GC_collect_a_little_inner GC_PROTO((int n)); + /* Do n units worth of garbage */ + /* collection work, if appropriate. */ + /* A unit is an amount appropriate for */ + /* HBLKSIZE bytes of allocation. */ +ptr_t GC_generic_malloc GC_PROTO((word lb, int k)); + /* Allocate an object of the given */ + /* kind. By default, there are only */ + /* a few kinds: composite(pointerfree), */ /* atomic, uncollectable, etc. */ /* We claim it's possible for clever */ /* client code that understands GC */ /* internals to add more, e.g. to */ /* communicate object layout info */ /* to the collector. */ -ptr_t GC_generic_malloc_ignore_off_page(/* bytes, kind */); - /* As above, but pointers past the */ - /* first page of the resulting object */ - /* are ignored. */ -ptr_t GC_generic_malloc_inner(/* bytes, kind */); - /* Ditto, but I already hold lock, etc. */ -ptr_t GC_generic_malloc_words_small GC_PROTO((size_t words, int kind)); - /* As above, but size in units of words */ - /* Bypasses MERGE_SIZES. Assumes */ - /* words <= MAXOBJSZ. */ -ptr_t GC_generic_malloc_inner_ignore_off_page(/* bytes, kind */); - /* Allocate an object, where */ - /* the client guarantees that there */ - /* will always be a pointer to the */ - /* beginning of the object while the */ - /* object is live. */ -ptr_t GC_allocobj(/* sz_inn_words, kind */); - /* Make the indicated */ - /* free list nonempty, and return its */ - /* head. */ - -void GC_init_headers(); -struct hblkhdr * GC_install_header(/*h*/); - /* Install a header for block h. */ - /* Return 0 on failure, or the header */ - /* otherwise. */ -GC_bool GC_install_counts(/*h, sz*/); - /* Set up forwarding counts for block */ - /* h of size sz. */ - /* Return FALSE on failure. */ -void GC_remove_header(/*h*/); - /* Remove the header for block h. */ -void GC_remove_counts(/*h, sz*/); - /* Remove forwarding counts for h. */ -hdr * GC_find_header(/*p*/); /* Debugging only. */ - -void GC_finalize(); /* Perform all indicated finalization actions */ - /* on unmarked objects. */ - /* Unreachable finalizable objects are enqueued */ - /* for processing by GC_invoke_finalizers. */ - /* Invoked with lock. */ - -void GC_add_to_heap(/*p, bytes*/); - /* Add a HBLKSIZE aligned chunk to the heap. */ - -void GC_print_obj(/* ptr_t p */); - /* P points to somewhere inside an object with */ - /* debugging info. Print a human readable */ - /* description of the object to stderr. */ -extern void (*GC_check_heap)(); - /* Check that all objects in the heap with */ - /* debugging info are intact. Print */ - /* descriptions of any that are not. */ -extern void (*GC_print_heap_obj)(/* ptr_t p */); - /* If possible print s followed by a more */ - /* detailed description of the object */ - /* referred to by p. */ - +ptr_t GC_generic_malloc_ignore_off_page GC_PROTO((size_t b, int k)); + /* As above, but pointers past the */ + /* first page of the resulting object */ + /* are ignored. */ +ptr_t GC_generic_malloc_inner GC_PROTO((word lb, int k)); + /* Ditto, but I already hold lock, etc. */ +ptr_t GC_generic_malloc_words_small GC_PROTO((size_t lw, int k)); + /* As above, but size in units of words */ + /* Bypasses MERGE_SIZES. Assumes */ + /* words <= MAXOBJSZ. */ +ptr_t GC_generic_malloc_inner_ignore_off_page GC_PROTO((size_t lb, int k)); + /* Allocate an object, where */ + /* the client guarantees that there */ + /* will always be a pointer to the */ + /* beginning of the object while the */ + /* object is live. */ +ptr_t GC_allocobj GC_PROTO((word sz, int kind)); + /* Make the indicated */ + /* free list nonempty, and return its */ + /* head. */ + +void GC_init_headers GC_PROTO((void)); +struct hblkhdr * GC_install_header GC_PROTO((struct hblk *h)); + /* Install a header for block h. */ + /* Return 0 on failure, or the header */ + /* otherwise. */ +GC_bool GC_install_counts GC_PROTO((struct hblk * h, word sz)); + /* Set up forwarding counts for block */ + /* h of size sz. */ + /* Return FALSE on failure. */ +void GC_remove_header GC_PROTO((struct hblk * h)); + /* Remove the header for block h. */ +void GC_remove_counts GC_PROTO((struct hblk * h, word sz)); + /* Remove forwarding counts for h. */ +hdr * GC_find_header GC_PROTO((ptr_t h)); /* Debugging only. */ + +void GC_finalize GC_PROTO((void)); + /* Perform all indicated finalization actions */ + /* on unmarked objects. */ + /* Unreachable finalizable objects are enqueued */ + /* for processing by GC_invoke_finalizers. */ + /* Invoked with lock. */ + +void GC_notify_or_invoke_finalizers GC_PROTO((void)); + /* If GC_finalize_on_demand is not set, invoke */ + /* eligible finalizers. Otherwise: */ + /* Call *GC_finalizer_notifier if there are */ + /* finalizers to be run, and we haven't called */ + /* this procedure yet this GC cycle. */ + +void GC_add_to_heap GC_PROTO((struct hblk *p, word bytes)); + /* Add a HBLKSIZE aligned chunk to the heap. */ + +void GC_print_obj GC_PROTO((ptr_t p)); + /* P points to somewhere inside an object with */ + /* debugging info. Print a human readable */ + /* description of the object to stderr. */ +extern void (*GC_check_heap) GC_PROTO((void)); + /* Check that all objects in the heap with */ + /* debugging info are intact. Print */ + /* descriptions of any that are not. */ +extern void (*GC_print_heap_obj) GC_PROTO((ptr_t p)); + /* If possible print s followed by a more */ + /* detailed description of the object */ + /* referred to by p. */ + +extern GC_bool GC_print_stats; /* Produce at least some logging output */ + /* Set from environment variable. */ + +/* Macros used for collector internal allocation. */ +/* These assume the collector lock is held. */ +#ifdef DBG_HDRS_ALL + extern GC_PTR GC_debug_generic_malloc_inner(size_t lb, int k); + extern GC_PTR GC_debug_generic_malloc_inner_ignore_off_page(size_t lb, + int k); +# define GC_INTERNAL_MALLOC GC_debug_generic_malloc_inner +# define GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE \ + GC_debug_generic_malloc_inner_ignore_off_page +# ifdef THREADS +# define GC_INTERNAL_FREE GC_debug_free_inner +# else +# define GC_INTERNAL_FREE GC_debug_free +# endif +#else +# define GC_INTERNAL_MALLOC GC_generic_malloc_inner +# define GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE \ + GC_generic_malloc_inner_ignore_off_page +# ifdef THREADS +# define GC_INTERNAL_FREE GC_free_inner +# else +# define GC_INTERNAL_FREE GC_free +# endif +#endif + /* Memory unmapping: */ #ifdef USE_MUNMAP void GC_unmap_old(void); @@ -1782,35 +1751,38 @@ extern void (*GC_print_heap_obj)(/* ptr_t p */); /* Virtual dirty bit implementation: */ /* Each implementation exports the following: */ -void GC_read_dirty(); /* Retrieve dirty bits. */ -GC_bool GC_page_was_dirty(/* struct hblk * h */); - /* Read retrieved dirty bits. */ -GC_bool GC_page_was_ever_dirty(/* struct hblk * h */); - /* Could the page contain valid heap pointers? */ -void GC_is_fresh(/* struct hblk * h, word number_of_blocks */); - /* Assert the region currently contains no */ - /* valid pointers. */ -void GC_write_hint(/* struct hblk * h */); - /* h is about to be written. */ -void GC_dirty_init(); - +void GC_read_dirty GC_PROTO((void)); + /* Retrieve dirty bits. */ +GC_bool GC_page_was_dirty GC_PROTO((struct hblk *h)); + /* Read retrieved dirty bits. */ +GC_bool GC_page_was_ever_dirty GC_PROTO((struct hblk *h)); + /* Could the page contain valid heap pointers? */ +void GC_is_fresh GC_PROTO((struct hblk *h, word n)); + /* Assert the region currently contains no */ + /* valid pointers. */ +void GC_write_hint GC_PROTO((struct hblk *h)); + /* h is about to be written. */ +void GC_dirty_init GC_PROTO((void)); + /* Slow/general mark bit manipulation: */ -GC_API GC_bool GC_is_marked(); -void GC_clear_mark_bit(); -void GC_set_mark_bit(); - +GC_API GC_bool GC_is_marked GC_PROTO((ptr_t p)); +void GC_clear_mark_bit GC_PROTO((ptr_t p)); +void GC_set_mark_bit GC_PROTO((ptr_t p)); + /* Stubborn objects: */ -void GC_read_changed(); /* Analogous to GC_read_dirty */ -GC_bool GC_page_was_changed(/* h */); /* Analogous to GC_page_was_dirty */ -void GC_clean_changing_list(); /* Collect obsolete changing list entries */ -void GC_stubborn_init(); - +void GC_read_changed GC_PROTO((void)); /* Analogous to GC_read_dirty */ +GC_bool GC_page_was_changed GC_PROTO((struct hblk * h)); + /* Analogous to GC_page_was_dirty */ +void GC_clean_changing_list GC_PROTO((void)); + /* Collect obsolete changing list entries */ +void GC_stubborn_init GC_PROTO((void)); + /* Debugging print routines: */ -void GC_print_block_list(); -void GC_print_hblkfreelist(); -void GC_print_heap_sects(); -void GC_print_static_roots(); -void GC_dump(); +void GC_print_block_list GC_PROTO((void)); +void GC_print_hblkfreelist GC_PROTO((void)); +void GC_print_heap_sects GC_PROTO((void)); +void GC_print_static_roots GC_PROTO((void)); +void GC_dump GC_PROTO((void)); #ifdef KEEP_BACK_PTRS void GC_store_back_pointer(ptr_t source, ptr_t dest); @@ -1829,10 +1801,10 @@ void GC_dump(); GC_API void GC_noop(); # endif -void GC_noop1(/* word arg */); +void GC_noop1 GC_PROTO((word arg)); /* Logging and diagnostic output: */ -GC_API void GC_printf GC_PROTO((char * format, long, long, long, long, long, long)); +GC_API void GC_printf GC_PROTO((GC_CONST char * format, long, long, long, long, long, long)); /* A version of printf that doesn't allocate, */ /* is restricted to long arguments, and */ /* (unfortunately) doesn't use varargs for */ @@ -1851,7 +1823,7 @@ GC_API void GC_printf GC_PROTO((char * format, long, long, long, long, long, lon # define GC_printf6(f,a,b,c,d,e,g) GC_printf(f, (long)a, (long)b, (long)c, \ (long)d, (long)e, (long)g) -void GC_err_printf(/* format, a, b, c, d, e, f */); +GC_API void GC_err_printf GC_PROTO((GC_CONST char * format, long, long, long, long, long, long)); # define GC_err_printf0(f) GC_err_puts(f) # define GC_err_printf1(f,a) GC_err_printf(f, (long)a, 0l, 0l, 0l, 0l, 0l) # define GC_err_printf2(f,a,b) GC_err_printf(f, (long)a, (long)b, 0l, 0l, 0l, 0l) @@ -1867,18 +1839,59 @@ void GC_err_printf(/* format, a, b, c, d, e, f */); (long)e, (long)g) /* Ditto, writes to stderr. */ -void GC_err_puts(/* char *s */); +void GC_err_puts GC_PROTO((GC_CONST char *s)); /* Write s to stderr, don't buffer, don't add */ /* newlines, don't ... */ +#if defined(LINUX) && !defined(SMALL_CONFIG) + void GC_err_write GC_PROTO((GC_CONST char *buf, size_t len)); + /* Write buf to stderr, don't buffer, don't add */ + /* newlines, don't ... */ +#endif + -# ifdef GC_ASSERTIONS +# ifdef GC_ASSERTIONS # define GC_ASSERT(expr) if(!(expr)) {\ GC_err_printf2("Assertion failure: %s:%ld\n", \ __FILE__, (unsigned long)__LINE__); \ ABORT("assertion failure"); } -# else +# else # define GC_ASSERT(expr) -# endif +# endif + +# ifdef PARALLEL_MARK + /* We need additional synchronization facilities from the thread */ + /* support. We believe these are less performance critical */ + /* than the main garbage collector lock; standard pthreads-based */ + /* implementations should be sufficient. */ + + /* The mark lock and condition variable. If the GC lock is also */ + /* acquired, the GC lock must be acquired first. The mark lock is */ + /* used to both protect some variables used by the parallel */ + /* marker, and to protect GC_fl_builder_count, below. */ + /* GC_notify_all_marker() is called when */ + /* the state of the parallel marker changes */ + /* in some significant way (see gc_mark.h for details). The */ + /* latter set of events includes incrementing GC_mark_no. */ + /* GC_notify_all_builder() is called when GC_fl_builder_count */ + /* reaches 0. */ + + extern void GC_acquire_mark_lock(); + extern void GC_release_mark_lock(); + extern void GC_notify_all_marker(); + extern void GC_notify_all_builder(); + extern void GC_wait_marker(); + /* extern void GC_wait_builder(); */ + extern void GC_wait_for_reclaim(); + + extern word GC_fl_builder_count; /* Protected by mark lock. */ + extern word GC_mark_no; /* Protected by mark lock. */ + + extern void GC_help_marker(word my_mark_no); + /* Try to help out parallel marker for mark cycle */ + /* my_mark_no. Returns if the mark cycle finishes or */ + /* was already done, or there was nothing to do for */ + /* some other reason. */ +# endif /* PARALLEL_MARK */ # endif /* GC_PRIVATE_H */ diff --git a/boehm-gc/include/private/gcconfig.h b/boehm-gc/include/private/gcconfig.h index 045617a..cf1b8eb 100644 --- a/boehm-gc/include/private/gcconfig.h +++ b/boehm-gc/include/private/gcconfig.h @@ -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) 1996 by Silicon Graphics. All rights reserved. + * Copyright (c) 2000 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. @@ -27,6 +28,11 @@ # define LINUX # endif +/* And one for NetBSD: */ +# if defined(__NetBSD__) +# define NETBSD +# endif + /* Determine the machine type: */ # if defined(sun) && defined(mc68000) # define M68K @@ -50,12 +56,14 @@ # endif # if defined(__NetBSD__) && defined(m68k) # define M68K -# define NETBSD # define mach_type_known # endif -# if defined(__NetBSD__) && defined(arm32) +# if defined(__NetBSD__) && defined(__powerpc__) +# define POWERPC +# define mach_type_known +# endif +# if defined(__NetBSD__) && defined(__arm32__) # define ARM32 -# define NETBSD # define mach_type_known # endif # if defined(vax) @@ -81,14 +89,17 @@ # endif # endif # endif /* !LINUX */ +# if defined(__NetBSD__) && defined(__MIPSEL__) +# undef ULTRIX +# endif # define mach_type_known # endif -# if defined(sequent) && defined(i386) +# if defined(sequent) && (defined(i386) || defined(__i386__)) # define I386 # define SEQUENT # define mach_type_known # endif -# if defined(sun) && defined(i386) +# if defined(sun) && (defined(i386) || defined(__i386__)) # define I386 # define SUNOS5 # define mach_type_known @@ -114,7 +125,7 @@ # define mach_type_known # endif # if defined(sparc) && defined(unix) && !defined(sun) && !defined(linux) \ - && !defined(__OpenBSD__) + && !defined(__OpenBSD__) && !(__NetBSD__) # define SPARC # define DRSNX # define mach_type_known @@ -123,6 +134,10 @@ # define RS6000 # define mach_type_known # endif +# if defined(__NetBSD__) && defined(__sparc__) +# define SPARC +# define mach_type_known +# endif # if defined(_M_XENIX) && defined(_M_SYSV) && defined(_M_I386) /* The above test may need refinement */ # define I386 @@ -146,6 +161,11 @@ # endif # define mach_type_known # endif +# if defined(__BEOS__) && defined(_X86_) +# define I386 +# define BEOS +# define mach_type_known +# endif # if defined(LINUX) && (defined(i386) || defined(__i386__)) # define I386 # define mach_type_known @@ -166,13 +186,17 @@ # define SPARC # define mach_type_known # endif -# if defined(LINUX) && defined(arm) +# if defined(LINUX) && defined(__arm__) # define ARM32 # define mach_type_known # endif +# if defined(LINUX) && defined(__sh__) +# define SH +# define mach_type_known +# endif # if defined(__alpha) || defined(__alpha__) # define ALPHA -# if !defined(LINUX) +# if !defined(LINUX) && !defined(NETBSD) # define OSF1 /* a.k.a Digital Unix */ # endif # define mach_type_known @@ -194,37 +218,42 @@ # define MACOS # define mach_type_known # endif -# if defined(macosx) +# if defined(macosx) || \ + defined(__APPLE__) && defined(__MACH__) && defined(__ppc__) # define MACOSX # define POWERPC # define mach_type_known # endif +# if defined(__APPLE__) && defined(__MACH__) && defined(__i386__) +# define MACOSX +# define I386 + --> Not really supported, but at least we recognize it. +# endif # if defined(NeXT) && defined(mc68000) # define M68K # define NEXT # define mach_type_known # endif -# if defined(NeXT) && defined(i386) +# if defined(NeXT) && (defined(i386) || defined(__i386__)) # define I386 # define NEXT # define mach_type_known # endif -# if defined(__OpenBSD__) && defined(i386) +# if defined(__OpenBSD__) && (defined(i386) || defined(__i386__)) # define I386 # define OPENBSD # define mach_type_known # endif -# if defined(__FreeBSD__) && defined(i386) +# if defined(__FreeBSD__) && (defined(i386) || defined(__i386__)) # define I386 # define FREEBSD # define mach_type_known # endif -# if defined(__NetBSD__) && defined(i386) +# if defined(__NetBSD__) && (defined(i386) || defined(__i386__)) # define I386 -# define NETBSD # define mach_type_known # endif -# if defined(bsdi) && defined(i386) +# if defined(bsdi) && (defined(i386) || defined(__i386__)) # define I386 # define BSDI # define mach_type_known @@ -244,11 +273,26 @@ /* DGUX defined */ # define mach_type_known # endif -# if (defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \ - || defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__) -# define I386 -# define MSWIN32 /* or Win32s */ +# if defined(_WIN32_WCE) + /* SH3, SH4, MIPS already defined for corresponding architectures */ +# if defined(SH3) || defined(SH4) +# define SH +# endif +# if defined(x86) +# define I386 +# endif +# if defined(ARM) +# define ARM32 +# endif +# define MSWINCE # define mach_type_known +# else +# if (defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \ + || defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define I386 +# define MSWIN32 /* or Win32s */ +# define mach_type_known +# endif # endif # if defined(__DJGPP__) # define I386 @@ -281,6 +325,11 @@ # define PJ # define mach_type_known # endif +# if defined(__embedded__) && defined(PPC) +# define POWERPC +# define NOSYS +# define mach_type_known +# endif /* Ivan Demakov */ # if defined(__WATCOMC__) && defined(__386__) # define I386 @@ -297,6 +346,10 @@ # endif # define mach_type_known # endif +# if defined(__s390__) && defined(LINUX) +# define S370 +# define mach_type_known +# endif /* Feel free to add more clauses here */ @@ -325,9 +378,9 @@ /* RS6000 ==> IBM RS/6000 AIX3.X */ /* RT ==> IBM PC/RT */ /* HP_PA ==> HP9000/700 & /800 */ - /* HP/UX */ - /* SPARC ==> SPARC under SunOS */ - /* (SUNOS4, SUNOS5, */ + /* HP/UX, LINUX */ + /* SPARC ==> SPARC v7/v8/v9 */ + /* (SUNOS4, SUNOS5, LINUX, */ /* DRSNX variants) */ /* ALPHA ==> DEC Alpha */ /* (OSF1 and LINUX variants) */ @@ -335,9 +388,12 @@ /* (CX_UX and DGUX) */ /* S370 ==> 370-like machine */ /* running Amdahl UTS4 */ + /* or a 390 running LINUX */ /* ARM32 ==> Intel StrongARM */ /* IA64 ==> Intel IA64 */ /* (e.g. Itanium) */ + /* SH ==> Hitachi SuperH */ + /* (LINUX & MSWINCE) */ /* @@ -389,7 +445,9 @@ * Gustavo Rodriguez-Rivera points out that on most (all?) Unix machines, * the value of environ is a pointer that can serve as STACKBOTTOM. * I expect that HEURISTIC2 can be replaced by this approach, which - * interferes far less with debugging. + * interferes far less with debugging. However it has the disadvantage + * that it's confused by a putenv call before the collector is initialized. + * This could be dealt with by intercepting putenv ... * * If no expression for STACKBOTTOM can be found, and neither of the above * heuristics are usable, the collector can still be used with all of the above @@ -462,8 +520,12 @@ # define MPROTECT_VDB # ifdef __ELF__ # define DYNAMIC_LOADING - extern char **__environ; -# define DATASTART ((ptr_t)(&__environ)) +# include +# if defined(__GLIBC__)&& __GLIBC__>=2 +# define LINUX_DATA_START +# else /* !GLIBC2 */ + extern char **__environ; +# define DATASTART ((ptr_t)(&__environ)) /* hideous kludge: __environ is the first */ /* word in crt0.o, and delimits the start */ /* of the data segment, no matter which */ @@ -472,6 +534,7 @@ /* would include .rodata, which may */ /* contain large read-only data tables */ /* that we'd rather not scan. */ +# endif /* !GLIBC2 */ extern int _end; # define DATAEND (&_end) # else @@ -567,11 +630,34 @@ # define DATAEND (&_end) # endif # ifdef MACOSX + /* There are reasons to suspect this may not be reliable. */ # define ALIGNMENT 4 # define OS_TYPE "MACOSX" # define DATASTART ((ptr_t) get_etext()) # define STACKBOTTOM ((ptr_t) 0xc0000000) # define DATAEND /* not needed */ +# define MPROTECT_VDB +# include +# define GETPAGESIZE() getpagesize() +# endif +# ifdef NETBSD +# define ALIGNMENT 4 +# define OS_TYPE "NETBSD" +# define HEURISTIC2 + extern char etext; +# define DATASTART GC_data_start +# define DYNAMIC_LOADING +# endif +# ifdef NOSYS +# define ALIGNMENT 4 +# define OS_TYPE "NOSYS" + extern void __end, __dso_handle; +# define DATASTART (&__dso_handle) /* OK, that's ugly. */ +# define DATAEND (&__end) + /* Stack starts at 0xE0000000 for the simulator. */ +# undef STACK_GRAN +# define STACK_GRAN 0x10000000 +# define HEURISTIC1 # endif # endif @@ -600,9 +686,12 @@ # ifdef SPARC # define MACH_TYPE "SPARC" -# define ALIGNMENT 4 /* Required by hardware */ +# if defined(__arch64__) || defined(__sparcv9) +# define ALIGNMENT 8 +# else +# define ALIGNMENT 4 /* Required by hardware */ +# endif # define ALIGN_DOUBLE - extern int etext; # ifdef SUNOS5 # define OS_TYPE "SUNOS5" extern int _etext; @@ -619,10 +708,18 @@ # define HEAP_START DATAEND # endif # define PROC_VDB -/* HEURISTIC1 reportedly no longer works under 2.7. Thus we */ -/* switched to HEURISTIC2, eventhough it creates some debugging */ -/* issues. */ -# define HEURISTIC2 +/* HEURISTIC1 reportedly no longer works under 2.7. */ +/* HEURISTIC2 probably works, but this appears to be preferable. */ +/* Apparently USRSTACK is defined to be USERLIMIT, but in some */ +/* installations that's undefined. We work around this with a */ +/* gross hack: */ +# include +# ifdef USERLIMIT + /* This should work everywhere, but doesn't. */ +# define STACKBOTTOM USRSTACK +# else +# define HEURISTIC2 +# endif # include # define GETPAGESIZE() sysconf(_SC_PAGESIZE) /* getpagesize() appeared to be missing from at least one */ @@ -661,21 +758,40 @@ # ifdef LINUX # define OS_TYPE "LINUX" # ifdef __ELF__ -# define LINUX_DATA_START # define DYNAMIC_LOADING # else - Linux Sparc non elf ? + Linux Sparc/a.out not supported # endif extern int _end; + extern int _etext; # define DATAEND (&_end) # define SVR4 -# define STACKBOTTOM ((ptr_t) 0xf0000000) +# ifdef __arch64__ +# define STACKBOTTOM ((ptr_t) 0x80000000000ULL) +# define DATASTART (ptr_t)GC_SysVGetDataStart(0x100000, &_etext) +# define CPP_WORDSZ 64 +# else +# define STACKBOTTOM ((ptr_t) 0xf0000000) +# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &_etext) +# endif # endif # ifdef OPENBSD # define OS_TYPE "OPENBSD" # define STACKBOTTOM ((ptr_t) 0xf8000000) + extern int etext; # define DATASTART ((ptr_t)(&etext)) # endif +# ifdef NETBSD +# define OS_TYPE "NETBSD" +# define HEURISTIC2 +# ifdef __ELF__ +# define DATASTART GC_data_start +# define DYNAMIC_LOADING +# else + extern char etext; +# define DATASTART ((ptr_t)(&etext)) +# endif +# endif # endif # ifdef I386 @@ -694,12 +810,25 @@ # define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff)) # define STACKBOTTOM ((ptr_t) 0x3ffff000) # endif +# ifdef BEOS +# define OS_TYPE "BEOS" +# include +# define GETPAGESIZE() B_PAGE_SIZE + extern int etext; +# define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff)) +# endif # ifdef SUNOS5 # define OS_TYPE "SUNOS5" extern int etext, _start; extern char * GC_SysVGetDataStart(); # define DATASTART GC_SysVGetDataStart(0x1000, &etext) -# define STACKBOTTOM ((ptr_t)(&_start)) +/* # define STACKBOTTOM ((ptr_t)(&_start)) worked through 2.7, */ +/* but reportedly breaks under 2.8. It appears that the stack */ +/* base is a property of the executable, so this should not break */ +/* old executables. */ +/* HEURISTIC2 probably works, but this appears to be preferable. */ +# include +# define STACKBOTTOM USRSTACK /** At least in Solaris 2.5, PROC_VDB gives wrong values for dirty bits. */ /*# define PROC_VDB*/ # define DYNAMIC_LOADING @@ -791,7 +920,7 @@ # ifdef USE_3DNOW_PREFETCH # define PREFETCH(x) \ __asm__ __volatile__ (" prefetch %0": : "m"(*(char *)(x))) -# define PREFETCH_FOR_WRITE(x) +# define PREFETCH_FOR_WRITE(x) \ __asm__ __volatile__ (" prefetchw %0": : "m"(*(char *)(x))) # endif # endif @@ -823,6 +952,7 @@ /* os_dep.c. OS2 actually has the right */ /* system call! */ # define DATAEND /* not needed */ +# define USE_GENERIC_PUSH_REGS # endif # ifdef MSWIN32 # define OS_TYPE "MSWIN32" @@ -833,6 +963,10 @@ # endif # define DATAEND /* not needed */ # endif +# ifdef MSWINCE +# define OS_TYPE "MSWINCE" +# define DATAEND /* not needed */ +# endif # ifdef DJGPP # define OS_TYPE "DJGPP" # include "stubinfo.h" @@ -851,6 +985,7 @@ # ifdef FREEBSD # define OS_TYPE "FREEBSD" # define MPROTECT_VDB +# define FREEBSD_STACKBOTTOM # endif # ifdef NETBSD # define OS_TYPE "NETBSD" @@ -861,7 +996,7 @@ # ifdef BSDI # define OS_TYPE "BSDI" # endif -# if defined(OPENBSD) || defined(FREEBSD) || defined(NETBSD) \ +# if defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \ || defined(THREE86BSD) || defined(BSDI) # define HEURISTIC2 extern char etext; @@ -960,6 +1095,28 @@ # endif # define DYNAMIC_LOADING # endif +# ifdef MSWINCE +# define OS_TYPE "MSWINCE" +# define ALIGNMENT 4 +# define DATAEND /* not needed */ +# endif +# if defined(NETBSD) + /* This also checked for __MIPSEL__ . Why? NETBSD recognition */ + /* should be handled at the top of the file. */ +# define ALIGNMENT 4 +# define OS_TYPE "NETBSD" +# define HEURISTIC2 +# define USE_GENERIC_PUSH_REGS 1 +# ifdef __ELF__ + extern int etext; +# define DATASTART GC_data_start +# define NEED_FIND_LIMIT +# define DYNAMIC_LOADING +# else +# define DATASTART ((ptr_t) 0x10000000) +# define STACKBOTTOM ((ptr_t) 0x7ffff000) +# endif /* _ELF_ */ +# endif # endif # ifdef RS6000 @@ -973,7 +1130,6 @@ # endif # ifdef HP_PA - /* OS is assumed to be HP/UX */ # define MACH_TYPE "HP_PA" # define OS_TYPE "HPUX" # ifdef __LP64__ @@ -984,9 +1140,25 @@ # define ALIGNMENT 4 # define ALIGN_DOUBLE # endif - extern int __data_start; -# define DATASTART ((ptr_t)(&__data_start)) -# if 0 +# if !defined(GC_HPUX_THREADS) && !defined(HPUX_THREADS) \ + && !defined(GC_LINUX_THREADS) && !defined(LINUX_THREADS) +# ifndef LINUX /* For now. */ +# define MPROTECT_VDB +# endif +# else +# define GENERIC_COMPARE_AND_SWAP + /* No compare-and-swap instruction. Use pthread mutexes */ + /* when we absolutely have to. */ +# ifdef PARALLEL_MARK +# define USE_MARK_BYTES + /* Minimize compare-and-swap usage. */ +# endif +# endif +# define STACK_GROWS_UP +# ifdef HPUX + extern int __data_start; +# define DATASTART ((ptr_t)(&__data_start)) +# if 0 /* The following appears to work for 7xx systems running HP/UX */ /* 9.xx Furthermore, it might result in much faster */ /* collections than HEURISTIC2, which may involve scanning */ @@ -995,39 +1167,66 @@ /* combinations. (Thanks to Raymond X.T. Nijssen for uncovering */ /* this.) */ # define STACKBOTTOM ((ptr_t) 0x7b033000) /* from /etc/conf/h/param.h */ -# else +# else /* Gustavo Rodriguez-Rivera suggested changing HEURISTIC2 */ - /* to this. We'll probably do this on other platforms, too. */ - /* For now I'll use it where I can test it. */ + /* to this. Note that the GC must be initialized before the */ + /* first putenv call. */ extern char ** environ; # define STACKBOTTOM ((ptr_t)environ) -# endif -# define STACK_GROWS_UP -# define DYNAMIC_LOADING -# ifndef HPUX_THREADS -# define MPROTECT_VDB -# endif -# include -# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE) -# endif +# endif +# define DYNAMIC_LOADING +# include +# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE) +# ifndef __GNUC__ +# define PREFETCH(x) { \ + register long addr = (long)(x); \ + (void) _asm ("LDW", 0, 0, addr, 0); \ + } +# endif +# endif /* HPUX */ +# ifdef LINUX +# define OS_TYPE "LINUX" +# define LINUX_STACKBOTTOM +# define DYNAMIC_LOADING +# define LINUX_DATA_START + extern int _end; +# define DATAEND (&_end) +# endif /* LINUX */ +# endif /* HP_PA */ # ifdef ALPHA # define MACH_TYPE "ALPHA" # define ALIGNMENT 8 # define USE_GENERIC_PUSH_REGS - /* Gcc and probably the DEC/Compaq compiler spill pointers to preserved */ - /* fp registers in some cases when the target is a 21264. The assembly */ - /* code doesn't handle that yet, and version dependencies make that a */ - /* bit tricky. Do the easy thing for now. */ + /* Gcc and probably the DEC/Compaq compiler spill pointers to preserved */ + /* fp registers in some cases when the target is a 21264. The assembly */ + /* code doesn't handle that yet, and version dependencies make that a */ + /* bit tricky. Do the easy thing for now. */ +# ifdef NETBSD +# define OS_TYPE "NETBSD" +# define HEURISTIC2 +# define DATASTART GC_data_start +# define ELFCLASS32 32 +# define ELFCLASS64 64 +# define ELF_CLASS ELFCLASS64 +# define CPP_WORDSZ 64 +# define DYNAMIC_LOADING +# endif # ifdef OSF1 # define OS_TYPE "OSF1" # define DATASTART ((ptr_t) 0x140000000) - extern _end; + extern int _end; # define DATAEND ((ptr_t) &_end) -# define HEURISTIC2 + extern char ** environ; + /* round up from the value of environ to the nearest page boundary */ + /* Probably breaks if putenv is called before collector */ + /* initialization. */ +# define STACKBOTTOM ((ptr_t)(((word)(environ) | (getpagesize()-1))+1)) +/* # define HEURISTIC2 */ /* Normally HEURISTIC2 is too conervative, since */ /* the text segment immediately follows the stack. */ /* Hence we give an upper pound. */ + /* This is currently unused, since we disabled HEURISTIC2 */ extern int __start; # define HEURISTIC2_LIMIT ((ptr_t)((word)(&__start) & ~(getpagesize()-1))) # define CPP_WORDSZ 64 @@ -1039,9 +1238,9 @@ # define CPP_WORDSZ 64 # define STACKBOTTOM ((ptr_t) 0x120000000) # ifdef __ELF__ -# define LINUX_DATA_START +# define SEARCH_FOR_DATA_START +# define DATASTART GC_data_start # define DYNAMIC_LOADING - /* This doesn't work if the collector is in a dynamic library. */ # else # define DATASTART ((ptr_t) 0x140000000) # endif @@ -1059,39 +1258,46 @@ /* Requires 16 byte alignment for malloc */ # define ALIGNMENT 8 # define USE_GENERIC_PUSH_REGS - /* We need to get preserved registers in addition to register windows. */ - /* That's easiest to do with setjmp. */ + /* We need to get preserved registers in addition to register */ + /* windows. That's easiest to do with setjmp. */ +# ifdef PARALLEL_MARK +# define USE_MARK_BYTES + /* Compare-and-exchange is too expensive to use for */ + /* setting mark bits. */ +# endif # 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) + /* The following works on NUE and older kernels: */ +/* # define STACKBOTTOM ((ptr_t) 0xa000000000000000l) */ + /* This does not work on NUE: */ +# define LINUX_STACKBOTTOM /* 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) -# if 1 -# define SEARCH_FOR_DATA_START -# define DATASTART GC_data_start -# else - extern int data_start; -# define DATASTART ((ptr_t)(&data_start)) -# endif + /* backing store. This is computed in */ + /* GC_linux_register_stack_base based on the following */ + /* constants: */ +# define BACKING_STORE_ALIGNMENT 0x100000 +# define BACKING_STORE_DISPLACEMENT 0x80000000 + extern char * GC_register_stackbottom; +# define BACKING_STORE_BASE ((ptr_t)GC_register_stackbottom) +# define SEARCH_FOR_DATA_START +# define DATASTART GC_data_start # define DYNAMIC_LOADING # define MPROTECT_VDB /* Requires Linux 2.3.47 or later. */ extern int _end; # define DATAEND (&_end) -# define PREFETCH(x) \ - __asm__ (" lfetch [%0]": : "r"((void *)(x))) -# define PREFETCH_FOR_WRITE(x) \ - __asm__ (" lfetch.excl [%0]": : "r"((void *)(x))) -# define CLEAR_DOUBLE(x) \ - __asm__ (" stf.spill [%0]=f0": : "r"((void *)(x))) +# ifdef __GNUC__ +# define PREFETCH(x) \ + __asm__ (" lfetch [%0]": : "r"((void *)(x))) +# define PREFETCH_FOR_WRITE(x) \ + __asm__ (" lfetch.excl [%0]": : "r"((void *)(x))) +# define CLEAR_DOUBLE(x) \ + __asm__ (" stf.spill [%0]=f0": : "r"((void *)(x))) +# endif # endif # endif @@ -1114,15 +1320,25 @@ # ifdef S370 # define MACH_TYPE "S370" -# define OS_TYPE "UTS4" # define ALIGNMENT 4 /* Required by hardware */ - extern int etext; +# define USE_GENERIC_PUSH_REGS +# ifdef UTS4 +# define OS_TYPE "UTS4" + extern int etext; extern int _etext; extern int _end; extern char * GC_SysVGetDataStart(); # define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &_etext) # define DATAEND (&_end) # define HEURISTIC2 +# endif +# ifdef LINUX +# define OS_TYPE "LINUX" +# define HEURISTIC1 +# define DYNAMIC_LOADING + extern int __data_start; +# define DATASTART ((ptr_t)(&__data_start)) +# endif # endif # if defined(PJ) @@ -1173,8 +1389,37 @@ # define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff)) # endif # endif +# ifdef MSWINCE +# define OS_TYPE "MSWINCE" +# define DATAEND /* not needed */ +# endif #endif +# ifdef SH +# define MACH_TYPE "SH" +# define ALIGNMENT 4 +# ifdef MSWINCE +# define OS_TYPE "MSWINCE" +# define DATAEND /* not needed */ +# endif +# ifdef LINUX +# define OS_TYPE "LINUX" +# define STACKBOTTOM ((ptr_t) 0x7c000000) +# define USE_GENERIC_PUSH_REGS +# define DYNAMIC_LOADING +# define LINUX_DATA_START + extern int _end; +# define DATAEND (&_end) +# endif +# endif + +# ifdef SH4 +# define MACH_TYPE "SH4" +# define OS_TYPE "MSWINCE" +# define ALIGNMENT 4 +# define DATAEND /* not needed */ +# endif + #ifdef LINUX_DATA_START /* Some Linux distributions arrange to define __data_start. Some */ /* define data_start as a weak symbol. The latter is technically */ @@ -1188,6 +1433,14 @@ # define DATASTART ((ptr_t)(&__data_start != 0? &__data_start : &data_start)) #endif +#if defined(LINUX) && defined(REDIRECT_MALLOC) + /* Rld appears to allocate some memory with its own allocator, and */ + /* some through malloc, which might be redirected. To make this */ + /* work with collectable memory, we have to scan memory allocated */ + /* by rld's internal malloc. */ +# define USE_PROC_FOR_LIBRARIES +#endif + # ifndef STACK_GROWS_UP # define STACK_GROWS_DOWN # endif @@ -1234,6 +1487,12 @@ # define SUNOS5SIGS # endif +# if defined(SVR4) || defined(LINUX) || defined(IRIX) || defined(HPUX) \ + || defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \ + || defined(BSD) || defined(AIX) || defined(MACOSX) || defined(OSF1) +# define UNIX_LIKE /* Basic Unix-like system calls work. */ +# endif + # if CPP_WORDSZ != 32 && CPP_WORDSZ != 64 -> bad word size # endif @@ -1264,6 +1523,10 @@ # undef MPROTECT_VDB /* Can't deal with address space holes. */ # endif +# ifdef PARALLEL_MARK +# undef MPROTECT_VDB /* For now. */ +# endif + # if !defined(PCR_VDB) && !defined(PROC_VDB) && !defined(MPROTECT_VDB) # define DEFAULT_VDB # endif @@ -1288,15 +1551,38 @@ ((word*)x)[1] = 0; # endif /* CLEAR_DOUBLE */ +/* Internally to the collector we test only the XXX_THREADS macros */ +/* not the GC_XXX_THREADS versions. Here we make sure the latter */ +/* are treated as equivalent. */ +#if defined(GC_SOLARIS_THREADS) && !defined(_SOLARIS_THREADS) +# define _SOLARIS_THREADS +#endif +#if defined(GC_SOLARIS_THREADS) && !defined(_SOLARIS_PTHREADS) +# define _SOLARIS_PTHREADS +#endif +#if defined(GC_IRIX_THREADS) && !defined(IRIX_THREADS) +# define IRIX_THREADS +#endif +#if defined(GC_LINUX_THREADS) && !defined(LINUX_THREADS) +# define LINUX_THREADS +#endif +#if defined(GC_WIN32_THREADS) && !defined(WIN32_THREADS) +# define WIN32_THREADS +#endif +#if defined(GC_HPUX_THREADS) && !defined(HPUX_THREADS) +# define HPUX_THREADS +#endif +#if defined(GC_OSF1_THREADS) && !defined(OSF1_THREADS) +# define OSF1_THREADS +#endif + +/* Internally we use SOLARIS_THREADS to test for either old or pthreads. */ # if defined(_SOLARIS_PTHREADS) && !defined(SOLARIS_THREADS) # define SOLARIS_THREADS # endif # if defined(IRIX_THREADS) && !defined(IRIX5) --> inconsistent configuration # endif -# if defined(IRIX_JDK_THREADS) && !defined(IRIX5) ---> inconsistent configuration -# endif # if defined(LINUX_THREADS) && !defined(LINUX) --> inconsistent configuration # endif @@ -1309,16 +1595,26 @@ # if defined(PCR) || defined(SRC_M3) || \ defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || \ defined(IRIX_THREADS) || defined(LINUX_THREADS) || \ - defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS) + defined(HPUX_THREADS) || defined(OSF1_THREADS) # define THREADS # endif -# if defined(HP_PA) || defined(M88K) || defined(POWERPC) \ - || (defined(I386) && defined(OS2)) || defined(UTS4) || defined(LINT) - /* Use setjmp based hack to mark from callee-save registers. */ +# if defined(HP_PA) || defined(M88K) || defined(POWERPC) && !defined(MACOSX) \ + || defined(LINT) || defined(MSWINCE) \ + || (defined(I386) && defined(__LCC__)) + /* Use setjmp based hack to mark from callee-save registers. */ + /* The define should move to the individual platform */ + /* descriptions. */ # define USE_GENERIC_PUSH_REGS # endif -# if defined(SPARC) && !defined(LINUX) +# if defined(I386) && defined(LINUX) + /* SAVE_CALL_CHAIN is supported if the code is compiled to save */ + /* frame pointers by default, i.e. no -fomit-frame-pointer flag. */ +# ifdef SAVE_CALL_COUNT +# define SAVE_CALL_CHAIN +# endif +# endif +# if defined(SPARC) # define SAVE_CALL_CHAIN # define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */ /* include assembly code to do it well. */