this repo has no description
at fixPythonPipStalling 104 lines 3.4 kB view raw
1#include <stdlib.h> 2#include <darling/emulation/linux_premigration/ext/for-xtrace.h> 3#include "tls.h" 4#include "memory.h" 5#include "lock.h" 6#include <darling/emulation/common/simple.h> 7#include <pthread/tsd_private.h> 8#include "xtracelib.h" 9 10#ifndef XTRACE_TLS_DEBUG 11 #define XTRACE_TLS_DEBUG 0 12#endif 13 14#if XTRACE_TLS_DEBUG 15 #define xtrace_tls_debug(x, ...) xtrace_log(x "\n", ## __VA_ARGS__) 16#else 17 #define xtrace_tls_debug(x, ...) 18#endif 19 20// 32 TLS vars should be enough, right? 21#define TLS_TABLE_MAX_SIZE 32 22 23typedef struct tls_table* tls_table_t; 24struct tls_table { 25 size_t size; 26 void* table[TLS_TABLE_MAX_SIZE][3]; 27}; 28 29// since we still need to handle some calls after pthread_terminate is called and libpthread unwinds its TLS right before calling pthread_terminate, 30// we have to use a slightly hackier technique: using one of the system's reserved but unused TLS keys; we use one from the range we currently reserve 31// for Darling. 32 33#include <darling/emulation/common/tsd.h> 34 35// TODO: also perform TLS cleanup for other threads when doing a fork 36 37extern "C" 38void xtrace_tls_thread_cleanup(void) { 39 tls_table_t table = (tls_table_t)_pthread_getspecific_direct(__PTK_DARLING_XTRACE_TLS); 40 if (!table) { 41 xtrace_tls_debug("no table to cleanup for this thread"); 42 return; 43 } 44 xtrace_tls_debug("destroying table %p", table); 45 for (size_t i = 0; i < table->size; ++i) { 46 if (table->table[i][2]) { 47 xtrace_tls_debug("destroying value %p for key %p", table->table[i][1], table->table[i][0]); 48 ((xtrace_tls_destructor_f)table->table[i][2])(table->table[1]); 49 } 50 xtrace_tls_debug("freeing value %p for key %p", table->table[i][1], table->table[i][0]); 51 xtrace_free(table->table[i][1]); 52 } 53 xtrace_tls_debug("freeing table %p", table); 54 xtrace_free(table); 55}; 56 57extern "C" 58void* xtrace_tls(void* key, size_t size, bool* created, xtrace_tls_destructor_f destructor) { 59 xtrace_tls_debug("looking up tls variable for key %p", key); 60 61 tls_table_t table = (tls_table_t)_pthread_getspecific_direct(__PTK_DARLING_XTRACE_TLS); 62 63 xtrace_tls_debug("got %p as table pointer from pthread", table); 64 65 // if the table doesn't exist yet, create it 66 if (table == NULL) { 67 xtrace_tls_debug("table is NULL, creating now..."); 68 table = (tls_table_t)xtrace_malloc(sizeof(struct tls_table)); 69 if (table == NULL) { 70 xtrace_abort("xtrace: failed TLS table memory allocation"); 71 } 72 table->size = 0; 73 _pthread_setspecific_direct(__PTK_DARLING_XTRACE_TLS, table); 74 } 75 76 // check if the key is already present 77 for (size_t i = 0; i < table->size; ++i) { 78 if (table->table[i][0] == key) { 79 xtrace_tls_debug("found entry in table for key %p with value %p", key, table->table[i][1]); 80 if (created) { 81 *created = false; 82 } 83 return table->table[i][1]; 84 } 85 } 86 87 // otherwise, create it 88 xtrace_tls_debug("creating new entry in table for key %p", key); 89 size_t index = table->size++; 90 if (index >= TLS_TABLE_MAX_SIZE) { 91 xtrace_abort("xtrace: too many TLS variables"); 92 } 93 table->table[index][0] = key; 94 table->table[index][1] = xtrace_malloc(size); 95 table->table[index][2] = (void*)destructor; 96 if (table->table[index][1] == NULL) { 97 xtrace_abort("xtrace: failed TLS variable memory allocation"); 98 } 99 xtrace_tls_debug("new table entry created for key %p with value %p", key, table->table[index][1]); 100 if (created) { 101 *created = true; 102 } 103 return table->table[index][1]; 104};