/* * Posix generic OS implementation for drawterm. */ #include "u.h" #ifndef _XOPEN_SOURCE /* for Apple and OpenBSD; not sure if needed */ #define _XOPEN_SOURCE 500 #endif #include #include #include #include #include #include #include #include "lib.h" #include "dat.h" #include "fns.h" typedef struct Oproc Oproc; struct Oproc { int nsleep; int nwakeup; pthread_mutex_t mutex; pthread_cond_t cond; }; static pthread_key_t prdakey; Proc* _getproc(void) { void *v; if((v = pthread_getspecific(prdakey)) == nil) panic("cannot getspecific"); return v; } void _setproc(Proc *p) { if(pthread_setspecific(prdakey, p) != 0) panic("cannot setspecific"); } void osinit(void) { if(pthread_key_create(&prdakey, 0)) panic("cannot pthread_key_create"); } #undef pipe void osnewproc(Proc *p) { Oproc *op; pthread_mutexattr_t attr; op = (Oproc*)p->oproc; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); pthread_mutex_init(&op->mutex, &attr); pthread_mutexattr_destroy(&attr); pthread_cond_init(&op->cond, 0); } void osmsleep(int ms) { struct timeval tv; tv.tv_sec = ms / 1000; tv.tv_usec = (ms % 1000) * 1000; /* micro */ if(select(0, NULL, NULL, NULL, &tv) < 0) panic("select"); } void osyield(void) { sched_yield(); } void oserrstr(void) { char *p; if((p = strerror(errno)) != nil) strecpy(up->errstr, up->errstr+ERRMAX, p); else snprint(up->errstr, ERRMAX, "unix error %d", errno); } void oserror(void) { oserrstr(); nexterror(); } static void* tramp(void*); void osproc(Proc *p) { pthread_t pid; if(pthread_create(&pid, nil, tramp, p)){ oserrstr(); panic("osproc: %r"); } sched_yield(); } static void* tramp(void *vp) { Proc *p; p = vp; if(pthread_setspecific(prdakey, p)) panic("cannot setspecific"); (*p->fn)(p->arg); /* BUG: leaks Proc */ pthread_setspecific(prdakey, 0); pthread_exit(0); return 0; } void procsleep(void) { Proc *p; Oproc *op; p = up; op = (Oproc*)p->oproc; pthread_mutex_lock(&op->mutex); op->nsleep++; while(op->nsleep > op->nwakeup) pthread_cond_wait(&op->cond, &op->mutex); pthread_mutex_unlock(&op->mutex); } void procwakeup(Proc *p) { Oproc *op; op = (Oproc*)p->oproc; pthread_mutex_lock(&op->mutex); op->nwakeup++; if(op->nwakeup == op->nsleep) pthread_cond_signal(&op->cond); pthread_mutex_unlock(&op->mutex); } int randfd; #undef open void randominit(void) { #ifdef USE_RANDOM srandom(getpid()+fastticks(nil)+ticks()); #else if((randfd = open("/dev/urandom", OREAD)) < 0) if((randfd = open("/dev/random", OREAD)) < 0) panic("open /dev/random: %r"); #endif } #undef read ulong randomread(void *v, ulong n) { #ifdef USE_RANDOM int i; for(i=0; i