diff options
-rw-r--r-- | acinclude.m4 | 20 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | libguile/__scm.h | 8 | ||||
-rw-r--r-- | libguile/gen-scmconfig.c | 7 | ||||
-rw-r--r-- | libguile/gen-scmconfig.h.in | 1 | ||||
-rw-r--r-- | libguile/threads.c | 34 | ||||
-rw-r--r-- | libguile/threads.h | 15 |
7 files changed, 80 insertions, 7 deletions
diff --git a/acinclude.m4 b/acinclude.m4 index 1b836ccbd..ed537d0bd 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -335,6 +335,26 @@ AC_DEFUN([GUILE_GNU_LD_RELRO], [ AC_SUBST([GNU_LD_FLAGS]) ]) +dnl GUILE_THREAD_LOCAL_STORAGE +dnl +dnl Check for compiler thread-local storage (TLS) support. +AC_DEFUN([GUILE_THREAD_LOCAL_STORAGE], [ + AC_CACHE_CHECK([whether the `__thread' storage class is available], + [ac_cv_have_thread_storage_class], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([__thread int tls_integer;], + [tls_integer = 123;])], + [ac_cv_have_thread_storage_class="yes"], + [ac_cv_have_thread_storage_class="no"])]) + + if test "x$ac_cv_have_thread_storage_class" = "xyes"; then + SCM_I_GSC_HAVE_THREAD_STORAGE_CLASS=1 + else + SCM_I_GSC_HAVE_THREAD_STORAGE_CLASS=0 + fi + + AC_SUBST([SCM_I_GSC_HAVE_THREAD_STORAGE_CLASS]) +]) + dnl GUILE_READLINE dnl dnl Check all the things needed by `guile-readline', the Readline diff --git a/configure.ac b/configure.ac index 8c791ca35..d01131100 100644 --- a/configure.ac +++ b/configure.ac @@ -1380,6 +1380,8 @@ AC_DEFINE(PTHREAD_ATTR_GETSTACK_WORKS, [1], [Define when pthread_att_get_stack w CFLAGS="$old_CFLAGS" AC_MSG_RESULT($works) +GUILE_THREAD_LOCAL_STORAGE + fi # with_threads=pthreads diff --git a/libguile/__scm.h b/libguile/__scm.h index d16415454..55f9f49e2 100644 --- a/libguile/__scm.h +++ b/libguile/__scm.h @@ -679,6 +679,14 @@ SCM_API SCM scm_apply_generic (SCM gf, SCM args); #define SCM_C_INLINE_KEYWORD #endif +/* Handling thread-local storage (TLS). */ + +#ifdef SCM_HAVE_THREAD_STORAGE_CLASS +# define SCM_THREAD_LOCAL __thread +#else +# define SCM_THREAD_LOCAL +#endif + #endif /* SCM___SCM_H */ /* diff --git a/libguile/gen-scmconfig.c b/libguile/gen-scmconfig.c index 0e897ca8c..bc0c2df20 100644 --- a/libguile/gen-scmconfig.c +++ b/libguile/gen-scmconfig.c @@ -404,6 +404,13 @@ main (int argc, char *argv[]) pf ("typedef long int scm_t_off;\n"); #endif + pf ("/* Define to 1 if the compiler supports the " + "`__thread' storage class. */\n"); + if (SCM_I_GSC_HAVE_THREAD_STORAGE_CLASS) + pf ("#define SCM_HAVE_THREAD_STORAGE_CLASS\n"); + else + pf ("/* #undef SCM_HAVE_THREAD_STORAGE_CLASS */\n"); + #if USE_DLL_IMPORT pf ("\n"); pf ("/* Define some additional CPP macros on Win32 platforms. */\n"); diff --git a/libguile/gen-scmconfig.h.in b/libguile/gen-scmconfig.h.in index 1be95af94..770e08196 100644 --- a/libguile/gen-scmconfig.h.in +++ b/libguile/gen-scmconfig.h.in @@ -30,6 +30,7 @@ #define SCM_I_GSC_USE_NULL_THREADS @SCM_I_GSC_USE_NULL_THREADS@ #define SCM_I_GSC_NEED_BRACES_ON_PTHREAD_ONCE_INIT @SCM_I_GSC_NEED_BRACES_ON_PTHREAD_ONCE_INIT@ #define SCM_I_GSC_NEED_BRACES_ON_PTHREAD_MUTEX_INITIALIZER @SCM_I_GSC_NEED_BRACES_ON_PTHREAD_MUTEX_INITIALIZER@ +#define SCM_I_GSC_HAVE_THREAD_STORAGE_CLASS @SCM_I_GSC_HAVE_THREAD_STORAGE_CLASS@ #define SCM_I_GSC_HAVE_STRUCT_DIRENT64 @SCM_I_GSC_HAVE_STRUCT_DIRENT64@ /* diff --git a/libguile/threads.c b/libguile/threads.c index 901695cfe..851cf9027 100644 --- a/libguile/threads.c +++ b/libguile/threads.c @@ -290,8 +290,27 @@ unblock_from_queue (SCM queue) /* Getting into and out of guile mode. */ +#ifdef SCM_HAVE_THREAD_STORAGE_CLASS + +/* When thread-local storage (TLS) is available, a pointer to the + current-thread object is kept in TLS. Note that storing the thread-object + itself in TLS (rather than a pointer to some malloc'd memory) is not + possible since thread objects may live longer than the actual thread they + represent. */ +SCM_THREAD_LOCAL scm_i_thread *scm_i_current_thread = NULL; + +# define SET_CURRENT_THREAD(_t) scm_i_current_thread = (_t) + +#else /* !SCM_HAVE_THREAD_STORAGE_CLASS */ + +/* Key used to retrieve the current thread with `pthread_getspecific ()'. */ scm_i_pthread_key_t scm_i_thread_key; +# define SET_CURRENT_THREAD(_t) \ + scm_i_pthread_setspecific (scm_i_thread_key, (_t)) + +#endif /* !SCM_HAVE_THREAD_STORAGE_CLASS */ + static scm_i_pthread_mutex_t thread_admin_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER; static scm_i_thread *all_threads = NULL; @@ -357,7 +376,7 @@ guilify_self_1 (SCM_STACKITEM *base) t->exited = 0; t->guile_mode = 0; - scm_i_pthread_setspecific (scm_i_thread_key, t); + SET_CURRENT_THREAD (t); scm_i_pthread_mutex_lock (&thread_admin_mutex); t->next_thread = all_threads; @@ -475,7 +494,7 @@ on_thread_exit (void *v) t->held_mutex = NULL; } - scm_i_pthread_setspecific (scm_i_thread_key, v); + SET_CURRENT_THREAD (v); /* Ensure the signal handling thread has been launched, because we might be shutting it down. */ @@ -514,9 +533,11 @@ on_thread_exit (void *v) scm_i_pthread_mutex_unlock (&thread_admin_mutex); - scm_i_pthread_setspecific (scm_i_thread_key, NULL); + SET_CURRENT_THREAD (NULL); } +#ifndef SCM_HAVE_THREAD_STORAGE_CLASS + static scm_i_pthread_once_t init_thread_key_once = SCM_I_PTHREAD_ONCE_INIT; static void @@ -525,6 +546,8 @@ init_thread_key (void) scm_i_pthread_key_create (&scm_i_thread_key, NULL); } +#endif + /* Perform any initializations necessary to bring the current thread into guile mode, initializing Guile itself, if necessary. @@ -542,9 +565,12 @@ scm_i_init_thread_for_guile (SCM_STACKITEM *base, SCM parent) { scm_i_thread *t; +#ifndef SCM_HAVE_THREAD_STORAGE_CLASS scm_i_pthread_once (&init_thread_key_once, init_thread_key); +#endif - if ((t = SCM_I_CURRENT_THREAD) == NULL) + t = SCM_I_CURRENT_THREAD; + if (t == NULL) { /* This thread has not been guilified yet. */ diff --git a/libguile/threads.h b/libguile/threads.h index f7908e4fb..5afe45faa 100644 --- a/libguile/threads.h +++ b/libguile/threads.h @@ -194,9 +194,18 @@ SCM_API void scm_dynwind_critical_section (SCM mutex); #ifdef BUILDING_LIBGUILE -# define SCM_I_CURRENT_THREAD \ - ((scm_i_thread *) scm_i_pthread_getspecific (scm_i_thread_key)) -SCM_API scm_i_pthread_key_t scm_i_thread_key; +# ifdef SCM_HAVE_THREAD_STORAGE_CLASS + +SCM_INTERNAL SCM_THREAD_LOCAL scm_i_thread *scm_i_current_thread; +# define SCM_I_CURRENT_THREAD (scm_i_current_thread) + +# else /* !SCM_HAVE_THREAD_STORAGE_CLASS */ + +SCM_INTERNAL scm_i_pthread_key_t scm_i_thread_key; +# define SCM_I_CURRENT_THREAD \ + ((scm_i_thread *) scm_i_pthread_getspecific (scm_i_thread_key)) + +# endif /* !SCM_HAVE_THREAD_STORAGE_CLASS */ # define scm_i_dynwinds() (SCM_I_CURRENT_THREAD->dynwinds) # define scm_i_set_dynwinds(w) (SCM_I_CURRENT_THREAD->dynwinds = (w)) |