apply patch from Tim Wiess to make the Boehm GC build on OpenBSD

svn: r18712
This commit is contained in:
Matthew Flatt 2010-04-01 13:54:56 +00:00
parent b2d65a1b95
commit e0b9bbeba8
14 changed files with 560 additions and 50 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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>

View File

@ -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)

View File

@ -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;

View File

@ -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 ");