$OpenBSD$
--- src/boehm-gc/openbsd.c.orig	Sat Apr 22 16:41:59 2006
+++ src/boehm-gc/openbsd.c	Sat Apr 22 16:43:10 2006
@@ -0,0 +1,135 @@
+/*
+ * Tools to implement HEURISTIC2
+ * This file is included in os_dep.c in place of the mess that's there
+ * This code correctly sets the sigprocmask.
+ *
+ * Notes:
+ *   OpenBSD pthreads already use a sigaltstack
+ *   The symbols UNIX_LIKE and NEED_FIND_LIMIT are undefined
+ *
+ * Author: "Frederick C. Druseikis" <fredd@cse.sc.edu>
+ * Date: April 2, 2006
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <setjmp.h>
+
+#ifndef OPENBSD
+/* these decls are sufficient for an independent compilation of openbsd.c */
+typedef char *ptr_t;
+typedef unsigned long word;
+typedef int GC_bool;
+#endif
+
+typedef void (*handler)(int);
+
+static void GC_noop2(ptr_t r, word w) {
+	static volatile word dummy;
+	dummy = w;
+#ifdef OPENBSD_DEBUG
+	GC_printf2("noop2 %0x %0x\n", r, dummy);
+#endif
+}
+
+#define MIN_PAGE_SIZE 4096
+
+static sigjmp_buf GC_jmp_buf;
+static struct sigaction old_segv_act;
+static sigset_t old_procmask;
+
+void GC_fault_handler(int sig)
+{
+	int dummy = 0;
+#ifdef OPENBSD_DEBUG
+	GC_printf1("fault handler %0x\n", &dummy);
+#endif
+    siglongjmp(GC_jmp_buf, 1);
+}
+
+void GC_set_and_save_fault_handler(handler h)
+{
+	sigset_t new;
+	struct sigaction act;
+
+	act.sa_handler = h;
+	act.sa_flags = SA_NODEFER | SA_ONSTACK;
+	sigemptyset(&act.sa_mask);
+	sigemptyset(&new);
+
+	if( sigprocmask(SIG_SETMASK,&new,&old_procmask) ) {
+		ABORT("sigprocmask");
+	}
+
+	if( sigaction(SIGSEGV, &act, &old_segv_act) ) {
+		ABORT("sigaction");
+	}
+}
+
+void GC_setup_temporary_fault_handler()
+{
+	GC_set_and_save_fault_handler(GC_fault_handler);
+}
+
+void GC_reset_fault_handler()
+{
+	sigprocmask(SIG_SETMASK,&old_procmask,NULL);
+	sigaction(SIGSEGV, &old_segv_act, 0);
+}
+
+/* Return the first nonaddressible location > p (up) or 	*/
+/* the smallest location q s.t. [q,p) is addressable (!up).	*/
+/* We assume that p (up) or p-1 (!up) is addressable.	*/
+
+ptr_t GC_find_limit(ptr_t p, GC_bool up)
+{
+	static ptr_t result;
+		/* Needs to be static, since otherwise it may not be	*/
+		/* preserved across the longjmp.  Can safely be 	*/
+		/* static since it's only called once, with the		*/
+		/* allocation lock held.				*/
+
+	GC_setup_temporary_fault_handler();
+
+	result = (ptr_t)(((word)(p)) & ~(MIN_PAGE_SIZE-1));
+#ifdef OPENBSD_DEBUG
+	printf("result = %0x\n", result );
+#endif
+
+	if (sigsetjmp(GC_jmp_buf,1) == 0) {
+		for (;;) {
+			if (up) {
+				result += MIN_PAGE_SIZE;
+			} else {
+				result -= MIN_PAGE_SIZE;
+			}
+			GC_noop2(result,(word)(*result));
+		}
+	}
+
+	GC_reset_fault_handler();
+
+	if (!up) {
+		result += MIN_PAGE_SIZE;
+	}
+	return(result);
+}
+
+extern ptr_t GC_stackbottom;
+
+ptr_t GC_data_start;
+
+void GC_init_openbsd_elf()
+{
+	int dummy = 0;
+
+	GC_data_start = GC_find_limit( (ptr_t) &end, FALSE);
+	GC_stackbottom = GC_find_limit( (ptr_t) &dummy, TRUE);
+#ifdef DEBUG_THREADS
+	GC_printf1("openbsd GC_data_start: %p\n", GC_data_start );
+	GC_printf1("openbsd GC_data_end:   %p\n", (void*) &end );
+	GC_printf1("openbsd GC_stackbottom: %p\n", GC_stackbottom );
+#endif
+}
