|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1982, 1986, 1989, 1993
28: * The Regents of the University of California. All rights reserved.
29: * (c) UNIX System Laboratories, Inc.
30: * All or some portions of this file are derived from material licensed
31: * to the University of California by American Telephone and Telegraph
32: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
33: * the permission of UNIX System Laboratories, Inc.
34: *
35: * Redistribution and use in source and binary forms, with or without
36: * modification, are permitted provided that the following conditions
37: * are met:
38: * 1. Redistributions of source code must retain the above copyright
39: * notice, this list of conditions and the following disclaimer.
40: * 2. Redistributions in binary form must reproduce the above copyright
41: * notice, this list of conditions and the following disclaimer in the
42: * documentation and/or other materials provided with the distribution.
43: * 3. All advertising materials mentioning features or use of this software
44: * must display the following acknowledgement:
45: * This product includes software developed by the University of
46: * California, Berkeley and its contributors.
47: * 4. Neither the name of the University nor the names of its contributors
48: * may be used to endorse or promote products derived from this software
49: * without specific prior written permission.
50: *
51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61: * SUCH DAMAGE.
62: *
63: * @(#)sys_generic.c 8.9 (Berkeley) 2/14/95
64: */
65:
66: #include <sys/param.h>
67: #include <sys/systm.h>
68: #include <sys/filedesc.h>
69: #include <sys/ioctl.h>
70: #include <sys/file.h>
71: #include <sys/proc.h>
72: #include <sys/socketvar.h>
73: #include <sys/uio.h>
74: #include <sys/kernel.h>
75: #include <sys/stat.h>
76: #include <sys/malloc.h>
77: #if KTRACE
78: #include <sys/ktrace.h>
79: #endif
80:
81: #include <sys/mount.h>
82: #include <sys/protosw.h>
83: #include <sys/ev.h>
84: #include <sys/user.h>
85: #include <kern/kdebug.h>
86:
87: /*
88: * Read system call.
89: */
90: struct read_args {
91: int fd;
92: char *cbuf;
93: u_int nbyte;
94: };
95: /* ARGSUSED */
96: read(p, uap, retval)
97: struct proc *p;
98: register struct read_args *uap;
99: register_t *retval;
100: {
101: struct uio auio;
102: struct iovec aiov;
103:
104: aiov.iov_base = (caddr_t)uap->cbuf;
105: aiov.iov_len = uap->nbyte;
106: auio.uio_iov = &aiov;
107: auio.uio_iovcnt = 1;
108: auio.uio_rw = UIO_READ;
109: return (rwuio(p, uap->fd, &auio, UIO_READ, retval));
110: }
111:
112: struct readv_args {
113: int fd;
114: struct iovec *iovp;
115: u_int iovcnt;
116: };
117: readv(p, uap, retval)
118: struct proc *p;
119: register struct readv_args *uap;
120: int *retval;
121: {
122: struct uio auio;
123: register struct iovec *iov;
124: int error;
125: struct iovec aiov[UIO_SMALLIOV];
126:
127: if (uap->iovcnt > UIO_SMALLIOV) {
128: if (uap->iovcnt > UIO_MAXIOV)
129: return (EINVAL);
130: if ((iov = (struct iovec *)
131: kalloc(sizeof(struct iovec) * (uap->iovcnt))) == 0)
132: return (ENOMEM);
133: } else
134: iov = aiov;
135: auio.uio_iov = iov;
136: auio.uio_iovcnt = uap->iovcnt;
137: auio.uio_rw = UIO_READ;
138: error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
139: uap->iovcnt * sizeof (struct iovec));
140: if (!error)
141: error = rwuio(p, uap->fd, &auio, UIO_READ, retval);
142: if (uap->iovcnt > UIO_SMALLIOV)
143: kfree(iov, sizeof(struct iovec)*uap->iovcnt);
144: return (error);
145: }
146:
147: /*
148: * Write system call
149: */
150: struct write_args {
151: int fd;
152: char *cbuf;
153: u_int nbyte;
154: };
155: write(p, uap, retval)
156: struct proc *p;
157: register struct write_args *uap;
158: int *retval;
159: {
160: struct uio auio;
161: struct iovec aiov;
162:
163: aiov.iov_base = uap->cbuf;
164: aiov.iov_len = uap->nbyte;
165: auio.uio_iov = &aiov;
166: auio.uio_iovcnt = 1;
167: auio.uio_rw = UIO_WRITE;
168: return (rwuio(p, uap->fd, &auio, UIO_WRITE, retval));
169: }
170:
171: struct writev_args {
172: int fd;
173: struct iovec *iovp;
174: u_int iovcnt;
175: };
176: writev(p, uap, retval)
177: struct proc *p;
178: register struct writev_args *uap;
179: int *retval;
180: {
181: struct uio auio;
182: register struct iovec *iov;
183: int error;
184: struct iovec aiov[UIO_SMALLIOV];
185:
186: if (uap->iovcnt > UIO_SMALLIOV) {
187: if (uap->iovcnt > UIO_MAXIOV)
188: return (EINVAL);
189: if ((iov = (struct iovec *)
190: kalloc(sizeof(struct iovec) * (uap->iovcnt))) == 0)
191: return (ENOMEM);
192: } else
193: iov = aiov;
194: auio.uio_iov = iov;
195: auio.uio_iovcnt = uap->iovcnt;
196: auio.uio_rw = UIO_WRITE;
197: error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
198: uap->iovcnt * sizeof (struct iovec));
199: if (!error)
200: error = rwuio(p, uap->fd, &auio, UIO_WRITE, retval);
201: if (uap->iovcnt > UIO_SMALLIOV)
202: kfree(iov, sizeof(struct iovec)*uap->iovcnt);
203: return (error);
204: }
205:
206: rwuio(p, fdes, uio, rw, retval)
207: struct proc *p;
208: int fdes;
209: register struct uio *uio;
210: enum uio_rw rw;
211: int *retval;
212: {
213: register struct file *fp;
214: register struct iovec *iov;
215: int i, count, flag, error;
216:
217: if (error = fdgetf(p, fdes, &fp))
218: return (error);
219:
220: if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) {
221: return(EBADF);
222: }
223: uio->uio_resid = 0;
224: uio->uio_segflg = UIO_USERSPACE;
225: uio->uio_procp = p;
226: iov = uio->uio_iov;
227: for (i = 0; i < uio->uio_iovcnt; i++) {
228: if (iov->iov_len < 0) {
229: return(EINVAL);
230: }
231: uio->uio_resid += iov->iov_len;
232: if (uio->uio_resid < 0) {
233: return(EINVAL);
234: }
235: iov++;
236: }
237: count = uio->uio_resid;
238: if (rw == UIO_READ) {
239: if (error = (*fp->f_ops->fo_read)(fp, uio, fp->f_cred))
240: if (uio->uio_resid != count && (error == ERESTART ||
241: error == EINTR || error == EWOULDBLOCK))
242: error = 0;
243: } else {
244: if (error = (*fp->f_ops->fo_write)(fp, uio, fp->f_cred)) {
245: if (uio->uio_resid != count && (error == ERESTART ||
246: error == EINTR || error == EWOULDBLOCK))
247: error = 0;
248: if (error == EPIPE)
249: psignal(p, SIGPIPE);
250: }
251: }
252: *retval = count - uio->uio_resid;
253: return(error);
254: }
255:
256: /*
257: * Ioctl system call
258: */
259: struct ioctl_args {
260: int fd;
261: u_long com;
262: caddr_t data;
263: };
264: /* ARGSUSED */
265: ioctl(p, uap, retval)
266: struct proc *p;
267: register struct ioctl_args *uap;
268: register_t *retval;
269: {
270: register struct file *fp;
271: register u_long com;
272: register int error;
273: register u_int size;
274: caddr_t data, memp;
275: int tmp;
276: #define STK_PARAMS 128
277: char stkbuf[STK_PARAMS];
278:
279: if (error = fdgetf(p, uap->fd, &fp))
280: return (error);
281:
282: if ((fp->f_flag & (FREAD | FWRITE)) == 0)
283: return (EBADF);
284:
285: /*### LD 6/11/97 Hack Alert: this is to get AppleTalk to work
286: * while implementing an ATioctl system call
287: */
288: #if NETAT
289: {
290: extern int appletalk_inited;
291:
292: if (appletalk_inited && ((uap->com & 0x0000FFFF) == 0xff99)) {
293: #ifdef APPLETALK_DEBUG
294: kprintf("ioctl: special AppleTalk \n");
295: #endif
296: error = (*fp->f_ops->fo_ioctl)(fp, uap->com, uap->data, p);
297: return(error);
298: }
299: }
300:
301: #endif /* NETAT */
302:
303:
304: switch (com = uap->com) {
305: case FIONCLEX:
306: *fdflags(p, uap->fd) &= ~UF_EXCLOSE;
307: return (0);
308: case FIOCLEX:
309: *fdflags(p, uap->fd) |= UF_EXCLOSE;
310: return (0);
311: }
312:
313: /*
314: * Interpret high order word to find amount of data to be
315: * copied to/from the user's address space.
316: */
317: size = IOCPARM_LEN(com);
318: if (size > IOCPARM_MAX)
319: return (ENOTTY);
320: memp = NULL;
321: if (size > sizeof (stkbuf)) {
322: if ((memp = (caddr_t)kalloc(size)) == 0)
323: return(ENOMEM);
324: data = memp;
325: } else
326: data = stkbuf;
327: if (com&IOC_IN) {
328: if (size) {
329: error = copyin(uap->data, data, (u_int)size);
330: if (error) {
331: if (memp)
332: kfree(memp, size);
333: return (error);
334: }
335: } else
336: *(caddr_t *)data = uap->data;
337: } else if ((com&IOC_OUT) && size)
338: /*
339: * Zero the buffer so the user always
340: * gets back something deterministic.
341: */
342: bzero(data, size);
343: else if (com&IOC_VOID)
344: *(caddr_t *)data = uap->data;
345:
346: switch (com) {
347:
348: case FIONBIO:
349: if (tmp = *(int *)data)
350: fp->f_flag |= FNONBLOCK;
351: else
352: fp->f_flag &= ~FNONBLOCK;
353: error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
354: break;
355:
356: case FIOASYNC:
357: if (tmp = *(int *)data)
358: fp->f_flag |= FASYNC;
359: else
360: fp->f_flag &= ~FASYNC;
361: error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
362: break;
363:
364: case FIOSETOWN:
365: tmp = *(int *)data;
366: if (fp->f_type == DTYPE_SOCKET) {
367: ((struct socket *)fp->f_data)->so_pgid = tmp;
368: error = 0;
369: break;
370: }
371: if (tmp <= 0) {
372: tmp = -tmp;
373: } else {
374: struct proc *p1 = pfind(tmp);
375: if (p1 == 0) {
376: error = ESRCH;
377: break;
378: }
379: tmp = p1->p_pgrp->pg_id;
380: }
381: error = (*fp->f_ops->fo_ioctl)
382: (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
383: break;
384:
385: case FIOGETOWN:
386: if (fp->f_type == DTYPE_SOCKET) {
387: error = 0;
388: *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
389: break;
390: }
391: error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p);
392: *(int *)data = -*(int *)data;
393: break;
394:
395: default:
396: error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
397: /*
398: * Copy any data to user, size was
399: * already set and checked above.
400: */
401: if (error == 0 && (com&IOC_OUT) && size)
402: error = copyout(data, uap->data, (u_int)size);
403: break;
404: }
405: if (memp)
406: kfree(memp, size);
407: return (error);
408: }
409:
410:
411: int selwait, nselcoll;
412:
413: /*
414: * Select system call.
415: */
416: struct select_args {
417: u_int nd;
418: fd_set *in;
419: fd_set *ou;
420: fd_set *ex;
421: struct timeval *tv;
422: };
423:
424: select(p, uap, retval)
425: register struct proc *p;
426: register struct select_args *uap;
427: register_t *retval;
428: {
429: fd_set ibits[3], obits[3];
430: struct timeval atv;
431: int s, ncoll, error = 0, timo;
432: u_int ni;
433: struct thread *th;
434: struct uthread *uth;
435:
436: th = current_thread();
437: uth = th->_uthread;
438:
439: bzero((caddr_t)ibits, sizeof(ibits));
440: bzero((caddr_t)obits, sizeof(obits));
441:
442: if (uap->nd > FD_SETSIZE)
443: return (EINVAL);
444: if (uap->nd > p->p_fd->fd_nfiles) {
445: /* forgiving; slightly wrong */
446: uap->nd = p->p_fd->fd_nfiles;
447: }
448: ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask);
449:
450: #define getbits(name, x) \
451: if (uap->name && (error = copyin((caddr_t)uap->name, \
452: (caddr_t)&ibits[x], ni))) \
453: goto done;
454: getbits(in, 0);
455: getbits(ou, 1);
456: getbits(ex, 2);
457: #undef getbits
458: if (uap->tv) {
459: error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
460: sizeof (atv));
461: if (error)
462: goto done;
463: if (itimerfix(&atv)) {
464: error = EINVAL;
465: goto done;
466: }
467: s = splhigh();
468: timeradd(&atv, &time, &atv);
469: timo = hzto(&atv);
470: splx(s);
471: } else
472: timo = 0;
473: retry:
474: ncoll = nselcoll;
475: p->p_flag |= P_SELECT;
476: error = selscan(p, ibits, obits, uap->nd, retval);
477: if (error || *retval)
478: goto done;
479: s = splhigh();
480: /* this should be timercmp(&time, &atv, >=) */
481: if (uap->tv && (time.tv_sec > atv.tv_sec ||
482: time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
483: splx(s);
484: goto done;
485: }
486: /*
487: * To effect a poll, the timeout argument should be
488: * non-nil, pointing to a zero-valued timeval structure.
489: */
490: if (uap->tv && (timo == 0)) {
491: splx(s);
492: goto done;
493: }
494: if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
495: splx(s);
496: goto retry;
497: }
498: p->p_flag &= ~P_SELECT;
499: error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
500: splx(s);
501: if (error == 0)
502: goto retry;
503: done:
504: p->p_flag &= ~P_SELECT;
505: /* select is not restarted after signals... */
506: if (error == ERESTART)
507: error = EINTR;
508: if (error == EWOULDBLOCK)
509: error = 0;
510: #define putbits(name, x) \
511: if (uap->name && (error2 = copyout((caddr_t)&obits[x], \
512: (caddr_t)uap->name, ni))) \
513: error = error2;
514: if (error == 0) {
515: int error2;
516:
517: putbits(in, 0);
518: putbits(ou, 1);
519: putbits(ex, 2);
520: #undef putbits
521: }
522: return (error);
523: }
524:
525: selscan(p, ibits, obits, nfd, retval)
526: struct proc *p;
527: fd_set *ibits, *obits;
528: int nfd;
529: register_t *retval;
530: {
531: register struct filedesc *fdp = p->p_fd;
532: register int msk, i, j, fd;
533: register fd_mask bits;
534: struct file *fp;
535: int n = 0;
536: static int flag[3] = { FREAD, FWRITE, 0 };
537:
538: for (msk = 0; msk < 3; msk++) {
539: for (i = 0; i < nfd; i += NFDBITS) {
540: bits = ibits[msk].fds_bits[i/NFDBITS];
541: while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
542: bits &= ~(1 << j);
543: fp = fdp->fd_ofiles[fd];
544: if (fp == NULL || (fdp->fd_ofileflags[fd] &
545: UF_RESERVED))
546: return (EBADF);
547: if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
548: FD_SET(fd, &obits[msk]);
549: n++;
550: }
551: }
552: }
553: }
554: *retval = n;
555: return (0);
556: }
557:
558: /*ARGSUSED*/
559: seltrue(dev, flag, p)
560: dev_t dev;
561: int flag;
562: struct proc *p;
563: {
564:
565: return (1);
566: }
567:
568: /*
569: * Record a select request.
570: */
571: void
572: selrecord(selector, sip)
573: struct proc *selector;
574: struct selinfo *sip;
575: {
576: int oldpri = splhigh();
577: thread_t my_thread = current_thread();
578: thread_t selthread;
579:
580: selthread = sip->si_thread;
581:
582: if (selthread == my_thread) {
583: splx(oldpri);
584: return;
585: }
586:
587: if (selthread && selthread->active &&
588: selthread->wait_event == (caddr_t)&selwait) {
589: sip->si_flags |= SI_COLL;
590: splx(oldpri);
591: }
592: else {
593: sip->si_thread = my_thread;
594: splx(oldpri);
595: thread_deallocate(selthread);
596: thread_reference(sip->si_thread);
597: }
598:
599: return;
600: }
601:
602: void
603: selwakeup(sip)
604: register struct selinfo *sip;
605: {
606: register thread_t the_thread = (thread_t)sip->si_thread;
607: int oldpri;
608:
609: if (the_thread == 0)
610: return;
611:
612: if (sip->si_flags & SI_COLL) {
613: nselcoll++;
614: sip->si_flags &= ~SI_COLL;
615: wakeup((caddr_t)&selwait);
616: }
617:
618: oldpri = splhigh();
619:
620: if (the_thread->active) {
621: /* protect p_flag minimally at splsched() */
622: if (the_thread->wait_event == &selwait)
623: clear_wait(the_thread, THREAD_AWAKENED, TRUE);
624: if (the_thread->task->proc)
625: the_thread->task->proc->p_flag &= ~P_SELECT;
626: }
627:
628: thread_deallocate_interrupt(the_thread);
629:
630: sip->si_thread = 0;
631:
632: splx(oldpri);
633:
634: }
635:
636: void selthreadclear(sip)
637: register struct selinfo *sip;
638: {
639:
640: if (sip->si_thread)
641: thread_deallocate_interrupt(sip->si_thread);
642:
643: }
644:
645:
646: /*
647: * called upon socket close. deque and free all events for
648: * the socket
649: */
650: evsofree(struct socket *sp)
651: {
652: struct eventqelt *eqp, *next;
653:
654: if (sp == NULL) return;
655:
656: for (eqp = sp->so_evlist.tqh_first; eqp != NULL; eqp = next) {
657: next = eqp->ee_slist.tqe_next;
658: evprocdeque(eqp->ee_proc, eqp); // remove from proc q if there
659: TAILQ_REMOVE(&sp->so_evlist, eqp, ee_slist); // remove from socket q
660: FREE(eqp, M_TEMP);
661: }
662: }
663:
664:
665: #define DBG_EVENT 0x10
666:
667: #define DBG_POST 0x10
668: #define DBG_WATCH 0x11
669: #define DBG_WAIT 0x12
670: #define DBG_MOD 0x13
671: #define DBG_EWAKEUP 0x14
672:
673: #define DBG_MISC_POST MISCDBG_CODE(DBG_EVENT,DBG_POST)
674: #define DBG_MISC_WATCH MISCDBG_CODE(DBG_EVENT,DBG_WATCH)
675: #define DBG_MISC_WAIT MISCDBG_CODE(DBG_EVENT,DBG_WAIT)
676: #define DBG_MISC_MOD MISCDBG_CODE(DBG_EVENT,DBG_MOD)
677: #define DBG_MISC_EWAKEUP MISCDBG_CODE(DBG_EVENT,DBG_EWAKEUP)
678:
679:
680:
681: /*
682: * enque this event if it's not already queued. wakeup
683: the proc if we do queue this event to it.
684: */
685: evprocenque(struct eventqelt *eqp)
686: {
687: struct proc *p;
688:
689: assert(eqp);
690: if (eqp->ee_flags & EV_QUEUED) {
691: return;
692: }
693: eqp->ee_flags |= EV_QUEUED;
694: eqp->ee_eventmask = 0; // disarm
695: p = eqp->ee_proc;
696: TAILQ_INSERT_TAIL(&p->p_evlist, eqp, ee_plist);
697: KERNEL_DEBUG(DBG_MISC_EWAKEUP,0,0,0,eqp,0);
698: wakeup(&p->p_evlist);
699: }
700:
701: /*
702: * given either a sockbuf or a socket run down the
703: * event list and queue ready events found
704: */
705: postevent(struct socket *sp, struct sockbuf *sb, int event)
706: {
707: int mask;
708: struct eventqelt *evq;
709:
710: if (sb) sp = sb->sb_so;
711: if (!sp || sp->so_evlist.tqh_first == NULL) return;
712:
713: KERNEL_DEBUG(DBG_MISC_POST|DBG_FUNC_START, 0,0,0,0,0);
714:
715: for (evq = sp->so_evlist.tqh_first;
716: evq != NULL; evq = evq->ee_slist.tqe_next) {
717:
718: mask = 0;
719:
720: /* ready for reading:
721: - byte cnt >= receive low water mark
722: - read-half of conn closed
723: - conn pending for listening sock
724: - socket error pending
725:
726: ready for writing
727: - byte cnt avail >= send low water mark
728: - write half of conn closed
729: - socket error pending
730: - non-blocking conn completed successfully
731:
732: exception pending
733: - out of band data
734: - sock at out of band mark
735:
736: */
737: switch (event & EV_DMASK) {
738:
739: case EV_RWBYTES:
740: case EV_OOB:
741: if (event & EV_OOB) {
742: if ((evq->ee_eventmask & EV_EX)) {
743: if (sp->so_oobmark || ((sp->so_state & SS_RCVATMARK))) {
744: mask |= EV_EX|EV_OOB;
745: }
746: }
747: }
748: if (event & EV_RWBYTES) {
749: if ((evq->ee_eventmask & EV_RE) && soreadable(sp)) {
750: mask |= EV_RE;
751: evq->ee_req.er_rcnt = sp->so_rcv.sb_cc;
752: }
753:
754: if ((evq->ee_eventmask & EV_WR) && sowriteable(sp)) {
755: mask |= EV_WR;
756: evq->ee_req.er_wcnt = sbspace(&sp->so_snd);
757: }
758: }
759: break;
760:
761: case EV_RCONN:
762: if ((evq->ee_eventmask & EV_RE)) {
763: evq->ee_req.er_rcnt = sp->so_qlen + 1; // incl this one
764: mask |= EV_RE|EV_RCONN;
765: }
766: break;
767:
768: case EV_WCONN:
769: if ((evq->ee_eventmask & EV_WR)) {
770: mask |= EV_WR|EV_WCONN;
771: }
772: break;
773:
774: case EV_RCLOSED:
775: if ((evq->ee_eventmask & EV_RE)) {
776: mask |= EV_RE|EV_RCLOSED;
777: break;
778: }
779:
780: case EV_WCLOSED:
781: if ((evq->ee_eventmask & EV_WR)) {
782: mask |= EV_WR|EV_WCLOSED;
783: break;
784: }
785:
786: case EV_FIN:
787: if (evq->ee_eventmask & EV_EX) {
788: mask |= EV_EX|EV_FIN;
789: break;
790: }
791:
792: case EV_RESET:
793: if (evq->ee_eventmask & EV_EX) {
794: mask |= EV_EX|EV_RESET;
795: break;
796: }
797:
798: default:
799: return;
800: } /* switch */
801:
802: if (mask) {
803: evq->ee_req.er_eventbits |= mask;
804: evprocenque(evq);
805: }
806: }
807: KERNEL_DEBUG(DBG_MISC_POST|DBG_FUNC_END, 0,0,0,0,0);
808: }
809:
810: /*
811: * remove and return the first event (eqp=NULL) or a specific
812: * event, or return NULL if no events found
813: */
814: struct eventqelt *
815: evprocdeque(struct proc *p, struct eventqelt *eqp)
816: {
817:
818:
819: if (eqp && ((eqp->ee_flags & EV_QUEUED) == NULL))
820: return(NULL);
821: if (p->p_evlist.tqh_first == NULL)
822: return(NULL);
823: if (eqp == NULL) { // remove first
824: eqp = p->p_evlist.tqh_first;
825: }
826: TAILQ_REMOVE(&p->p_evlist, eqp, ee_plist);
827: eqp->ee_flags &= ~EV_QUEUED;
828: return(eqp);
829: }
830:
831: struct evwatch_args {
832: struct eventreq *u_req;
833: int u_eventmask;
834: };
835:
836:
837: /*
838: * watchevent system call. user passes us an event to watch
839: * for. we malloc an event object, initialize it, and queue
840: * it to the open socket. when the event occurs, postevent()
841: * will enque it back to our proc where we can retrieve it
842: * via waitevent().
843: *
844: * should this prevent duplicate events on same socket?
845: */
846: int
847: watchevent(p, uap, retval)
848: struct proc *p;
849: struct evwatch_args *uap;
850: register_t *retval;
851: {
852: struct eventqelt *eqp = (struct eventqelt *)0;
853: struct eventqelt *np;
854: struct eventreq *erp;
855: struct file *fp;
856: struct socket *sp;
857: int error;
858:
859: // get a qelt and fill with users req
860: MALLOC(eqp, struct eventqelt *, sizeof(struct eventqelt), M_TEMP, M_WAITOK);
861: if (!eqp) panic("can't MALLOC eqp");
862: erp = &eqp->ee_req;
863: // get users request pkt
864: if (error = copyin((caddr_t)uap->u_req, (caddr_t)erp,
865: sizeof(struct eventreq))) {
866: FREE(eqp, M_TEMP);
867: KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
868: return(error);
869: }
870: KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_START, 0,
871: erp->er_handle,uap->u_eventmask,eqp,0);
872: // validate, freeing qelt if errors
873: error = 0;
874: if (erp->er_type != EV_FD) {
875: error = EINVAL;
876: } else if (erp->er_handle < 0) {
877: error = EBADF;
878: } else if (erp->er_handle > p->p_fd->fd_nfiles) {
879: error = EBADF;
880: } else if ((fp = *fdfile(p, erp->er_handle)) == NULL) {
881: error = EBADF;
882: } else if (fp->f_type != DTYPE_SOCKET) {
883: error = EINVAL;
884: }
885: if (error) {
886: FREE(eqp,M_TEMP);
887: KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
888: return(error);
889: }
890:
891: erp->er_rcnt = erp->er_wcnt = erp->er_eventbits = 0;
892: eqp->ee_proc = p;
893: eqp->ee_eventmask = uap->u_eventmask & EV_MASK;
894: eqp->ee_flags = 0;
895:
896: sp = (struct socket *)fp->f_data;
897: assert(sp != NULL);
898:
899: // only allow one watch per file per proc
900: for (np = sp->so_evlist.tqh_first; np != NULL; np = np->ee_slist.tqe_next) {
901: if (np->ee_proc == p) {
902: FREE(eqp,M_TEMP);
903: KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
904: return(EINVAL);
905: }
906: }
907:
908: TAILQ_INSERT_TAIL(&sp->so_evlist, eqp, ee_slist);
909: postevent(sp, 0, EV_RWBYTES); // catch existing events
910: KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
911: return(0);
912: }
913:
914: struct evwait_args {
915: struct eventreq *u_req;
916: struct timeval *tv;
917: };
918:
919: /*
920: * waitevent system call.
921: * grabs the next waiting event for this proc and returns
922: * it. if no events, user can request to sleep with timeout
923: * or poll mode (tv=NULL);
924: */
925: int
926: waitevent(p, uap, retval)
927: struct proc *p;
928: struct evwait_args *uap;
929: register_t *retval;
930: {
931: int error = 0;
932: struct eventqelt *eqp;
933: int timo;
934: struct timeval atv;
935: int s;
936:
937: if (uap->tv) {
938: error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
939: sizeof (atv));
940: if (error)
941: return(error);
942: if (itimerfix(&atv)) {
943: error = EINVAL;
944: return(error);
945: }
946: s = splhigh();
947: timeradd(&atv, &time, &atv);
948: timo = hzto(&atv);
949: splx(s);
950: } else
951: timo = 0;
952:
953: KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_START, 0,0,0,0,0);
954:
955: retry:
956: s = splhigh();
957: if ((eqp = evprocdeque(p,NULL)) != NULL) {
958: splx(s);
959: error = copyout((caddr_t)&eqp->ee_req, (caddr_t)uap->u_req,
960: sizeof(struct eventreq));
961: KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_END, 0,
962: eqp->ee_req.er_handle,eqp->ee_req.er_eventbits,eqp,0);
963: return(error);
964: } else {
965: if (uap->tv && (timo == 0)) {
966: splx(s);
967: *retval = 1; // poll failed
968: return(error);
969: }
970:
971: KERNEL_DEBUG(DBG_MISC_WAIT, 1,0,0,0,0);
972: error = tsleep(&p->p_evlist, PSOCK | PCATCH, "waitevent", timo);
973: KERNEL_DEBUG(DBG_MISC_WAIT, 0,0,2,p->p_evlist.tqh_first,0);
974: splx(s);
975: if (error == 0)
976: goto retry;
977: if (error == ERESTART)
978: error = EINTR;
979: if (error == EWOULDBLOCK) {
980: *retval = 1;
981: error = 0;
982: }
983: }
984: KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_END, 0,0,0,0,0);
985: return(error);
986: }
987:
988: struct modwatch_args {
989: struct eventreq *u_req;
990: int u_eventmask;
991: };
992:
993: /*
994: * modwatch system call. user passes in event to modify.
995: * if we find it we reset the event bits and que/deque event
996: * it needed.
997: */
998: int
999: modwatch(p, uap, retval)
1000: struct proc *p;
1001: struct modwatch_args *uap;
1002: register_t *retval;
1003: {
1004: struct eventreq er;
1005: struct eventreq *erp = &er;
1006: struct eventqelt *evq;
1007: int error;
1008: struct file *fp;
1009: struct socket *sp;
1010: int flag;
1011:
1012:
1013: // get users request pkt
1014: if (error = copyin((caddr_t)uap->u_req, (caddr_t)erp,
1015: sizeof(struct eventreq))) return(error);
1016:
1017: if (erp->er_type != EV_FD) return(EINVAL);
1018: if (erp->er_handle < 0) return(EBADF);
1019: if (erp->er_handle > p->p_fd->fd_nfiles) return(EBADF);
1020: if ((fp = *fdfile(p, erp->er_handle)) == NULL)
1021: return(EBADF);
1022: if (fp->f_type != DTYPE_SOCKET) return(EINVAL); // for now must be sock
1023: sp = (struct socket *)fp->f_data;
1024: assert(sp != NULL);
1025:
1026: // locate event if possible
1027: for (evq = sp->so_evlist.tqh_first;
1028: evq != NULL; evq = evq->ee_slist.tqe_next) {
1029: if (evq->ee_proc == p) break;
1030: }
1031: if (evq == NULL) {
1032: return(EINVAL);
1033: }
1034:
1035:
1036: if (uap->u_eventmask == EV_RM) {
1037: evprocdeque(p, evq);
1038: TAILQ_REMOVE(&sp->so_evlist, evq, ee_slist);
1039: FREE(evq, M_TEMP);
1040: return(0);
1041: }
1042:
1043: switch (uap->u_eventmask & EV_MASK) {
1044:
1045: case 0:
1046: flag = 0;
1047: break;
1048:
1049: case EV_RE:
1050: case EV_WR:
1051: case EV_RE|EV_WR:
1052: flag = EV_RWBYTES;
1053: break;
1054:
1055: case EV_EX:
1056: flag = EV_OOB;
1057: break;
1058:
1059: case EV_EX|EV_RE:
1060: case EV_EX|EV_WR:
1061: case EV_EX|EV_RE|EV_WR:
1062: flag = EV_OOB|EV_RWBYTES;
1063: break;
1064:
1065: default:
1066: return(EINVAL);
1067: }
1068:
1069: evq->ee_eventmask = uap->u_eventmask & EV_MASK;
1070: evprocdeque(p, evq);
1071: evq->ee_req.er_eventbits = 0;
1072: postevent(sp, 0, flag);
1073: return(0);
1074: }
1075:
1076:
1077:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.