Update of /cvsroot/sbcl/sbcl/src/runtime
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13036/src/runtime
Modified Files:
Tag: lutex-branch
Config.x86-darwin bsd-os.c bsd-os.h coreparse.c darwin-os.c
gc-common.c interrupt.c interrupt.h linux-os.c linux-os.h
runtime.h save.c thread.c x86-arch.c x86-arch.h
x86-darwin-os.h
Added Files:
Tag: lutex-branch
darwin-os.h x86-darwin-os.c
Log Message:
0.9.10.46.lutex-branch
* Thread and lutex support on MacOS X on Intel
* NJF's lutex work
* x86-darwin support for TLS using %fs
* More detailed description of the changes required to support
threads and lutexes will appear when this gets merged onto
the HEAD.
--- NEW FILE: darwin-os.h ---
/* this is meant to be included from bsd-os.h */
#include <mach/mach_init.h>
#include <mach/task.h>
#include <mach/semaphore.h>
#if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
#include <sys/semaphore.h>
#endif
/* man pages claim that the third argument is a sigcontext struct,
but ucontext_t is defined, matches sigcontext where sensible,
offers better access to mcontext, and is of course the SUSv2-
mandated type of the third argument, so we use that instead.
If Apple is going to break ucontext_t out of spite, I'm going
to be cross with them ;) -- PRM */
#if defined(LISP_FEATURE_X86)
#include <sys/ucontext.h>
#include <sys/_types.h>
typedef struct ucontext os_context_t;
#if defined(LISP_FEATURE_MACH_SEMAPHORES)
typedef semaphore_t os_sem_t;
#else
typedef sem_t os_sem_t;
#endif
#else
#include <ucontext.h>
typedef ucontext_t os_context_t;
#endif
#define SIG_MEMORY_FAULT SIGBUS
#define SIG_INTERRUPT_THREAD (SIGWINCH)
#define SIG_STOP_FOR_GC (SIGINFO)
--- NEW FILE: x86-darwin-os.c ---
#include <architecture/i386/table.h>
#include <i386/user_ldt.h>
void set_data_desc_size(data_desc_t* desc, unsigned long size) {
desc->limit00 = (size - 1) & 0xffff;
desc->limit16 = ((size - 1) >> 16) &0xf;
}
void set_data_desc_addr(data_desc_t* desc, void* addr) {
desc->base00 = (unsigned int)addr & 0xffff;
desc->base16 = ((unsigned int)addr & 0xff0000) >> 16;
desc->base24 = ((unsigned int)addr & 0xff000000) >> 24;
}
Index: Config.x86-darwin
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/Config.x86-darwin,v
retrieving revision 1.1
retrieving revision 1.1.2.1
diff -u -d -r1.1 -r1.1.2.1
--- Config.x86-darwin 6 Mar 2006 10:02:18 -0000 1.1
+++ Config.x86-darwin 21 Mar 2006 19:28:01 -0000 1.1.2.1
@@ -10,7 +10,7 @@
# files for more information.
CFLAGS = -g -Wall -O2 -fdollars-in-identifiers
-OS_SRC = bsd-os.c x86-bsd-os.c darwin-os.c ppc-darwin-dlshim.c x86-darwin-langinfo.c
+OS_SRC = bsd-os.c x86-bsd-os.c darwin-os.c x86-darwin-os.c ppc-darwin-dlshim.c x86-darwin-langinfo.c
OS_LIBS = -lSystem -lc -ldl
OS_OBJS = x86-darwin-rospace.o
Index: bsd-os.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/bsd-os.c,v
retrieving revision 1.38
retrieving revision 1.38.2.1
diff -u -d -r1.38 -r1.38.2.1
--- bsd-os.c 15 Mar 2006 03:01:59 -0000 1.38
+++ bsd-os.c 21 Mar 2006 19:28:01 -0000 1.38.2.1
@@ -58,6 +58,12 @@
static void freebsd_init();
#endif /* __FreeBSD__ */
+#ifdef LISP_FEATURE_DARWIN
+#include <architecture/i386/table.h>
+#include <i386/user_ldt.h>
+#include <mach/mach_init.h>
+#endif /* LISP_FEATURE_DARWIN */
+
void
os_init(char *argv[], char *envp[])
{
@@ -321,16 +327,41 @@
#endif /* LISP_FEATURE_X86 */
}
#endif /* __FreeBSD__ */
-
-/* threads */
-/* no threading in any *BSD variant on any CPU (yet? in sbcl-0.8.0 anyway) */
+int arch_os_thread_init(struct thread *thread) {
+
#ifdef LISP_FEATURE_SB_THREAD
-#error "Define threading support functions"
+
+#if defined(LISP_FEATURE_X86) && defined(LISP_FEATURE_DARWIN)
+ int n;
+ data_desc_t ldt_entry = { 0, 0, 0, DESC_DATA_WRITE,
+ 3, 1, 0, DESC_DATA_32B, DESC_GRAN_BYTE, 0 };
+
+ set_data_desc_addr(&ldt_entry, (unsigned long) thread);
+ set_data_desc_size(&ldt_entry, dynamic_values_bytes);
+
+ n = i386_set_ldt(LDT_AUTO_ALLOC, (union ldt_entry*) &ldt_entry, 1);
+
+ if (n < 0) {
+ return 0;
+ }
+
+ __asm__ __volatile__ ("movw %w0, %%fs" : : "q"
+ ((n << 3) /* selector number */
+ + (1 << 2) /* TI set = LDT */
+ + 3)); /* privilege level */
+ thread->tls_cookie=n;
+
+ pthread_setspecific(specials,thread);
#else
-int arch_os_thread_init(struct thread *thread) {
- stack_t sigstack;
+#error "Define threading support functions"
+#endif
+
+#endif
+
#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
+ stack_t sigstack;
+
/* Signal handlers are run on the control stack, so if it is exhausted
* we had better use an alternate stack for whatever signal tells us
* we've exhausted it */
@@ -339,12 +370,13 @@
sigstack.ss_size = 32*SIGSTKSZ;
sigaltstack(&sigstack,0);
#endif
+
return 1; /* success */
}
+
int arch_os_thread_cleanup(struct thread *thread) {
return 1; /* success */
}
-#endif
#ifdef LISP_FEATURE_DARWIN
/* defined in ppc-darwin-os.c instead */
Index: bsd-os.h
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/bsd-os.h,v
retrieving revision 1.16
retrieving revision 1.16.2.1
diff -u -d -r1.16 -r1.16.2.1
--- bsd-os.h 6 Mar 2006 10:02:37 -0000 1.16
+++ bsd-os.h 21 Mar 2006 19:28:02 -0000 1.16.2.1
@@ -77,24 +77,7 @@
#define SIG_MEMORY_FAULT SIGSEGV
#elif defined LISP_FEATURE_DARWIN
- /* man pages claim that the third argument is a sigcontext struct,
- but ucontext_t is defined, matches sigcontext where sensible,
- offers better access to mcontext, and is of course the SUSv2-
- mandated type of the third argument, so we use that instead.
- If Apple is going to break ucontext_t out of spite, I'm going
- to be cross with them ;) -- PRM */
-
-#if defined(LISP_FEATURE_X86)
-#include <sys/ucontext.h>
-#include <sys/_types.h>
-typedef struct ucontext os_context_t;
-#else
-#include <ucontext.h>
-typedef ucontext_t os_context_t;
-#endif
-
-#define SIG_MEMORY_FAULT SIGBUS
-
+#include "darwin-os.h"
#else
#error unsupported BSD variant
#endif
Index: coreparse.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/coreparse.c,v
retrieving revision 1.32
retrieving revision 1.32.2.1
diff -u -d -r1.32 -r1.32.2.1
--- coreparse.c 4 Mar 2006 21:45:34 -0000 1.32
+++ coreparse.c 21 Mar 2006 19:28:02 -0000 1.32.2.1
@@ -35,6 +35,9 @@
#include "validate.h"
#include "gc-internal.h"
+/* lutex stuff */
+#include "genesis/sap.h"
+
unsigned char build_id[] =
#include "../../output/build-id.tmp"
;
@@ -285,6 +288,42 @@
initial_function = (lispobj)*ptr;
break;
+#if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
+ case LUTEX_TABLE_CORE_ENTRY_TYPE_CODE:
+ SHOW("LUTEX_TABLE_CORE_ENTRY_TYPE_CODE case");
+ {
+ size_t n_lutexes = *ptr;
+ size_t fdoffset = (*(ptr + 1) + 1) * (os_vm_page_size);
+ size_t data_length = n_lutexes * sizeof(struct sap *);
+ struct sap **lutexes_to_resurrect = malloc(data_length);
+ long bytes_read;
+
+ lseek(fd, fdoffset + file_offset, SEEK_SET);
+
+ FSHOW((stderr, "attempting to read %ld lutexes from core\n", n_lutexes));
+ bytes_read = read(fd, lutexes_to_resurrect, data_length);
+
+ /* XXX */
+ if (bytes_read != data_length) {
+ lose("Could not read the lutex table");
+ }
+ else {
+ int i;
+
+ for (i=0; i<n_lutexes; ++i) {
+ struct sap *lutex = lutexes_to_resurrect[i];
+
+ FSHOW((stderr, "re-init'ing lutex @ %p\n", lutex));
+ lutex->pointer = malloc(sizeof(os_sem_t));
+ futex_init((os_sem_t *)lutex->pointer);
+ }
+
+ free(lutexes_to_resurrect);
+ }
+ break;
+ }
+#endif
+
#ifdef LISP_FEATURE_GENCGC
case PAGE_TABLE_CORE_ENTRY_TYPE_CODE:
{
Index: darwin-os.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/darwin-os.c,v
retrieving revision 1.1
retrieving revision 1.1.2.1
diff -u -d -r1.1 -r1.1.2.1
--- darwin-os.c 6 Mar 2006 10:02:45 -0000 1.1
+++ darwin-os.c 21 Mar 2006 19:28:02 -0000 1.1.2.1
@@ -22,6 +22,11 @@
#include <limits.h>
#include <mach-o/dyld.h>
#include "bsd-os.h"
+#include <errno.h>
+
+#if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
+#include <sys/semaphore.h>
+#endif
char *
os_get_runtime_executable_path()
@@ -36,3 +41,91 @@
return copied_string(path);
}
+
+#if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
+
+#if defined(LISP_FEATURE_MACH_SEMAPHORES)
+
+/* DEBUGGING CRAP THAT NEEDS TO GO AWAY! */
+/*
+int wait_attempt_count = 0;
+int wake_attempt_count = 0;
+
+ if (wait_attempt_count++ > 1000)
+ exit(1);
+*/
+
+int futex_init(os_sem_t *semaphore)
+{
+ kern_return_t ret;
+ FSHOW_SIGNAL((stderr, "/initializing semaphore @ %p\n", semaphore));
+ ret = semaphore_create(current_task(), semaphore, SYNC_POLICY_FIFO, 1);
+ FSHOW_SIGNAL((stderr, "/semaphore_create said %d\n", ret));
+ return ret;
+}
+
+int futex_wait(os_sem_t *semaphore)
+{
+ kern_return_t ret;
+ FSHOW_SIGNAL((stderr, "/waiting on semaphore @ %p\n", semaphore));
+ ret = semaphore_wait(*semaphore);
+ FSHOW_SIGNAL((stderr, "/semaphore_wait said %d\n", ret));
+ return ret;
+}
+
+int futex_wake(os_sem_t *semaphore)
+{
+ kern_return_t ret;
+ FSHOW_SIGNAL((stderr, "/waking semaphore @ %p\n", semaphore));
+ ret = semaphore_signal(*semaphore);
+ FSHOW_SIGNAL((stderr, "/semaphore_wake said %d\n", ret));
+ return ret;
+}
+
+int futex_destroy(os_sem_t *semaphore)
+{
+ kern_return_t ret;
+ FSHOW_SIGNAL((stderr, "/destroying semaphore @ %p\n", semaphore));
+ ret = semaphore_destroy(current_task(), *semaphore);
+ FSHOW_SIGNAL((stderr, "/semaphore_destroy said %d\n", ret));
+ return ret;
+}
+
+#else
+
+int futex_init(os_sem_t *semaphore)
+{
+ int ret;
+ printf("Initializing semaphore @ %p\n", semaphore);
+ ret = sem_init(semaphore, 0, 1);
+ printf("sem_init said %d, errno: %d\n", ret, errno);
+ return ret;
+}
+
+int futex_wait(os_sem_t *semaphore)
+{
+ int ret;
+ printf("Waiting on semaphore %p\n", semaphore);
+ ret = sem_wait(semaphore);
+ printf("sem_wait said %d, errno: %d\n", ret, errno);
+ return ret;
+}
+
+int futex_wake(os_sem_t *semaphore)
+{
+ int ret;
+ printf("Waking on semaphore %p\n", semaphore);
+ ret = sem_post(semaphore);
+ printf("sem_post said %d, errno: %d\n", ret, errno);
+ return ret;
+}
+
+int futex_destroy(os_sem_t *semaphore)
+{
+ return sem_destroy(semaphore);
+}
+
+#endif /* MACH_SEMAPHORES */
+
+#endif
+
Index: gc-common.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/gc-common.c,v
retrieving revision 1.37
retrieving revision 1.37.2.1
diff -u -d -r1.37 -r1.37.2.1
--- gc-common.c 1 Mar 2006 09:10:32 -0000 1.37
+++ gc-common.c 21 Mar 2006 19:28:02 -0000 1.37.2.1
@@ -1478,6 +1478,34 @@
}
#endif
+/* lutex support */
+#if defined(LISP_FEATURE_SB_LUTEX)
+static long
+scav_lutex(lispobj *where, lispobj object)
+{
+ /* scavenge the sap */
+ scavenge(where + 1, 1);
+
+ return sizeof(struct lutex)/sizeof(lispobj);
+}
+
+static lispobj
+trans_lutex(lispobj object)
+{
+ lispobj copied;
+ gc_assert(is_lisp_pointer(object));
+ copied = copy_object(object, sizeof(struct lutex)/sizeof(lispobj));
+
+ return copied;
+}
+
+static long
+size_lutex(lispobj *where)
+{
+ return sizeof(struct lutex)/sizeof(lispobj);
+}
+#endif
+
#define WEAK_POINTER_NWORDS \
CEILING((sizeof(struct weak_pointer) / sizeof(lispobj)), 2)
@@ -1745,6 +1773,9 @@
#else
scavtab[FDEFN_WIDETAG] = scav_fdefn;
#endif
+#ifdef LISP_FEATURE_SB_LUTEX
+ scavtab[LUTEX_WIDETAG] = scav_lutex;
+#endif
/* transport other table, initialized same way as scavtab */
for (i = 0; i < ((sizeof transother)/(sizeof transother[0])); i++)
@@ -1877,6 +1908,9 @@
transother[WEAK_POINTER_WIDETAG] = trans_weak_pointer;
transother[INSTANCE_HEADER_WIDETAG] = trans_boxed;
transother[FDEFN_WIDETAG] = trans_boxed;
+#ifdef LISP_FEATURE_SB_LUTEX
+ transother[LUTEX_WIDETAG] = trans_lutex;
+#endif
/* size table, initialized the same way as scavtab */
for (i = 0; i < ((sizeof sizetab)/(sizeof sizetab[0])); i++)
@@ -2017,6 +2051,9 @@
sizetab[WEAK_POINTER_WIDETAG] = size_weak_pointer;
sizetab[INSTANCE_HEADER_WIDETAG] = size_boxed;
sizetab[FDEFN_WIDETAG] = size_boxed;
+#ifdef LISP_FEATURE_SB_LUTEX
+ sizetab[LUTEX_WIDETAG] = size_lutex;
+#endif
}
Index: interrupt.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/interrupt.c,v
retrieving revision 1.110
retrieving revision 1.110.2.1
diff -u -d -r1.110 -r1.110.2.1
--- interrupt.c 21 Feb 2006 22:59:33 -0000 1.110
+++ interrupt.c 21 Mar 2006 19:28:02 -0000 1.110.2.1
@@ -362,11 +362,21 @@
struct thread *thread;
struct interrupt_data *data;
+ FSHOW_SIGNAL((stderr,
+ "/entering interrupt_handle_pending\n"));
check_blockables_blocked_or_lose();
+ FSHOW_SIGNAL((stderr,
+ "/interrupt_handle_pending 1a\n"));
thread=arch_os_get_current_thread();
+
+ FSHOW_SIGNAL((stderr,
+ "/interrupt_handle_pending 1b\n"));
data=thread->interrupt_data;
+ FSHOW_SIGNAL((stderr,
+ "/interrupt_handle_pending 2\n"));
+
/* If pseudo_atomic_interrupted is set then the interrupt is going
* to be handled now, ergo it's safe to clear it. */
@@ -378,6 +388,8 @@
if (SymbolValue(GC_INHIBIT,thread)==NIL) {
#ifdef LISP_FEATURE_SB_THREAD
if (SymbolValue(STOP_FOR_GC_PENDING,thread) != NIL) {
+ FSHOW_SIGNAL((stderr,
+ "/interrupt_handle_pending 3\n"));
/* another thread has already initiated a gc, this attempt
* might as well be cancelled */
SetSymbolValue(GC_PENDING,NIL,thread);
@@ -458,6 +470,12 @@
#endif
union interrupt_handler handler;
check_blockables_blocked_or_lose();
+#if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_X86)
+ FSHOW_SIGNAL((stderr, " sigtrap handler restoring fs: %x\n",
+ *CONTEXT_ADDR_FROM_STEM(fs)));
+ __asm__ __volatile__ ("movw %w0, %%fs" : : "q"
+ (*CONTEXT_ADDR_FROM_STEM(fs))); /* privilege level */
+#endif
#ifndef LISP_FEATURE_WIN32
if (sigismember(&deferrable_sigset,signal))
check_interrupts_enabled_or_lose(context);
@@ -469,6 +487,8 @@
delivered we appear to have a null FPU control word. */
os_restore_fp_control(context);
#endif
+
+
handler = interrupt_handlers[signal];
if (ARE_SAME_HANDLER(handler.c, SIG_IGN)) {
@@ -651,11 +671,24 @@
maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context)
{
os_context_t *context = arch_os_get_context(&void_context);
- struct thread *thread=arch_os_get_current_thread();
- struct interrupt_data *data=thread->interrupt_data;
+
+ struct thread *thread;
+ struct interrupt_data *data;
+
+#if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_X86)
+ FSHOW_SIGNAL((stderr, " sigtrap handler restoring fs: %x\n",
+ *CONTEXT_ADDR_FROM_STEM(fs)));
+ __asm__ __volatile__ ("movw %w0, %%fs" : : "q"
+ (*CONTEXT_ADDR_FROM_STEM(fs))); /* privilege level */
+#endif
+
+ thread=arch_os_get_current_thread();
+ data=thread->interrupt_data;
+
#ifdef LISP_FEATURE_LINUX
os_restore_fp_control(context);
#endif
+
if(maybe_defer_handler(interrupt_handle_now,data,signal,info,context))
return;
interrupt_handle_now(signal, info, context);
@@ -673,6 +706,14 @@
#ifdef LISP_FEATURE_LINUX
os_restore_fp_control(context);
#endif
+
+#if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_X86)
+ FSHOW_SIGNAL((stderr, " sigtrap handler restoring fs: %x\n",
+ *CONTEXT_ADDR_FROM_STEM(fs)));
+ __asm__ __volatile__ ("movw %w0, %%fs" : : "q"
+ (*CONTEXT_ADDR_FROM_STEM(fs))); /* privilege level */
+#endif
+
check_blockables_blocked_or_lose();
check_interrupts_enabled_or_lose(context);
interrupt_low_level_handlers[signal](signal, info, void_context);
@@ -686,11 +727,23 @@
low_level_maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context)
{
os_context_t *context = arch_os_get_context(&void_context);
- struct thread *thread=arch_os_get_current_thread();
- struct interrupt_data *data=thread->interrupt_data;
+ struct thread *thread;
+ struct interrupt_data *data;
+
+#if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_X86)
+ FSHOW_SIGNAL((stderr, " sigtrap handler restoring fs: %x\n",
+ *CONTEXT_ADDR_FROM_STEM(fs)));
+ __asm__ __volatile__ ("movw %w0, %%fs" : : "q"
+ (*CONTEXT_ADDR_FROM_STEM(fs))); /* privilege level */
+#endif
+
+ thread=arch_os_get_current_thread();
+ data=thread->interrupt_data;
+
#ifdef LISP_FEATURE_LINUX
os_restore_fp_control(context);
#endif
+
if(maybe_defer_handler(low_level_interrupt_handle_now,data,
signal,info,context))
return;
@@ -704,6 +757,8 @@
#ifdef LISP_FEATURE_SB_THREAD
+#define SIG_STOP_FOR_GC_MASK 1 << (SIG_STOP_FOR_GC - 1)
+
void
sig_stop_for_gc_handler(int signal, siginfo_t *info, void *void_context)
{
@@ -711,7 +766,10 @@
struct thread *thread=arch_os_get_current_thread();
sigset_t ss;
- if ((arch_pseudo_atomic_atomic(context) ||
+ FSHOW_SIGNAL((stderr,"CLH: DEBUG!!! thread=%lu sig_stop_for_gc\n",
+ thread->os_thread));
+
+ if ((arch_pseudo_atomic_atomic(context) ||
SymbolValue(GC_INHIBIT,thread) != NIL)) {
SetSymbolValue(STOP_FOR_GC_PENDING,T,thread);
if (SymbolValue(GC_INHIBIT,thread) == NIL)
@@ -735,7 +793,12 @@
sigemptyset(&ss); sigaddset(&ss,SIG_STOP_FOR_GC);
/* It is possible to get SIGCONT (and probably other
* non-blockable signals) here. */
+#ifdef LISP_FEATURE_DARWIN
+ while (sigpending(&ss), !(ss & SIG_STOP_FOR_GC_MASK));
+#else
while (sigwaitinfo(&ss,0) != SIG_STOP_FOR_GC);
+#endif
+
FSHOW_SIGNAL((stderr,"thread=%lu resumed\n",thread->os_thread));
if(thread->state!=STATE_RUNNING) {
lose("sig_stop_for_gc_handler: wrong thread state on wakeup: %ld\n",
Index: interrupt.h
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/interrupt.h,v
retrieving revision 1.25
retrieving revision 1.25.4.1
diff -u -d -r1.25 -r1.25.4.1
--- interrupt.h 17 Oct 2005 10:58:30 -0000 1.25
+++ interrupt.h 21 Mar 2006 19:28:14 -0000 1.25.4.1
@@ -13,6 +13,7 @@
#define _INCLUDE_INTERRUPT_H_
#include <signal.h>
+#include <string.h>
/*
* This is a workaround for some slightly silly Linux/GNU Libc
Index: linux-os.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/linux-os.c,v
retrieving revision 1.60
retrieving revision 1.60.2.1
diff -u -d -r1.60 -r1.60.2.1
--- linux-os.c 21 Feb 2006 23:40:36 -0000 1.60
+++ linux-os.c 21 Mar 2006 19:28:14 -0000 1.60.2.1
@@ -34,6 +34,9 @@
#include "runtime.h"
#include "genesis/static-symbols.h"
#include "genesis/fdefn.h"
+#ifdef LISP_FEATURE_SB_THREAD
+#include "genesis/futex.h"
+#endif
#include <sys/socket.h>
#include <sys/utsname.h>
@@ -60,7 +63,34 @@
size_t os_vm_page_size;
-#ifdef LISP_FEATURE_SB_THREAD
+#if defined(LISP_FEATURE_SB_THREAD)
+#if defined(LISP_FEATURE_SB_LUTEX)
+
+int futex_init(os_sem_t *semaphore)
+{
+ printf("Initializing semaphore @ %p\n", semaphore);
+
+ return sem_init(semaphore, 0, 1);
+}
+
+int futex_wait(os_sem_t *semaphore)
+{
+ printf("Waiting on semaphore %p\n", semaphore);
+ return sem_wait(semaphore);
+}
+
+int futex_wake(os_sem_t *semaphore)
+{
+ printf("Waking on semaphore %p\n", semaphore);
+ return sem_post(semaphore);
+}
+
+int futex_destroy(os_sem_t *semaphore)
+{
+ return sem_destroy(semaphore);
+}
+
+#else
#include <sys/syscall.h>
#include <unistd.h>
#include <errno.h>
@@ -92,6 +122,7 @@
return sys_futex(lock_word,FUTEX_WAKE,n,0);
}
#endif
+#endif
int linux_sparc_siginfo_bug = 0;
@@ -144,12 +175,14 @@
#endif
}
#ifdef LISP_FEATURE_SB_THREAD
+#if !defined(LISP_FEATURE_SB_LUTEX)
futex_wait(futex,-1);
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");
}
+#endif
if(! isnptl()) {
lose("This version of SBCL only works correctly with the NPTL threading\n"
"library. Please use a newer glibc, use an older SBCL, or stop using\n"
Index: linux-os.h
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/linux-os.h,v
retrieving revision 1.13
retrieving revision 1.13.6.1
diff -u -d -r1.13 -r1.13.6.1
--- linux-os.h 19 Jun 2005 19:35:41 -0000 1.13
+++ linux-os.h 21 Mar 2006 19:28:14 -0000 1.13.6.1
@@ -31,6 +31,7 @@
typedef size_t os_vm_size_t;
typedef off_t os_vm_offset_t;
typedef int os_vm_prot_t;
+typedef sem_t os_sem_t;
#define OS_VM_PROT_READ PROT_READ
#define OS_VM_PROT_WRITE PROT_WRITE
Index: runtime.h
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/runtime.h,v
retrieving revision 1.25
retrieving revision 1.25.2.1
diff -u -d -r1.25 -r1.25.2.1
--- runtime.h 6 Mar 2006 10:03:00 -0000 1.25
+++ runtime.h 21 Mar 2006 19:28:14 -0000 1.25.2.1
@@ -35,7 +35,7 @@
* necessarily reentrant. But it can still be very convenient for
* figuring out what's going on when you have a signal handling
* problem.. */
-#define QSHOW_SIGNALS 0
+#define QSHOW_SIGNALS 1
#if QSHOW_SIGNALS
#define FSHOW_SIGNAL FSHOW
@@ -63,6 +63,7 @@
#if defined(LISP_FEATURE_SB_THREAD)
#include <pthread.h>
+#include <semaphore.h>
typedef pthread_t os_thread_t;
#else
typedef pid_t os_thread_t;
Index: save.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/save.c,v
retrieving revision 1.25
retrieving revision 1.25.2.1
diff -u -d -r1.25 -r1.25.2.1
--- save.c 21 Feb 2006 22:59:34 -0000 1.25
+++ save.c 21 Mar 2006 19:28:14 -0000 1.25.2.1
@@ -34,6 +34,11 @@
#include "genesis/static-symbols.h"
#include "genesis/symbol.h"
+#ifdef LISP_FEATURE_SB_LUTEX
+#include "genesis/sap.h"
+#include "genesis/lutex.h"
+#endif
+
static void
write_lispobj(lispobj obj, FILE *file)
{
@@ -76,6 +81,76 @@
return ((data - file_offset) / os_vm_page_size) - 1;
}
+#if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
+/* saving lutexes in the core */
+static void **lutex_addresses;
+static long n_lutexes = 0;
+static long max_lutexes = 0;
+
+static long
+default_scan_action(lispobj *obj)
+{
+ return (sizetab[widetag_of(*obj)])(obj);
+}
+
+static long
+lutex_scan_action(lispobj *obj)
+{
+ /* note the address of the lutex */
+ if(n_lutexes >= max_lutexes) {
+ max_lutexes *= 2;
+ lutex_addresses = realloc(lutex_addresses, max_lutexes * sizeof(void *));
+ }
+
+ {
+ struct lutex *lutex = (struct lutex *) obj;
+ struct sap *semaphore = (struct sap *) native_pointer(lutex->semaphore);
+ lutex_addresses[n_lutexes] = semaphore;
+ n_lutexes++;
+ }
+
+ return (*sizetab[widetag_of(*obj)])(obj);
+}
+
+typedef long (*scan_table[256])(lispobj *obj);
+
+static void
+scan_objects(lispobj *start, long n_words, scan_table table)
+{
+ lispobj *end = start + n_words;
+ lispobj *object_ptr;
+ long n_words_scanned;
+ for (object_ptr = start;
+ object_ptr < end;
+ object_ptr += n_words_scanned) {
+ lispobj obj = *object_ptr;
+
+ n_words_scanned = (table[widetag_of(obj)])(object_ptr);
+ }
+}
+
+static void
+scan_for_lutexes(lispobj *addr, long n_words)
+{
+ int i;
+ scan_table lutex_scan_table;
+
+ /* allocate a little space to get started */
+ lutex_addresses = malloc(16*sizeof(void *));
+ max_lutexes = 16;
+
+ /* initialize the mapping table */
+ for(i = 0; i < ((sizeof lutex_scan_table)/(sizeof lutex_scan_table[0])); ++i) {
+ lutex_scan_table[i] = default_scan_action;
+ }
+
+ lutex_scan_table[LUTEX_WIDETAG] = lutex_scan_action;
+
+ /* do the scan */
+ scan_objects(addr, n_words, lutex_scan_table);
+}
+#endif
+
static void
output_space(FILE *file, int id, lispobj *addr, lispobj *end, os_vm_offset_t file_offset)
{
@@ -88,6 +163,11 @@
bytes = words * sizeof(lispobj);
+#if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
+ printf("scanning space for lutexes...\n");
+ scan_for_lutexes((char *)addr, words);
+#endif
+
printf("writing %d bytes from the %s space at 0x%08lx\n",
bytes, names[id], (unsigned long)addr);
@@ -217,6 +297,22 @@
}
#endif
+#if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
+ if(n_lutexes > 0) {
+ long offset;
+ printf("writing %d lutexes to the core...\n", n_lutexes);
+ write_lispobj(LUTEX_TABLE_CORE_ENTRY_TYPE_CODE, file);
+ /* word count of the entry */
+ write_lispobj(4, file);
+ /* indicate how many lutexes we saved */
+ write_lispobj(n_lutexes, file);
+ /* save the lutexes */
+ offset = write_bytes(file, (char *) lutex_addresses,
+ n_lutexes * sizeof(*lutex_addresses), core_start_pos);
+ write_lispobj(offset, file);
+ }
+#endif
+
write_lispobj(END_CORE_ENTRY_TYPE_CODE, file);
/* Write a trailing header, ignored when parsing the core normally.
Index: thread.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/thread.c,v
retrieving revision 1.62
retrieving revision 1.62.2.1
diff -u -d -r1.62 -r1.62.2.1
--- thread.c 3 Jan 2006 09:52:38 -0000 1.62
+++ thread.c 21 Mar 2006 19:28:14 -0000 1.62.2.1
@@ -59,7 +59,10 @@
int dynamic_values_bytes=4096*sizeof(lispobj); /* same for all threads */
struct thread * volatile all_threads;
extern struct interrupt_data * global_interrupt_data;
+
+#ifdef LISP_FEATURE_LINUX
extern int linux_no_threads_p;
+#endif
#ifdef LISP_FEATURE_SB_THREAD
pthread_mutex_t all_threads_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -345,6 +348,10 @@
pthread_attr_t attr;
sigset_t newset,oldset;
boolean r=1;
+ int retcode, initcode, sizecode, addrcode;
+
+ FSHOW_SIGNAL((stderr,"/create_os_thread: creating new thread\n"));
+
sigemptyset(&newset);
/* Blocking deferrable signals is enough, no need to block
* SIG_STOP_FOR_GC because the child process is not linked onto
@@ -352,12 +359,30 @@
sigaddset_deferrable(&newset);
thread_sigmask(SIG_BLOCK, &newset, &oldset);
- if((pthread_attr_init(&attr)) ||
+ if((initcode = pthread_attr_init(&attr)) ||
+ /* don't ask */
+#if defined(LISP_FEATURE_DARWIN)
+ /* Darwin apparently wants the stack size to be evenly divisible
+ by the page size... */
+ (sizecode = pthread_attr_setstacksize(&attr, THREAD_CONTROL_STACK_SIZE-4096)) ||
+ (addrcode = pthread_attr_setstackaddr(&attr, th->control_stack_start)) ||
+#else
(pthread_attr_setstack(&attr,th->control_stack_start,
THREAD_CONTROL_STACK_SIZE-16)) ||
- (pthread_create
- (kid_tid,&attr,(void *(*)(void *))new_thread_trampoline,th)))
+#endif
+ (retcode = pthread_create
+ (kid_tid,&attr,(void *(*)(void *))new_thread_trampoline,th))) {
+ FSHOW_SIGNAL((stderr, "attr signature %lx\n", attr.__sig));
+ FSHOW_SIGNAL((stderr, "init, size, addr = %d, %d, %d\n", initcode, sizecode, addrcode));
+ FSHOW_SIGNAL((stderr, printf("pthread_create returned %d, errno %d\n", retcode, errno)));
+ FSHOW_SIGNAL((stderr, "wanted stack size %d, min stack size %d\n",
+ THREAD_CONTROL_STACK_SIZE-16, PTHREAD_STACK_MIN));
+ if(retcode < 0) {
+ perror("create_os_thread");
+ }
+
r=0;
+ }
thread_sigmask(SIG_SETMASK,&oldset,0);
return r;
}
@@ -366,7 +391,9 @@
struct thread *th;
os_thread_t kid_tid;
+#ifdef LISP_FEATURE_LINUX
if(linux_no_threads_p) return 0;
+#endif
/* Assuming that a fresh thread struct has no lisp objects in it,
* linking it to all_threads can be left to the thread itself
Index: x86-arch.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/x86-arch.c,v
retrieving revision 1.38
retrieving revision 1.38.2.1
diff -u -d -r1.38 -r1.38.2.1
--- x86-arch.c 15 Mar 2006 03:02:13 -0000 1.38
+++ x86-arch.c 21 Mar 2006 19:28:15 -0000 1.38.2.1
@@ -213,6 +213,14 @@
os_context_t *context = (os_context_t*)void_context;
unsigned int trap;
+#if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_X86)
+ FSHOW_SIGNAL((stderr, " sigtrap handler restoring fs: %x\n",
+ *CONTEXT_ADDR_FROM_STEM(fs)));
+ __asm__ __volatile__ ("movw %w0, %%fs" : : "q"
+ (*CONTEXT_ADDR_FROM_STEM(fs))); /* privilege level */
+#endif
+
+
#ifndef LISP_FEATURE_WIN32
if (single_stepping && (signal==SIGTRAP))
{
@@ -305,6 +313,13 @@
sigill_handler(int signal, siginfo_t *siginfo, void *void_context) {
os_context_t *context = (os_context_t*)void_context;
+#if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_X86)
+ FSHOW_SIGNAL((stderr, " sigill handler restoring fs: %x\n",
+ *CONTEXT_ADDR_FROM_STEM(fs)));
+ __asm__ __volatile__ ("movw %w0, %%fs" : : "q"
+ (*CONTEXT_ADDR_FROM_STEM(fs))); /* privilege level */
+#endif
+
#if defined(LISP_FEATURE_DARWIN)
if (*((unsigned short *)*os_context_pc_addr(context)) == 0x0b0f) {
*os_context_pc_addr(context) += 2;
Index: x86-arch.h
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/x86-arch.h,v
retrieving revision 1.12
retrieving revision 1.12.2.1
diff -u -d -r1.12 -r1.12.2.1
--- x86-arch.h 26 Jan 2006 21:51:32 -0000 1.12
+++ x86-arch.h 21 Mar 2006 19:28:15 -0000 1.12.2.1
@@ -26,11 +26,20 @@
if(*word==value)
lose("recursive get_spinlock: 0x%x,%ld\n",word,value);
do {
+#if defined(LISP_FEATURE_DARWIN)
+ asm ("xor %0,%0;\n\
+ lock/cmpxchg %1,%2"
+ : "=a" (eax)
+ : "r" (value), "m" (*word)
+ : "memory", "cc");
+#else
asm ("xor %0,%0\n\
lock cmpxchg %1,%2"
: "=a" (eax)
: "r" (value), "m" (*word)
: "memory", "cc");
+#endif
+
} while(eax!=0);
#else
*word=value;
@@ -49,10 +58,17 @@
swap_lispobjs(volatile lispobj *dest, lispobj value)
{
lispobj old_value;
+#if defined(LISP_FEATURE_DARWIN)
+ asm ("lock/xchg %0,(%1)"
+ : "=r" (old_value)
+ : "r" (dest), "0" (value)
+ : "memory");
+#else
asm ("lock xchg %0,(%1)"
: "=r" (old_value)
: "r" (dest), "0" (value)
: "memory");
+#endif
return old_value;
}
Index: x86-darwin-os.h
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/x86-darwin-os.h,v
retrieving revision 1.1
retrieving revision 1.1.2.1
diff -u -d -r1.1 -r1.1.2.1
--- x86-darwin-os.h 6 Mar 2006 10:03:59 -0000 1.1
+++ x86-darwin-os.h 21 Mar 2006 19:28:15 -0000 1.1.2.1
@@ -1,10 +1,16 @@
#ifndef _X86_DARWIN_OS_H
#define _X86_DARWIN_OS_H
+#include <architecture/i386/table.h>
+#include <i386/user_ldt.h>
+
static inline os_context_t *arch_os_get_context(void **void_context) {
return (os_context_t *) *void_context;
}
+void set_data_desc_size(data_desc_t* desc, unsigned int size);
+void set_data_desc_addr(data_desc_t* desc, void* addr);
+
#define CONTEXT_ADDR_FROM_STEM(stem) &context->uc_mcontext->ss.stem
#define DARWIN_FIX_CONTEXT(context)
|