From: Jeff Hostetler Date: Tue, 28 May 2019 14:57:50 GMT Subject: Re: [PATCH 0/1] trace2: fix tracing when NO_PTHREADS is defined Message-ID: <47db8f30-846b-12d0-250e-4bccf1e19c45@jeffhostetler.com> In-Reply-To: <20190528062804.GE7946@sigill.intra.peff.net> On 5/28/2019 2:28 AM, Jeff King wrote: > On Sat, May 25, 2019 at 05:43:55PM +0700, Duy Nguyen wrote: > >>> +typedef struct { >>> + void *data; >>> + /* extra indirection because setspecific is passed key by value */ >>> + void **vdata; >> >> Ha! I was thinking a separate key->value mapping which is complicated >> in C. But this works pretty well for a single thread, and it even >> supports multiple keys. > > I really wish that all of the functions passed the pthread_key_t by > reference. That would make it possible to define the key as a single > pointer. > > I'm not sure if pthread_key_t's are meant to be shallow-copyable. I.e., > should this work: > > void foo(pthread_key_t *out) > { > pthread_key_t tmp; > pthread_key_create(&tmp, NULL); > *out = tmp; > } > ... > pthread_key_t k; > foo(&k); > pthread_setspecific(k, some_ptr); > > It does not with my proposed plan, because the pointer in tmp.data went > out of scope, leaving tmp.vdata (and thus k.vdata) as a dangling > pointer. > > The code above seems like a vaguely crazy thing to do. But if we want to > be absolutely paranoid, we'd have to malloc() an extra pointer in the > create() function, instead of carrying it inside the key. Or just make a > global "void *thread_specific_data[PTHREAD_KEYS_MAX]" and make each key > an integer index into it. > > It's pretty clear that they expect one of those two implementations, > given that POSIX says key creation can report either ENOMEM, or EAGAIN > if we exceed PTHREAD_KEYS_MAX. :) > > -Peff > Yes, a fixed global void* array should be fine. Besides there aren't that many calls to pthread_key_create() (My use in Trace2 is the second, right?), so just create an arbitrary value for PTHREAD_KEYS_MAX and be done. Jeff