Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}