void *__tls_get_addr(size_t *v)
{
pthread_t self = __pthread_self();
- if (v[0]<=(size_t)self->dtv[0] && self->dtv[v[0]])
+ if (v[0]<=(size_t)self->dtv[0])
return (char *)self->dtv[v[0]]+v[1];
/* Block signals to make accessing new TLS async-signal-safe */
sigset_t set;
pthread_sigmask(SIG_BLOCK, SIGALL_SET, &set);
- if (v[0]<=(size_t)self->dtv[0] && self->dtv[v[0]]) {
+ if (v[0]<=(size_t)self->dtv[0]) {
pthread_sigmask(SIG_SETMASK, &set, 0);
return (char *)self->dtv[v[0]]+v[1];
}
self->dtv = newdtv;
}
- /* Get new TLS memory from new DSO */
- unsigned char *mem = p->new_tls +
- (p->tls_size + p->tls_align) * a_fetch_add(&p->new_tls_idx,1);
- mem += ((uintptr_t)p->tls_image - (uintptr_t)mem) & (p->tls_align-1);
- self->dtv[v[0]] = mem;
- memcpy(mem, p->tls_image, p->tls_len);
+ /* Get new TLS memory from all new DSOs up to the requested one */
+ unsigned char *mem;
+ for (p=head; ; p=p->next) {
+ if (!p->tls_id || self->dtv[p->tls_id]) continue;
+ mem = p->new_tls + (p->tls_size + p->tls_align)
+ * a_fetch_add(&p->new_tls_idx,1);
+ mem += ((uintptr_t)p->tls_image - (uintptr_t)mem)
+ & (p->tls_align-1);
+ self->dtv[p->tls_id] = mem;
+ memcpy(mem, p->tls_image, p->tls_len);
+ if (p->tls_id == v[0]) break;
+ }
pthread_sigmask(SIG_SETMASK, &set, 0);
return mem + v[1];
}