xref: /plan9-contrib/sys/src/cmd/unix/drawterm/kern/posix.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
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