+#ifdef __FreeBSD__
+extern int getosreldate(void);
+
+int sig_memory_fault;
+
+static void freebsd_init()
+{
+ /* Memory fault signal on FreeBSD was changed from SIGBUS to
+ * SIGSEGV. */
+ if (getosreldate() < 700004)
+ sig_memory_fault = SIGBUS;
+ else
+ sig_memory_fault = SIGSEGV;
+
+ /* Quote from sbcl-devel (NIIMI Satoshi): "Some OSes, like FreeBSD
+ * 4.x with GENERIC kernel, does not enable SSE support even on
+ * SSE capable CPUs". Detect this situation and skip the
+ * fast_bzero sse/base selection logic that's normally done in
+ * x86-assem.S.
+ */
+#ifdef LISP_FEATURE_X86
+ {
+ size_t len;
+ int instruction_sse;
+
+ len = sizeof(instruction_sse);
+ if (sysctlbyname("hw.instruction_sse", &instruction_sse, &len,
+ NULL, 0) == 0 && instruction_sse != 0) {
+ /* Use the SSE detector */
+ fast_bzero_pointer = fast_bzero_detect;
+ }
+ }
+#endif /* LISP_FEATURE_X86 */
+}
+
+#if defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_SB_PTHREAD_FUTEX) \
+ && !defined(LISP_FEATURE_SB_LUTEX)
+int
+futex_wait(int *lock_word, long oldval, long sec, unsigned long usec)
+{
+ struct timespec timeout;
+ int ret;
+
+ if (sec < 0)
+ ret = umtx_wait((void *)lock_word, oldval, NULL);
+ else {
+ timeout.tv_sec = sec;
+ timeout.tv_nsec = usec * 1000;
+ ret = umtx_wait((void *)lock_word, oldval, &timeout);
+ }
+
+ switch (ret) {
+ case 0:
+ return 0;
+ case ETIMEDOUT:
+ return 1;
+ case EINTR:
+ return 2;
+ default:
+ /* EWOULDBLOCK and others, need to check the lock */
+ return -1;
+ }
+}
+
+int
+futex_wake(int *lock_word, int n)
+{
+ return umtx_wake((void *)lock_word, n);
+}
+#endif
+#endif /* __FreeBSD__ */
+
+#ifdef LISP_FEATURE_DARWIN
+/* defined in ppc-darwin-os.c instead */
+#elif defined(LISP_FEATURE_FREEBSD)
+#ifndef KERN_PROC_PATHNAME
+#define KERN_PROC_PATHNAME 12
+#endif
+
+char *
+os_get_runtime_executable_path(int external)
+{
+ char path[PATH_MAX + 1];
+
+ if (getosreldate() >= 600024) {
+ /* KERN_PROC_PATHNAME is available */
+ size_t len = PATH_MAX + 1;
+ int mib[4];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PATHNAME;
+ mib[3] = -1;
+ if (sysctl(mib, 4, &path, &len, NULL, 0) != 0)
+ return NULL;
+ } else {
+ int size;
+ size = readlink("/proc/curproc/file", path, sizeof(path) - 1);
+ if (size < 0)
+ return NULL;
+ path[size] = '\0';
+ }
+ if (strcmp(path, "unknown") == 0)
+ return NULL;
+ return copied_string(path);
+}
+#elif defined(LISP_FEATURE_NETBSD) || defined(LISP_FEATURE_OPENBSD)
+char *
+os_get_runtime_executable_path(int external)
+{
+ struct stat sb;
+ if (!external && stat("/proc/curproc/file", &sb) == 0)
+ return copied_string("/proc/curproc/file");
+ return NULL;
+}
+#else /* Not DARWIN or FREEBSD or NETBSD or OPENBSD */
+char *
+os_get_runtime_executable_path(int external)
+{
+ return NULL;
+}
+#endif
+
+#ifdef __OpenBSD__
+
+int openbsd_use_fxsave = 0;
+
+void
+openbsd_init()
+{
+#ifdef LISP_FEATURE_X86
+ int mib[2];
+ size_t size;
+#endif
+ /*
+ * Show a warning if it looks like the memory available after
+ * allocating the spaces won't be at least this much.
+ */
+#ifdef LISP_FEATURE_X86_64
+ const int wantfree = 64 * 1024 * 1024;