Commits

Taavi Burns committed 6d6c66e

WIP re-implementing __thread locals using the POSIX pthread interface, so it works on OSX.

Next up is fixing rpython/translator/stm/src_stm/et.c and rpython/translator/stm/src_stm/rpyintf.c .

Comments (0)

Files changed (4)

rpython/translator/c/funcgen.py

         # XXX
         from rpython.rtyper.lltypesystem.rstr import STR
         format = ['%s']
-        argv = ['pypy_debug_threadid']
+        argv = ['get_debug_tls()->pypy_debug_threadid']
         free_line = ""
         for arg in op.args:
             T = arg.concretetype

rpython/translator/c/node.py

         self._funccodegen_owner = None
 
     def getptrname(self):
+        if self.is_thread_local():
+            return '((%s)pthread_getspecific(%s_tls_key))' % (
+                self.implementationtypename.replace('@', '*'),
+                self.name)
         return '(&%s)' % self.name
 
     def getTYPE(self):
         if llgroup.member_of_group(self.obj):
             return
         type, name = self.get_declaration()
+        if self.is_thread_local():
+            yield 'extern pthread_key_t ' + name + '_tls_key;'
+            return
         yield '%s;' % (
             forward_cdecl(type, name, self.db.standalone,
                           self.is_thread_local()))
     def implementation(self):
         if llgroup.member_of_group(self.obj):
             return []
+        type, name = self.get_declaration()
+        if self.is_thread_local():
+            return [
+                'pthread_key_t ' + name + '_tls_key;'
+            ]
         lines = list(self.initializationexpr())
-        type, name = self.get_declaration()
         if name != self.name:
             lines[0] = '{ ' + lines[0]    # extra braces around the 'a' part
             lines[-1] += ' }'             # of the union
         return lines
 
     def startupcode(self):
+        if self.is_thread_local():
+            return [
+                "if (!pthread_key_create(&%s_tls_key, NULL)) {" % self.name,
+                '    error = "failed to create pthread TLS key";',
+                "}",
+            ]
         return []
 
     def getlength(self):

rpython/translator/c/src/debug_print.c

 #include <unistd.h>
 #include <time.h>
 #include <sys/time.h>
+#include <pthread.h>
 #else
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
+#error threadlocals not implemented on windows here yet
 #endif
 #include "common_header.h"
 #include "src/profiling.h"
 #include "src/debug_print.h"
 
-__thread long pypy_have_debug_prints = -1;
 FILE *pypy_debug_file = NULL;   /* XXX make it thread-local too? */
 static unsigned char debug_ready = 0;
 static unsigned char debug_profile = 0;
-__thread char debug_start_colors_1[32];
-__thread char debug_start_colors_2[28];
-__thread char pypy_debug_threadid[16];
 static char *debug_stop_colors = "";
 static char *debug_prefix = NULL;
 
+
+/* TLS STUFF */
+
+pthread_key_t debug_tls_key = 0;
+
+static pthread_once_t tls_init_once_control = PTHREAD_ONCE_INIT;
+
+static void tls_destructor(void *tls)
+{
+  pthread_setspecific(debug_tls_key, NULL);
+  free(tls);
+}
+
+static void tls_init(void)
+{
+  pthread_key_create(&debug_tls_key, tls_destructor);
+}
+
+debug_tls_t *get_debug_tls(void)
+{
+  debug_tls_t *debug_tls;
+  debug_tls = pthread_getspecific(debug_tls_key);
+  if (!debug_tls)
+    {
+      debug_tls = malloc(sizeof(debug_tls_t));
+      debug_tls->pypy_have_debug_prints = -1;
+      pthread_setspecific(debug_tls_key, debug_tls);
+    }
+  return debug_tls;
+}
+
+/* TLS STUFF */
+
+
 static void pypy_debug_open(void)
 {
   char *filename = getenv("PYPYLOG");
+  pthread_once(&tls_init_once_control, tls_init);
   if (filename)
 #ifndef _WIN32
     unsetenv("PYPYLOG");   /* don't pass it to subprocesses */
 {
     revision_t counter;
     char *p;
+    debug_tls_t *debug_tls = get_debug_tls();
     while (1) {
         counter = threadcounter;
         if (bool_cas(&threadcounter, counter, counter + 1))
     }
     if (debug_stop_colors[0] == 0) {
         /* not a tty output: no colors */
-        sprintf(debug_start_colors_1, "%d# ", (int)counter);
-        sprintf(debug_start_colors_2, "%d# ", (int)counter);
-        sprintf(pypy_debug_threadid, "%d#", (int)counter);
+        sprintf(debug_tls->debug_start_colors_1, "%d# ", (int)counter);
+        sprintf(debug_tls->debug_start_colors_2, "%d# ", (int)counter);
+        sprintf(debug_tls->pypy_debug_threadid, "%d#", (int)counter);
     }
     else {
         /* tty output */
         int color = 31 + (int)(counter % 7);
-        sprintf(debug_start_colors_1, "\033[%dm%d# \033[1m",
+        sprintf(debug_tls->debug_start_colors_1, "\033[%dm%d# \033[1m",
                 color, (int)counter);
-        sprintf(debug_start_colors_2, "\033[%dm%d# ",
+        sprintf(debug_tls->debug_start_colors_2, "\033[%dm%d# ",
                 color, (int)counter);
-        sprintf(pypy_debug_threadid, "\033[%dm%d#\033[0m",
+        sprintf(debug_tls->pypy_debug_threadid, "\033[%dm%d#\033[0m",
                 color, (int)counter);
     }
 }
 {
   pypy_debug_ensure_opened();
   /* Enter a nesting level.  Nested debug_prints are disabled by default
-     because the following left shift introduces a 0 in the last bit.
+     because the following left shift introduces a 1 in the last bit.
      Note that this logic assumes that we are never going to nest
      debug_starts more than 31 levels (63 on 64-bits). */
-  pypy_have_debug_prints <<= 1;
+  debug_tls_t *debug_tls = get_debug_tls();
+  debug_tls->pypy_have_debug_prints <<= 1;
   if (!debug_profile)
     {
       /* non-profiling version */
           return;
         }
       /* else make this subsection active */
-      pypy_have_debug_prints |= 1;
+      debug_tls->pypy_have_debug_prints |= 1;
     }
-  if (!debug_start_colors_1[0])
+  if (!debug_tls->debug_start_colors_1[0])
     _prepare_display_colors();
-  display_startstop("{", "", category, debug_start_colors_1);
+  display_startstop("{", "", category, debug_tls->debug_start_colors_1);
 }
 
 void pypy_debug_stop(const char *category)
 {
-  if (debug_profile | (pypy_have_debug_prints & 1))
-    display_startstop("", "}", category, debug_start_colors_2);
-  pypy_have_debug_prints >>= 1;
+  debug_tls_t *debug_tls = get_debug_tls();
+  if (debug_profile | (debug_tls->pypy_have_debug_prints & 1))
+    display_startstop("", "}", category, debug_tls->debug_start_colors_2);
+  debug_tls->pypy_have_debug_prints >>= 1;
 }

rpython/translator/c/src/debug_print.h

 */
 
 /* macros used by the generated code */
-#define PYPY_HAVE_DEBUG_PRINTS    (pypy_have_debug_prints & 1 ? \
+#define PYPY_HAVE_DEBUG_PRINTS    (get_debug_tls()->pypy_have_debug_prints & 1 ? \
                                    (pypy_debug_ensure_opened(), 1) : 0)
 #define PYPY_DEBUG_FILE           pypy_debug_file
 #define PYPY_DEBUG_START(cat)     pypy_debug_start(cat)
 #define PYPY_DEBUG_STOP(cat)      pypy_debug_stop(cat)
 #define OP_DEBUG_OFFSET(res)      res = pypy_debug_offset()
-#define OP_HAVE_DEBUG_PRINTS(r)   r = (pypy_have_debug_prints & 1)
+#define OP_HAVE_DEBUG_PRINTS(r)   r = (get_debug_tls()->pypy_have_debug_prints & 1)
 #define OP_DEBUG_FLUSH() fflush(pypy_debug_file)
 
 /************************************************************/
 
+typedef struct {
+  long pypy_have_debug_prints;
+  char debug_start_colors_1[32];
+  char debug_start_colors_2[28];
+  char pypy_debug_threadid[16];
+} debug_tls_t;
+
 /* prototypes (internal use only) */
 void pypy_debug_ensure_opened(void);
 void pypy_debug_start(const char *category);
 void pypy_debug_stop(const char *category);
 long pypy_debug_offset(void);
+debug_tls_t *get_debug_tls(void);
 
-extern __thread long pypy_have_debug_prints;
-extern __thread char pypy_debug_threadid[];
 extern FILE *pypy_debug_file;
 
 #define OP_LL_READ_TIMESTAMP(val) READ_TIMESTAMP(val)