From 5c4dc10837d7f66311a5da622e054ea168483a5c Mon Sep 17 00:00:00 2001 From: Bryce McKinlay Date: Thu, 12 Aug 2004 22:14:23 +0100 Subject: [PATCH] Initial revision From-SVN: r85897 --- boehm-gc/NT_STATIC_THREADS_MAKEFILE | 60 +++++++++ boehm-gc/doc/simple_example.html | 202 ++++++++++++++++++++++++++++ boehm-gc/tests/middle.c | 25 ++++ 3 files changed, 287 insertions(+) create mode 100644 boehm-gc/NT_STATIC_THREADS_MAKEFILE create mode 100644 boehm-gc/doc/simple_example.html create mode 100644 boehm-gc/tests/middle.c diff --git a/boehm-gc/NT_STATIC_THREADS_MAKEFILE b/boehm-gc/NT_STATIC_THREADS_MAKEFILE new file mode 100644 index 00000000000..a7582af620b --- /dev/null +++ b/boehm-gc/NT_STATIC_THREADS_MAKEFILE @@ -0,0 +1,60 @@ +# Makefile for Windows NT. Assumes Microsoft compiler. +# DLLs are included in the root set under NT, but not under win32S. +# Use "nmake nodebug=1 all" for optimized versions of library, gctest and editor. + +MY_CPU=X86 +CPU=$(MY_CPU) +!include + +OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj malloc.obj stubborn.obj dyn_load.obj typd_mlc.obj ptr_chck.obj gc_cpp.obj mallocx.obj win32_threads.obj + +all: gctest.exe cord\de.exe test_cpp.exe + +.c.obj: + $(cc) $(cdebug) $(cflags) $(cvars) -Iinclude -DSILENT -DALL_INTERIOR_POINTERS -D__STDC__ -DGC_NOT_DLL -DGC_WIN32_THREADS $*.c /Fo$*.obj + +.cpp.obj: + $(cc) $(cdebug) $(cflags) $(cvars) -Iinclude -DSILENT -DALL_INTERIOR_POINTERS -DGC_NOT_DLL $*.CPP -DGC_WIN32_THREADS /Fo$*.obj + +$(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h + +gc.lib: $(OBJS) + lib /MACHINE:i386 /out:gc.lib $(OBJS) +# The original NT SDK used lib32 instead of lib + +gctest.exe: tests\test.obj gc.lib +# The following works for win32 debugging. For win32s debugging use debugtype:coff +# and add mapsympe line. +# This produces a "GUI" applications that opens no windows and writes to the log file +# "gc.log". This is done to make the result runnable under win32s. + $(link) -debug:full -debugtype:cv $(guiflags) -stack:131072 -out:$*.exe tests\test.obj $(guilibs) gc.lib +# mapsympe -n -o gctest.sym gctest.exe + +cord\de_win.rbj: cord\de_win.res + cvtres /MACHINE:$(MY_CPU) /OUT:cord\de_win.rbj cord\de_win.res + +cord\de.obj cord\de_win.obj: include\cord.h include\private\cord_pos.h cord\de_win.h cord\de_cmds.h + +cord\de_win.res: cord\de_win.rc cord\de_win.h cord\de_cmds.h + $(rc) $(rcvars) -r -fo cord\de_win.res $(cvars) cord\de_win.rc + +# Cord/de is a real win32 gui application. +cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj cord\de_win.rbj gc.lib + $(link) -debug:full -debugtype:cv $(guiflags) -stack:16384 -out:cord\de.exe cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj cord\de_win.rbj gc.lib $(guilibs) + +gc_cpp.obj: include\gc_cpp.h include\gc.h + +gc_cpp.cpp: gc_cpp.cc + copy gc_cpp.cc gc_cpp.cpp + +test_cpp.cpp: tests\test_cpp.cc + copy tests\test_cpp.cc test_cpp.cpp + +# This generates the C++ test executable. The executable expects +# a single numeric argument, which is the number of iterations. +# The output appears in the file "gc.log". +test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib + $(link) -debug:full -debugtype:cv $(guiflags) -stack:16384 -out:test_cpp.exe test_cpp.obj gc.lib $(guilibs) + + + diff --git a/boehm-gc/doc/simple_example.html b/boehm-gc/doc/simple_example.html new file mode 100644 index 00000000000..0bc0953ef03 --- /dev/null +++ b/boehm-gc/doc/simple_example.html @@ -0,0 +1,202 @@ + + +Using the Garbage Collector: A simple example + + +

Using the Garbage Collector: A simple example

+The following consists of step-by-step instructions for building and +using the collector. We'll assume a Linux/gcc platform and +a single-threaded application. The green +text contains information about other platforms or scenarios. +It can be skipped, especially on first reading. +

Building the collector

+If you haven't already so, unpack the collector and enter +the newly created directory with +
+tar xvfz gc.tar.gz
+cd gc
+
+

+You can configure, build, and install the collector in a private +directory, say /home/xyz/gc, with the following commands: +

+./configure --prefix=/home/xyz/gc --disable-threads
+make
+make check
+make install
+
+Here the "make check" command is optional, but highly recommended. +It runs a basic correctness test which usually takes well under a minute. + +

Other platforms

+On non-Unix, non-Linux platforms, the collector is usually built by copying +the appropriate makefile (see the platform-specific README in doc/README.xxx +in the distribution) to the file "Makefile" (overwriting the copy of +Makefile.direct that was originally there), and then typing "make" +(or "nmake" or ...). This builds the library in the source tree. You may +want to move it and the files in the include directory to a more convenient +place. +

+If you use a makefile that does not require running a configure script, +you should first look at the makefile, and adjust any options that are +documented there. +

+If your platform provides a "make" utility, that is generally preferred +to platform- and compiler- dependent "project" files. (At least that is the +strong preference of the would-be maintainer of those project files.) +

Threads

+If you need thread support, configure the collector with +
+--enable-threads=posix --enable-thread-local-alloc --enable-parallel-mark
+
+instead of +--disable-threads +If your target is a real old-fashioned uniprocessor (no "hyperthreading", +etc.) you will want to omit --enable-parallel-mark. +

C++

+You will need to include the C++ support, which unfortunately tends to +be among the least portable parts of the collector, since it seems +to rely on some corner cases of the language. On Linux, it +suffices to add --enable-cplusplus to the configure options. +
+

Writing the program

+You will need a +
+#include "gc.h"
+
+at the beginning of every file that allocates memory through the +garbage collector. Call GC_MALLOC wherever you would +have call malloc. This initializes memory to zero like +calloc; there is no need to explicitly clear the +result. +

+If you know that an object will not contain pointers to the +garbage-collected heap, and you don't need it to be initialized, +call GC_MALLOC_ATOMIC instead. +

+A function GC_FREE is provided but need not be called. +For very small objects, your program will probably perform better if +you do not call it, and let the collector do its job. +

+A GC_REALLOC function behaves like the C library realloc. +It allocates uninitialized pointer-free memory if the original +object was allocated that way. +

+The following program loop.c is a trivial example: +

+#include "gc.h"
+#include <assert.h>
+#include <stdio.h>
+
+int main()
+{
+  int i;
+
+  GC_INIT();	/* Optional on Linux/X86; see below.  */
+  for (i = 0; i < 10000000; ++i)
+   {
+     int **p = (int **) GC_MALLOC(sizeof(int *));
+     int *q = (int *) GC_MALLOC_ATOMIC(sizeof(int));
+     assert(*p == 0);
+     *p = (int *) GC_REALLOC(q, 2 * sizeof(int));
+     if (i % 100000 == 0)
+       printf("Heap size = %d\n", GC_get_heap_size());
+   }
+  return 0;
+}
+
+ +

Interaction with the system malloc

+It is usually best not to mix garbage-collected allocation with the system +malloc-free. If you do, you need to be careful not to store +pointers to the garbage-collected heap in memory allocated with the system +malloc. +

Other Platforms

+On some other platforms it is necessary to call GC_INIT() from the main program, +which is presumed to be part of the main executable, not a dynamic library. +This can never hurt, and is thus generally good practice. + +

Threads

+For a multithreaded program some more rules apply: +
    +
  • +Files that either allocate through the GC or make thread-related calls +should first define the macro GC_THREADS, and then +include "gc.h". On some platforms this will redefine some +threads primitives, e.g. to let the collector keep track of thread creation. +
  • +To take advantage of fast thread-local allocation, use the following instead +of including gc.h: +
    +#define GC_REDIRECT_TO_LOCAL
    +#include "gc_local_alloc.h"
    +
    +This will cause GC_MALLOC and GC_MALLOC_ATOMIC to keep per-thread allocation +caches, and greatly reduce the number of lock acquisitions during allocation. +
+ +

C++

+In the case of C++, you need to be especially careful not to store pointers +to the garbage-collected heap in areas that are not traced by the collector. +The collector includes some alternate interfaces +to make that easier. + +

Debugging

+Additional debug checks can be performed by defining GC_DEBUG before +including gc.h. Additional options are available if the collector +is also built with --enable-full_debug and all allocations are +performed with GC_DEBUG defined. + +

What if I can't rewrite/recompile my program?

+You may be able to build the collector with --enable-redirect-malloc +and set the LD_PRELOAD environment variable to point to the resulting +library, thus replacing the standard malloc with its garbage-collected +counterpart. This is rather platform dependent. See the +leak detection documentation for some more details. + +
+ +

Compiling and linking

+ +The above application loop.c test program can be compiled and linked +with + +
+cc -I/home/xyz/gc/include loop.c /home/xyz/gc/lib/libgc.a -o loop
+
+ +The -I option directs the compiler to the right include +directory. In this case, we list the static library +directly on the compile line; the dynamic library could have been +used instead, provided we arranged for the dynamic loader to find +it, e.g. by setting LD_LIBRARY_PATH. + + + +

Threads

+ +On pthread platforms, you will of course also have to link with +-lpthread, +and compile with any thread-safety options required by your compiler. +On some platforms, you may also need to link with -ldl +or -lrt. +Looking at threadlibs.c in the GC build directory +should give you the appropriate +list if a plain -lpthread doesn't work. + +
+ +

Running the executable

+ +The executable can of course be run normally, e.g. by typing + +
+./loop
+
+ +The operation of the collector is affected by a number of environment variables. +For example, setting GC_PRINT_STATS produces some +GC statistics on stdout. +See README.environment in the distribution for details. + + diff --git a/boehm-gc/tests/middle.c b/boehm-gc/tests/middle.c new file mode 100644 index 00000000000..5d9360af521 --- /dev/null +++ b/boehm-gc/tests/middle.c @@ -0,0 +1,25 @@ +/* + * Test at the boundary between small and large objects. + * Inspired by a test case from Zoltan Varga. + */ +#include +#include + +int main () +{ + int i; + + GC_all_interior_pointers = 0; + + for (i = 0; i < 20000; ++i) { + GC_malloc_atomic (4096); + GC_malloc (4096); + } + for (i = 0; i < 20000; ++i) { + GC_malloc_atomic (2048); + GC_malloc (2048); + } + printf("Final heap size is %ld\n", GC_get_heap_size()); + return 0; +} + -- 2.30.2