[m-rev.] for review: thread-local storage

Peter Wang wangp at students.cs.mu.OZ.AU
Mon Jul 3 18:00:11 AEST 2006


On saturn, for a program sitting in a tight loop only, asm_jump.par.gc
is ~6 times faster after this patch.  asm_jump.gc is still ~1.4 times
faster than that.


Estimated hours taken: 5
Branches: main

When possible, make use of the gcc `__thread' extension for introducing
thread-local variables.  Currently we use the POSIX thread facility for storing
the address of the Mercury engine that is running on the current thread, i.e.
pthread_getspecific/pthread_setspecific.  If gcc global registers are not
used, then each access of a Mercury register incurs a call to
`pthread_getspecific'.  Using the `__thread' extension is very much faster.

(If gcc global registers are used then the address of the Mercury engine is
kept in a hardward register.)


configure.in:
	Check if compiler has the `__thread' extension.

runtime/mercury_conf.h.in:
	#define MR_TLS if `__thread' can be used.

runtime/mercury_context.c:
runtime/mercury_engine.h:
runtime/mercury_thread.c:
	Make `MR_thread_engine_base' a thread-local variable if possible,
	instead of using pthread_getspecific().

	#define MR_set_thread_engine_base() to hide the differences between
	when `__thread' is used or not.


Index: configure.in
===================================================================
RCS file: /home/mercury1/repository/mercury/configure.in,v
retrieving revision 1.455
diff -u -r1.455 configure.in
--- configure.in	28 Jun 2006 08:14:18 -0000	1.455
+++ configure.in	3 Jul 2006 07:37:02 -0000
@@ -2569,6 +2569,22 @@
 
 #-----------------------------------------------------------------------------#
 
+AC_MSG_CHECKING(whether we can use thread-local storage class extension)
+AC_CACHE_VAL(mercury_cv_tls,
+	AC_TRY_COMPILE([],[
+		static __thread int thread_local_variable;
+	],
+	[mercury_cv_tls=yes],
+	[mercury_cv_tls=no])
+)
+AC_MSG_RESULT($mercury_cv_tls)
+
+if test "$mercury_cv_tls" = yes; then
+	AC_DEFINE(MR_TLS)
+fi
+
+#-----------------------------------------------------------------------------#
+
 #
 # Figure out which is the best grade to use for various different purposes.
 # In particular, choose the default grade for compiling applications.
Index: runtime/mercury_conf.h.in
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf.h.in,v
retrieving revision 1.54
diff -u -r1.54 mercury_conf.h.in
--- runtime/mercury_conf.h.in	28 Jun 2006 04:46:21 -0000	1.54
+++ runtime/mercury_conf.h.in	3 Jul 2006 06:23:00 -0000
@@ -358,8 +358,11 @@
 ** Digital Unix doesn't conform to the letter of the Posix standard
 ** for Pthreads.
 **
+** MR_TLS is defined if the thread-local storage extension is supported.
+** That is, the compiler extends the C language with the `__thread' specifier.
 */
 #undef MR_DIGITAL_UNIX_PTHREADS
+#undef MR_TLS
 
 /*
 ** The bytecode files represent floats in 64-bit IEEE format.
Index: runtime/mercury_context.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_context.c,v
retrieving revision 1.45
diff -u -r1.45 mercury_context.c
--- runtime/mercury_context.c	29 Jun 2006 03:53:34 -0000	1.45
+++ runtime/mercury_context.c	3 Jul 2006 06:23:00 -0000
@@ -69,7 +69,9 @@
     pthread_mutex_init(&free_context_list_lock, MR_MUTEX_ATTR);
     pthread_mutex_init(&MR_global_lock, MR_MUTEX_ATTR);
     pthread_mutex_init(&MR_pending_contexts_lock, MR_MUTEX_ATTR);
+  #ifndef MR_TLS
     MR_KEY_CREATE(&MR_engine_base_key, NULL);
+  #endif
     MR_KEY_CREATE(&MR_exception_handler_key, NULL);
 
 #endif
Index: runtime/mercury_engine.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_engine.h,v
retrieving revision 1.38
diff -u -r1.38 mercury_engine.h
--- runtime/mercury_engine.h	30 Mar 2006 06:55:59 -0000	1.38
+++ runtime/mercury_engine.h	3 Jul 2006 06:19:03 -0000
@@ -400,10 +400,20 @@
 
 #ifdef  MR_THREAD_SAFE
 
-  extern MercuryThreadKey   MR_engine_base_key;
+  #ifdef MR_TLS
+    extern __thread MercuryEngine *MR_thread_engine_base;
 
-  #define MR_thread_engine_base \
-    ((MercuryEngine *) MR_GETSPECIFIC(MR_engine_base_key))
+    #define MR_set_thread_engine_base(eng) \
+      do { MR_thread_engine_base = eng; } while (0)
+  #else
+    extern MercuryThreadKey   MR_engine_base_key;
+
+    #define MR_thread_engine_base \
+      ((MercuryEngine *) MR_GETSPECIFIC(MR_engine_base_key))
+
+    #define MR_set_thread_engine_base(eng) \
+      pthread_setspecific(MR_engine_base_key, eng)
+  #endif
 
   #if MR_NUM_REAL_REGS > 0
     #define MR_ENGINE_BASE_REGISTER
Index: runtime/mercury_thread.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_thread.c,v
retrieving revision 1.23
diff -u -r1.23 mercury_thread.c
--- runtime/mercury_thread.c	16 Sep 2005 16:43:55 -0000	1.23
+++ runtime/mercury_thread.c	3 Jul 2006 06:13:51 -0000
@@ -19,7 +19,11 @@
 
 #ifdef  MR_THREAD_SAFE
   MercuryThreadKey  MR_exception_handler_key;
-  MercuryThreadKey  MR_engine_base_key;
+  #ifdef MR_TLS
+    __thread MercuryEngine *MR_thread_engine_base;
+  #else
+    MercuryThreadKey MR_engine_base_key;
+  #endif
   MercuryLock       MR_global_lock;
 #endif
 
@@ -80,14 +84,14 @@
     ** Check to see whether there is already an engine that is initialized
     ** in this thread.  If so we just return, there's nothing for us to do.
     */
-    if (MR_GETSPECIFIC(MR_engine_base_key)) {
+    if (MR_thread_engine_base != NULL) {
         return MR_FALSE;
     }
 #endif
     eng = MR_create_engine();
 
 #ifdef MR_THREAD_SAFE
-    pthread_setspecific(MR_engine_base_key, eng);
+    MR_set_thread_engine_base(eng);
     MR_restore_registers();
   #ifdef MR_ENGINE_BASE_REGISTER
     MR_engine_base_word = (MR_Word) eng;
@@ -133,8 +137,8 @@
 #ifdef MR_THREAD_SAFE
     MercuryEngine   *eng;
 
-    eng = MR_GETSPECIFIC(MR_engine_base_key);
-    pthread_setspecific(MR_engine_base_key, NULL);
+    eng = MR_thread_engine_base;
+    MR_set_thread_engine_base(NULL);
     /*
     ** XXX calling destroy_engine(eng) here appears to segfault.
     ** This should probably be investigated and fixed.
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list