#include "threadimpl.h"#include "BSD.c" #include <dlfcn.h> struct thread_tag { struct thread_tag *next; spinlock_t l; volatile int key; void *data;}; static spinlock_t mlock;static spinlock_t dl_lock;static spinlock_t tag_lock;static struct thread_tag *thread_tag_store = nil;static uint nextkey = 0; void_thread_malloc_lock(void){ _spinlock(&mlock);} void_thread_malloc_unlock(void){ _spinunlock(&mlock);} void_thread_malloc_init(void){} /* * for ld.so */void_thread_dl_lock(int t){ if(t) _spinunlock(&dl_lock); else _spinlock(&dl_lock);} /* * for libc */static void_thread_tag_init(void **tag){ struct thread_tag *t; _spinlock(&tag_lock); if(*tag == nil) { t = malloc(sizeof (*t)); if(t != nil) { memset(&t->l, 0, sizeof(t->l)); t->key = nextkey++; *tag = t; } } _spinunlock(&tag_lock);} void_thread_tag_lock(void **tag){ struct thread_tag *t; if(*tag == nil) _thread_tag_init(tag); t = *tag; _spinlock(&t->l);} void_thread_tag_unlock(void **tag){ struct thread_tag *t; if(*tag == nil) _thread_tag_init(tag); t = *tag; _spinunlock(&t->l);} static void *_thread_tag_insert(struct thread_tag *t, void *v){ t->data = v; t->next = thread_tag_store; thread_tag_store = t; return t;} static void *_thread_tag_lookup(struct thread_tag *tag, int size){ struct thread_tag *t; void *p; _spinlock(&tag->l); for(t = thread_tag_store; t != nil; t = t->next) if(t->key == tag->key) break; if(t == nil) { p = malloc(size); if(p == nil) { _spinunlock(&tag->l); return nil; } _thread_tag_insert(tag, p); } _spinunlock(&tag->l); return tag->data;} void *_thread_tag_storage(void **tag, void *storage, size_t n, void *err){ struct thread_tag *t; void *r; if(*tag == nil) _thread_tag_init(tag); t = *tag; r = _thread_tag_lookup(t, n); if(r == nil) r = err; else memcpy(r, storage, n); return r;} void_pthreadinit(void){ __isthreaded = 1; dlctl(nil, DL_SETTHREADLCK, _thread_dl_lock); signal(SIGUSR2, sigusr2handler);}
#include "threadimpl.h"
#include "BSD.c"
#include <dlfcn.h>
struct thread_tag {
struct thread_tag *next;
spinlock_t l;
volatile int key;
void *data;
};
static spinlock_t mlock;
static spinlock_t dl_lock;
static spinlock_t tag_lock;
static struct thread_tag *thread_tag_store = nil;
static uint nextkey = 0;
void
_thread_malloc_lock(void)
{
_spinlock(&mlock);
}
void
_thread_malloc_unlock(void)
{
_spinunlock(&mlock);
}
void
_thread_malloc_init(void)
{
}
/*
* for ld.so
*/
void
_thread_dl_lock(int t)
{
if(t)
_spinunlock(&dl_lock);
else
_spinlock(&dl_lock);
}
/*
* for libc
*/
static void
_thread_tag_init(void **tag)
{
struct thread_tag *t;
_spinlock(&tag_lock);
if(*tag == nil) {
t = malloc(sizeof (*t));
if(t != nil) {
memset(&t->l, 0, sizeof(t->l));
t->key = nextkey++;
*tag = t;
}
}
_spinunlock(&tag_lock);
}
void
_thread_tag_lock(void **tag)
{
struct thread_tag *t;
if(*tag == nil)
_thread_tag_init(tag);
t = *tag;
_spinlock(&t->l);
}
void
_thread_tag_unlock(void **tag)
{
struct thread_tag *t;
if(*tag == nil)
_thread_tag_init(tag);
t = *tag;
_spinunlock(&t->l);
}
static void *
_thread_tag_insert(struct thread_tag *t, void *v)
{
t->data = v;
t->next = thread_tag_store;
thread_tag_store = t;
return t;
}
static void *
_thread_tag_lookup(struct thread_tag *tag, int size)
{
struct thread_tag *t;
void *p;
_spinlock(&tag->l);
for(t = thread_tag_store; t != nil; t = t->next)
if(t->key == tag->key)
break;
if(t == nil) {
p = malloc(size);
if(p == nil) {
_spinunlock(&tag->l);
return nil;
}
_thread_tag_insert(tag, p);
}
_spinunlock(&tag->l);
return tag->data;
}
void *
_thread_tag_storage(void **tag, void *storage, size_t n, void *err)
{
struct thread_tag *t;
void *r;
if(*tag == nil)
_thread_tag_init(tag);
t = *tag;
r = _thread_tag_lookup(t, n);
if(r == nil)
r = err;
else
memcpy(r, storage, n);
return r;
}
void
_pthreadinit(void)
{
__isthreaded = 1;
dlctl(nil, DL_SETTHREADLCK, _thread_dl_lock);
signal(SIGUSR2, sigusr2handler);
}