correctly init v_ralen and v_maxra
[unix-history] / usr / src / sys / kern / sys_generic.c
CommitLineData
da7c5cc6 1/*
9302ea08
KB
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
da7c5cc6 4 *
dbf0c423 5 * %sccs.include.redist.c%
c4ec2128 6 *
cf5ef508 7 * @(#)sys_generic.c 8.4 (Berkeley) %G%
da7c5cc6 8 */
ffe28cfe 9
38a01dbe
KB
10#include <sys/param.h>
11#include <sys/systm.h>
12#include <sys/filedesc.h>
13#include <sys/ioctl.h>
14#include <sys/file.h>
15#include <sys/proc.h>
16#include <sys/socketvar.h>
17#include <sys/uio.h>
18#include <sys/kernel.h>
19#include <sys/stat.h>
20#include <sys/malloc.h>
46814581 21#ifdef KTRACE
38a01dbe 22#include <sys/ktrace.h>
46814581 23#endif
ffe28cfe
BJ
24
25/*
26 * Read system call.
27 */
1d369105 28struct read_args {
7121fdf0
KB
29 int fd;
30 char *buf;
31 u_int nbyte;
1d369105 32};
25ed1cf1 33/* ARGSUSED */
c9714ae3
KM
34read(p, uap, retval)
35 struct proc *p;
1d369105 36 register struct read_args *uap;
c9714ae3
KM
37 int *retval;
38{
c4ec2128 39 register struct file *fp;
5e00df3b 40 register struct filedesc *fdp = p->p_fd;
32a43ee2
BJ
41 struct uio auio;
42 struct iovec aiov;
c4ec2128
KM
43 long cnt, error = 0;
44#ifdef KTRACE
45 struct iovec ktriov;
46#endif
ffe28cfe 47
7121fdf0
KB
48 if (((u_int)uap->fd) >= fdp->fd_nfiles ||
49 (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
c4ec2128 50 (fp->f_flag & FREAD) == 0)
d9c2f47f 51 return (EBADF);
7121fdf0
KB
52 aiov.iov_base = (caddr_t)uap->buf;
53 aiov.iov_len = uap->nbyte;
32a43ee2
BJ
54 auio.uio_iov = &aiov;
55 auio.uio_iovcnt = 1;
7121fdf0 56 auio.uio_resid = uap->nbyte;
c4ec2128
KM
57 auio.uio_rw = UIO_READ;
58 auio.uio_segflg = UIO_USERSPACE;
221dba7d 59 auio.uio_procp = p;
c4ec2128
KM
60#ifdef KTRACE
61 /*
62 * if tracing, save a copy of iovec
63 */
c9714ae3 64 if (KTRPOINT(p, KTR_GENIO))
c4ec2128
KM
65 ktriov = aiov;
66#endif
7121fdf0 67 cnt = uap->nbyte;
9754d709
MK
68 if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
69 if (auio.uio_resid != cnt && (error == ERESTART ||
70 error == EINTR || error == EWOULDBLOCK))
71 error = 0;
c4ec2128
KM
72 cnt -= auio.uio_resid;
73#ifdef KTRACE
c9714ae3 74 if (KTRPOINT(p, KTR_GENIO) && error == 0)
7121fdf0 75 ktrgenio(p->p_tracep, uap->fd, UIO_READ, &ktriov, cnt, error);
c4ec2128 76#endif
c9714ae3 77 *retval = cnt;
d9c2f47f 78 return (error);
b9429893
BJ
79}
80
c9714ae3
KM
81/*
82 * Scatter read system call.
83 */
1d369105
CT
84struct readv_args {
85 int fdes;
86 struct iovec *iovp;
7121fdf0 87 u_int iovcnt;
1d369105 88};
c9714ae3
KM
89readv(p, uap, retval)
90 struct proc *p;
1d369105 91 register struct readv_args *uap;
c9714ae3
KM
92 int *retval;
93{
c4ec2128 94 register struct file *fp;
5e00df3b 95 register struct filedesc *fdp = p->p_fd;
b9429893 96 struct uio auio;
c4ec2128 97 register struct iovec *iov;
7b7210d3 98 struct iovec *needfree;
c4ec2128
KM
99 struct iovec aiov[UIO_SMALLIOV];
100 long i, cnt, error = 0;
7121fdf0 101 u_int iovlen;
c4ec2128
KM
102#ifdef KTRACE
103 struct iovec *ktriov = NULL;
104#endif
b9429893 105
7121fdf0 106 if (((u_int)uap->fdes) >= fdp->fd_nfiles ||
43ed8e9d 107 (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
c4ec2128 108 (fp->f_flag & FREAD) == 0)
d9c2f47f 109 return (EBADF);
c9773de9
MK
110 /* note: can't use iovlen until iovcnt is validated */
111 iovlen = uap->iovcnt * sizeof (struct iovec);
46814581 112 if (uap->iovcnt > UIO_SMALLIOV) {
c4ec2128 113 if (uap->iovcnt > UIO_MAXIOV)
d9c2f47f 114 return (EINVAL);
c9773de9 115 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
7b7210d3
CT
116 needfree = iov;
117 } else {
46814581 118 iov = aiov;
7b7210d3
CT
119 needfree = NULL;
120 }
46814581 121 auio.uio_iov = iov;
b9429893 122 auio.uio_iovcnt = uap->iovcnt;
c4ec2128
KM
123 auio.uio_rw = UIO_READ;
124 auio.uio_segflg = UIO_USERSPACE;
221dba7d 125 auio.uio_procp = p;
c9773de9 126 if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
46814581 127 goto done;
c4ec2128
KM
128 auio.uio_resid = 0;
129 for (i = 0; i < uap->iovcnt; i++) {
130 if (iov->iov_len < 0) {
131 error = EINVAL;
132 goto done;
133 }
134 auio.uio_resid += iov->iov_len;
135 if (auio.uio_resid < 0) {
136 error = EINVAL;
137 goto done;
138 }
139 iov++;
140 }
141#ifdef KTRACE
142 /*
143 * if tracing, save a copy of iovec
144 */
c9714ae3 145 if (KTRPOINT(p, KTR_GENIO)) {
c4ec2128
KM
146 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
147 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
148 }
149#endif
150 cnt = auio.uio_resid;
9754d709
MK
151 if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
152 if (auio.uio_resid != cnt && (error == ERESTART ||
153 error == EINTR || error == EWOULDBLOCK))
154 error = 0;
c4ec2128
KM
155 cnt -= auio.uio_resid;
156#ifdef KTRACE
157 if (ktriov != NULL) {
e64d087d 158 if (error == 0)
51322105
KM
159 ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov,
160 cnt, error);
c4ec2128
KM
161 FREE(ktriov, M_TEMP);
162 }
163#endif
c9714ae3 164 *retval = cnt;
46814581 165done:
7b7210d3
CT
166 if (needfree)
167 FREE(needfree, M_IOV);
d9c2f47f 168 return (error);
ffe28cfe
BJ
169}
170
171/*
172 * Write system call
173 */
1d369105 174struct write_args {
7121fdf0
KB
175 int fd;
176 char *buf;
177 u_int nbyte;
1d369105 178};
c9714ae3
KM
179write(p, uap, retval)
180 struct proc *p;
1d369105 181 register struct write_args *uap;
c9714ae3
KM
182 int *retval;
183{
c4ec2128 184 register struct file *fp;
5e00df3b 185 register struct filedesc *fdp = p->p_fd;
b9429893
BJ
186 struct uio auio;
187 struct iovec aiov;
c4ec2128
KM
188 long cnt, error = 0;
189#ifdef KTRACE
190 struct iovec ktriov;
191#endif
ffe28cfe 192
7121fdf0
KB
193 if (((u_int)uap->fd) >= fdp->fd_nfiles ||
194 (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
c4ec2128 195 (fp->f_flag & FWRITE) == 0)
d9c2f47f 196 return (EBADF);
7121fdf0
KB
197 aiov.iov_base = (caddr_t)uap->buf;
198 aiov.iov_len = uap->nbyte;
b9429893
BJ
199 auio.uio_iov = &aiov;
200 auio.uio_iovcnt = 1;
7121fdf0 201 auio.uio_resid = uap->nbyte;
c4ec2128
KM
202 auio.uio_rw = UIO_WRITE;
203 auio.uio_segflg = UIO_USERSPACE;
221dba7d 204 auio.uio_procp = p;
c4ec2128
KM
205#ifdef KTRACE
206 /*
207 * if tracing, save a copy of iovec
208 */
c9714ae3 209 if (KTRPOINT(p, KTR_GENIO))
c4ec2128
KM
210 ktriov = aiov;
211#endif
7121fdf0 212 cnt = uap->nbyte;
9754d709
MK
213 if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
214 if (auio.uio_resid != cnt && (error == ERESTART ||
215 error == EINTR || error == EWOULDBLOCK))
216 error = 0;
217 if (error == EPIPE)
c9714ae3 218 psignal(p, SIGPIPE);
9754d709 219 }
c4ec2128
KM
220 cnt -= auio.uio_resid;
221#ifdef KTRACE
c9714ae3 222 if (KTRPOINT(p, KTR_GENIO) && error == 0)
7121fdf0 223 ktrgenio(p->p_tracep, uap->fd, UIO_WRITE,
51322105 224 &ktriov, cnt, error);
c4ec2128 225#endif
c9714ae3 226 *retval = cnt;
d9c2f47f 227 return (error);
b9429893
BJ
228}
229
c9714ae3
KM
230/*
231 * Gather write system call
232 */
1d369105 233struct writev_args {
7121fdf0 234 int fd;
1d369105 235 struct iovec *iovp;
7121fdf0 236 u_int iovcnt;
1d369105 237};
c9714ae3
KM
238writev(p, uap, retval)
239 struct proc *p;
1d369105 240 register struct writev_args *uap;
c9714ae3
KM
241 int *retval;
242{
c4ec2128 243 register struct file *fp;
5e00df3b 244 register struct filedesc *fdp = p->p_fd;
b9429893 245 struct uio auio;
c4ec2128 246 register struct iovec *iov;
7b7210d3 247 struct iovec *needfree;
c4ec2128
KM
248 struct iovec aiov[UIO_SMALLIOV];
249 long i, cnt, error = 0;
7121fdf0 250 u_int iovlen;
c4ec2128
KM
251#ifdef KTRACE
252 struct iovec *ktriov = NULL;
253#endif
b9429893 254
7121fdf0
KB
255 if (((u_int)uap->fd) >= fdp->fd_nfiles ||
256 (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
c4ec2128 257 (fp->f_flag & FWRITE) == 0)
d9c2f47f 258 return (EBADF);
c9773de9
MK
259 /* note: can't use iovlen until iovcnt is validated */
260 iovlen = uap->iovcnt * sizeof (struct iovec);
46814581 261 if (uap->iovcnt > UIO_SMALLIOV) {
c4ec2128 262 if (uap->iovcnt > UIO_MAXIOV)
d9c2f47f 263 return (EINVAL);
c9773de9 264 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
7b7210d3
CT
265 needfree = iov;
266 } else {
46814581 267 iov = aiov;
7b7210d3
CT
268 needfree = NULL;
269 }
46814581 270 auio.uio_iov = iov;
b9429893 271 auio.uio_iovcnt = uap->iovcnt;
c4ec2128
KM
272 auio.uio_rw = UIO_WRITE;
273 auio.uio_segflg = UIO_USERSPACE;
221dba7d 274 auio.uio_procp = p;
c9773de9 275 if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
46814581 276 goto done;
c4ec2128
KM
277 auio.uio_resid = 0;
278 for (i = 0; i < uap->iovcnt; i++) {
b9429893 279 if (iov->iov_len < 0) {
c4ec2128
KM
280 error = EINVAL;
281 goto done;
b9429893 282 }
c4ec2128
KM
283 auio.uio_resid += iov->iov_len;
284 if (auio.uio_resid < 0) {
285 error = EINVAL;
286 goto done;
b9429893 287 }
2a0114a8 288 iov++;
b9429893 289 }
46814581 290#ifdef KTRACE
c4ec2128
KM
291 /*
292 * if tracing, save a copy of iovec
293 */
c9714ae3 294 if (KTRPOINT(p, KTR_GENIO)) {
46814581 295 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
c4ec2128 296 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
46814581
MK
297 }
298#endif
c4ec2128 299 cnt = auio.uio_resid;
9754d709
MK
300 if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
301 if (auio.uio_resid != cnt && (error == ERESTART ||
302 error == EINTR || error == EWOULDBLOCK))
303 error = 0;
304 if (error == EPIPE)
c9714ae3 305 psignal(p, SIGPIPE);
9754d709 306 }
c4ec2128 307 cnt -= auio.uio_resid;
46814581
MK
308#ifdef KTRACE
309 if (ktriov != NULL) {
e64d087d 310 if (error == 0)
7121fdf0 311 ktrgenio(p->p_tracep, uap->fd, UIO_WRITE,
51322105 312 ktriov, cnt, error);
46814581
MK
313 FREE(ktriov, M_TEMP);
314 }
315#endif
c9714ae3 316 *retval = cnt;
c4ec2128 317done:
7b7210d3
CT
318 if (needfree)
319 FREE(needfree, M_IOV);
d9c2f47f 320 return (error);
4147b3f6 321}
ffe28cfe
BJ
322
323/*
324 * Ioctl system call
ffe28cfe 325 */
1d369105 326struct ioctl_args {
7121fdf0
KB
327 int fd;
328 int com;
329 caddr_t data;
1d369105 330};
c9714ae3
KM
331/* ARGSUSED */
332ioctl(p, uap, retval)
333 struct proc *p;
1d369105 334 register struct ioctl_args *uap;
c9714ae3
KM
335 int *retval;
336{
337 register struct file *fp;
cb84e0ab 338 register struct filedesc *fdp;
9754d709 339 register int com, error;
b9429893 340 register u_int size;
cb84e0ab
KB
341 caddr_t data, memp;
342 int tmp;
c0bb7b0e 343#define STK_PARAMS 128
08eb908c 344 char stkbuf[STK_PARAMS];
ffe28cfe 345
cb84e0ab 346 fdp = p->p_fd;
7121fdf0
KB
347 if ((u_int)uap->fd >= fdp->fd_nfiles ||
348 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
d9c2f47f 349 return (EBADF);
cb84e0ab
KB
350
351 if ((fp->f_flag & (FREAD | FWRITE)) == 0)
d9c2f47f 352 return (EBADF);
4b72e2f9 353
cb84e0ab
KB
354 switch (com = uap->com) {
355 case FIONCLEX:
7121fdf0 356 fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE;
d9c2f47f 357 return (0);
cb84e0ab
KB
358 case FIOCLEX:
359 fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE;
360 return (0);
ffe28cfe 361 }
4b72e2f9
SL
362
363 /*
cb84e0ab
KB
364 * Interpret high order word to find amount of data to be
365 * copied to/from the user's address space.
4b72e2f9 366 */
c0bb7b0e 367 size = IOCPARM_LEN(com);
9754d709 368 if (size > IOCPARM_MAX)
d9c2f47f 369 return (ENOTTY);
cb84e0ab 370 memp = NULL;
08eb908c 371 if (size > sizeof (stkbuf)) {
f452da3a 372 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
e0b18aec 373 data = memp;
cb84e0ab
KB
374 } else
375 data = stkbuf;
471f17ed
SL
376 if (com&IOC_IN) {
377 if (size) {
7121fdf0 378 error = copyin(uap->data, data, (u_int)size);
9754d709 379 if (error) {
e0b18aec
KM
380 if (memp)
381 free(memp, M_IOCTLOPS);
d9c2f47f 382 return (error);
e0b18aec 383 }
471f17ed 384 } else
7121fdf0 385 *(caddr_t *)data = uap->data;
471f17ed
SL
386 } else if ((com&IOC_OUT) && size)
387 /*
46814581
MK
388 * Zero the buffer so the user always
389 * gets back something deterministic.
471f17ed 390 */
c0bb7b0e 391 bzero(data, size);
a76b60f6 392 else if (com&IOC_VOID)
7121fdf0 393 *(caddr_t *)data = uap->data;
4b72e2f9 394
88a7a62a
SL
395 switch (com) {
396
397 case FIONBIO:
221dba7d 398 if (tmp = *(int *)data)
93080c46 399 fp->f_flag |= FNONBLOCK;
221dba7d 400 else
93080c46 401 fp->f_flag &= ~FNONBLOCK;
221dba7d 402 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
c0bb7b0e 403 break;
88a7a62a
SL
404
405 case FIOASYNC:
221dba7d
KM
406 if (tmp = *(int *)data)
407 fp->f_flag |= FASYNC;
408 else
409 fp->f_flag &= ~FASYNC;
410 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
c0bb7b0e 411 break;
88a7a62a
SL
412
413 case FIOSETOWN:
221dba7d
KM
414 tmp = *(int *)data;
415 if (fp->f_type == DTYPE_SOCKET) {
416 ((struct socket *)fp->f_data)->so_pgid = tmp;
417 error = 0;
418 break;
419 }
420 if (tmp <= 0) {
421 tmp = -tmp;
422 } else {
423 struct proc *p1 = pfind(tmp);
424 if (p1 == 0) {
425 error = ESRCH;
426 break;
427 }
428 tmp = p1->p_pgrp->pg_id;
429 }
430 error = (*fp->f_ops->fo_ioctl)
431 (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
c0bb7b0e 432 break;
4b72e2f9 433
88a7a62a 434 case FIOGETOWN:
221dba7d
KM
435 if (fp->f_type == DTYPE_SOCKET) {
436 error = 0;
437 *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
438 break;
439 }
440 error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
441 *(int *)data = -*(int *)data;
c0bb7b0e 442 break;
221dba7d 443
c0bb7b0e 444 default:
8429d022 445 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
c0bb7b0e
MK
446 /*
447 * Copy any data to user, size was
448 * already set and checked above.
449 */
9754d709 450 if (error == 0 && (com&IOC_OUT) && size)
7121fdf0 451 error = copyout(data, uap->data, (u_int)size);
c0bb7b0e 452 break;
88a7a62a 453 }
e0b18aec
KM
454 if (memp)
455 free(memp, M_IOCTLOPS);
d9c2f47f 456 return (error);
ffe28cfe
BJ
457}
458
44adcf01 459int selwait, nselcoll;
d441e5bc 460
ffe28cfe 461/*
88a7a62a 462 * Select system call.
ffe28cfe 463 */
1d369105 464struct select_args {
a298f08c 465 u_int nd;
1d369105
CT
466 fd_set *in, *ou, *ex;
467 struct timeval *tv;
468};
c9714ae3
KM
469select(p, uap, retval)
470 register struct proc *p;
1d369105 471 register struct select_args *uap;
c9714ae3
KM
472 int *retval;
473{
b8e71e77 474 fd_set ibits[3], obits[3];
88a7a62a 475 struct timeval atv;
a298f08c
KM
476 int s, ncoll, error = 0, timo;
477 u_int ni;
88a7a62a 478
01b0e233
MK
479 bzero((caddr_t)ibits, sizeof(ibits));
480 bzero((caddr_t)obits, sizeof(obits));
a298f08c
KM
481 if (uap->nd > FD_SETSIZE)
482 return (EINVAL);
8429d022
MK
483 if (uap->nd > p->p_fd->fd_nfiles)
484 uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */
a298f08c 485 ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask);
88a7a62a
SL
486
487#define getbits(name, x) \
a298f08c
KM
488 if (uap->name && \
489 (error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], ni))) \
490 goto done;
88a7a62a
SL
491 getbits(in, 0);
492 getbits(ou, 1);
493 getbits(ex, 2);
494#undef getbits
495
496 if (uap->tv) {
9754d709 497 error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
88a7a62a 498 sizeof (atv));
9754d709 499 if (error)
88a7a62a
SL
500 goto done;
501 if (itimerfix(&atv)) {
9754d709 502 error = EINVAL;
88a7a62a
SL
503 goto done;
504 }
2b6d0fc1
CT
505 s = splclock();
506 timevaladd(&atv, (struct timeval *)&time);
9754d709 507 timo = hzto(&atv);
4fc80098
KM
508 /*
509 * Avoid inadvertently sleeping forever.
510 */
511 if (timo == 0)
512 timo = 1;
856f902f 513 splx(s);
9754d709
MK
514 } else
515 timo = 0;
88a7a62a
SL
516retry:
517 ncoll = nselcoll;
cf5ef508 518 p->p_flag |= P_SELECT;
8429d022 519 error = selscan(p, ibits, obits, uap->nd, retval);
c9714ae3 520 if (error || *retval)
88a7a62a 521 goto done;
c4e1f1e5 522 s = splhigh();
e394e134
SL
523 /* this should be timercmp(&time, &atv, >=) */
524 if (uap->tv && (time.tv_sec > atv.tv_sec ||
525 time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
88a7a62a
SL
526 splx(s);
527 goto done;
528 }
cf5ef508 529 if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
88a7a62a
SL
530 splx(s);
531 goto retry;
532 }
cf5ef508 533 p->p_flag &= ~P_SELECT;
9754d709 534 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
88a7a62a 535 splx(s);
9754d709
MK
536 if (error == 0)
537 goto retry;
88a7a62a 538done:
cf5ef508 539 p->p_flag &= ~P_SELECT;
9754d709
MK
540 /* select is not restarted after signals... */
541 if (error == ERESTART)
542 error = EINTR;
543 if (error == EWOULDBLOCK)
544 error = 0;
88a7a62a 545#define putbits(name, x) \
a298f08c
KM
546 if (uap->name && \
547 (error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, ni))) \
548 error = error2;
9754d709 549 if (error == 0) {
a298f08c
KM
550 int error2;
551
79f403fc
MK
552 putbits(in, 0);
553 putbits(ou, 1);
554 putbits(ex, 2);
88a7a62a 555#undef putbits
79f403fc 556 }
d9c2f47f 557 return (error);
88a7a62a
SL
558}
559
8429d022
MK
560selscan(p, ibits, obits, nfd, retval)
561 struct proc *p;
b8e71e77 562 fd_set *ibits, *obits;
c9714ae3 563 int nfd, *retval;
88a7a62a 564{
8429d022 565 register struct filedesc *fdp = p->p_fd;
7b7210d3 566 register int msk, i, j, fd;
b8e71e77 567 register fd_mask bits;
88a7a62a 568 struct file *fp;
7b7210d3
CT
569 int n = 0;
570 static int flag[3] = { FREAD, FWRITE, 0 };
88a7a62a 571
7b7210d3 572 for (msk = 0; msk < 3; msk++) {
b8e71e77 573 for (i = 0; i < nfd; i += NFDBITS) {
7b7210d3
CT
574 bits = ibits[msk].fds_bits[i/NFDBITS];
575 while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
d441e5bc 576 bits &= ~(1 << j);
7b7210d3
CT
577 fp = fdp->fd_ofiles[fd];
578 if (fp == NULL)
579 return (EBADF);
580 if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
581 FD_SET(fd, &obits[msk]);
d441e5bc
MK
582 n++;
583 }
88a7a62a
SL
584 }
585 }
586 }
c9714ae3 587 *retval = n;
7b7210d3 588 return (0);
88a7a62a
SL
589}
590
ffe28cfe 591/*ARGSUSED*/
8429d022 592seltrue(dev, flag, p)
88a7a62a
SL
593 dev_t dev;
594 int flag;
8429d022 595 struct proc *p;
ffe28cfe
BJ
596{
597
88a7a62a 598 return (1);
ffe28cfe 599}
1edb1cf8 600
4a4fcc2c
KM
601/*
602 * Record a select request.
603 */
604void
605selrecord(selector, sip)
606 struct proc *selector;
607 struct selinfo *sip;
608{
609 struct proc *p;
610 pid_t mypid;
611
612 mypid = selector->p_pid;
613 if (sip->si_pid == mypid)
614 return;
615 if (sip->si_pid && (p = pfind(sip->si_pid)) &&
616 p->p_wchan == (caddr_t)&selwait)
617 sip->si_flags |= SI_COLL;
618 else
619 sip->si_pid = mypid;
620}
621
622/*
623 * Do a wakeup when a selectable event occurs.
624 */
625void
626selwakeup(sip)
627 register struct selinfo *sip;
1edb1cf8 628{
4a4fcc2c
KM
629 register struct proc *p;
630 int s;
1edb1cf8 631
4a4fcc2c
KM
632 if (sip->si_pid == 0)
633 return;
634 if (sip->si_flags & SI_COLL) {
88a7a62a 635 nselcoll++;
4a4fcc2c 636 sip->si_flags &= ~SI_COLL;
88a7a62a
SL
637 wakeup((caddr_t)&selwait);
638 }
9c2b41ec
KM
639 p = pfind(sip->si_pid);
640 sip->si_pid = 0;
641 if (p != NULL) {
4a4fcc2c 642 s = splhigh();
6bc3aba9
MK
643 if (p->p_wchan == (caddr_t)&selwait) {
644 if (p->p_stat == SSLEEP)
cb84e0ab 645 setrunnable(p);
6bc3aba9
MK
646 else
647 unsleep(p);
cf5ef508
KB
648 } else if (p->p_flag & P_SELECT)
649 p->p_flag &= ~P_SELECT;
88a7a62a
SL
650 splx(s);
651 }
1edb1cf8 652}