#include "threadimpl.h" #include "BSD.c" #include 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); }