On Wed, May 22, 2019 at 09:23:39AM -0400, Jeff Hostetler wrote: > I was wondering about that too as the proper long term solution. > We would need (as the discussion suggests [1]) to properly > respect/represent the pthread_key_t argument. > > For now, I've guarded my usage of pthread_getspecific() in the trace2 > (similar to what index-pack does), so its not urgent that we update it. > And I'd rather we take this simple trace2 fix now and not try to combine > it with fixes for the pthread macros. Especially now as we're in the RC > cycle for 2.22. Yeah, I think that makes sense. > I'll make a note to revisit the pthread code after 2.22. For fun, here's a constant-time zero-allocation implementation that I came up with. It passes t0211 with NO_PTHREADS, but I didn't test it beyond that. diff --git a/thread-utils.h b/thread-utils.h index 4961487ed9..f466215742 100644 --- a/thread-utils.h +++ b/thread-utils.h @@ -18,7 +18,7 @@ #define pthread_t int #define pthread_mutex_t int #define pthread_cond_t int -#define pthread_key_t int +#define pthread_key_t git_pthread_key_t #define pthread_mutex_init(mutex, attr) dummy_pthread_init(mutex) #define pthread_mutex_lock(mutex) @@ -31,16 +31,49 @@ #define pthread_cond_broadcast(cond) #define pthread_cond_destroy(cond) -#define pthread_key_create(key, attr) dummy_pthread_init(key) -#define pthread_key_delete(key) +#define pthread_key_create(key, destroy) git_pthread_key_create(key, destroy) +#define pthread_key_delete(key) git_pthread_key_delete(key) #define pthread_create(thread, attr, fn, data) \ dummy_pthread_create(thread, attr, fn, data) #define pthread_join(thread, retval) \ dummy_pthread_join(thread, retval) -#define pthread_setspecific(key, data) -#define pthread_getspecific(key) NULL +#define pthread_setspecific(key, data) git_pthread_setspecific(key, data) +#define pthread_getspecific(key) git_pthread_getspecific(key) + +typedef struct { + void *data; + /* extra indirection because setspecific is passed key by value */ + void **vdata; +} git_pthread_key_t; + +static inline int git_pthread_key_create(git_pthread_key_t *key, + void (*destroy)(void *)) +{ + key->data = NULL; + key->vdata = &key->data; + /* We don't use this; alternatively we could all via atexit(). */ + if (destroy) + BUG("NO_PTHREADS does not support pthread key destructors"); + return 0; +} + +static inline int git_pthread_key_delete(git_pthread_key_t key) +{ + /* noop */ + return 0; +} + +static inline void git_pthread_setspecific(git_pthread_key_t key, void *data) +{ + *(key.vdata) = data; +} + +static inline void *git_pthread_getspecific(git_pthread_key_t key) +{ + return key.data; +} int dummy_pthread_create(pthread_t *pthread, const void *attr, void *(*fn)(void *), void *data);