From: Nikodemus Siivola Date: Mon, 5 Dec 2011 17:39:57 +0000 (+0200) Subject: fix threaded PPC build, refactor new semaphore code X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;h=d1942842cebf682ea4161792b2920eec7ccfe179;p=sbcl.git fix threaded PPC build, refactor new semaphore code Refactor the recent semaphore code into nicer shape. * No point in having these functions as inline functions. * Move shared logic to os-common.c, and conditionalize it on CANNOT_USE_POSIX_SEM_T, which platform specific headers can define if they implement their own versions. (Darwin now, Windows in the future.) * PPC needs genesis/thread.h in assembly, not thread.h. --- diff --git a/src/runtime/darwin-os.c b/src/runtime/darwin-os.c index affbc72..df53e98 100644 --- a/src/runtime/darwin-os.c +++ b/src/runtime/darwin-os.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -171,3 +172,48 @@ void darwin_init(void) #endif +#ifdef LISP_FEATURE_SB_THREAD + +inline void +os_sem_init(os_sem_t *sem, unsigned int value) +{ + if (KERN_SUCCESS!=semaphore_create(current_mach_task, sem, SYNC_POLICY_FIFO, (int)value)) + lose("os_sem_init(%p): %s", sem, strerror(errno)); +} + +inline void +os_sem_wait(os_sem_t *sem, char *what) +{ + kern_return_t ret; + restart: + FSHOW((stderr, "%s: os_sem_wait(%p)\n", what, sem)); + ret = semaphore_wait(*sem); + FSHOW((stderr, "%s: os_sem_wait(%p) => %s\n", what, sem, + KERN_SUCCESS==ret ? "ok" : strerror(errno))); + switch (ret) { + case KERN_SUCCESS: + return; + case KERN_OPERATION_TIMED_OUT: + fprintf(stderr, "%s: os_sem_wait(%p): %s", what, sem, strerror(errno)); + goto restart; + default: + lose("%s: os_sem_wait(%p): %s", what, sem, strerror(errno)); + } +} + +void +os_sem_post(os_sem_t *sem, char *what) +{ + if (KERN_SUCCESS!=semaphore_signal(*sem)) + lose("%s: os_sem_post(%p): %s", what, sem, strerror(errno)); + FSHOW((stderr, "%s: os_sem_post(%p) ok\n", what, sem)); +} + +void +os_sem_destroy(os_sem_t *sem) +{ + if (-1==semaphore_destroy(current_mach_task, *sem)) + lose("os_sem_destroy(%p): %s", sem, strerror(errno)); +} + +#endif diff --git a/src/runtime/darwin-os.h b/src/runtime/darwin-os.h index a308fb1..9d0e000 100644 --- a/src/runtime/darwin-os.h +++ b/src/runtime/darwin-os.h @@ -40,4 +40,10 @@ extern mach_port_t current_mach_task; void darwin_init(void); +#ifdef LISP_FEATURE_SB_THREAD +#define CANNOT_USE_POSIX_SEM_T +#include +typedef semaphore_t os_sem_t; +#endif + #endif /* _DARWIN_OS_H */ diff --git a/src/runtime/os-common.c b/src/runtime/os-common.c index 3fdf925..fa845bf 100644 --- a/src/runtime/os-common.c +++ b/src/runtime/os-common.c @@ -73,3 +73,41 @@ os_get_errno(void) { return errno; } + + +#if defined(LISP_FEATURE_SB_THREAD) && !defined(CANNOT_USE_POSIX_SEM_T) + +void +os_sem_init(os_sem_t *sem, unsigned int value) +{ + if (-1==sem_init(sem, 0, value)) + lose("os_sem_init(%p, %u): %s", sem, value, strerror(errno)); + FSHOW((stderr, "os_sem_init(%p, %u)\n", sem, value)); +} + +void +os_sem_wait(os_sem_t *sem, char *what) +{ + FSHOW((stderr, "%s: os_sem_wait(%p) ...\n", what, sem)); + while (-1 == sem_wait(sem)) + if (EINTR!=errno) + lose("%s: os_sem_wait(%p): %s", what, sem, strerror(errno)); + FSHOW((stderr, "%s: os_sem_wait(%p) => ok\n", what, sem)); +} + +void +os_sem_post(sem_t *sem, char *what) +{ + if (-1 == sem_post(sem)) + lose("%s: os_sem_post(%p): %s", what, sem, strerror(errno)); + FSHOW((stderr, "%s: os_sem_post(%p)\n", what, sem)); +} + +void +os_sem_destroy(os_sem_t *sem) +{ + if (-1==sem_destroy(sem)) + lose("os_sem_destroy(%p): %s", sem, strerror(errno)); +} + +#endif diff --git a/src/runtime/os.h b/src/runtime/os.h index 8170a70..9dd1649 100644 --- a/src/runtime/os.h +++ b/src/runtime/os.h @@ -195,4 +195,15 @@ extern char *os_get_runtime_executable_path(int external_path); typedef os_vm_size_t word_t; #define WORD_FMTX OS_VM_SIZE_FMTX +#ifdef LISP_FEATURE_SB_THREAD +# ifndef CANNOT_USE_POSIX_SEM_T +# include + typedef sem_t os_sem_t; +# endif + void os_sem_init(os_sem_t *sem, unsigned int value); + void os_sem_wait(os_sem_t *sem, char *what); + void os_sem_post(os_sem_t *sem, char *what); + void os_sem_destroy(os_sem_t *sem); +#endif + #endif diff --git a/src/runtime/ppc-assem.S b/src/runtime/ppc-assem.S index 128b3e0..3f0dd99 100644 --- a/src/runtime/ppc-assem.S +++ b/src/runtime/ppc-assem.S @@ -10,7 +10,7 @@ #include "genesis/funcallable-instance.h" #include "genesis/static-symbols.h" #ifdef LISP_FEATURE_SB_THREAD -#include "thread.h" +#include "genesis/thread.h" #endif #ifdef LISP_FEATURE_DARWIN diff --git a/src/runtime/thread.c b/src/runtime/thread.c index 1e8402a..7a18c5a 100644 --- a/src/runtime/thread.c +++ b/src/runtime/thread.c @@ -119,6 +119,80 @@ unlink_thread(struct thread *th) if (th->next) th->next->prev = th->prev; } + +/* Only access thread state with blockables blocked. */ +lispobj +thread_state(struct thread *thread) +{ + lispobj state; + sigset_t old; + block_blockable_signals(NULL, &old); + os_sem_wait(thread->state_sem, "thread_state"); + state = thread->state; + os_sem_post(thread->state_sem, "thread_state"); + thread_sigmask(SIG_SETMASK, &old, NULL); + return state; +} + +void +set_thread_state(struct thread *thread, lispobj state) +{ + int i, waitcount = 0; + sigset_t old; + block_blockable_signals(NULL, &old); + os_sem_wait(thread->state_sem, "set_thread_state"); + if (thread->state != state) { + if ((STATE_STOPPED==state) || + (STATE_DEAD==state)) { + waitcount = thread->state_not_running_waitcount; + thread->state_not_running_waitcount = 0; + for (i=0; istate_not_running_sem, "set_thread_state (not running)"); + } + if ((STATE_RUNNING==state) || + (STATE_DEAD==state)) { + waitcount = thread->state_not_stopped_waitcount; + thread->state_not_stopped_waitcount = 0; + for (i=0; istate_not_stopped_sem, "set_thread_state (not stopped)"); + } + thread->state = state; + } + os_sem_post(thread->state_sem, "set_thread_state"); + thread_sigmask(SIG_SETMASK, &old, NULL); +} + +void +wait_for_thread_state_change(struct thread *thread, lispobj state) +{ + sigset_t old; + os_sem_t *wait_sem; + block_blockable_signals(NULL, &old); + start: + os_sem_wait(thread->state_sem, "wait_for_thread_state_change"); + if (thread->state == state) { + switch (state) { + case STATE_RUNNING: + wait_sem = thread->state_not_running_sem; + thread->state_not_running_waitcount++; + break; + case STATE_STOPPED: + wait_sem = thread->state_not_stopped_sem; + thread->state_not_stopped_waitcount++; + break; + default: + lose("Invalid state in wait_for_thread_state_change: "OBJ_FMTX"\n", state); + } + } else { + wait_sem = NULL; + } + os_sem_post(thread->state_sem, "wait_for_thread_state_change"); + if (wait_sem) { + os_sem_wait(wait_sem, "wait_for_thread_state_change"); + goto start; + } + thread_sigmask(SIG_SETMASK, &old, NULL); +} #endif static int diff --git a/src/runtime/thread.h b/src/runtime/thread.h index 71d3342..fcc51b0 100644 --- a/src/runtime/thread.h +++ b/src/runtime/thread.h @@ -4,8 +4,6 @@ #include #include #include -#include -#include #include "sbcl.h" #include "globals.h" #include "runtime.h" @@ -18,16 +16,6 @@ struct alloc_region { }; #include "genesis/symbol.h" #include "genesis/static-symbols.h" -#ifdef LISP_FEATURE_SB_THREAD -# ifndef LISP_FEATURE_DARWIN -# include - typedef sem_t os_sem_t; -# else -# include - typedef semaphore_t os_sem_t; -# endif -#endif - #include "genesis/thread.h" #include "genesis/fdefn.h" #include "interrupt.h" @@ -37,162 +25,9 @@ struct alloc_region { }; #define STATE_DEAD MAKE_FIXNUM(3) #ifdef LISP_FEATURE_SB_THREAD - -# ifndef LISP_FEATURE_DARWIN - -static inline void -os_sem_init(os_sem_t *sem, unsigned int value) -{ - if (-1==sem_init(sem, 0, value)) - lose("os_sem_init(%p, %u): %s", sem, value, strerror(errno)); - FSHOW((stderr, "os_sem_init(%p, %u)\n", sem, value)); -} - -static inline void -os_sem_wait(os_sem_t *sem, char *what) -{ - FSHOW((stderr, "%s: os_sem_wait(%p) ...\n", what, sem)); - while (-1 == sem_wait(sem)) - if (EINTR!=errno) - lose("%s: os_sem_wait(%p): %s", what, sem, strerror(errno)); - FSHOW((stderr, "%s: os_sem_wait(%p) => ok\n", what, sem)); -} - -static inline void -os_sem_post(sem_t *sem, char *what) -{ - if (-1 == sem_post(sem)) - lose("%s: os_sem_post(%p): %s", what, sem, strerror(errno)); - FSHOW((stderr, "%s: os_sem_post(%p)\n", what, sem)); -} - -static inline void -os_sem_destroy(os_sem_t *sem) -{ - if (-1==sem_destroy(sem)) - lose("os_sem_destroy(%p): %s", sem, strerror(errno)); -} - -# else - -static inline void -os_sem_init(os_sem_t *sem, unsigned int value) -{ - if (KERN_SUCCESS!=semaphore_create(current_mach_task, sem, SYNC_POLICY_FIFO, (int)value)) - lose("os_sem_init(%p): %s", sem, strerror(errno)); -} - -static inline void -os_sem_wait(os_sem_t *sem, char *what) -{ - kern_return_t ret; - restart: - FSHOW((stderr, "%s: os_sem_wait(%p)\n", what, sem)); - ret = semaphore_wait(*sem); - FSHOW((stderr, "%s: os_sem_wait(%p) => %s\n", what, sem, - KERN_SUCCESS==ret ? "ok" : strerror(errno))); - switch (ret) { - case KERN_SUCCESS: - return; - case KERN_OPERATION_TIMED_OUT: - fprintf(stderr, "%s: os_sem_wait(%p): %s", what, sem, strerror(errno)); - goto restart; - default: - lose("%s: os_sem_wait(%p): %s", what, sem, strerror(errno)); - } -} - -static inline void -os_sem_post(os_sem_t *sem, char *what) -{ - if (KERN_SUCCESS!=semaphore_signal(*sem)) - lose("%s: os_sem_post(%p): %s", what, sem, strerror(errno)); - FSHOW((stderr, "%s: os_sem_post(%p) ok\n", what, sem)); -} - -static inline void -os_sem_destroy(os_sem_t *sem) -{ - if (-1==semaphore_destroy(current_mach_task, *sem)) - lose("os_sem_destroy(%p): %s", sem, strerror(errno)); -} - -# endif - -/* Only access thread state with blockables blocked. */ -static inline lispobj -thread_state(struct thread *thread) -{ - lispobj state; - sigset_t old; - block_blockable_signals(NULL, &old); - os_sem_wait(thread->state_sem, "thread_state"); - state = thread->state; - os_sem_post(thread->state_sem, "thread_state"); - thread_sigmask(SIG_SETMASK, &old, NULL); - return state; -} - -static inline void -set_thread_state(struct thread *thread, lispobj state) -{ - int i, waitcount = 0; - sigset_t old; - block_blockable_signals(NULL, &old); - os_sem_wait(thread->state_sem, "set_thread_state"); - if (thread->state != state) { - if ((STATE_STOPPED==state) || - (STATE_DEAD==state)) { - waitcount = thread->state_not_running_waitcount; - thread->state_not_running_waitcount = 0; - for (i=0; istate_not_running_sem, "set_thread_state (not running)"); - } - if ((STATE_RUNNING==state) || - (STATE_DEAD==state)) { - waitcount = thread->state_not_stopped_waitcount; - thread->state_not_stopped_waitcount = 0; - for (i=0; istate_not_stopped_sem, "set_thread_state (not stopped)"); - } - thread->state = state; - } - os_sem_post(thread->state_sem, "set_thread_state"); - thread_sigmask(SIG_SETMASK, &old, NULL); -} - -static inline void -wait_for_thread_state_change(struct thread *thread, lispobj state) -{ - sigset_t old; - os_sem_t *wait_sem; - block_blockable_signals(NULL, &old); - start: - os_sem_wait(thread->state_sem, "wait_for_thread_state_change"); - if (thread->state == state) { - switch (state) { - case STATE_RUNNING: - wait_sem = thread->state_not_running_sem; - thread->state_not_running_waitcount++; - break; - case STATE_STOPPED: - wait_sem = thread->state_not_stopped_sem; - thread->state_not_stopped_waitcount++; - break; - default: - lose("Invalid state in wait_for_thread_state_change: "OBJ_FMTX"\n", state); - } - } else { - wait_sem = NULL; - } - os_sem_post(thread->state_sem, "wait_for_thread_state_change"); - if (wait_sem) { - os_sem_wait(wait_sem, "wait_for_thread_state_change"); - goto start; - } - thread_sigmask(SIG_SETMASK, &old, NULL); -} - +lispobj thread_state(struct thread *thread); +void set_thread_state(struct thread *thread, lispobj state); +void wait_for_thread_state_change(struct thread *thread, lispobj state); extern pthread_key_t lisp_thread; #endif