/* values taken from the kernel's linux/futex.h. This header file
doesn't exist in userspace, which is our excuse for not grovelling
them automatically */
-#define FUTEX_WAIT (0)
-#define FUTEX_WAKE (1)
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+/* This is also copied from linux/futex.h so that a binary compiled on
+ * a not so recent Linux system can still take advantage of private
+ * futexes when available.*/
+#define FUTEX_WAIT_PRIVATE (0+128)
+#define FUTEX_WAKE_PRIVATE (1+128)
#define FUTEX_FD (2)
#define FUTEX_REQUEUE (3)
+/* Not static so that Lisp may query it. */
+boolean futex_private_supported_p;
+
+static inline int
+futex_wait_op()
+{
+ return (futex_private_supported_p ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT);
+}
+
+static inline int
+futex_wake_op()
+{
+ return (futex_private_supported_p ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE);
+}
+
#define sys_futex sbcl_sys_futex
static inline int sys_futex (void *futex, int op, int val, struct timespec *rel)
{
return syscall (SYS_futex, futex, op, val, rel);
}
+static void
+futex_init()
+{
+ int x = 0;
+ sys_futex(&x, FUTEX_WAIT, 1, 0);
+ if (errno == ENOSYS)
+ lose("This version of SBCL is compiled with threading support, but your kernel\n"
+ "is too old to support this. Please use a more recent kernel or\n"
+ "a version of SBCL without threading support.\n");
+ sys_futex(&x, FUTEX_WAIT_PRIVATE, 1, 0);
+ if (errno == EWOULDBLOCK) {
+ futex_private_supported_p = 1;
+ } else {
+ futex_private_supported_p = 0;
+ SHOW("No futex private suppport\n");
+ }
+}
+
int
futex_wait(int *lock_word, int oldval, long sec, unsigned long usec)
{
struct timespec timeout;
int t;
- again:
if (sec<0) {
- t = sys_futex(lock_word,FUTEX_WAIT,oldval, 0);
+ t = sys_futex(lock_word, futex_wait_op(), oldval, 0);
}
else {
- timeout.tv_sec = sec;
- timeout.tv_nsec = usec * 1000;
- t = sys_futex(lock_word,FUTEX_WAIT,oldval, &timeout);
+ timeout.tv_sec = sec;
+ timeout.tv_nsec = usec * 1000;
+ t = sys_futex(lock_word, futex_wait_op(), oldval, &timeout);
}
if (t==0)
return 0;
else if (errno==ETIMEDOUT)
return 1;
else if (errno==EINTR)
- /* spurious wakeup from interrupt */
- goto again;
+ return 2;
else
/* EWOULDBLOCK and others, need to check the lock */
return -1;
int
futex_wake(int *lock_word, int n)
{
- return sys_futex(lock_word,FUTEX_WAKE,n,0);
+ return sys_futex(lock_word, futex_wake_op(),n,0);
}
#endif
{
/* Conduct various version checks: do we have enough mmap(), is
* this a sparc running 2.2, can we do threads? */
-#if defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_SB_LUTEX) && !defined(LISP_FEATURE_SB_PTHREAD_FUTEX)
- int *futex=0;
-#endif
struct utsname name;
int major_version;
int minor_version;
}
#ifdef LISP_FEATURE_SB_THREAD
#if !defined(LISP_FEATURE_SB_LUTEX) && !defined(LISP_FEATURE_SB_PTHREAD_FUTEX)
- futex_wait(futex,-1,-1,0);
- if(errno==ENOSYS) {
- lose("This version of SBCL is compiled with threading support, but your kernel\n"
- "is too old to support this. Please use a more recent kernel or\n"
- "a version of SBCL without threading support.\n");
- }
+ futex_init();
#endif
if(! isnptl()) {
lose("This version of SBCL only works correctly with the NPTL threading\n"
lose("An mprotect call failed with ENOMEM. This probably means that the maximum amount\n"
"of separate memory mappings was exceeded. To fix the problem, either increase\n"
"the maximum with e.g. 'echo 262144 > /proc/sys/vm/max_map_count' or recompile\n"
- "SBCL with a larger value for GENCGC-PAGE-SIZE in 'src/target/parms.lisp'.");
+ "SBCL with a larger value for GENCGC-PAGE-BYTES in\n"
+ "'src/compiler/target/backend-parms.lisp'.");
} else {
perror("mprotect");
}
* page fault on this OS.
*/
static void
-sigsegv_handler(int signal, siginfo_t *info, void* void_context)
+sigsegv_handler(int signal, siginfo_t *info, os_context_t *context)
{
- os_context_t *context = arch_os_get_context(&void_context);
os_vm_address_t addr = arch_get_bad_addr(signal, info, context);
#ifdef LISP_FEATURE_ALPHA
if (!cheneygc_handle_wp_violation(context, addr))
#endif
if (!handle_guard_page_triggered(context, addr))
-#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
lisp_memory_fault_error(context, addr);
-#else
- interrupt_handle_now(signal, info, context);
-#endif
}
void