Changeset: 54dd0625ee0b for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/54dd0625ee0b
Modified Files:
        clients/Tests/exports.stable.out
        gdk/gdk_system.c
        gdk/gdk_system.h
        sql/backends/monet5/UDF/capi/capi.c
Branch: default
Log Message:

Use thread-local storage instead of arrays indexed by thread id for CAPI.


diffs (276 lines):

diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -357,6 +357,7 @@ size_t HEAPvmsize(Heap *h);
 void IMPSdestroy(BAT *b);
 lng IMPSimprintsize(BAT *b);
 int MT_access(const char *pathname, int mode);
+gdk_return MT_alloc_tls(MT_TLS_t *newkey);
 int MT_check_nr_cores(void);
 void MT_cond_broadcast(MT_Cond *cond);
 void MT_cond_destroy(MT_Cond *cond);
@@ -393,6 +394,8 @@ void MT_thread_setdata(void *data);
 void MT_thread_setlockwait(MT_Lock *lock);
 void MT_thread_setsemawait(MT_Sema *sema);
 void MT_thread_setworking(const char *work);
+void *MT_tls_get(MT_TLS_t key);
+void MT_tls_set(MT_TLS_t key, void *val);
 void OIDXdestroy(BAT *b);
 ssize_t OIDfromStr(const char *src, size_t *len, oid **dst, bool external);
 ssize_t OIDtoStr(str *dst, size_t *len, const oid *src, bool external);
diff --git a/gdk/gdk_system.c b/gdk/gdk_system.c
--- a/gdk/gdk_system.c
+++ b/gdk/gdk_system.c
@@ -225,11 +225,11 @@ static pthread_key_t threadkey;
 #define thread_setself(self)   pthread_setspecific(threadkey, self)
 #else
 static CRITICAL_SECTION winthread_cs;
-static DWORD threadslot = TLS_OUT_OF_INDEXES;
+static DWORD threadkey = TLS_OUT_OF_INDEXES;
 #define thread_lock()          EnterCriticalSection(&winthread_cs)
 #define thread_unlock()                LeaveCriticalSection(&winthread_cs)
-#define thread_self()          TlsGetValue(threadslot)
-#define thread_setself(self)   TlsSetValue(threadslot, self)
+#define thread_self()          TlsGetValue(threadkey)
+#define thread_setself(self)   TlsSetValue(threadkey, self)
 #endif
 static bool thread_initialized = false;
 
@@ -361,16 +361,16 @@ MT_thread_init(void)
                return false;
        }
 #else
-       threadslot = TlsAlloc();
-       if (threadslot == TLS_OUT_OF_INDEXES) {
+       threadkey = TlsAlloc();
+       if (threadkey == TLS_OUT_OF_INDEXES) {
                GDKwinerror("Creating thread-local slot for thread failed");
                return false;
        }
        mainthread.wtid = GetCurrentThreadId();
        if (thread_setself(&mainthread) == 0) {
                GDKwinerror("Setting thread-local value failed");
-               TlsFree(threadslot);
-               threadslot = TLS_OUT_OF_INDEXES;
+               TlsFree(threadkey);
+               threadkey = TLS_OUT_OF_INDEXES;
                return false;
        }
        InitializeCriticalSection(&winthread_cs);
@@ -457,6 +457,46 @@ find_mtthread(MT_Id tid)
        return t;
 }
 
+gdk_return
+MT_alloc_tls(MT_TLS_t *newkey)
+{
+#ifdef HAVE_PTHREAD_H
+       int ret;
+       if ((ret = pthread_key_create(newkey, NULL)) != 0) {
+               GDKsyserr(ret, "Creating TLS key for thread failed");
+               return GDK_FAIL;
+       }
+#else
+       if ((*newkey = TlsAlloc()) == TLS_OUT_OF_INDEXES) {
+               GDKwinerror("Creating TLS key for thread failed");
+               return GDK_FAIL;
+       }
+#endif
+       return GDK_SUCCEED;
+}
+
+void
+MT_tls_set(MT_TLS_t key, void *val)
+{
+#ifdef HAVE_PTHREAD_H
+       pthread_setspecific(key, val);
+#else
+       assert(key != TLS_OUT_OF_INDEXES);
+       TlsSetValue(key, val);
+#endif
+}
+
+void *
+MT_tls_get(MT_TLS_t key)
+{
+#ifdef HAVE_PTHREAD_H
+       return pthread_getspecific(key);
+#else
+       assert(key != TLS_OUT_OF_INDEXES);
+       return TlsGetValue(key);
+#endif
+}
+
 const char *
 MT_thread_getname(void)
 {
diff --git a/gdk/gdk_system.h b/gdk/gdk_system.h
--- a/gdk/gdk_system.h
+++ b/gdk/gdk_system.h
@@ -436,6 +436,8 @@ typedef struct MT_RWLock {
 
 #define MT_rwlock_wrunlock(l)  ReleaseSRWLockExclusive(&(l)->lock)
 
+typedef DWORD MT_TLS_t;
+
 #else
 
 typedef struct MT_Lock {
@@ -606,8 +608,14 @@ MT_rwlock_wrtry(MT_RWLock *l)
 
 #endif
 
+typedef pthread_key_t MT_TLS_t;
+
 #endif
 
+gdk_export gdk_return MT_alloc_tls(MT_TLS_t *newkey);
+gdk_export void MT_tls_set(MT_TLS_t key, void *val);
+gdk_export void *MT_tls_get(MT_TLS_t key);
+
 #ifdef LOCK_STATS
 gdk_export void GDKlockstatistics(int);
 gdk_export MT_Lock * volatile GDKlocklist;
diff --git a/sql/backends/monet5/UDF/capi/capi.c 
b/sql/backends/monet5/UDF/capi/capi.c
--- a/sql/backends/monet5/UDF/capi/capi.c
+++ b/sql/backends/monet5/UDF/capi/capi.c
@@ -39,7 +39,6 @@ static bool option_enable_mprotect = fal
 const char *longjmp_enableflag = "enable_longjmp";
 static bool option_enable_longjmp = false;
 
-struct _allocated_region;
 typedef struct _allocated_region {
        struct _allocated_region *next;
 } allocated_region;
@@ -54,8 +53,11 @@ typedef struct _mprotected_region {
 
 static char *mprotect_region(void *addr, size_t len,
                                                         mprotected_region 
**regions);
-static allocated_region *allocated_regions[THREADS];
-static jmp_buf jump_buffer[THREADS];
+struct capi_tls_s {
+       allocated_region *ar;
+       jmp_buf jb;
+};
+static MT_TLS_t capi_tls_key;
 
 typedef char *(*jitted_function)(void **inputs, void **outputs,
                                                                 
malloc_function_ptr malloc, free_function_ptr free);
@@ -94,6 +96,7 @@ static str CUDFprelude(void)
                cudf_initialized = true;
                option_enable_mprotect = GDKgetenv_istrue(mprotect_enableflag) 
|| GDKgetenv_isyes(mprotect_enableflag);
                option_enable_longjmp = GDKgetenv_istrue(longjmp_enableflag) || 
GDKgetenv_isyes(longjmp_enableflag);
+               MT_alloc_tls(&capi_tls_key);
        }
        return MAL_SUCCEED;
 }
@@ -111,13 +114,12 @@ static bool WriteTextToFile(FILE *f, con
 
 static _Noreturn void handler(int sig, siginfo_t *si, void *unused)
 {
-       MT_Id tid = MT_getpid();
-
        (void)sig;
        (void)si;
        (void)unused;
 
-       longjmp(jump_buffer[tid-1], 1);
+       struct capi_tls_s *tls = MT_tls_get(capi_tls_key);
+       longjmp(tls->jb, 1);
 }
 
 static bool can_mprotect_region(void* addr) {
@@ -173,18 +175,18 @@ static void *jump_GDK_malloc(size_t size
                return NULL;
        void *ptr = GDKmalloc(size);
        if (!ptr && option_enable_longjmp) {
-               longjmp(jump_buffer[MT_getpid()-1], 2);
+               struct capi_tls_s *tls = MT_tls_get(capi_tls_key);
+               longjmp(tls->jb, 2);
        }
        return ptr;
 }
 
-static void *add_allocated_region(void *ptr)
+static inline void *add_allocated_region(void *ptr)
 {
-       allocated_region *region;
-       MT_Id tid = MT_getpid();
-       region = (allocated_region *)ptr;
-       region->next = allocated_regions[tid-1];
-       allocated_regions[tid-1] = region;
+       allocated_region *region = (allocated_region *)ptr;
+       struct capi_tls_s *tls = MT_tls_get(capi_tls_key);
+       region->next = tls->ar;
+       tls->ar = region;
        return (char *)ptr + sizeof(allocated_region);
 }
 
@@ -215,7 +217,10 @@ static void wrapped_GDK_free(void* ptr) 
                }                                                               
       \
                b = COLnew(0, TYPE_##tpename, count, TRANSIENT);                
       \
                if (!b) {                                                       
       \
-                       if (option_enable_longjmp) 
longjmp(jump_buffer[MT_getpid()-1], 2); \
+                       if (option_enable_longjmp) {                            
           \
+                               struct capi_tls_s *tls = 
MT_tls_get(capi_tls_key);             \
+                               longjmp(tls->jb, 2);                            
               \
+                       }                                                       
           \
                        else return;                                            
           \
                }                                                               
       \
                self->bat = (void*) b;                                          
       \
@@ -480,7 +485,6 @@ static str CUDFeval(Client cntxt, MalBlk
        BUN expression_hash = 0, funcname_hash = 0;
        cached_functions *cached_function;
        char *function_parameters = NULL;
-       MT_Id tid = MT_getpid();
        size_t input_size = 0;
        bit non_grouped_aggregate = 0;
 
@@ -490,9 +494,12 @@ static str CUDFeval(Client cntxt, MalBlk
 
        size_t extra_inputs = 0;
 
-       (void)cntxt;
+       struct capi_tls_s tls;
 
-       allocated_regions[tid-1] = NULL;
+       tls.ar = NULL;
+       MT_tls_set(capi_tls_key, &tls);
+
+       (void)cntxt;
 
        if (!GDKgetenv_istrue("embedded_c") && !GDKgetenv_isyes("embedded_c"))
                throw(MAL, "cudf.eval", "Embedded C has not been enabled. "
@@ -1325,7 +1332,8 @@ static str CUDFeval(Client cntxt, MalBlk
        // this longjmp point is used for some error handling in the C function
        // such as failed mallocs
        if (option_enable_longjmp) {
-               ret = setjmp(jump_buffer[tid-1]);
+               struct capi_tls_s *tls = MT_tls_get(capi_tls_key);
+               ret = setjmp(tls->jb);
                if (ret < 0) {
                        // error value
                        msg = createException(MAL, "cudf.eval", "Failed setjmp: 
%s",
@@ -1588,6 +1596,7 @@ wrapup:
        GDKfree(fname);
        GDKfree(oname);
        GDKfree(libname);
+       MT_tls_set(capi_tls_key, NULL);
        if (option_enable_mprotect) {
                if (sa.sa_sigaction) {
                        (void) sigaction(SIGSEGV, &oldsa, NULL);
@@ -1603,10 +1612,10 @@ wrapup:
                        regions = next;
                }
        }
-       while (allocated_regions[tid-1]) {
-               allocated_region *next = allocated_regions[tid-1]->next;
-               GDKfree(allocated_regions[tid-1]);
-               allocated_regions[tid-1] = next;
+       while (tls.ar != NULL) {
+               allocated_region *next = tls.ar->next;
+               GDKfree(tls.ar);
+               tls.ar = next;
        }
        if (option_enable_mprotect) {
                // block segfaults and bus errors again after we exit
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to