X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fthread.c;h=53ae855865c4a92f8df253136b0d9c74bae9c4e4;hb=743831e679b673a5680a0afd8402911516bf50e2;hp=ebdafaaf9a24645a73c459f6df2993d5388ff628;hpb=dca9c046b59d56ecddf36169f6994119ef8aeace;p=sbcl.git diff --git a/src/runtime/thread.c b/src/runtime/thread.c index ebdafaa..53ae855 100644 --- a/src/runtime/thread.c +++ b/src/runtime/thread.c @@ -33,7 +33,6 @@ #include "runtime.h" #include "validate.h" /* for BINDING_STACK_SIZE etc */ -#include "alloc.h" #include "thread.h" #include "arch.h" #include "target-arch-os.h" @@ -43,6 +42,7 @@ #include "genesis/cons.h" #include "genesis/fdefn.h" #include "interr.h" /* for lose() */ +#include "alloc.h" #include "gc-internal.h" #ifdef LISP_FEATURE_WIN32 @@ -63,8 +63,6 @@ #define LOCK_CREATE_THREAD #endif -#define ALIEN_STACK_SIZE (1*1024*1024) /* 1Mb size chosen at random */ - #ifdef LISP_FEATURE_SB_THREAD struct thread_post_mortem { #ifdef DELAY_THREAD_POST_MORTEM @@ -94,6 +92,7 @@ static pthread_mutex_t create_thread_lock = PTHREAD_MUTEX_INITIALIZER; #ifdef LISP_FEATURE_GCC_TLS __thread struct thread *current_thread; #endif +pthread_key_t lisp_thread = 0; #endif #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64) @@ -129,13 +128,21 @@ initial_thread_trampoline(struct thread *th) #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64) lispobj *args = NULL; #endif +#ifdef LISP_FEATURE_SB_THREAD + pthread_setspecific(lisp_thread, (void *)1); +#endif function = th->no_tls_value_marker; th->no_tls_value_marker = NO_TLS_VALUE_MARKER_WIDETAG; if(arch_os_thread_init(th)==0) return 1; link_thread(th); th->os_thread=thread_self(); #ifndef LISP_FEATURE_WIN32 - protect_control_stack_guard_page(1); + protect_control_stack_hard_guard_page(1, NULL); + protect_binding_stack_hard_guard_page(1, NULL); + protect_alien_stack_hard_guard_page(1, NULL); + protect_control_stack_guard_page(1, NULL); + protect_binding_stack_guard_page(1, NULL); + protect_alien_stack_guard_page(1, NULL); #endif #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64) @@ -258,8 +265,9 @@ new_thread_trampoline(struct thread *th) int result, lock_ret; FSHOW((stderr,"/creating thread %lu\n", thread_self())); - check_deferrables_blocked_or_lose(); - check_gc_signals_unblocked_or_lose(); + check_deferrables_blocked_or_lose(0); + check_gc_signals_unblocked_or_lose(0); + pthread_setspecific(lisp_thread, (void *)1); function = th->no_tls_value_marker; th->no_tls_value_marker = NO_TLS_VALUE_MARKER_WIDETAG; if(arch_os_thread_init(th)==0) { @@ -268,7 +276,9 @@ new_thread_trampoline(struct thread *th) } th->os_thread=thread_self(); - protect_control_stack_guard_page(1); + protect_control_stack_guard_page(1, NULL); + protect_binding_stack_guard_page(1, NULL); + protect_alien_stack_guard_page(1, NULL); /* Since GC can only know about this thread from the all_threads * list and we're just adding this thread to it, there is no * danger of deadlocking even with SIG_STOP_FOR_GC blocked (which @@ -282,7 +292,7 @@ new_thread_trampoline(struct thread *th) result = funcall0(function); /* Block GC */ - block_blockable_signals(); + block_blockable_signals(0, 0); set_thread_state(th, STATE_DEAD); /* SIG_STOP_FOR_GC is blocked and GC might be waiting for this @@ -403,6 +413,7 @@ create_thread_struct(lispobj initial_function) { th->binding_stack_start= (lispobj*)((void*)th->control_stack_start+thread_control_stack_size); th->control_stack_end = th->binding_stack_start; + th->control_stack_guard_page_protected = T; th->alien_stack_start= (lispobj*)((void*)th->binding_stack_start+BINDING_STACK_SIZE); th->binding_stack_pointer=th->binding_stack_start; @@ -470,6 +481,9 @@ create_thread_struct(lispobj initial_function) { } th->interrupt_data->pending_handler = 0; th->interrupt_data->gc_blocked_deferrables = 0; +#ifdef LISP_FEATURE_PPC + th->interrupt_data->allocation_trap_context = 0; +#endif th->no_tls_value_marker=initial_function; th->stepping = NIL; @@ -484,6 +498,9 @@ kern_return_t mach_thread_init(mach_port_t thread_exception_port); void create_initial_thread(lispobj initial_function) { struct thread *th=create_thread_struct(initial_function); +#ifdef LISP_FEATURE_SB_THREAD + pthread_key_create(&lisp_thread, 0); +#endif if(th) { #ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER setup_mach_exception_handling_thread(); @@ -512,7 +529,7 @@ boolean create_os_thread(struct thread *th,os_thread_t *kid_tid) /* Blocking deferrable signals is enough, no need to block * SIG_STOP_FOR_GC because the child process is not linked onto * all_threads until it's ready. */ - thread_sigmask(SIG_BLOCK, &deferrable_sigset, &oldset); + block_deferrable_signals(0, &oldset); #ifdef LOCK_CREATE_THREAD retcode = pthread_mutex_lock(&create_thread_lock); @@ -521,13 +538,15 @@ boolean create_os_thread(struct thread *th,os_thread_t *kid_tid) #endif if((initcode = pthread_attr_init(th->os_attr)) || - /* call_into_lisp_first_time switches the stack for the initial thread. For the - * others, we use this. */ - (pthread_attr_setstack(th->os_attr,th->control_stack_start,thread_control_stack_size)) || + /* call_into_lisp_first_time switches the stack for the initial + * thread. For the others, we use this. */ + (pthread_attr_setstack(th->os_attr,th->control_stack_start, + thread_control_stack_size)) || (retcode = pthread_create (kid_tid,th->os_attr,(void *(*)(void *))new_thread_trampoline,th))) { FSHOW_SIGNAL((stderr, "init = %d\n", initcode)); - FSHOW_SIGNAL((stderr, printf("pthread_create returned %d, errno %d\n", retcode, errno))); + FSHOW_SIGNAL((stderr, "pthread_create returned %d, errno %d\n", + retcode, errno)); if(retcode < 0) { perror("create_os_thread"); } @@ -550,7 +569,7 @@ os_thread_t create_thread(lispobj initial_function) { /* Must defend against async unwinds. */ if (SymbolValue(INTERRUPTS_ENABLED, thread) != NIL) lose("create_thread is not safe when interrupts are enabled.\n"); - + /* Assuming that a fresh thread struct has no lisp objects in it, * linking it to all_threads can be left to the thread itself * without fear of gc lossage. initial_function violates this @@ -690,39 +709,51 @@ thread_yield() int kill_safely(os_thread_t os_thread, int signal) { + FSHOW_SIGNAL((stderr,"/kill_safely: %lu, %d\n", os_thread, signal)); + { #ifdef LISP_FEATURE_SB_THREAD - sigset_t oldset; - struct thread *thread; - /* pthread_kill is not async signal safe and we don't want to be - * interrupted while holding the lock. */ - thread_sigmask(SIG_BLOCK, &deferrable_sigset, &oldset); - pthread_mutex_lock(&all_threads_lock); - for (thread = all_threads; thread; thread = thread->next) { - if (thread->os_thread == os_thread) { - int status = pthread_kill(os_thread, signal); - if (status) - lose("kill_safely: pthread_kill failed with %d\n", status); - break; + sigset_t oldset; + struct thread *thread; + /* pthread_kill is not async signal safe and we don't want to be + * interrupted while holding the lock. */ + block_deferrable_signals(0, &oldset); + pthread_mutex_lock(&all_threads_lock); + for (thread = all_threads; thread; thread = thread->next) { + if (thread->os_thread == os_thread) { + int status = pthread_kill(os_thread, signal); + if (status) + lose("kill_safely: pthread_kill failed with %d\n", status); + break; + } } - } - pthread_mutex_unlock(&all_threads_lock); - thread_sigmask(SIG_SETMASK,&oldset,0); - if (thread) - return 0; - else - return -1; + pthread_mutex_unlock(&all_threads_lock); + thread_sigmask(SIG_SETMASK,&oldset,0); + if (thread) + return 0; + else + return -1; #else - int status; - if (os_thread != getpid()) - lose("kill_safely: who do you want to kill? %d?\n", os_thread); - status = kill(os_thread, signal); - if (status == 0) { - return 0; - } else if (status == ESRCH) { - return -1; - } else { - lose("cannot send signal %d to process %lu: %d, %s\n", - signal, os_thread, status, strerror(status)); - } + int status; + if (os_thread != 0) + lose("kill_safely: who do you want to kill? %d?\n", os_thread); + /* Dubious (as in don't know why it works) workaround for the + * signal sometimes not being generated on darwin. */ +#ifdef LISP_FEATURE_DARWIN + { + sigset_t oldset; + sigprocmask(SIG_BLOCK, &deferrable_sigset, &oldset); + status = raise(signal); + sigprocmask(SIG_SETMASK,&oldset,0); + } +#else + status = raise(signal); +#endif + if (status == 0) { + return 0; + } else { + lose("cannot raise signal %d, %d %s\n", + signal, status, strerror(errno)); + } #endif + } }