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