1*8ccd4a63SDavid du Colombier /* 2*8ccd4a63SDavid du Colombier * Posix generic OS implementation for drawterm. 3*8ccd4a63SDavid du Colombier */ 4*8ccd4a63SDavid du Colombier 5*8ccd4a63SDavid du Colombier #define _XOPEN_SOURCE 500 6*8ccd4a63SDavid du Colombier #include <pthread.h> 7*8ccd4a63SDavid du Colombier #include <time.h> 8*8ccd4a63SDavid du Colombier #include <sys/time.h> 9*8ccd4a63SDavid du Colombier #include <signal.h> 10*8ccd4a63SDavid du Colombier #include <pwd.h> 11*8ccd4a63SDavid du Colombier #include <errno.h> 12*8ccd4a63SDavid du Colombier 13*8ccd4a63SDavid du Colombier #include "u.h" 14*8ccd4a63SDavid du Colombier #include "lib.h" 15*8ccd4a63SDavid du Colombier #include "dat.h" 16*8ccd4a63SDavid du Colombier #include "fns.h" 17*8ccd4a63SDavid du Colombier 18*8ccd4a63SDavid du Colombier typedef struct Oproc Oproc; 19*8ccd4a63SDavid du Colombier struct Oproc 20*8ccd4a63SDavid du Colombier { 21*8ccd4a63SDavid du Colombier int nsleep; 22*8ccd4a63SDavid du Colombier int nwakeup; 23*8ccd4a63SDavid du Colombier pthread_mutex_t mutex; 24*8ccd4a63SDavid du Colombier pthread_cond_t cond; 25*8ccd4a63SDavid du Colombier }; 26*8ccd4a63SDavid du Colombier 27*8ccd4a63SDavid du Colombier static pthread_key_t prdakey; 28*8ccd4a63SDavid du Colombier 29*8ccd4a63SDavid du Colombier Proc* 30*8ccd4a63SDavid du Colombier _getproc(void) 31*8ccd4a63SDavid du Colombier { 32*8ccd4a63SDavid du Colombier void *v; 33*8ccd4a63SDavid du Colombier 34*8ccd4a63SDavid du Colombier if((v = pthread_getspecific(prdakey)) == nil) 35*8ccd4a63SDavid du Colombier panic("cannot getspecific"); 36*8ccd4a63SDavid du Colombier return v; 37*8ccd4a63SDavid du Colombier } 38*8ccd4a63SDavid du Colombier 39*8ccd4a63SDavid du Colombier void 40*8ccd4a63SDavid du Colombier _setproc(Proc *p) 41*8ccd4a63SDavid du Colombier { 42*8ccd4a63SDavid du Colombier if(pthread_setspecific(prdakey, p) != 0) 43*8ccd4a63SDavid du Colombier panic("cannot setspecific"); 44*8ccd4a63SDavid du Colombier } 45*8ccd4a63SDavid du Colombier 46*8ccd4a63SDavid du Colombier void 47*8ccd4a63SDavid du Colombier osinit(void) 48*8ccd4a63SDavid du Colombier { 49*8ccd4a63SDavid du Colombier if(pthread_key_create(&prdakey, 0)) 50*8ccd4a63SDavid du Colombier panic("cannot pthread_key_create"); 51*8ccd4a63SDavid du Colombier } 52*8ccd4a63SDavid du Colombier 53*8ccd4a63SDavid du Colombier #undef pipe 54*8ccd4a63SDavid du Colombier void 55*8ccd4a63SDavid du Colombier osnewproc(Proc *p) 56*8ccd4a63SDavid du Colombier { 57*8ccd4a63SDavid du Colombier Oproc *op; 58*8ccd4a63SDavid du Colombier pthread_mutexattr_t attr; 59*8ccd4a63SDavid du Colombier 60*8ccd4a63SDavid du Colombier op = (Oproc*)p->oproc; 61*8ccd4a63SDavid du Colombier pthread_mutexattr_init(&attr); 62*8ccd4a63SDavid du Colombier pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); 63*8ccd4a63SDavid du Colombier pthread_mutex_init(&op->mutex, &attr); 64*8ccd4a63SDavid du Colombier pthread_mutexattr_destroy(&attr); 65*8ccd4a63SDavid du Colombier pthread_cond_init(&op->cond, 0); 66*8ccd4a63SDavid du Colombier } 67*8ccd4a63SDavid du Colombier 68*8ccd4a63SDavid du Colombier void 69*8ccd4a63SDavid du Colombier osmsleep(int ms) 70*8ccd4a63SDavid du Colombier { 71*8ccd4a63SDavid du Colombier struct timeval tv; 72*8ccd4a63SDavid du Colombier 73*8ccd4a63SDavid du Colombier tv.tv_sec = ms / 1000; 74*8ccd4a63SDavid du Colombier tv.tv_usec = (ms % 1000) * 1000; /* micro */ 75*8ccd4a63SDavid du Colombier if(select(0, NULL, NULL, NULL, &tv) < 0) 76*8ccd4a63SDavid du Colombier panic("select"); 77*8ccd4a63SDavid du Colombier } 78*8ccd4a63SDavid du Colombier 79*8ccd4a63SDavid du Colombier void 80*8ccd4a63SDavid du Colombier osyield(void) 81*8ccd4a63SDavid du Colombier { 82*8ccd4a63SDavid du Colombier sched_yield(); 83*8ccd4a63SDavid du Colombier } 84*8ccd4a63SDavid du Colombier 85*8ccd4a63SDavid du Colombier void 86*8ccd4a63SDavid du Colombier oserrstr(void) 87*8ccd4a63SDavid du Colombier { 88*8ccd4a63SDavid du Colombier char *p; 89*8ccd4a63SDavid du Colombier 90*8ccd4a63SDavid du Colombier if((p = strerror(errno)) != nil) 91*8ccd4a63SDavid du Colombier strecpy(up->errstr, up->errstr+ERRMAX, p); 92*8ccd4a63SDavid du Colombier else 93*8ccd4a63SDavid du Colombier snprint(up->errstr, ERRMAX, "unix error %d", errno); 94*8ccd4a63SDavid du Colombier } 95*8ccd4a63SDavid du Colombier 96*8ccd4a63SDavid du Colombier void 97*8ccd4a63SDavid du Colombier oserror(void) 98*8ccd4a63SDavid du Colombier { 99*8ccd4a63SDavid du Colombier oserrstr(); 100*8ccd4a63SDavid du Colombier nexterror(); 101*8ccd4a63SDavid du Colombier } 102*8ccd4a63SDavid du Colombier 103*8ccd4a63SDavid du Colombier static void* tramp(void*); 104*8ccd4a63SDavid du Colombier 105*8ccd4a63SDavid du Colombier void 106*8ccd4a63SDavid du Colombier osproc(Proc *p) 107*8ccd4a63SDavid du Colombier { 108*8ccd4a63SDavid du Colombier pthread_t pid; 109*8ccd4a63SDavid du Colombier 110*8ccd4a63SDavid du Colombier if(pthread_create(&pid, nil, tramp, p)){ 111*8ccd4a63SDavid du Colombier oserrstr(); 112*8ccd4a63SDavid du Colombier panic("osproc: %r"); 113*8ccd4a63SDavid du Colombier } 114*8ccd4a63SDavid du Colombier sched_yield(); 115*8ccd4a63SDavid du Colombier } 116*8ccd4a63SDavid du Colombier 117*8ccd4a63SDavid du Colombier static void* 118*8ccd4a63SDavid du Colombier tramp(void *vp) 119*8ccd4a63SDavid du Colombier { 120*8ccd4a63SDavid du Colombier Proc *p; 121*8ccd4a63SDavid du Colombier 122*8ccd4a63SDavid du Colombier p = vp; 123*8ccd4a63SDavid du Colombier if(pthread_setspecific(prdakey, p)) 124*8ccd4a63SDavid du Colombier panic("cannot setspecific"); 125*8ccd4a63SDavid du Colombier (*p->fn)(p->arg); 126*8ccd4a63SDavid du Colombier /* BUG: leaks Proc */ 127*8ccd4a63SDavid du Colombier pthread_setspecific(prdakey, 0); 128*8ccd4a63SDavid du Colombier pthread_exit(0); 129*8ccd4a63SDavid du Colombier return 0; 130*8ccd4a63SDavid du Colombier } 131*8ccd4a63SDavid du Colombier 132*8ccd4a63SDavid du Colombier void 133*8ccd4a63SDavid du Colombier procsleep(void) 134*8ccd4a63SDavid du Colombier { 135*8ccd4a63SDavid du Colombier Proc *p; 136*8ccd4a63SDavid du Colombier Oproc *op; 137*8ccd4a63SDavid du Colombier 138*8ccd4a63SDavid du Colombier p = up; 139*8ccd4a63SDavid du Colombier op = (Oproc*)p->oproc; 140*8ccd4a63SDavid du Colombier pthread_mutex_lock(&op->mutex); 141*8ccd4a63SDavid du Colombier op->nsleep++; 142*8ccd4a63SDavid du Colombier while(op->nsleep > op->nwakeup) 143*8ccd4a63SDavid du Colombier pthread_cond_wait(&op->cond, &op->mutex); 144*8ccd4a63SDavid du Colombier pthread_mutex_unlock(&op->mutex); 145*8ccd4a63SDavid du Colombier } 146*8ccd4a63SDavid du Colombier 147*8ccd4a63SDavid du Colombier void 148*8ccd4a63SDavid du Colombier procwakeup(Proc *p) 149*8ccd4a63SDavid du Colombier { 150*8ccd4a63SDavid du Colombier Oproc *op; 151*8ccd4a63SDavid du Colombier 152*8ccd4a63SDavid du Colombier op = (Oproc*)p->oproc; 153*8ccd4a63SDavid du Colombier pthread_mutex_lock(&op->mutex); 154*8ccd4a63SDavid du Colombier op->nwakeup++; 155*8ccd4a63SDavid du Colombier if(op->nwakeup == op->nsleep) 156*8ccd4a63SDavid du Colombier pthread_cond_signal(&op->cond); 157*8ccd4a63SDavid du Colombier pthread_mutex_unlock(&op->mutex); 158*8ccd4a63SDavid du Colombier } 159*8ccd4a63SDavid du Colombier 160*8ccd4a63SDavid du Colombier int randfd; 161*8ccd4a63SDavid du Colombier #undef open 162*8ccd4a63SDavid du Colombier void 163*8ccd4a63SDavid du Colombier randominit(void) 164*8ccd4a63SDavid du Colombier { 165*8ccd4a63SDavid du Colombier #ifdef USE_RANDOM 166*8ccd4a63SDavid du Colombier srandom(getpid()+fastticks(nil)+ticks()); 167*8ccd4a63SDavid du Colombier #else 168*8ccd4a63SDavid du Colombier if((randfd = open("/dev/urandom", OREAD)) < 0) 169*8ccd4a63SDavid du Colombier if((randfd = open("/dev/random", OREAD)) < 0) 170*8ccd4a63SDavid du Colombier panic("open /dev/random: %r"); 171*8ccd4a63SDavid du Colombier #endif 172*8ccd4a63SDavid du Colombier } 173*8ccd4a63SDavid du Colombier 174*8ccd4a63SDavid du Colombier #undef read 175*8ccd4a63SDavid du Colombier ulong 176*8ccd4a63SDavid du Colombier randomread(void *v, ulong n) 177*8ccd4a63SDavid du Colombier { 178*8ccd4a63SDavid du Colombier #ifdef USE_RANDOM 179*8ccd4a63SDavid du Colombier int i; 180*8ccd4a63SDavid du Colombier 181*8ccd4a63SDavid du Colombier for(i=0; i<n; i++) 182*8ccd4a63SDavid du Colombier ((uchar*)v)[i] = random(); 183*8ccd4a63SDavid du Colombier return n; 184*8ccd4a63SDavid du Colombier #else 185*8ccd4a63SDavid du Colombier int m; 186*8ccd4a63SDavid du Colombier 187*8ccd4a63SDavid du Colombier if((m = read(randfd, v, n)) != n) 188*8ccd4a63SDavid du Colombier panic("short read from /dev/random: %d but %d", n, m); 189*8ccd4a63SDavid du Colombier return m; 190*8ccd4a63SDavid du Colombier #endif 191*8ccd4a63SDavid du Colombier } 192*8ccd4a63SDavid du Colombier 193*8ccd4a63SDavid du Colombier #undef time 194*8ccd4a63SDavid du Colombier long 195*8ccd4a63SDavid du Colombier seconds(void) 196*8ccd4a63SDavid du Colombier { 197*8ccd4a63SDavid du Colombier return time(0); 198*8ccd4a63SDavid du Colombier } 199*8ccd4a63SDavid du Colombier 200*8ccd4a63SDavid du Colombier ulong 201*8ccd4a63SDavid du Colombier ticks(void) 202*8ccd4a63SDavid du Colombier { 203*8ccd4a63SDavid du Colombier static long sec0 = 0, usec0; 204*8ccd4a63SDavid du Colombier struct timeval t; 205*8ccd4a63SDavid du Colombier 206*8ccd4a63SDavid du Colombier if(gettimeofday(&t, nil) < 0) 207*8ccd4a63SDavid du Colombier return 0; 208*8ccd4a63SDavid du Colombier if(sec0 == 0){ 209*8ccd4a63SDavid du Colombier sec0 = t.tv_sec; 210*8ccd4a63SDavid du Colombier usec0 = t.tv_usec; 211*8ccd4a63SDavid du Colombier } 212*8ccd4a63SDavid du Colombier return (t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000; 213*8ccd4a63SDavid du Colombier } 214*8ccd4a63SDavid du Colombier 215