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);