167 lines · 2.6 KB · C
RawDownload
#include "threadimpl.h" #undef exits#undef _exits static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER; static voidlockinit(Lock *lk){	pthread_mutexattr_t attr; 	pthread_mutex_lock(&initmutex);	if(lk->init == 0){		pthread_mutexattr_init(&attr);		pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);		pthread_mutex_init(&lk->mutex, &attr);		pthread_mutexattr_destroy(&attr);		lk->init = 1;	}	pthread_mutex_unlock(&initmutex);} int_threadlock(Lock *lk, int block, ulong pc){	int r; 	if(!lk->init)		lockinit(lk);	if(block){		if(pthread_mutex_lock(&lk->mutex) != 0)			abort();		return 1;	}else{		r = pthread_mutex_trylock(&lk->mutex);		if(r == 0)			return 1;		if(r == EBUSY)			return 0;		abort();		return 0;	}} void_threadunlock(Lock *lk, ulong pc){	if(pthread_mutex_unlock(&lk->mutex) != 0)		abort();} void_procsleep(_Procrendez *r){	/* r is protected by r->l, which we hold */	pthread_cond_init(&r->cond, 0);	r->asleep = 1;	pthread_cond_wait(&r->cond, &r->l->mutex);	pthread_cond_destroy(&r->cond);	r->asleep = 0;} void_procwakeup(_Procrendez *r){	if(r->asleep){		r->asleep = 0;		pthread_cond_signal(&r->cond);	}} void_procwakeupandunlock(_Procrendez *r){	if(r->asleep){		r->asleep = 0;		pthread_cond_signal(&r->cond);	}	unlock(r->l);} static voidstartprocfn(void *v){	void **a;	void (*fn)(void*);	Proc *p; 	a = (void**)v;	fn = (void(*)(void*))a[0];	p = a[1];	free(a);	p->osprocid = pthread_self();	pthread_detach(p->osprocid); 	(*fn)(p); 	pthread_exit(0);} void_procstart(Proc *p, void (*fn)(Proc*)){	void **a; 	a = malloc(2*sizeof a[0]);	if(a == nil)		sysfatal("_procstart malloc: %r");	a[0] = (void*)fn;	a[1] = p; 	if(pthread_create(&p->osprocid, nil, (void*(*)(void*))startprocfn, (void*)a) < 0){		fprint(2, "pthread_create: %r\n");		abort();	}} static pthread_key_t prockey; Proc*_threadproc(void){	Proc *p; 	p = pthread_getspecific(prockey);	return p;} void_threadsetproc(Proc *p){	pthread_setspecific(prockey, p);} void_pthreadinit(void){	static struct utsname un;	pthread_t id; 	if(uname(&un) < 0)		fprint(2, "warning: uname failed: %r\n");	if(strcmp(un.sysname, "Linux") == 0){		/*		 * Want to distinguish between the old LinuxThreads pthreads		 * and the new NPTL implementation.  NPTL uses much bigger		 * thread IDs.		 */		id = pthread_self();		if(*(ulong*)(void*)&id < 1024*1024)			sysfatal("cannot use LinuxThreads as pthread library; see %s/src/libthread/README.Linux", get9root());	}	pthread_key_create(&prockey, 0);} voidthreadexitsall(char *msg){	exits(msg);} void_threadpexit(void){	pthread_exit(0);}