summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--acinclude.m420
-rw-r--r--configure.ac2
-rw-r--r--libguile/__scm.h8
-rw-r--r--libguile/gen-scmconfig.c7
-rw-r--r--libguile/gen-scmconfig.h.in1
-rw-r--r--libguile/threads.c34
-rw-r--r--libguile/threads.h15
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))