summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Flatt <mflatt@racket-lang.org>2010-04-01 13:54:56 +0000
committerIvan Maidanski <ivmai@mail.ru>2013-11-03 13:45:37 +0400
commit817cf5cc5d7a85f8a66fea734d39ca55bbd94155 (patch)
treedadd3b6e0de8bccd0629b9525ff3db1195862692
parentd3bbce9b0b00d262c1be5a1389ed202f02dc26b1 (diff)
downloadbdwgc-817cf5cc5d7a85f8a66fea734d39ca55bbd94155.tar.gz
apply patch from Tim Wiess to make the Boehm GC build on OpenBSD
svn: r18712
-rw-r--r--Makefile.in9
-rw-r--r--doc/gc.man44
-rw-r--r--dyn_load.c6
-rw-r--r--include/gc_config_macros.h6
-rw-r--r--include/private/gcconfig.h188
-rw-r--r--include/private/openbsd_stop_world.h12
-rw-r--r--mach_dep.c4
-rw-r--r--misc.c2
-rw-r--r--openbsd_stop_world.c162
-rw-r--r--os_dep.c156
-rw-r--r--pthread_stop_world.c2
-rw-r--r--pthread_support.c13
-rw-r--r--tests/test.c3
-rw-r--r--threadlibs.c3
14 files changed, 560 insertions, 50 deletions
diff --git a/Makefile.in b/Makefile.in
index 04523047..c44038fe 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -345,14 +345,14 @@ OBJS= alloc.@LTO@ reclaim.@LTO@ allchblk.@LTO@ misc.@LTO@ mach_dep.@LTO@ mach_de
headers.@LTO@ mark.@LTO@ obj_map.@LTO@ blacklst.@LTO@ finalize.@LTO@ new_hblk.@LTO@ dbg_mlc.@LTO@ \
malloc.@LTO@ stubborn.@LTO@ checksums.@LTO@ pthread_support.@LTO@ pthread_stop_world.@LTO@ \
darwin_stop_world.@LTO@ typd_mlc.@LTO@ ptr_chck.@LTO@ mallocx.@LTO@ gcj_mlc.@LTO@ specific.@LTO@ \
- gc_dlopen.@LTO@ backgraph.@LTO@ win32_threads.@LTO@ thread_local_alloc.@LTO@
+ gc_dlopen.@LTO@ backgraph.@LTO@ win32_threads.@LTO@ thread_local_alloc.@LTO@ openbsd_stop_world.@LTO@
CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c mach_dep1.c os_dep.c mark_rts.c \
headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c \
new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c \
checksums.c pthread_support.c pthread_stop_world.c darwin_stop_world.c \
typd_mlc.c ptr_chck.c mallocx.c gcj_mlc.c specific.c gc_dlopen.c \
- backgraph.c win32_threads.c thread_local_alloc.c
+ backgraph.c win32_threads.c thread_local_alloc.c openbsd_stop_world.c
CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordtest.c include/cord.h include/ec.h include/private/cord_pos.h cord/de_win.c cord/de_win.h cord/de_cmds.h cord/de_win.ICO cord/de_win.RC
@@ -377,7 +377,7 @@ SRCS= $(CSRCS) mips_sgi_mach_dep.s rs6000_mach_dep.s alpha_mach_dep.S \
include/gc_config_macros.h include/private/pthread_support.h \
include/private/pthread_stop_world.h include/private/darwin_semaphore.h \
include/private/darwin_stop_world.h include/private/thread_local_alloc.h \
- $(CORD_SRCS)
+ include/private/openbsd_stop_world.h $(CORD_SRCS)
DOC_FILES= README.QUICK doc/README.Mac doc/README.MacOSX doc/README.O2 \
doc/README.amiga doc/README.cords doc/debugging.html \
@@ -816,6 +816,9 @@ pthread_stop_world.@LTO@: $(srcdir)/pthread_stop_world.c
darwin_stop_world.@LTO@: $(srcdir)/darwin_stop_world.c
$(CC) $(CFLAGS) -c $(srcdir)/darwin_stop_world.c
+openbsd_stop_world.@LTO@: $(srcdir)/openbsd_stop_world.c
+ $(CC) $(CFLAGS) -c $(srcdir)/openbsd_stop_world.c
+
backgraph.@LTO@: $(srcdir)/backgraph.c
$(CC) $(CFLAGS) -c $(srcdir)/backgraph.c
diff --git a/doc/gc.man b/doc/gc.man
index 2a550c71..558759d3 100644
--- a/doc/gc.man
+++ b/doc/gc.man
@@ -1,4 +1,4 @@
-.TH GC_MALLOC 1L "2 October 2003"
+.TH GC_MALLOC 3 "2 October 2003"
.SH NAME
GC_malloc, GC_malloc_atomic, GC_free, GC_realloc, GC_enable_incremental, GC_register_finalizer, GC_malloc_ignore_off_page, GC_malloc_atomic_ignore_off_page, GC_set_warn_proc \- Garbage collecting malloc replacement
.SH SYNOPSIS
@@ -82,6 +82,48 @@ This may temporarily write protect pages in the heap. See the README file for m
.LP
Other facilities not discussed here include limited facilities to support incremental collection on machines without appropriate VM support, provisions for providing more explicit object layout information to the garbage collector, more direct support for ``weak'' pointers, support for ``abortable'' garbage collections during idle time, etc.
.LP
+.SH "PORT INFORMATION"
+.LP
+In this (OpenBSD package) installation,
+.I gc.h
+and
+.I gc_cpp.h
+will be found in
+.I /usr/local/include ,
+and the libraries in
+.I /usr/local/lib.
+.LP
+These libraries have been compiled as drop-in replacements
+for malloc and free (which is to say, all malloc
+calls will allocate garbage-collectable data).
+There is no need to include "gc.h" in your C files unless you want
+access to the debugging (and other) functions defined there,
+or unless you want to explicitly use
+.I GC_malloc_uncollectable
+for some allocations.
+Just link against them whenever you want either garbage
+collection or leak detection.
+.LP
+The C++ header file, "gc_cpp.h",
+.I is
+necessary for C++ programs, to obtain the appropriate
+definitions of the
+.I new
+and
+.I delete
+operators.
+The comments in both of these header files presently
+provide far better documentation
+for the package than this man page;
+look there for more information.
+.LP
+Both libraries are compiled without (explicit) support
+for the experimental
+.I gc
+extension of
+.I g++.
+This may or may not make a difference.
+.LP
.SH "SEE ALSO"
The README and gc.h files in the distribution. More detailed definitions of the functions exported by the collector are given there. (The above list is not complete.)
.LP
diff --git a/dyn_load.c b/dyn_load.c
index 8f5626ea..5fe133a0 100644
--- a/dyn_load.c
+++ b/dyn_load.c
@@ -85,9 +85,9 @@ static int (*GC_has_static_roots)(const char *, void *, size_t);
#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
(defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \
+ (defined(OPENBSD) && defined(__ELF__)) || \
(defined(NETBSD) && defined(__ELF__)) || defined(HURD)
# include <stddef.h>
-# include <elf.h>
# include <link.h>
#endif
@@ -100,7 +100,7 @@ static int (*GC_has_static_roots)(const char *, void *, size_t);
# else
# define ElfW(type) Elf64_##type
# endif
-# elif defined(NETBSD)
+# elif defined(NETBSD) || defined(OPENBSD)
# if ELFSIZE == 32
# define ElfW(type) Elf32_##type
# else
@@ -468,7 +468,7 @@ GC_bool GC_register_main_static_data()
/* This doesn't necessarily work in all cases, e.g. with preloaded
* dynamic libraries. */
-#if defined(NETBSD)
+#if defined(NETBSD) || defined(OPENBSD)
# include <sys/exec_elf.h>
/* for compatibility with 1.4.x */
# ifndef DT_DEBUG
diff --git a/include/gc_config_macros.h b/include/gc_config_macros.h
index 8d9fe621..d2476b28 100644
--- a/include/gc_config_macros.h
+++ b/include/gc_config_macros.h
@@ -65,7 +65,7 @@
defined(GC_DGUX386_THREADS) || defined(GC_DARWIN_THREADS) || \
defined(GC_AIX_THREADS) || defined(GC_NETBSD_THREADS) || \
(defined(GC_WIN32_THREADS) && defined(__CYGWIN32__)) || \
- defined(GC_GNU_THREADS)
+ defined(GC_GNU_THREADS) || defined(GC_OPENBSD_THREADS)
# define GC_PTHREADS
# endif
@@ -102,6 +102,10 @@
# define GC_DARWIN_THREADS
# define GC_PTHREADS
# endif
+# if !defined(GC_PTHREADS) && defined(__OpenBSD__)
+# define GC_OPENBSD_THREADS
+# define GC_PTHREADS
+# endif
# if !defined(GC_PTHREADS) && (defined(__FreeBSD__) || defined(__DragonFly__))
# define GC_FREEBSD_THREADS
# define GC_PTHREADS
diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h
index 98fe8b5f..c8e60f3c 100644
--- a/include/private/gcconfig.h
+++ b/include/private/gcconfig.h
@@ -64,7 +64,7 @@
/* Determine the machine type: */
# if defined(__arm__) || defined(__thumb__)
# define ARM32
-# if !defined(LINUX) && !defined(NETBSD)
+# if !defined(LINUX) && !defined(NETBSD) && !defined(OPENBSD)
# define NOSYS
# define mach_type_known
# endif
@@ -75,14 +75,18 @@
# if defined(hp9000s300)
# error M68K based HP machines no longer supported.
# endif
-# if defined(OPENBSD) && defined(m68k)
-# define M68K
-# define mach_type_known
-# endif
# if defined(OPENBSD) && defined(__sparc__)
# define SPARC
# define mach_type_known
# endif
+# if defined(OPENBSD) && defined(__arm__)
+# define ARM32
+# define mach_type_known
+# endif
+# if defined(OPENBSD) && defined(__sh__)
+# define SH
+# define mach_type_known
+# endif
# if defined(NETBSD) && (defined(m68k) || defined(__m68k__))
# define M68K
# define mach_type_known
@@ -99,7 +103,7 @@
# define SH
# define mach_type_known
# endif
-# if defined(vax)
+# if defined(vax) || defined(__vax__)
# define VAX
# ifdef ultrix
# define ULTRIX
@@ -117,7 +121,7 @@
# if defined(nec_ews) || defined(_nec_ews)
# define EWS4800
# endif
-# if !defined(LINUX) && !defined(EWS4800) && !defined(NETBSD)
+# if !defined(LINUX) && !defined(EWS4800) && !defined(NETBSD) && !defined(OPENBSD)
# if defined(ultrix) || defined(__ultrix)
# define ULTRIX
# else
@@ -198,7 +202,7 @@
# if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
|| defined(hppa) || defined(__hppa__)
# define HP_PA
-# if !defined(LINUX) && !defined(HPUX)
+# if !defined(LINUX) && !defined(HPUX) && !defined(OPENBSD)
# define HPUX
# endif
# define mach_type_known
@@ -219,6 +223,10 @@
# define I386
# define mach_type_known
# endif
+# if defined(OPENBSD) && defined(__amd64__)
+# define X86_64
+# define mach_type_known
+# endif
# if defined(LINUX) && defined(__x86_64__)
# define X86_64
# define mach_type_known
@@ -290,6 +298,11 @@
# define MACOS
# define mach_type_known
# endif
+# if defined(__OpenBSD__) && (defined(__powerpc__))
+# define POWERPC
+# define OPENBSD
+# define mach_type_known
+# endif
# if defined(macosx) || (defined(__APPLE__) && defined(__MACH__))
# define DARWIN
# if defined(__ppc__) || defined(__ppc64__)
@@ -653,17 +666,6 @@
# ifdef M68K
# define MACH_TYPE "M68K"
# define ALIGNMENT 2
-# ifdef OPENBSD
-# define OS_TYPE "OPENBSD"
-# define HEURISTIC2
-# ifdef __ELF__
-# define DATASTART GC_data_start
-# define DYNAMIC_LOADING
-# else
- extern char etext[];
-# define DATASTART ((ptr_t)(etext))
-# endif
-# endif
# ifdef NETBSD
# define OS_TYPE "NETBSD"
# define HEURISTIC2
@@ -796,6 +798,22 @@
should be looked into some more */
# define NO_PTHREAD_TRYLOCK
# endif
+# ifdef OPENBSD
+# define OS_TYPE "OPENBSD"
+# define ALIGNMENT 4
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 268
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)(__data_start))
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
+# endif
# ifdef FREEBSD
# define ALIGNMENT 4
# define OS_TYPE "FREEBSD"
@@ -963,9 +981,18 @@
# endif
# ifdef OPENBSD
# define OS_TYPE "OPENBSD"
-# define STACKBOTTOM ((ptr_t) 0xf8000000)
- extern int etext[];
-# define DATASTART ((ptr_t)(etext))
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 232
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)(__data_start))
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
# endif
# ifdef NETBSD
# define OS_TYPE "NETBSD"
@@ -1211,6 +1238,18 @@
# endif
# ifdef OPENBSD
# define OS_TYPE "OPENBSD"
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 176
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)(__data_start))
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
# endif
# ifdef FREEBSD
# define OS_TYPE "FREEBSD"
@@ -1246,7 +1285,7 @@
# ifdef BSDI
# define OS_TYPE "BSDI"
# endif
-# if defined(OPENBSD) || defined(NETBSD) \
+# if defined(NETBSD) \
|| defined(THREE86BSD) || defined(BSDI)
# define HEURISTIC2
extern char etext[];
@@ -1416,6 +1455,22 @@
# define STACKBOTTOM ((ptr_t) 0x7ffff000)
# endif /* _ELF_ */
# endif
+# ifdef OPENBSD
+# define OS_TYPE "OPENBSD"
+# define ALIGNMENT 4
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 808
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int _fdata[];
+# define DATASTART ((ptr_t)(_fdata))
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
+# endif
# if defined(NONSTOP)
# define CPP_WORDSZ 32
# define OS_TYPE "NONSTOP"
@@ -1436,7 +1491,7 @@
# define CPP_WORDSZ 32
# define ALIGNMENT 4
# endif
-# if !defined(GC_HPUX_THREADS) && !defined(GC_LINUX_THREADS)
+# if !defined(GC_HPUX_THREADS) && !defined(GC_LINUX_THREADS) && !defined(OPENBSD)
# ifndef LINUX /* For now. */
# define MPROTECT_VDB
# endif
@@ -1485,6 +1540,21 @@
extern int _end[];
# define DATAEND (&_end)
# endif /* LINUX */
+# ifdef OPENBSD
+# define OS_TYPE "OPENBSD"
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 520
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)(__data_start))
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
+# endif
# endif /* HP_PA */
# ifdef ALPHA
@@ -1502,15 +1572,19 @@
# endif
# ifdef OPENBSD
# define OS_TYPE "OPENBSD"
-# define HEURISTIC2
-# ifdef __ELF__ /* since OpenBSD/Alpha 2.9 */
-# define DATASTART GC_data_start
-# define ELFCLASS32 32
-# define ELFCLASS64 64
-# define ELF_CLASS ELFCLASS64
-# else /* ECOFF, until OpenBSD/Alpha 2.7 */
-# define DATASTART ((ptr_t) 0x140000000)
-# endif
+# define ELF_CLASS ELFCLASS64
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 816
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)(__data_start))
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
# endif
# ifdef FREEBSD
# define OS_TYPE "FREEBSD"
@@ -1678,6 +1752,7 @@
# ifdef CX_UX
# define OS_TYPE "CX_UX"
# define DATASTART ((((word)etext + 0x3fffff) & ~0x3fffff) + 0x10000)
+# define STACKBOTTOM ((char*)0xf0000000) /* determined empirically */
# endif
# ifdef DGUX
# define OS_TYPE "DGUX"
@@ -1777,6 +1852,22 @@
# define OS_TYPE "MSWINCE"
# define DATAEND /* not needed */
# endif
+# ifdef OPENBSD
+# define ALIGNMENT 4
+# define OS_TYPE "OPENBSD"
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 176
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)(__data_start))
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
+# endif
# ifdef NOSYS
/* __data_start is usually defined in the target linker script. */
extern int __data_start[];
@@ -1820,6 +1911,21 @@
# define DATASTART GC_data_start
# define DYNAMIC_LOADING
# endif
+# ifdef OPENBSD
+# define OS_TYPE "OPENBSD"
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 332
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)(__data_start))
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
+# endif
# endif
# ifdef SH4
@@ -1852,6 +1958,22 @@
# ifndef HBLKSIZE
# define HBLKSIZE 4096
# endif
+# ifdef OPENBSD
+# define OS_TYPE "OPENBSD"
+# define ELF_CLASS ELFCLASS64
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 400
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)(__data_start))
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
+# endif
# define CACHE_LINE_SIZE 64
# ifdef LINUX
# define OS_TYPE "LINUX"
diff --git a/include/private/openbsd_stop_world.h b/include/private/openbsd_stop_world.h
new file mode 100644
index 00000000..7f423ad5
--- /dev/null
+++ b/include/private/openbsd_stop_world.h
@@ -0,0 +1,12 @@
+#ifndef GC_OPENBSD_STOP_WORLD_H
+#define GC_OPENBSD_STOP_WORLD_H
+
+#if !defined(GC_OPENBSD_THREADS)
+#error openbsd_stop_world.h included without GC_OPENBSD_THREADS defined
+#endif
+
+struct thread_stop_info {
+ ptr_t stack_ptr; /* Valid only when stopped. */
+};
+
+#endif
diff --git a/mach_dep.c b/mach_dep.c
index b282b7fc..1f1270e8 100644
--- a/mach_dep.c
+++ b/mach_dep.c
@@ -159,7 +159,7 @@ void GC_push_regs()
# undef HAVE_PUSH_REGS
#endif
-#if !defined(HAVE_PUSH_REGS) && defined(UNIX_LIKE)
+#if !defined(HAVE_PUSH_REGS) && defined(UNIX_LIKE) && !defined(OPENBSD)
# define _XOPEN_SOURCE /* PLTSCHEME: for Mac OS X */
# include <ucontext.h>
#endif
@@ -176,7 +176,7 @@ void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *),
# if defined(HAVE_PUSH_REGS)
GC_push_regs();
# elif defined(UNIX_LIKE) && !defined(DARWIN) && !defined(ARM32) && \
- !defined(HURD)
+ !defined(HURD) && !defined(OPENBSD)
/* Older versions of Darwin seem to lack getcontext(). */
/* ARM Linux often doesn't support a real getcontext(). */
ucontext_t ctxt;
diff --git a/misc.c b/misc.c
index 17e6637c..7b1a37bb 100644
--- a/misc.c
+++ b/misc.c
@@ -622,7 +622,7 @@ void GC_init_inner()
# if defined(SEARCH_FOR_DATA_START)
GC_init_linux_data_start();
# endif
-# if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
+# if defined(NETBSD) && defined(__ELF__)
if (!GC_no_dls) /* PLTSCHEME: hack */
GC_init_netbsd_elf();
# endif
diff --git a/openbsd_stop_world.c b/openbsd_stop_world.c
new file mode 100644
index 00000000..a7e84bf9
--- /dev/null
+++ b/openbsd_stop_world.c
@@ -0,0 +1,162 @@
+#include "private/pthread_support.h"
+
+/* derived from pthread_stop_world.c */
+
+# if defined(GC_OPENBSD_THREADS)
+
+/* We hold allocation lock. Should do exactly the right thing if the */
+/* world is stopped. Should not fail if it isn't. */
+void GC_push_all_stacks()
+{
+ GC_bool found_me = FALSE;
+ size_t nthreads = 0;
+ int i;
+ GC_thread p;
+ ptr_t lo, hi;
+ pthread_t me = pthread_self();
+
+ if (!GC_thr_initialized) GC_thr_init();
+# if DEBUG_THREADS
+ GC_printf("Pushing stacks from thread 0x%x\n", (unsigned) me);
+# endif
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
+ for (p = GC_threads[i]; p != 0; p = p -> next) {
+ if (p -> flags & FINISHED) continue;
+ ++nthreads;
+ if (THREAD_EQUAL(p -> id, me)) {
+# ifdef SPARC
+ lo = (ptr_t)GC_save_regs_in_stack();
+# else
+ lo = GC_approx_sp();
+# endif
+ found_me = TRUE;
+ } else {
+ lo = p -> stop_info.stack_ptr;
+ }
+ if ((p -> flags & MAIN_THREAD) == 0) {
+ hi = p -> stack_end;
+ } else {
+ /* The original stack. */
+ hi = GC_stackbottom;
+ }
+# if DEBUG_THREADS
+ GC_printf("Stack for thread 0x%x = [%p,%p)\n",
+ (unsigned)(p -> id), lo, hi);
+# endif
+ if (0 == lo) ABORT("GC_push_all_stacks: sp not set!\n");
+# ifdef STACK_GROWS_UP
+ /* We got them backwards! */
+ GC_push_all_stack(hi, lo);
+# else
+ GC_push_all_stack(lo, hi);
+# endif
+ }
+ }
+ if (GC_print_stats == VERBOSE) {
+ GC_log_printf("Pushed %d thread stacks\n", nthreads);
+ }
+ if (!found_me && !GC_in_thread_creation)
+ ABORT("Collecting from unknown thread.");
+}
+
+/* We hold the allocation lock. Suspend all threads that might */
+/* still be running. */
+void GC_suspend_all()
+{
+ int i;
+ GC_thread p;
+ int result;
+ pthread_t my_thread = pthread_self();
+
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
+ for (p = GC_threads[i]; p != 0; p = p -> next) {
+ if (!THREAD_EQUAL(p -> id, my_thread)) {
+ if (p -> flags & FINISHED) continue;
+ if (p -> thread_blocked) /* Will wait */ continue;
+# if DEBUG_THREADS
+ GC_printf("Suspending thread 0x%x\n",
+ (unsigned)(p -> id));
+# endif
+
+ if (pthread_suspend_np(p -> id) != 0)
+ ABORT("pthread_suspend_np failed");
+
+ /*
+ * This will only work for userland pthreads. It will
+ * fail badly on rthreads. Perhaps we should consider
+ * a pthread_sp_np() function that returns the stack
+ * pointer for a suspended thread and implement in
+ * both pthreads and rthreads.
+ */
+ p -> stop_info.stack_ptr = *(ptr_t*)((char *)p -> id + UTHREAD_SP_OFFSET);
+ }
+ }
+ }
+}
+
+void GC_stop_world()
+{
+ int i;
+
+ GC_ASSERT(I_HOLD_LOCK());
+# if DEBUG_THREADS
+ GC_printf("Stopping the world from 0x%x\n", (unsigned)pthread_self());
+# endif
+
+ /* Make sure all free list construction has stopped before we start. */
+ /* No new construction can start, since free list construction is */
+ /* required to acquire and release the GC lock before it starts, */
+ /* and we have the lock. */
+# ifdef PARALLEL_MARK
+ GC_acquire_mark_lock();
+ GC_ASSERT(GC_fl_builder_count == 0);
+ /* We should have previously waited for it to become zero. */
+# endif /* PARALLEL_MARK */
+
+ GC_suspend_all();
+
+# ifdef PARALLEL_MARK
+ GC_release_mark_lock();
+# endif
+ #if DEBUG_THREADS
+ GC_printf("World stopped from 0x%x\n", (unsigned)pthread_self());
+ #endif
+}
+
+/* Caller holds allocation lock, and has held it continuously since */
+/* the world stopped. */
+void GC_start_world()
+{
+ pthread_t my_thread = pthread_self();
+ register int i;
+ register GC_thread p;
+ register int result;
+
+# if DEBUG_THREADS
+ GC_printf("World starting\n");
+# endif
+
+ for (i = 0; i < THREAD_TABLE_SZ; i++) {
+ for (p = GC_threads[i]; p != 0; p = p -> next) {
+ if (!THREAD_EQUAL(p -> id, my_thread)) {
+ if (p -> flags & FINISHED) continue;
+ if (p -> thread_blocked) continue;
+ #if DEBUG_THREADS
+ GC_printf("Resuming thread 0x%x\n",
+ (unsigned)(p -> id));
+ #endif
+
+ if (pthread_resume_np(p -> id) != 0)
+ ABORT("pthread_kill failed");
+ }
+ }
+ }
+# if DEBUG_THREADS
+ GC_printf("World started\n");
+# endif
+}
+
+void GC_stop_init() {
+}
+
+#endif
diff --git a/os_dep.c b/os_dep.c
index c6d4fcbb..815f58d3 100644
--- a/os_dep.c
+++ b/os_dep.c
@@ -495,7 +495,7 @@ static void *tiny_sbrk(ptrdiff_t increment)
#define sbrk tiny_sbrk
# endif /* ECOS */
-#if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
+#if defined(NETBSD) && defined(__ELF__)
ptr_t GC_data_start;
void GC_init_netbsd_elf(void)
@@ -508,6 +508,103 @@ static void *tiny_sbrk(ptrdiff_t increment)
}
#endif
+#if defined(OPENBSD)
+ static struct sigaction old_segv_act;
+ sigjmp_buf GC_jmp_buf_openbsd;
+
+# if defined(GC_OPENBSD_THREADS)
+# include <sys/syscall.h>
+ sigset_t __syscall(quad_t, ...);
+# endif
+
+ /*
+ * Dont use GC_find_limit() because siglongjmp out of the
+ * signal handler by-passes our userland pthreads lib, leaving
+ * SIGSEGV and SIGPROF masked. Instead use this custom one
+ * that works-around the issues.
+ */
+
+ /*ARGSUSED*/
+ void GC_fault_handler_openbsd(int sig)
+ {
+ siglongjmp(GC_jmp_buf_openbsd, 1);
+ }
+
+ /* Return the first nonaddressible location > p or bound */
+ /* Requires allocation lock. */
+ ptr_t GC_find_limit_openbsd(ptr_t p, ptr_t bound)
+ {
+ static volatile ptr_t result;
+ /* Safer if static, since otherwise it may not be */
+ /* preserved across the longjmp. Can safely be */
+ /* static since it's only called with the */
+ /* allocation lock held. */
+ struct sigaction act;
+ size_t pgsz = (size_t)sysconf(_SC_PAGESIZE);
+
+ GC_ASSERT(I_HOLD_LOCK());
+
+ act.sa_handler = GC_fault_handler_openbsd;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_NODEFER | SA_RESTART;
+ sigaction(SIGSEGV, &act, &old_segv_act);
+
+ if (sigsetjmp(GC_jmp_buf_openbsd, 1) == 0) {
+ result = (ptr_t)(((word)(p)) & ~(pgsz-1));
+ for (;;) {
+ result += pgsz;
+ if (result >= bound) {
+ result = bound;
+ break;
+ }
+ GC_noop1((word)(*result));
+ }
+ }
+
+# if defined(GC_OPENBSD_THREADS)
+ /* due to the siglongjump we need to manually unmask SIGPROF */
+ __syscall(SYS_sigprocmask, SIG_UNBLOCK, sigmask(SIGPROF));
+# endif
+
+ sigaction(SIGSEGV, &old_segv_act, 0);
+
+ return(result);
+ }
+
+ /* Return first addressable location > p or bound */
+ /* Requires allocation lock. */
+ ptr_t GC_skip_hole_openbsd(ptr_t p, ptr_t bound)
+ {
+ static volatile ptr_t result;
+ struct sigaction act;
+ size_t pgsz = (size_t)sysconf(_SC_PAGESIZE);
+ static volatile int firstpass;
+
+ GC_ASSERT(I_HOLD_LOCK());
+
+ act.sa_handler = GC_fault_handler_openbsd;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_NODEFER | SA_RESTART;
+ sigaction(SIGSEGV, &act, &old_segv_act);
+
+ firstpass = 1;
+ result = (ptr_t)(((word)(p)) & ~(pgsz-1));
+ if (sigsetjmp(GC_jmp_buf_openbsd, 1) != 0 || firstpass) {
+ firstpass = 0;
+ result += pgsz;
+ if (result >= bound) {
+ result = bound;
+ } else
+ GC_noop1((word)(*result));
+ }
+
+ sigaction(SIGSEGV, &old_segv_act, 0);
+
+ return(result);
+ }
+#endif
+
+
# ifdef OS2
# include <stddef.h>
@@ -1113,7 +1210,7 @@ ptr_t GC_get_main_stack_base(void)
#if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \
&& !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS) \
- && !defined(CYGWIN32)
+ && !defined(CYGWIN32) && !defined(GC_OPENBSD_THREADS)
ptr_t GC_get_main_stack_base(void)
{
@@ -1222,6 +1319,35 @@ int GC_get_stack_base(struct GC_stack_base *b)
#endif /* GC_LINUX_THREADS */
+#if defined(GC_OPENBSD_THREADS)
+
+/* Find the stack using pthread_stackseg_np() */
+
+# include <sys/signal.h>
+# include <pthread.h>
+# include <pthread_np.h>
+
+#define HAVE_GET_STACK_BASE
+
+int GC_get_stack_base(struct GC_stack_base *sb)
+{
+ stack_t stack;
+ pthread_stackseg_np(pthread_self(), &stack);
+ sb->mem_base = stack.ss_sp;
+ return GC_SUCCESS;
+}
+
+/* This is always called from the main thread. */
+ptr_t GC_get_main_stack_base(void)
+{
+ struct GC_stack_base sb;
+
+ GC_get_stack_base(&sb);
+ return (ptr_t)sb.mem_base;
+}
+
+#endif /* GC_OPENBSD_THREADS */
+
#ifndef HAVE_GET_STACK_BASE
/* Retrieve stack base. */
/* Using the GC_find_limit version is risky. */
@@ -1670,6 +1796,31 @@ ptr_t GC_FreeBSDGetDataStart(size_t max_page_size, ptr_t etext_addr)
#else /* !OS2 && !Windows && !AMIGA */
+#if defined(OPENBSD)
+
+/*
+ * Depending on arch alignment there can be multiple holes
+ * between DATASTART & DATAEND. Scan from DATASTART - DATAEND
+ * and register each region.
+ */
+void GC_register_data_segments(void)
+{
+ ptr_t region_start, region_end;
+
+ region_start = DATASTART;
+
+ for(;;) {
+ region_end = GC_find_limit_openbsd(region_start, DATAEND);
+ GC_add_roots_inner(region_start, region_end, FALSE);
+ if (region_end < DATAEND)
+ region_start = GC_skip_hole_openbsd(region_end, DATAEND);
+ else
+ break;
+ }
+}
+
+# else /* !OS2 && !Windows && !AMIGA && !OPENBSD */
+
void GC_register_data_segments(void)
{
# if !defined(PCR) && !defined(MACOS)
@@ -1727,6 +1878,7 @@ void GC_register_data_segments(void)
/* change. */
}
+# endif /* ! OPENBSD */
# endif /* ! AMIGA */
# endif /* ! MSWIN32 && ! MSWINCE*/
# endif /* ! OS2 */
diff --git a/pthread_stop_world.c b/pthread_stop_world.c
index c542aebc..3e7bda65 100644
--- a/pthread_stop_world.c
+++ b/pthread_stop_world.c
@@ -1,7 +1,7 @@
#include "private/pthread_support.h"
#if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS) && \
- !defined(GC_DARWIN_THREADS)
+ !defined(GC_DARWIN_THREADS) && !defined(GC_OPENBSD_THREADS)
#include <signal.h>
#include <semaphore.h>
diff --git a/pthread_support.c b/pthread_support.c
index 8ca1a3a6..8c59a447 100644
--- a/pthread_support.c
+++ b/pthread_support.c
@@ -774,6 +774,9 @@ void GC_thr_init(void)
# if defined(GC_NETBSD_THREADS)
GC_nprocs = get_ncpu();
# endif
+# if defined(GC_OPENBSD_THREADS)
+ GC_nprocs = 1;
+# endif
# if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
int ncpus = 1;
size_t len = sizeof(ncpus);
@@ -845,7 +848,7 @@ void GC_init_parallel(void)
}
-#if !defined(GC_DARWIN_THREADS)
+#if !defined(GC_DARWIN_THREADS) && !defined(GC_OPENBSD_THREADS)
int WRAP_FUNC(pthread_sigmask)(int how, const sigset_t *set, sigset_t *oset)
{
sigset_t fudged_set;
@@ -1100,6 +1103,12 @@ void * GC_start_routine(void * arg)
GC_enable();
# endif
return GC_inner_start_routine(&sb, arg);
+# elif defined(GC_OPENBSD_THREADS)
+ /* On OpenBSD GC_get_stack_base() doesn't cause any allocations */
+ struct GC_stack_base sb;
+ if (GC_get_stack_base(&sb) != GC_SUCCESS)
+ ABORT("Failed to get thread stack base.");
+ return GC_inner_start_routine(&sb, arg);
# else
return GC_call_with_stack_base(GC_inner_start_routine, arg);
# endif
@@ -1294,7 +1303,7 @@ void GC_generic_lock(pthread_mutex_t * lock)
/* as STL alloc.h. This isn't really the right way to do this. */
/* but until the POSIX scheduling mess gets straightened out ... */
-volatile AO_TS_t GC_allocate_lock = 0;
+volatile AO_TS_t GC_allocate_lock = AO_TS_INITIALIZER;
void GC_lock(void)
diff --git a/tests/test.c b/tests/test.c
index 60335414..839faf89 100644
--- a/tests/test.c
+++ b/tests/test.c
@@ -1627,7 +1627,8 @@ int main()
pthread_attr_init(&attr);
# if defined(GC_IRIX_THREADS) || defined(GC_FREEBSD_THREADS) \
- || defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)
+ || defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS) \
+ || defined(GC_OPENBSD_THREADS)
pthread_attr_setstacksize(&attr, 1000000);
# endif
n_tests = 0;
diff --git a/threadlibs.c b/threadlibs.c
index f2ab5825..667fa2f6 100644
--- a/threadlibs.c
+++ b/threadlibs.c
@@ -18,6 +18,9 @@ int main()
# endif
printf("-lpthread\n");
# endif
+# if defined(GC_OPENBSD_THREADS)
+ printf("-pthread\n");
+# endif
# if defined(GC_FREEBSD_THREADS)
# ifdef GC_USE_DLOPEN_WRAP
printf("-ldl ");