xref: /plan9/sys/src/cmd/unix/drawterm/kern/posix.c (revision 96cbc34f1b36a29efdcfd47b10e70703a690febc)
18ccd4a63SDavid du Colombier /*
28ccd4a63SDavid du Colombier  * Posix generic OS implementation for drawterm.
38ccd4a63SDavid du Colombier  */
48ccd4a63SDavid du Colombier 
5*96cbc34fSDavid du Colombier #include "u.h"
6*96cbc34fSDavid du Colombier 
7*96cbc34fSDavid du Colombier #ifndef _XOPEN_SOURCE	/* for Apple and OpenBSD; not sure if needed */
88ccd4a63SDavid du Colombier #define _XOPEN_SOURCE 500
9*96cbc34fSDavid du Colombier #endif
10*96cbc34fSDavid du Colombier 
118ccd4a63SDavid du Colombier #include <pthread.h>
128ccd4a63SDavid du Colombier #include <time.h>
138ccd4a63SDavid du Colombier #include <sys/time.h>
14ec59a3ddSDavid du Colombier #include <sys/select.h>
158ccd4a63SDavid du Colombier #include <signal.h>
168ccd4a63SDavid du Colombier #include <pwd.h>
178ccd4a63SDavid du Colombier #include <errno.h>
188ccd4a63SDavid du Colombier 
198ccd4a63SDavid du Colombier #include "lib.h"
208ccd4a63SDavid du Colombier #include "dat.h"
218ccd4a63SDavid du Colombier #include "fns.h"
228ccd4a63SDavid du Colombier 
238ccd4a63SDavid du Colombier typedef struct Oproc Oproc;
248ccd4a63SDavid du Colombier struct Oproc
258ccd4a63SDavid du Colombier {
268ccd4a63SDavid du Colombier 	int nsleep;
278ccd4a63SDavid du Colombier 	int nwakeup;
288ccd4a63SDavid du Colombier 	pthread_mutex_t mutex;
298ccd4a63SDavid du Colombier 	pthread_cond_t cond;
308ccd4a63SDavid du Colombier };
318ccd4a63SDavid du Colombier 
328ccd4a63SDavid du Colombier static pthread_key_t prdakey;
338ccd4a63SDavid du Colombier 
348ccd4a63SDavid du Colombier Proc*
_getproc(void)358ccd4a63SDavid du Colombier _getproc(void)
368ccd4a63SDavid du Colombier {
378ccd4a63SDavid du Colombier 	void *v;
388ccd4a63SDavid du Colombier 
398ccd4a63SDavid du Colombier 	if((v = pthread_getspecific(prdakey)) == nil)
408ccd4a63SDavid du Colombier 		panic("cannot getspecific");
418ccd4a63SDavid du Colombier 	return v;
428ccd4a63SDavid du Colombier }
438ccd4a63SDavid du Colombier 
448ccd4a63SDavid du Colombier void
_setproc(Proc * p)458ccd4a63SDavid du Colombier _setproc(Proc *p)
468ccd4a63SDavid du Colombier {
478ccd4a63SDavid du Colombier 	if(pthread_setspecific(prdakey, p) != 0)
488ccd4a63SDavid du Colombier 		panic("cannot setspecific");
498ccd4a63SDavid du Colombier }
508ccd4a63SDavid du Colombier 
518ccd4a63SDavid du Colombier void
osinit(void)528ccd4a63SDavid du Colombier osinit(void)
538ccd4a63SDavid du Colombier {
548ccd4a63SDavid du Colombier 	if(pthread_key_create(&prdakey, 0))
558ccd4a63SDavid du Colombier 		panic("cannot pthread_key_create");
568ccd4a63SDavid du Colombier }
578ccd4a63SDavid du Colombier 
588ccd4a63SDavid du Colombier #undef pipe
598ccd4a63SDavid du Colombier void
osnewproc(Proc * p)608ccd4a63SDavid du Colombier osnewproc(Proc *p)
618ccd4a63SDavid du Colombier {
628ccd4a63SDavid du Colombier 	Oproc *op;
638ccd4a63SDavid du Colombier 	pthread_mutexattr_t attr;
648ccd4a63SDavid du Colombier 
658ccd4a63SDavid du Colombier 	op = (Oproc*)p->oproc;
668ccd4a63SDavid du Colombier 	pthread_mutexattr_init(&attr);
678ccd4a63SDavid du Colombier 	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
688ccd4a63SDavid du Colombier 	pthread_mutex_init(&op->mutex, &attr);
698ccd4a63SDavid du Colombier 	pthread_mutexattr_destroy(&attr);
708ccd4a63SDavid du Colombier 	pthread_cond_init(&op->cond, 0);
718ccd4a63SDavid du Colombier }
728ccd4a63SDavid du Colombier 
738ccd4a63SDavid du Colombier void
osmsleep(int ms)748ccd4a63SDavid du Colombier osmsleep(int ms)
758ccd4a63SDavid du Colombier {
768ccd4a63SDavid du Colombier 	struct timeval tv;
778ccd4a63SDavid du Colombier 
788ccd4a63SDavid du Colombier 	tv.tv_sec = ms / 1000;
798ccd4a63SDavid du Colombier 	tv.tv_usec = (ms % 1000) * 1000; /* micro */
808ccd4a63SDavid du Colombier 	if(select(0, NULL, NULL, NULL, &tv) < 0)
818ccd4a63SDavid du Colombier 		panic("select");
828ccd4a63SDavid du Colombier }
838ccd4a63SDavid du Colombier 
848ccd4a63SDavid du Colombier void
osyield(void)858ccd4a63SDavid du Colombier osyield(void)
868ccd4a63SDavid du Colombier {
878ccd4a63SDavid du Colombier 	sched_yield();
888ccd4a63SDavid du Colombier }
898ccd4a63SDavid du Colombier 
908ccd4a63SDavid du Colombier void
oserrstr(void)918ccd4a63SDavid du Colombier oserrstr(void)
928ccd4a63SDavid du Colombier {
938ccd4a63SDavid du Colombier 	char *p;
948ccd4a63SDavid du Colombier 
958ccd4a63SDavid du Colombier 	if((p = strerror(errno)) != nil)
968ccd4a63SDavid du Colombier 		strecpy(up->errstr, up->errstr+ERRMAX, p);
978ccd4a63SDavid du Colombier 	else
988ccd4a63SDavid du Colombier 		snprint(up->errstr, ERRMAX, "unix error %d", errno);
998ccd4a63SDavid du Colombier }
1008ccd4a63SDavid du Colombier 
1018ccd4a63SDavid du Colombier void
oserror(void)1028ccd4a63SDavid du Colombier oserror(void)
1038ccd4a63SDavid du Colombier {
1048ccd4a63SDavid du Colombier 	oserrstr();
1058ccd4a63SDavid du Colombier 	nexterror();
1068ccd4a63SDavid du Colombier }
1078ccd4a63SDavid du Colombier 
1088ccd4a63SDavid du Colombier static void* tramp(void*);
1098ccd4a63SDavid du Colombier 
1108ccd4a63SDavid du Colombier void
osproc(Proc * p)1118ccd4a63SDavid du Colombier osproc(Proc *p)
1128ccd4a63SDavid du Colombier {
1138ccd4a63SDavid du Colombier 	pthread_t pid;
1148ccd4a63SDavid du Colombier 
1158ccd4a63SDavid du Colombier 	if(pthread_create(&pid, nil, tramp, p)){
1168ccd4a63SDavid du Colombier 		oserrstr();
1178ccd4a63SDavid du Colombier 		panic("osproc: %r");
1188ccd4a63SDavid du Colombier 	}
1198ccd4a63SDavid du Colombier 	sched_yield();
1208ccd4a63SDavid du Colombier }
1218ccd4a63SDavid du Colombier 
1228ccd4a63SDavid du Colombier static void*
tramp(void * vp)1238ccd4a63SDavid du Colombier tramp(void *vp)
1248ccd4a63SDavid du Colombier {
1258ccd4a63SDavid du Colombier 	Proc *p;
1268ccd4a63SDavid du Colombier 
1278ccd4a63SDavid du Colombier 	p = vp;
1288ccd4a63SDavid du Colombier 	if(pthread_setspecific(prdakey, p))
1298ccd4a63SDavid du Colombier 		panic("cannot setspecific");
1308ccd4a63SDavid du Colombier 	(*p->fn)(p->arg);
1318ccd4a63SDavid du Colombier 	/* BUG: leaks Proc */
1328ccd4a63SDavid du Colombier 	pthread_setspecific(prdakey, 0);
1338ccd4a63SDavid du Colombier 	pthread_exit(0);
1348ccd4a63SDavid du Colombier 	return 0;
1358ccd4a63SDavid du Colombier }
1368ccd4a63SDavid du Colombier 
1378ccd4a63SDavid du Colombier void
procsleep(void)1388ccd4a63SDavid du Colombier procsleep(void)
1398ccd4a63SDavid du Colombier {
1408ccd4a63SDavid du Colombier 	Proc *p;
1418ccd4a63SDavid du Colombier 	Oproc *op;
1428ccd4a63SDavid du Colombier 
1438ccd4a63SDavid du Colombier 	p = up;
1448ccd4a63SDavid du Colombier 	op = (Oproc*)p->oproc;
1458ccd4a63SDavid du Colombier 	pthread_mutex_lock(&op->mutex);
1468ccd4a63SDavid du Colombier 	op->nsleep++;
1478ccd4a63SDavid du Colombier 	while(op->nsleep > op->nwakeup)
1488ccd4a63SDavid du Colombier 		pthread_cond_wait(&op->cond, &op->mutex);
1498ccd4a63SDavid du Colombier 	pthread_mutex_unlock(&op->mutex);
1508ccd4a63SDavid du Colombier }
1518ccd4a63SDavid du Colombier 
1528ccd4a63SDavid du Colombier void
procwakeup(Proc * p)1538ccd4a63SDavid du Colombier procwakeup(Proc *p)
1548ccd4a63SDavid du Colombier {
1558ccd4a63SDavid du Colombier 	Oproc *op;
1568ccd4a63SDavid du Colombier 
1578ccd4a63SDavid du Colombier 	op = (Oproc*)p->oproc;
1588ccd4a63SDavid du Colombier 	pthread_mutex_lock(&op->mutex);
1598ccd4a63SDavid du Colombier 	op->nwakeup++;
1608ccd4a63SDavid du Colombier 	if(op->nwakeup == op->nsleep)
1618ccd4a63SDavid du Colombier 		pthread_cond_signal(&op->cond);
1628ccd4a63SDavid du Colombier 	pthread_mutex_unlock(&op->mutex);
1638ccd4a63SDavid du Colombier }
1648ccd4a63SDavid du Colombier 
1658ccd4a63SDavid du Colombier int randfd;
1668ccd4a63SDavid du Colombier #undef open
1678ccd4a63SDavid du Colombier void
randominit(void)1688ccd4a63SDavid du Colombier randominit(void)
1698ccd4a63SDavid du Colombier {
1708ccd4a63SDavid du Colombier #ifdef USE_RANDOM
1718ccd4a63SDavid du Colombier 	srandom(getpid()+fastticks(nil)+ticks());
1728ccd4a63SDavid du Colombier #else
1738ccd4a63SDavid du Colombier 	if((randfd = open("/dev/urandom", OREAD)) < 0)
1748ccd4a63SDavid du Colombier 	if((randfd = open("/dev/random", OREAD)) < 0)
1758ccd4a63SDavid du Colombier 		panic("open /dev/random: %r");
1768ccd4a63SDavid du Colombier #endif
1778ccd4a63SDavid du Colombier }
1788ccd4a63SDavid du Colombier 
1798ccd4a63SDavid du Colombier #undef read
1808ccd4a63SDavid du Colombier ulong
randomread(void * v,ulong n)1818ccd4a63SDavid du Colombier randomread(void *v, ulong n)
1828ccd4a63SDavid du Colombier {
1838ccd4a63SDavid du Colombier #ifdef USE_RANDOM
1848ccd4a63SDavid du Colombier 	int i;
1858ccd4a63SDavid du Colombier 
1868ccd4a63SDavid du Colombier 	for(i=0; i<n; i++)
1878ccd4a63SDavid du Colombier 		((uchar*)v)[i] = random();
1888ccd4a63SDavid du Colombier 	return n;
1898ccd4a63SDavid du Colombier #else
1908ccd4a63SDavid du Colombier 	int m;
1918ccd4a63SDavid du Colombier 
1928ccd4a63SDavid du Colombier 	if((m = read(randfd, v, n)) != n)
1938ccd4a63SDavid du Colombier 		panic("short read from /dev/random: %d but %d", n, m);
1948ccd4a63SDavid du Colombier 	return m;
1958ccd4a63SDavid du Colombier #endif
1968ccd4a63SDavid du Colombier }
1978ccd4a63SDavid du Colombier 
1988ccd4a63SDavid du Colombier #undef time
1998ccd4a63SDavid du Colombier long
seconds(void)2008ccd4a63SDavid du Colombier seconds(void)
2018ccd4a63SDavid du Colombier {
2028ccd4a63SDavid du Colombier 	return time(0);
2038ccd4a63SDavid du Colombier }
2048ccd4a63SDavid du Colombier 
2058ccd4a63SDavid du Colombier ulong
ticks(void)2068ccd4a63SDavid du Colombier ticks(void)
2078ccd4a63SDavid du Colombier {
2088ccd4a63SDavid du Colombier 	static long sec0 = 0, usec0;
2098ccd4a63SDavid du Colombier 	struct timeval t;
2108ccd4a63SDavid du Colombier 
2118ccd4a63SDavid du Colombier 	if(gettimeofday(&t, nil) < 0)
2128ccd4a63SDavid du Colombier 		return 0;
2138ccd4a63SDavid du Colombier 	if(sec0 == 0){
2148ccd4a63SDavid du Colombier 		sec0 = t.tv_sec;
2158ccd4a63SDavid du Colombier 		usec0 = t.tv_usec;
2168ccd4a63SDavid du Colombier 	}
2178ccd4a63SDavid du Colombier 	return (t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000;
2188ccd4a63SDavid du Colombier }
2198ccd4a63SDavid du Colombier 
220ec59a3ddSDavid du Colombier long
showfilewrite(char * a,int n)221ec59a3ddSDavid du Colombier showfilewrite(char *a, int n)
222ec59a3ddSDavid du Colombier {
223ec59a3ddSDavid du Colombier 	error("not implemented");
224ec59a3ddSDavid du Colombier 	return -1;
225ec59a3ddSDavid du Colombier }
226