change gdium conf to print message out both on uart and lcd
[pmon-gdium.git] / sys / kern / sys_generic.c
blobed8506316006e731e6b8a58969032b6502d61e7f
1 /* $Id: sys_generic.c,v 1.1.1.1 2006/09/14 01:59:08 root Exp $ */
2 /* $OpenBSD: sys_generic.c,v 1.20 1999/08/04 19:18:13 deraadt Exp $ */
3 /* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */
5 /*
6 * Copyright (c) 1996 Theo de Raadt
7 * Copyright (c) 1982, 1986, 1989, 1993
8 * The Regents of the University of California. All rights reserved.
9 * (c) UNIX System Laboratories, Inc.
10 * All or some portions of this file are derived from material licensed
11 * to the University of California by American Telephone and Telegraph
12 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
13 * the permission of UNIX System Laboratories, Inc.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. All advertising materials mentioning features or use of this software
24 * must display the following acknowledgement:
25 * This product includes software developed by the University of
26 * California, Berkeley and its contributors.
27 * 4. Neither the name of the University nor the names of its contributors
28 * may be used to endorse or promote products derived from this software
29 * without specific prior written permission.
31 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
35 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 * SUCH DAMAGE.
43 * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/filedesc.h>
49 #include <sys/ioctl.h>
50 #include <sys/file.h>
51 #include <sys/proc.h>
52 #include <sys/socketvar.h>
53 #include <sys/signalvar.h>
54 #include <sys/uio.h>
55 #include <sys/kernel.h>
56 #include <sys/stat.h>
57 #include <sys/malloc.h>
58 #include <sys/poll.h>
59 #ifdef KTRACE
60 #include <sys/ktrace.h>
61 #endif
63 #if 0
64 #include <sys/mount.h>
65 #endif
66 #include <sys/syscallargs.h>
68 int selscan __P((struct proc *, fd_set *, fd_set *, int, register_t *));
69 int seltrue __P((dev_t, int, struct proc *));
70 void pollscan __P((struct proc *, struct pollfd *, int, register_t *));
73 * Read system call.
75 /* ARGSUSED */
76 int
77 sys_read(p, v, retval)
78 struct proc *p;
79 void *v;
80 register_t *retval;
82 register struct sys_read_args /* {
83 syscallarg(int) fd;
84 syscallarg(void *) buf;
85 syscallarg(size_t) nbyte;
86 } */ *uap = v;
87 register struct file *fp;
88 register struct filedesc *fdp = p->p_fd;
89 struct uio auio;
90 struct iovec aiov;
91 long cnt, error = 0;
92 #ifdef KTRACE
93 struct iovec ktriov;
94 #endif
96 if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
97 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
98 (fp->f_flag & FREAD) == 0)
99 return (EBADF);
100 /* Don't allow nbyte to be larger than max return val */
101 if (SCARG(uap, nbyte) > SSIZE_MAX)
102 return(EINVAL);
103 aiov.iov_base = (caddr_t)SCARG(uap, buf);
104 aiov.iov_len = SCARG(uap, nbyte);
105 auio.uio_iov = &aiov;
106 auio.uio_iovcnt = 1;
107 auio.uio_resid = SCARG(uap, nbyte);
108 auio.uio_rw = UIO_READ;
109 auio.uio_segflg = UIO_USERSPACE;
110 auio.uio_procp = p;
111 #ifdef KTRACE
113 * if tracing, save a copy of iovec
115 if (KTRPOINT(p, KTR_GENIO))
116 ktriov = aiov;
117 #endif
118 cnt = SCARG(uap, nbyte);
119 error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred);
120 if (error)
121 if (auio.uio_resid != cnt && (error == ERESTART ||
122 error == EINTR || error == EWOULDBLOCK))
123 error = 0;
124 cnt -= auio.uio_resid;
125 #ifdef KTRACE
126 if (KTRPOINT(p, KTR_GENIO) && error == 0)
127 ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, &ktriov,
128 cnt, error);
129 #endif
130 *retval = cnt;
131 return (error);
135 * Scatter read system call.
138 sys_readv(p, v, retval)
139 struct proc *p;
140 void *v;
141 register_t *retval;
143 register struct sys_readv_args /* {
144 syscallarg(int) fd;
145 syscallarg(struct iovec *) iovp;
146 syscallarg(int) iovcnt;
147 } */ *uap = v;
148 register struct file *fp;
149 register struct filedesc *fdp = p->p_fd;
150 struct uio auio;
151 register struct iovec *iov;
152 struct iovec *needfree;
153 struct iovec aiov[UIO_SMALLIOV];
154 long i, cnt, error = 0;
155 u_int iovlen;
156 #ifdef KTRACE
157 struct iovec *ktriov = NULL;
158 #endif
160 if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
161 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
162 (fp->f_flag & FREAD) == 0)
163 return (EBADF);
164 if (SCARG(uap, iovcnt) <= 0)
165 return (EINVAL);
166 /* note: can't use iovlen until iovcnt is validated */
167 iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
168 if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
169 if (SCARG(uap, iovcnt) > IOV_MAX)
170 return (EINVAL);
171 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
172 needfree = iov;
173 } else {
174 iov = aiov;
175 needfree = NULL;
177 auio.uio_iov = iov;
178 auio.uio_iovcnt = SCARG(uap, iovcnt);
179 auio.uio_rw = UIO_READ;
180 auio.uio_segflg = UIO_USERSPACE;
181 auio.uio_procp = p;
182 error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen);
183 if (error)
184 goto done;
185 auio.uio_resid = 0;
186 for (i = 0; i < SCARG(uap, iovcnt); i++, iov++) {
187 /* Don't allow sum > SSIZE_MAX */
188 if (iov->iov_len > SSIZE_MAX ||
189 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
190 error = EINVAL;
191 goto done;
194 #ifdef KTRACE
196 * if tracing, save a copy of iovec
198 if (KTRPOINT(p, KTR_GENIO)) {
199 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
200 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
202 #endif
203 cnt = auio.uio_resid;
204 error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred);
205 if (error)
206 if (auio.uio_resid != cnt && (error == ERESTART ||
207 error == EINTR || error == EWOULDBLOCK))
208 error = 0;
209 cnt -= auio.uio_resid;
210 #ifdef KTRACE
211 if (ktriov != NULL) {
212 if (error == 0)
213 ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, ktriov,
214 cnt, error);
215 FREE(ktriov, M_TEMP);
217 #endif
218 *retval = cnt;
219 done:
220 if (needfree)
221 FREE(needfree, M_IOV);
222 return (error);
226 * Write system call
229 sys_write(p, v, retval)
230 struct proc *p;
231 void *v;
232 register_t *retval;
234 register struct sys_write_args /* {
235 syscallarg(int) fd;
236 syscallarg(void *) buf;
237 syscallarg(size_t) nbyte;
238 } */ *uap = v;
239 register struct file *fp;
240 register struct filedesc *fdp = p->p_fd;
241 struct uio auio;
242 struct iovec aiov;
243 long cnt, error = 0;
244 #ifdef KTRACE
245 struct iovec ktriov;
246 #endif
248 if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
249 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
250 (fp->f_flag & FWRITE) == 0)
251 return (EBADF);
252 /* Don't allow nbyte to be larger than max return val */
253 if (SCARG(uap, nbyte) > SSIZE_MAX)
254 return(EINVAL);
255 aiov.iov_base = (caddr_t)SCARG(uap, buf);
256 aiov.iov_len = SCARG(uap, nbyte);
257 auio.uio_iov = &aiov;
258 auio.uio_iovcnt = 1;
259 auio.uio_resid = SCARG(uap, nbyte);
260 auio.uio_rw = UIO_WRITE;
261 auio.uio_segflg = UIO_USERSPACE;
262 auio.uio_procp = p;
263 #ifdef KTRACE
265 * if tracing, save a copy of iovec
267 if (KTRPOINT(p, KTR_GENIO))
268 ktriov = aiov;
269 #endif
270 cnt = SCARG(uap, nbyte);
271 error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred);
272 if (error) {
273 if (auio.uio_resid != cnt && (error == ERESTART ||
274 error == EINTR || error == EWOULDBLOCK))
275 error = 0;
276 if (error == EPIPE)
277 psignal(p, SIGPIPE);
279 cnt -= auio.uio_resid;
280 #ifdef KTRACE
281 if (KTRPOINT(p, KTR_GENIO) && error == 0)
282 ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
283 &ktriov, cnt, error);
284 #endif
285 *retval = cnt;
286 return (error);
290 * Gather write system call
293 sys_writev(p, v, retval)
294 struct proc *p;
295 void *v;
296 register_t *retval;
298 register struct sys_writev_args /* {
299 syscallarg(int) fd;
300 syscallarg(struct iovec *) iovp;
301 syscallarg(int) iovcnt;
302 } */ *uap = v;
303 register struct file *fp;
304 register struct filedesc *fdp = p->p_fd;
305 struct uio auio;
306 register struct iovec *iov;
307 struct iovec *needfree;
308 struct iovec aiov[UIO_SMALLIOV];
309 long i, cnt, error = 0;
310 u_int iovlen;
311 #ifdef KTRACE
312 struct iovec *ktriov = NULL;
313 #endif
315 if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
316 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
317 (fp->f_flag & FWRITE) == 0)
318 return (EBADF);
319 if (SCARG(uap, iovcnt) <= 0)
320 return (EINVAL);
321 /* note: can't use iovlen until iovcnt is validated */
322 iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
323 if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
324 if (SCARG(uap, iovcnt) > IOV_MAX)
325 return (EINVAL);
326 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
327 needfree = iov;
328 } else {
329 iov = aiov;
330 needfree = NULL;
332 auio.uio_iov = iov;
333 auio.uio_iovcnt = SCARG(uap, iovcnt);
334 auio.uio_rw = UIO_WRITE;
335 auio.uio_segflg = UIO_USERSPACE;
336 auio.uio_procp = p;
337 error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen);
338 if (error)
339 goto done;
340 auio.uio_resid = 0;
341 for (i = 0; i < SCARG(uap, iovcnt); i++, iov++) {
342 /* Don't allow sum > SSIZE_MAX */
343 if (iov->iov_len > SSIZE_MAX ||
344 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
345 error = EINVAL;
346 goto done;
349 #ifdef KTRACE
351 * if tracing, save a copy of iovec
353 if (KTRPOINT(p, KTR_GENIO)) {
354 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
355 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
357 #endif
358 cnt = auio.uio_resid;
359 error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred);
360 if (error) {
361 if (auio.uio_resid != cnt && (error == ERESTART ||
362 error == EINTR || error == EWOULDBLOCK))
363 error = 0;
364 if (error == EPIPE)
365 psignal(p, SIGPIPE);
367 cnt -= auio.uio_resid;
368 #ifdef KTRACE
369 if (ktriov != NULL) {
370 if (error == 0)
371 ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
372 ktriov, cnt, error);
373 FREE(ktriov, M_TEMP);
375 #endif
376 *retval = cnt;
377 done:
378 if (needfree)
379 FREE(needfree, M_IOV);
380 return (error);
384 * Ioctl system call
386 /* ARGSUSED */
388 sys_ioctl(p, v, retval)
389 struct proc *p;
390 void *v;
391 register_t *retval;
393 register struct sys_ioctl_args /* {
394 syscallarg(int) fd;
395 syscallarg(u_long) com;
396 syscallarg(caddr_t) data;
397 } */ *uap = v;
398 register struct file *fp;
399 register struct filedesc *fdp;
400 register u_long com;
401 register int error;
402 register u_int size;
403 caddr_t data, memp;
404 int tmp;
405 #define STK_PARAMS 128
406 char stkbuf[STK_PARAMS];
408 fdp = p->p_fd;
409 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
410 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
411 return (EBADF);
413 if ((fp->f_flag & (FREAD | FWRITE)) == 0)
414 return (EBADF);
416 switch (com = SCARG(uap, com)) {
417 case FIONCLEX:
418 fdp->fd_ofileflags[SCARG(uap, fd)] &= ~UF_EXCLOSE;
419 return (0);
420 case FIOCLEX:
421 fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE;
422 return (0);
426 * Interpret high order word to find amount of data to be
427 * copied to/from the user's address space.
429 size = IOCPARM_LEN(com);
430 if (size > IOCPARM_MAX)
431 return (ENOTTY);
432 memp = NULL;
433 if (size > sizeof (stkbuf)) {
434 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
435 data = memp;
436 } else
437 data = stkbuf;
438 if (com&IOC_IN) {
439 if (size) {
440 error = copyin(SCARG(uap, data), data, (u_int)size);
441 if (error) {
442 if (memp)
443 free(memp, M_IOCTLOPS);
444 return (error);
446 } else
447 *(caddr_t *)data = SCARG(uap, data);
448 } else if ((com&IOC_OUT) && size)
450 * Zero the buffer so the user always
451 * gets back something deterministic.
453 bzero(data, size);
454 else if (com&IOC_VOID)
455 *(caddr_t *)data = SCARG(uap, data);
457 switch (com) {
459 case FIONBIO:
460 if ((tmp = *(int *)data) != 0)
461 fp->f_flag |= FNONBLOCK;
462 else
463 fp->f_flag &= ~FNONBLOCK;
464 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
465 break;
467 case FIOASYNC:
468 if ((tmp = *(int *)data) != 0)
469 fp->f_flag |= FASYNC;
470 else
471 fp->f_flag &= ~FASYNC;
472 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
473 break;
475 case FIOSETOWN:
476 tmp = *(int *)data;
477 if (fp->f_type == DTYPE_SOCKET) {
478 struct socket *so = (struct socket *)fp->f_data;
480 so->so_pgid = tmp;
481 #ifdef NOTUSE_BY_PMON
482 so->so_siguid = p->p_cred->p_ruid;
483 so->so_sigeuid = p->p_ucred->cr_uid;
484 #else
485 so->so_siguid = 0;
486 so->so_sigeuid = 0;
487 #endif
488 error = 0;
489 break;
491 if (tmp <= 0) {
492 tmp = -tmp;
493 } else {
494 #ifdef NOTUSED_BY_PMON
495 struct proc *p1 = pfind(tmp);
496 if (p1 == 0) {
497 error = ESRCH;
498 break;
500 tmp = p1->p_pgrp->pg_id;
501 #else
502 tmp = 0;
503 #endif
505 error = (*fp->f_ops->fo_ioctl)
506 (fp, TIOCSPGRP, (caddr_t)&tmp, p);
507 break;
509 case FIOGETOWN:
510 if (fp->f_type == DTYPE_SOCKET) {
511 error = 0;
512 *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
513 break;
515 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p);
516 *(int *)data = -*(int *)data;
517 break;
519 default:
520 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
522 * Copy any data to user, size was
523 * already set and checked above.
525 if (error == 0 && (com&IOC_OUT) && size)
526 error = copyout(data, SCARG(uap, data), (u_int)size);
527 break;
529 if (memp)
530 free(memp, M_IOCTLOPS);
531 return (error);
534 int selwait, nselcoll;
537 * Select system call.
540 sys_select(p, v, retval)
541 register struct proc *p;
542 void *v;
543 register_t *retval;
545 register struct sys_select_args /* {
546 syscallarg(int) nd;
547 syscallarg(fd_set *) in;
548 syscallarg(fd_set *) ou;
549 syscallarg(fd_set *) ex;
550 syscallarg(struct timeval *) tv;
551 } */ *uap = v;
552 fd_set bits[6], *pibits[3], *pobits[3];
553 struct timeval atv;
554 int s, ncoll, error = 0, timo;
555 u_int ni;
557 if (SCARG(uap, nd) > p->p_fd->fd_nfiles) {
558 /* forgiving; slightly wrong */
559 SCARG(uap, nd) = p->p_fd->fd_nfiles;
561 ni = howmany(SCARG(uap, nd), NFDBITS) * sizeof(fd_mask);
562 if (SCARG(uap, nd) > FD_SETSIZE) {
563 caddr_t mbits;
565 if ((mbits = malloc(ni * 6, M_TEMP, M_WAITOK)) == NULL) {
566 error = EINVAL;
567 goto cleanup;
569 bzero(mbits, ni * 6);
570 pibits[0] = (fd_set *)&mbits[ni * 0];
571 pibits[1] = (fd_set *)&mbits[ni * 1];
572 pibits[2] = (fd_set *)&mbits[ni * 2];
573 pobits[0] = (fd_set *)&mbits[ni * 3];
574 pobits[1] = (fd_set *)&mbits[ni * 4];
575 pobits[2] = (fd_set *)&mbits[ni * 5];
576 } else {
577 bzero((caddr_t)bits, sizeof(bits));
578 pibits[0] = &bits[0];
579 pibits[1] = &bits[1];
580 pibits[2] = &bits[2];
581 pobits[0] = &bits[3];
582 pobits[1] = &bits[4];
583 pobits[2] = &bits[5];
586 #define getbits(name, x) \
587 if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, name), \
588 (caddr_t)pibits[x], ni))) \
589 goto done;
590 getbits(in, 0);
591 getbits(ou, 1);
592 getbits(ex, 2);
593 #undef getbits
595 if (SCARG(uap, tv)) {
596 error = copyin((caddr_t)SCARG(uap, tv), (caddr_t)&atv,
597 sizeof (atv));
598 if (error)
599 goto done;
600 if (itimerfix(&atv)) {
601 error = EINVAL;
602 goto done;
604 s = splclock();
605 timeradd(&atv, &time, &atv);
606 timo = hzto(&atv);
608 * Avoid inadvertently sleeping forever.
610 if (timo == 0)
611 timo = 1;
612 splx(s);
613 } else
614 timo = 0;
615 retry:
616 ncoll = nselcoll;
617 p->p_flag |= P_SELECT;
618 error = selscan(p, pibits[0], pobits[0], SCARG(uap, nd), retval);
619 if (error || *retval)
620 goto done;
621 s = splhigh();
622 /* this should be timercmp(&time, &atv, >=) */
623 if (SCARG(uap, tv) && (time.tv_sec > atv.tv_sec ||
624 (time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec))) {
625 splx(s);
626 goto done;
628 if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
629 splx(s);
630 goto retry;
632 p->p_flag &= ~P_SELECT;
633 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
634 splx(s);
635 if (error == 0)
636 goto retry;
637 done:
638 p->p_flag &= ~P_SELECT;
639 /* select is not restarted after signals... */
640 if (error == ERESTART)
641 error = EINTR;
642 if (error == EWOULDBLOCK)
643 error = 0;
644 #define putbits(name, x) \
645 if (SCARG(uap, name) && (error2 = copyout((caddr_t)pobits[x], \
646 (caddr_t)SCARG(uap, name), ni))) \
647 error = error2;
648 if (error == 0) {
649 int error2;
651 putbits(in, 0);
652 putbits(ou, 1);
653 putbits(ex, 2);
654 #undef putbits
657 cleanup:
658 if (pibits[0] != &bits[0])
659 free(pibits[0], M_TEMP);
660 return (error);
664 selscan(p, ibits, obits, nfd, retval)
665 struct proc *p;
666 fd_set *ibits, *obits;
667 int nfd;
668 register_t *retval;
670 caddr_t cibits = (caddr_t)ibits, cobits = (caddr_t)obits;
671 register struct filedesc *fdp = p->p_fd;
672 register int msk, i, j, fd;
673 register fd_mask bits;
674 struct file *fp;
675 int ni, n = 0;
676 static int flag[3] = { FREAD, FWRITE, 0 };
679 * if nfd > FD_SETSIZE then the fd_set's contain nfd bits (rounded
680 * up to the next byte) otherwise the fd_set's are normal sized.
682 ni = sizeof(fd_set);
683 if (nfd > FD_SETSIZE)
684 ni = howmany(nfd, NFDBITS) * sizeof(fd_mask);
686 for (msk = 0; msk < 3; msk++) {
687 fd_set *pibits = (fd_set *)&cibits[msk*ni];
688 fd_set *pobits = (fd_set *)&cobits[msk*ni];
690 for (i = 0; i < nfd; i += NFDBITS) {
691 bits = pibits->fds_bits[i/NFDBITS];
692 while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
693 bits &= ~(1 << j);
694 fp = fdp->fd_ofiles[fd];
695 if (fp == NULL)
696 return (EBADF);
697 if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
698 FD_SET(fd, pobits);
699 n++;
704 *retval = n;
705 return (0);
708 /*ARGSUSED*/
710 seltrue(dev, flag, p)
711 dev_t dev;
712 int flag;
713 struct proc *p;
716 return (1);
720 * Record a select request.
722 void
723 selrecord(selector, sip)
724 struct proc *selector;
725 struct selinfo *sip;
727 struct proc *p;
728 pid_t mypid;
730 mypid = selector->p_pid;
731 if (sip->si_selpid == mypid)
732 return;
733 if (sip->si_selpid && (p = pfind(sip->si_selpid)) &&
734 p->p_wchan == (caddr_t)&selwait)
735 sip->si_flags |= SI_COLL;
736 else
737 sip->si_selpid = mypid;
741 * Do a wakeup when a selectable event occurs.
743 void
744 selwakeup(sip)
745 register struct selinfo *sip;
747 register struct proc *p;
748 int s;
750 if (sip->si_selpid == 0)
751 return;
752 if (sip->si_flags & SI_COLL) {
753 nselcoll++;
754 sip->si_flags &= ~SI_COLL;
755 wakeup((caddr_t)&selwait);
757 p = pfind(sip->si_selpid);
758 sip->si_selpid = 0;
759 if (p != NULL) {
760 s = splhigh();
761 if (p->p_wchan == (caddr_t)&selwait) {
762 if (p->p_stat == SSLEEP)
763 setrunnable(p);
764 else
765 unsleep(p);
766 } else if (p->p_flag & P_SELECT)
767 p->p_flag &= ~P_SELECT;
768 splx(s);
772 void
773 pollscan(p, pl, nfd, retval)
774 struct proc *p;
775 struct pollfd *pl;
776 int nfd;
777 register_t *retval;
779 register struct filedesc *fdp = p->p_fd;
780 register int msk, i;
781 struct file *fp;
782 int x, n = 0;
783 static int flag[3] = { FREAD, FWRITE, 0 };
784 static int pflag[3] = { POLLIN|POLLRDNORM, POLLOUT, POLLERR };
787 * XXX: We need to implement the rest of the flags.
789 for (i = 0; i < nfd; i++) {
790 fp = fdp->fd_ofiles[pl[i].fd];
791 if (fp == NULL) {
792 if (pl[i].events & POLLNVAL) {
793 pl[i].revents |= POLLNVAL;
794 n++;
796 continue;
798 for (x = msk = 0; msk < 3; msk++) {
799 if (pl[i].events & pflag[msk]) {
800 if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
801 pl[i].revents |= pflag[msk] &
802 pl[i].events;
803 x++;
807 if (x)
808 n++;
810 *retval = n;
814 * We are using the same mechanism as select only we encode/decode args
815 * differently.
818 sys_poll(p, v, retval)
819 register struct proc *p;
820 void *v;
821 register_t *retval;
823 struct sys_poll_args *uap = v;
824 size_t sz;
825 struct pollfd pfds[4], *pl = pfds;
826 int msec = SCARG(uap, timeout);
827 struct timeval atv;
828 int timo, ncoll, i, s, error, error2;
829 extern int nselcoll, selwait;
831 /* XXX constrain; This may not match standards */
832 if (SCARG(uap, nfds) > p->p_fd->fd_nfiles)
833 SCARG(uap, nfds) = p->p_fd->fd_nfiles;
834 sz = sizeof(struct pollfd) * SCARG(uap, nfds);
836 /* optimize for the default case, of a small nfds value */
837 if (sz > sizeof(pfds))
838 pl = (struct pollfd *) malloc(sz, M_TEMP, M_WAITOK);
840 if ((error = copyin(SCARG(uap, fds), pl, sz)) != 0)
841 goto bad;
843 for (i = 0; i < SCARG(uap, nfds); i++)
844 pl[i].revents = 0;
846 if (msec != -1) {
847 atv.tv_sec = msec / 1000;
848 atv.tv_usec = (msec - (atv.tv_sec * 1000)) * 1000;
850 if (itimerfix(&atv)) {
851 error = EINVAL;
852 goto done;
854 s = splclock();
855 timeradd(&atv, &time, &atv);
856 timo = hzto(&atv);
858 * Avoid inadvertently sleeping forever.
860 if (timo == 0)
861 timo = 1;
862 splx(s);
863 } else
864 timo = 0;
866 retry:
867 ncoll = nselcoll;
868 p->p_flag |= P_SELECT;
869 pollscan(p, pl, SCARG(uap, nfds), retval);
870 if (*retval)
871 goto done;
872 s = splhigh();
873 if (timo && timercmp(&time, &atv, >=)) {
874 splx(s);
875 goto done;
877 if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
878 splx(s);
879 goto retry;
881 p->p_flag &= ~P_SELECT;
882 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "poll", timo);
883 splx(s);
884 if (error == 0)
885 goto retry;
887 done:
888 p->p_flag &= ~P_SELECT;
889 /* poll is not restarted after signals... */
890 if (error == ERESTART)
891 error = EINTR;
892 if (error == EWOULDBLOCK)
893 error = 0;
894 if ((error2 = copyout(pl, SCARG(uap, fds), sz)) != 0)
895 error = error2;
896 bad:
897 if (pl != pfds)
898 free((char *) pl, M_TEMP);
899 return (error);