Commit 9c86f251 authored by eg's avatar eg

.

parent b6c3d590
......@@ -1249,10 +1249,10 @@ installdirs-am:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(pkgincludedir)"; do \
test -z "$$dir" || $(mkdir_p) "$$dir"; \
done
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install:
install-exec:
install-data:
uninstall:
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
......
# Makefile for Windows NT. Assumes Microsoft compiler, and a single thread.
# 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 <ntwin32.mak>
# Atomic_ops installation directory. For win32, the source directory
# should do, since we only need the headers.
# We assume this was manually unpacked, since I'm not sure there is
# a Windows standard command line tool to do this.
AO_VERSION=1.1
AO_SRC_DIR=libatomic_ops-$(AO_VERSION)/src
AO_INCLUDE_DIR=$(AO_SRC_DIR)
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 -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -D__STDC__ -DGC_NOT_DLL -DGC_WIN32_THREADS $*.c /Fo$*.obj
.cpp.obj:
$(cc) $(cdebug) $(cflags) $(cvars) -Iinclude -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)
AO_SCR_DIR:
tar xvfz $(AO_SRC_DIR).tar.gz;
#! /bin/sh
set -e
# These version are ok, pre-1.7 is not. Post 1.7 may produce a lot of
# warnings for unrelated projects, so prefer 1.7 for now.
am_version=
for v in 1.7 1.9 1.8; do
if type -p &>/dev/null automake-$v; then
am_version="-$v"
break
fi
done
if [ -z "$am_version" ]; then
case "`automake --version`" in
*\ 0.*|*\ 1.[0-6].*|*\ 1.[0-6]\ *)
echo "$0: Automake-1.7 or later is needed."
exit 2
;;
esac
fi
set -x
libtoolize --automake --force
aclocal$am_version
automake$am_version -ac
autoconf
set +x
echo
echo "Ready to run './configure'."
echo
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: Boehm-Demers-Weiser Conservative Garbage Collector
Description: A garbage collector for C and C++
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -lgc
Cflags: -I${includedir}
This diff is collapsed.
#!/bin/sh
P=`pwd`/libatomic_ops-install
cd libatomic_ops-*[0-9]
./configure --prefix=$P
lib_LTLIBRARIES += libcord.la
libcord_la_SOURCES = \
cord/cordbscs.c \
cord/cordprnt.c \
cord/cordtest.c \
cord/cordxtra.c
EXTRA_DIST += \
cord/cordbscs.c cord/cordtest.c cord/de.c \
cord/cordprnt.c cord/cordxtra.c cord/de_cmds.h \
cord/de_win.h cord/de_win.c cord/de_win.RC cord/de_win.ICO
This diff is collapsed.
Darwin/MacOSX Support - December 16, 2003
=========================================
Important Usage Notes
=====================
GC_init() MUST be called before calling any other GC functions. This
is necessary to properly register segments in dynamic libraries. This
call is required even if you code does not use dynamic libraries as the
dyld code handles registering all data segments.
When your use of the garbage collector is confined to dylibs and you
cannot call GC_init() before your libraries' static initializers have
run and perhaps called GC_malloc(), create an initialization routine
for each library to call GC_init():
#include <gc/gc.h>
extern "C" void my_library_init() { GC_init(); }
Compile this code into a my_library_init.o, and link it into your
dylib. When you link the dylib, pass the -init argument with
_my_library_init (e.g. gcc -dynamiclib -o my_library.dylib a.o b.o c.o
my_library_init.o -init _my_library_init). This causes
my_library_init() to be called before any static initializers, and
will initialize the garbage collector properly.
Note: It doesn't hurt to call GC_init() more than once, so it's best,
if you have an application or set of libraries that all use the
garbage collector, to create an initialization routine for each of
them that calls GC_init(). Better safe than sorry.
The incremental collector is still a bit flaky on darwin. It seems to
work reliably with workarounds for a few possible bugs in place however
these workaround may not work correctly in all cases. There may also
be additional problems that I have not found.
Thread-local GC allocation will not work with threads that are not
created using the GC-provided override of pthread_create(). Threads
created without the GC-provided pthread_create() do not have the
necessary data structures in the GC to store this data.
Implementation Information
==========================
Darwin/MacOSX support is nearly complete. Thread support is reliable on
Darwin 6.x (MacOSX 10.2) and there have been reports of success on older
Darwin versions (MacOSX 10.1). Shared library support had also been
added and the gc can be run from a shared library. There is currently only
support for Darwin/PPC although adding x86 support should be trivial.
Thread support is implemented in terms of mach thread_suspend and
thread_resume calls. These provide a very clean interface to thread
suspension. This implementation doesn't rely on pthread_kill so the
code works on Darwin < 6.0 (MacOSX 10.1). All the code to stop and
start the world is located in darwin_stop_world.c.
Since not all uses of the GC enable clients to override pthread_create()
before threads have been created, the code for stopping the world has
been rewritten to look for threads using Mach kernel calls. Each
thread identified in this way is suspended and resumed as above. In
addition, since Mach kernel threads do not contain pointers to their
stacks, a stack-walking function has been written to find the stack
limits. Given an initial stack pointer (for the current thread, a
pointer to a stack-allocated local variable will do; for a non-active
thread, we grab the value of register 1 (on PowerPC)), it
will walk the PPC Mach-O-ABI compliant stack chain until it reaches the
top of the stack. This appears to work correctly for GCC-compiled C,
C++, Objective-C, and Objective-C++ code, as well as for Java
programs that use JNI. If you run code that does not follow the stack
layout or stack pointer conventions laid out in the PPC Mach-O ABI,
then this will likely crash the garbage collector.
The original incremental collector support unfortunatelly no longer works
on recent Darwin versions. It also relied on some undocumented kernel
structures. Mach, however, does have a very clean interface to exception
handing. The current implementation uses Mach's exception handling.
Much thanks goes to Andrew Stone, Dietmar Planitzer, Andrew Begel,
Jeff Sturm, and Jesse Rosenstock for all their work on the
Darwin/OS X port.
-Brian Alliet
brian@brianweb.net
Older Information (Most of this no longer applies to the current code)
======================================================================
While the GC should work on MacOS X Server, MacOS X and Darwin, I only tested
it on MacOS X Server.
I've added a PPC assembly version of GC_push_regs(), thus the setjmp() hack is
no longer necessary. Incremental collection is supported via mprotect/signal.
The current solution isn't really optimal because the signal handler must decode
the faulting PPC machine instruction in order to find the correct heap address.
Further, it must poke around in the register state which the kernel saved away
in some obscure register state structure before it calls the signal handler -
needless to say the layout of this structure is no where documented.
Threads and dynamic libraries are not yet supported (adding dynamic library
support via the low-level dyld API shouldn't be that hard).
The original MacOS X port was brought to you by Andrew Stone.
June, 1 2000
Dietmar Planitzer
dave.pl@ping.at
Note from Andrew Begel:
One more fix to enable gc.a to link successfully into a shared library for
MacOS X. You have to add -fno-common to the CFLAGS in the Makefile. MacOSX
disallows common symbols in anything that eventually finds its way into a
shared library. (I don't completely understand why, but -fno-common seems to
work and doesn't mess up the garbage collector's functionality).
Feb 26, 2003
Jeff Sturm and Jesse Rosenstock provided a patch that adds thread support.
GC_MACOSX_THREADS should be defined in the build and in clients. Real
dynamic library support is still missing, i.e. dynamic library data segments
are still not scanned. Code that stores pointers to the garbage collected
heap in statically allocated variables should not reside in a dynamic
library. This still doesn't appear to be 100% reliable.
Mar 10, 2003
Brian Alliet contributed dynamic library support for MacOSX. It could also
use more testing.
#
#
# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
#
# Permission is hereby granted to use or copy this program
# for any purpose, provided the above notices are retained on all copies.
# Permission to modify the code and to distribute modified code is granted,
# provided the above notices are retained, and a notice that the code was
# modified is included with the above copyright notice.
#
# Modified by: Grzegorz Jakacki <jakacki at acm dot org>
# Modified by: Petter Urkedal <petter.urkedal@nordita.dk>
## Process this file with automake to produce Makefile.in.
# installed documentation
#
dist_pkgdata_DATA = \
doc/barrett_diagram \
doc/debugging.html \
doc/gc.man \
doc/gcdescr.html \
doc/README \
doc/README.amiga \
doc/README.arm.cross \
doc/README.autoconf \
doc/README.changes \
doc/README.contributors \
doc/README.cords \
doc/README.DGUX386 \
doc/README.dj \
doc/README.environment \
doc/README.ews4800 \
doc/README.hp \
doc/README.linux \
doc/README.Mac \
doc/README.MacOSX \
doc/README.macros \
doc/README.OS2 \
doc/README.rs6000 \
doc/README.sgi \
doc/README.solaris2 \
doc/README.uts \
doc/README.win32 \
doc/overview.html \
doc/tree.html \
doc/leak.html \
doc/gcinterface.html \
doc/scale.html \
doc/README.darwin \
doc/simple_example.html \
doc/porting.html
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<HTML>
<HEAD>
<TITLE>Using the Garbage Collector: A simple example</title>
</head>
<BODY>
<H1>Using the Garbage Collector: A simple example</h1>
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. <FONT COLOR=green>The green
text contains information about other platforms or scenarios.
It can be skipped, especially on first reading</font>.
<H2>Building the collector</h2>
If you haven't already so, unpack the collector and enter
the newly created directory with
<PRE>
tar xvfz gc<version>.tar.gz
cd gc<version>
</pre>
<P>
You can configure, build, and install the collector in a private
directory, say /home/xyz/gc, with the following commands:
<PRE>
./configure --prefix=/home/xyz/gc --disable-threads
make
make check
make install
</pre>
Here the "<TT>make check</tt>" command is optional, but highly recommended.
It runs a basic correctness test which usually takes well under a minute.
<FONT COLOR=green>
<H3>Other platforms</h3>
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.
<P>
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.
<P>
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.)
<H3>Threads</h3>
If you need thread support, configure the collector with
<PRE>
--enable-threads=posix --enable-thread-local-alloc --enable-parallel-mark
</pre>
instead of
<TT>--disable-threads</tt>
If your target is a real old-fashioned uniprocessor (no "hyperthreading",
etc.) you will want to omit <TT>--enable-parallel-mark</tt>.
<H3>C++</h3>
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 <TT>--enable-cplusplus</tt> to the configure options.
</font>
<H2>Writing the program</h2>
You will need a
<PRE>
#include "gc.h"
</pre>
at the beginning of every file that allocates memory through the
garbage collector. Call <TT>GC_MALLOC</tt> wherever you would
have call <TT>malloc</tt>. This initializes memory to zero like
<TT>calloc</tt>; there is no need to explicitly clear the
result.
<P>
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 <TT>GC_MALLOC_ATOMIC</tt> instead.
<P>
A function <TT>GC_FREE</tt> 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.
<P>
A <TT>GC_REALLOC</tt> function behaves like the C library <TT>realloc</tt>.
It allocates uninitialized pointer-free memory if the original
object was allocated that way.
<P>
The following program <TT>loop.c</tt> is a trivial example:
<PRE>
#include "gc.h"
#include &lt;assert.h&gt;
#include &lt;stdio.h&gt;
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;
}
</pre>
<FONT COLOR=green>
<H3>Interaction with the system malloc</h3>
It is usually best not to mix garbage-collected allocation with the system
<TT>malloc-free</tt>. If you do, you need to be careful not to store
pointers to the garbage-collected heap in memory allocated with the system
<TT>malloc</tt>.
<H3>Other Platforms</h3>
On some other platforms it is necessary to call <TT>GC_INIT()</tt> 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.
<H3>Threads</h3>
For a multithreaded program some more rules apply:
<UL>
<LI>
Files that either allocate through the GC <I>or make thread-related calls</i>
should first define the macro <TT>GC_THREADS</tt>, and then
include <TT>"gc.h"</tt>. On some platforms this will redefine some
threads primitives, e.g. to let the collector keep track of thread creation.
<LI>
To take advantage of fast thread-local allocation, use the following instead
of including <TT>gc.h</tt>:
<PRE>
#define GC_REDIRECT_TO_LOCAL
#include "gc_local_alloc.h"
</pre>
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.
</ul>
<H3>C++</h3>
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 <A HREF="gcinterface.html">alternate interfaces</a>
to make that easier.
<H3>Debugging</h3>
Additional debug checks can be performed by defining <TT>GC_DEBUG</tt> before
including <TT>gc.h</tt>. Additional options are available if the collector
is also built with <TT>--enable-full_debug</tt> and all allocations are
performed with <TT>GC_DEBUG</tt> defined.
<H3>What if I can't rewrite/recompile my program?</h3>
You may be able to build the collector with <TT>--enable-redirect-malloc</tt>
and set the <TT>LD_PRELOAD</tt> environment variable to point to the resulting
library, thus replacing the standard <TT>malloc</tt> with its garbage-collected
counterpart. This is rather platform dependent. See the
<A HREF="leak.html">leak detection documentation</a> for some more details.
</font>
<H2>Compiling and linking</h2>
The above application <TT>loop.c</tt> test program can be compiled and linked
with
<PRE>
cc -I/home/xyz/gc/include loop.c /home/xyz/gc/lib/libgc.a -o loop
</pre>
The <TT>-I</tt> 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 <TT>LD_LIBRARY_PATH</tt>.
<FONT COLOR=green>
<H3>Threads</h3>
On pthread platforms, you will of course also have to link with
<TT>-lpthread</tt>,
and compile with any thread-safety options required by your compiler.
On some platforms, you may also need to link with <TT>-ldl</tt>
or <TT>-lrt</tt>.
Looking at threadlibs.c in the GC build directory
should give you the appropriate
list if a plain <TT>-lpthread</tt> doesn't work.
</font>
<H2>Running the executable</h2>
The executable can of course be run normally, e.g. by typing
<PRE>
./loop
</pre>
The operation of the collector is affected by a number of environment variables.
For example, setting <TT>GC_PRINT_STATS</tt> produces some
GC statistics on stdout.
See <TT>README.environment</tt> in the distribution for details.
</body>
</html>
/*
* This should never be included directly. It is included only from gc.h.
* We separate it only to make gc.h more suitable as documentation.
*
* Some tests for old macros. These violate our namespace rules and will
* disappear shortly. Use the GC_ names.
*/
#if defined(SOLARIS_THREADS) || defined(_SOLARIS_THREADS) \
|| defined(_SOLARIS_PTHREADS) || defined(GC_SOLARIS_PTHREADS)
/* We no longer support old style Solaris threads. */
/* GC_SOLARIS_THREADS now means pthreads. */
# define GC_SOLARIS_THREADS
#endif
#if defined(IRIX_THREADS)
# define GC_IRIX_THREADS
#endif
#if defined(DGUX_THREADS)
# if !defined(GC_DGUX386_THREADS)
# define GC_DGUX386_THREADS
# endif
#endif
#if defined(AIX_THREADS)
# define GC_AIX_THREADS
#endif
#if defined(HPUX_THREADS)
# define GC_HPUX_THREADS
#endif
#if defined(OSF1_THREADS)
# define GC_OSF1_THREADS
#endif
#if defined(LINUX_THREADS)
# define GC_LINUX_THREADS
#endif
#if defined(WIN32_THREADS)
# define GC_WIN32_THREADS
#endif
#if defined(USE_LD_WRAP)
# define GC_USE_LD_WRAP
#endif
#if !defined(_REENTRANT) && (defined(GC_SOLARIS_THREADS) \
|| defined(GC_HPUX_THREADS) \
|| defined(GC_AIX_THREADS) \
|| defined(GC_LINUX_THREADS))
# define _REENTRANT
/* Better late than never. This fails if system headers that */
/* depend on this were previously included. */
#endif
#if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
# define _POSIX4A_DRAFT10_SOURCE 1
#endif
# if defined(GC_SOLARIS_THREADS) || defined(GC_FREEBSD_THREADS) || \
defined(GC_IRIX_THREADS) || defined(GC_LINUX_THREADS) || \
defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || \
defined(GC_DGUX386_THREADS) || defined(GC_DARWIN_THREADS) || \
defined(GC_AIX_THREADS) || \
(defined(GC_WIN32_THREADS) && defined(__CYGWIN32__))
# define GC_PTHREADS
# endif
#if defined(GC_THREADS) && !defined(GC_PTHREADS)
# if defined(__linux__)
# define GC_LINUX_THREADS
# define GC_PTHREADS
# endif
# if !defined(LINUX) && (defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
|| defined(hppa) || defined(__HPPA))
# define GC_HPUX_THREADS
# define GC_PTHREADS
# endif
# if !defined(__linux__) && (defined(__alpha) || defined(__alpha__))
# define GC_OSF1_THREADS
# define GC_PTHREADS
# endif
# if defined(__mips) && !defined(__linux__)
# define GC_IRIX_THREADS
# define GC_PTHREADS
# endif
# if defined(__sparc) && !defined(__linux__) \
|| defined(sun) && (defined(i386) || defined(__i386__))
# define GC_SOLARIS_THREADS
# define GC_PTHREADS
# endif
# if defined(__APPLE__) && defined(__MACH__) && defined(__ppc__)
# define GC_DARWIN_THREADS
# define GC_PTHREADS
# endif
# if !defined(GC_PTHREADS) && defined(__FreeBSD__)
# define GC_FREEBSD_THREADS
# define GC_PTHREADS
# endif
# if defined(DGUX) && (defined(i386) || defined(__i386__))
# define GC_DGUX386_THREADS
# define GC_PTHREADS
# endif
# if defined(_AIX)
# define GC_AIX_THREADS
# define GC_PTHREADS
# endif
#endif /* GC_THREADS */
#if defined(GC_THREADS) && !defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS) \
&& (defined(_WIN32) || defined(_MSC_VER) || defined(__CYGWIN__) \
|| defined(__MINGW32__) || defined(__BORLANDC__) \
|| defined(_WIN32_WCE))
# define GC_WIN32_THREADS
# if defined(__CYGWIN__)
# define GC_PTHREADS
# endif
#endif
# define __GC
# ifndef _WIN32_WCE
# include <stddef.h>
# else /* ! _WIN32_WCE */
/* Yet more kluges for WinCE */
# include <stdlib.h> /* size_t is defined here */
typedef long ptrdiff_t; /* ptrdiff_t is not defined */
# endif
#if defined(_DLL) && !defined(GC_NOT_DLL) && !defined(GC_DLL)
# define GC_DLL
#endif
#if defined(__MINGW32__) && defined(GC_DLL)
# ifdef GC_BUILD
# define GC_API __declspec(dllexport)
# else
# define GC_API __declspec(dllimport)
# endif
#endif
#if (defined(__DMC__) || defined(_MSC_VER)) && defined(GC_DLL)
# ifdef GC_BUILD
# define GC_API extern __declspec(dllexport)
# else
# define GC_API __declspec(dllimport)
# endif
#endif
#if defined(__WATCOMC__) && defined(GC_DLL)
# ifdef GC_BUILD
# define GC_API extern __declspec(dllexport)
# else
# define GC_API extern __declspec(dllimport)
# endif
#endif
#ifndef GC_API
#define GC_API extern
#endif
/*
* Copyright (c) 1999-2005 Hewlett-Packard Development Company, L.P.
*
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
*
* Permission is hereby granted to use or copy this program
* for any purpose, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is granted,
* provided the above notices are retained, and a notice that the code was
* modified is included with the above copyright notice.
*/
#ifndef GC_TINY_FL_H
#define GC_TINY_FL_H
/*
* Constants and data structures for "tiny" free lists.
* These are used for thread-local allocation or in-lined allocators.
* Each global free list also essentially starts with one of these.
* However, global free lists are known to the GC. "Tiny" free lists
* are basically private to the client. Their contents are viewed as
* "in use" and marked accordingly by the core of the GC.
*
* Note that inlined code might know about the layout of these and the constants
* involved. Thus any change here may invalidate clients, and such changes should
* be avoided. Hence we keep this as simple as possible.
*/
/*
* We always set GRANULE_BYTES to twice the length of a pointer.
* This means that all allocation requests are rounded up to the next
* multiple of 16 on 64-bit architectures or 8 on 32-bit architectures.
* This appears to be a reasonable compromise between fragmentation overhead
* and space usage for mark bits (usually mark bytes).
* On many 64-bit architectures some memory references require 16-byte
* alignment, making this necessary anyway.
* For a few 32-bit architecture (e.g. x86), we may also need 16-byte alignment
* for certain memory references. But currently that does not seem to be the
* default for all conventional malloc implementations, so we ignore that
* problem.
* It would always be safe, and often useful, to be able to allocate very
* small objects with smaller alignment. But that would cost us mark bit
* space, so we no longer do so.
*/
#ifndef GC_GRANULE_BYTES
# if defined(__LP64__) || defined (_LP64) || defined(_WIN64) \
|| defined(__s390x__) || defined(__x86_64__) \
|| defined(__alpha__) || defined(__powerpc64__) \
|| defined(__arch64__)
# define GC_GRANULE_BYTES 16
# define GC_GRANULE_WORDS 2
# else
# define GC_GRANULE_BYTES 8
# define GC_GRANULE_WORDS 2
# endif