solaris_pthreads.c solaris_threads.c specific.c stubborn.c typd_mlc.c \
backgraph.c win32_threads.c \
pthread_support.c pthread_stop_world.c darwin_stop_world.c \
-mach_dep.c $(asm_libgc_sources)
+openbsd_stop_world.c mach_dep.c $(asm_libgc_sources)
# Include THREADDLLIBS here to ensure that the correct versions of
# linuxthread semaphore functions get linked:
fi
AC_DEFINE(THREAD_LOCAL_ALLOC)
;;
+ *-*-openbsd*)
+ AC_DEFINE(GC_OPENBSD_THREADS)
+ if test "${enable_parallel_mark}" = yes; then
+ AC_DEFINE(PARALLEL_MARK)
+ fi
+ AC_DEFINE(THREAD_LOCAL_ALLOC)
+ ;;
*-*-osf*)
AC_DEFINE(GC_OSF1_THREADS)
if test "${enable_parallel_mark}" = yes; then
!defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \
!defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \
!(defined(FREEBSD) && defined(__ELF__)) && \
+ !(defined(OPENBSD) && (defined(__ELF__) || defined(M68K))) && \
!(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \
!defined(DARWIN)
--> We only know how to find data segments of dynamic libraries for the
#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>
+# if !defined(OPENBSD)
# include <elf.h>
+# endif
# include <link.h>
#endif
#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
(defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \
+ (defined(OPENBSD) && defined(__ELF__)) || \
(defined(NETBSD) && defined(__ELF__)) || defined(HURD)
/* This doesn't necessarily work in all cases, e.g. with preloaded
* dynamic libraries. */
-#if defined(NETBSD)
+#if defined(NETBSD) || defined(OPENBSD)
+# if !defined(OPENBSD)
# include <sys/exec_elf.h>
+# endif
/* for compatibility with 1.4.x */
# ifndef DT_DEBUG
# define DT_DEBUG 21
defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || \
defined(GC_DGUX386_THREADS) || defined(GC_DARWIN_THREADS) || \
defined(GC_AIX_THREADS) || defined(GC_NETBSD_THREADS) || \
+ defined(GC_OPENBSD_THREADS) || \
(defined(GC_WIN32_THREADS) && defined(__CYGWIN32__))
# define GC_PTHREADS
# endif
# 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__)
# define GC_FREEBSD_THREADS
# define GC_PTHREADS
# 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
# endif
# ifdef OPENBSD
# define OS_TYPE "OPENBSD"
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 192
+# 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"
extern char etext[];
# define SEARCH_FOR_DATA_START
# 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
# endif
#if defined(LINUX) && defined(USE_MMAP)
#if defined(GC_DARWIN_THREADS)
# include "private/darwin_stop_world.h"
+#elif defined(GC_OPENBSD_THREADS)
+# include "private/openbsd_stop_world.h"
#else
# include "private/pthread_stop_world.h"
#endif
/* the stack. Return sp. */
# ifdef SPARC
asm(" .seg \"text\"");
-# if defined(SVR4) || defined(NETBSD) || defined(FREEBSD)
+# if defined(SVR4) || defined(NETBSD) || defined(FREEBSD) || defined(OPENBSD)
asm(" .globl GC_save_regs_in_stack");
asm("GC_save_regs_in_stack:");
asm(" .type GC_save_regs_in_stack,#function");
int GC_get_suspend_signal GC_PROTO(())
{
-#if defined(SIG_SUSPEND) && defined(GC_PTHREADS) && !defined(GC_MACOSX_THREADS)
+#if defined(SIG_SUSPEND) && defined(GC_PTHREADS) && !defined(GC_MACOSX_THREADS) && !defined(GC_OPENBSD_THREADS)
return SIG_SUSPEND;
#else
return -1;
# if defined(SEARCH_FOR_DATA_START)
GC_init_linux_data_start();
# endif
-# if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
+# if defined(NETBSD) && defined(__ELF__)
GC_init_netbsd_elf();
# endif
# if defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS) \
#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()
}
#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>
#endif /* FREEBSD_STACKBOTTOM */
#if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \
- && !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS)
+ && !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS) \
+ && !defined(GC_OPENBSD_THREADS)
ptr_t GC_get_stack_base()
{
# endif /* ! AMIGA, !OS 2, ! MS Windows, !BEOS, !NOSYS, !ECOS */
+#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
+
+ptr_t GC_get_stack_base()
+{
+ stack_t stack;
+ pthread_stackseg_np(pthread_self(), &stack);
+ return stack.ss_sp;
+}
+
+#endif /* GC_OPENBSD_THREADS */
+
/*
* Register static data segment(s) as roots.
* If more data segments are added later then they need to be registered
#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()
{
# if !defined(PCR) && !defined(SRC_M3) && !defined(MACOS)
/* change. */
}
+# endif /* ! OPENBSD */
# endif /* ! AMIGA */
# endif /* ! MSWIN32 && ! MSWINCE*/
# endif /* ! OS2 */
#if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
&& !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS) \
- && !defined(GC_DARWIN_THREADS) && !defined(GC_AIX_THREADS)
+ && !defined(GC_DARWIN_THREADS) && !defined(GC_AIX_THREADS) \
+ && !defined(GC_OPENBSD_THREADS)
#include <signal.h>
#include <semaphore.h>
# if (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \
defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)) || \
- defined(GC_NETBSD_THREADS) && !defined(USE_PTHREAD_SPECIFIC)
+ defined(GC_NETBSD_THREADS) && !defined(USE_PTHREAD_SPECIFIC) || \
+ defined(GC_OPENBSD_THREADS)
# define USE_PTHREAD_SPECIFIC
# endif
# include <sys/sysctl.h>
#endif /* GC_DARWIN_THREADS */
-#if defined(GC_NETBSD_THREADS)
+#if defined(GC_NETBSD_THREADS) || defined(GC_OPENBSD_THREADS)
# include <sys/param.h>
# include <sys/sysctl.h>
#endif
GC_nprocs = sysconf(_SC_NPROC_ONLN);
if (GC_nprocs <= 0) GC_nprocs = 1;
# endif
-# if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS) || defined(GC_NETBSD_THREADS)
+# if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS) || defined(GC_NETBSD_THREADS) || defined(GC_OPENBSD_THREADS)
int ncpus = 1;
size_t len = sizeof(ncpus);
sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0);
}
-#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;
|| defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)
printf("-lpthread\n");
# endif
-# if defined(GC_FREEBSD_THREADS)
+# if defined(GC_FREEBSD_THREADS) || defined(GC_OPENBSD_THREADS)
# if (__FREEBSD_version >= 500000)
printf("-lpthread\n");
# else