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