source: rtems-libbsd/freebsd/sys/kern/sys_generic.c @ e599318

4.115-freebsd-12freebsd-9.3
Last change on this file since e599318 was e599318, checked in by Sebastian Huber <sebastian.huber@…>, on Oct 9, 2013 at 8:52:54 PM

Update files to match FreeBSD layout

Add compatibility with Newlib header files. Some FreeBSD header files
are mapped by the translation script:

o rtems/bsd/sys/_types.h
o rtems/bsd/sys/errno.h
o rtems/bsd/sys/lock.h
o rtems/bsd/sys/param.h
o rtems/bsd/sys/resource.h
o rtems/bsd/sys/time.h
o rtems/bsd/sys/timespec.h
o rtems/bsd/sys/types.h
o rtems/bsd/sys/unistd.h

It is now possible to include <sys/socket.h> directly for example.

Generate one Makefile which builds everything including tests.

  • Property mode set to 100644
File size: 35.7 KB
Line 
1#include <machine/rtems-bsd-config.h>
2
3/*-
4 * Copyright (c) 1982, 1986, 1989, 1993
5 *      The Regents of the University of California.  All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 *      @(#)sys_generic.c       8.5 (Berkeley) 1/21/94
37 */
38
39#include <sys/cdefs.h>
40__FBSDID("$FreeBSD$");
41
42
43#include <rtems/bsd/local/opt_compat.h>
44#include <rtems/bsd/local/opt_ktrace.h>
45
46#include <rtems/bsd/sys/param.h>
47#include <sys/systm.h>
48#include <sys/sysproto.h>
49#include <sys/filedesc.h>
50#include <sys/filio.h>
51#include <sys/fcntl.h>
52#include <sys/file.h>
53#include <sys/proc.h>
54#include <sys/signalvar.h>
55#include <sys/socketvar.h>
56#include <sys/uio.h>
57#include <sys/kernel.h>
58#include <sys/ktr.h>
59#include <sys/limits.h>
60#include <sys/malloc.h>
61#include <sys/poll.h>
62#include <sys/resourcevar.h>
63#include <sys/selinfo.h>
64#include <sys/sleepqueue.h>
65#include <sys/syscallsubr.h>
66#include <sys/sysctl.h>
67#include <sys/sysent.h>
68#include <sys/vnode.h>
69#include <sys/bio.h>
70#ifndef __rtems__
71#include <sys/buf.h>
72#endif
73#include <sys/condvar.h>
74#ifdef KTRACE
75#include <sys/ktrace.h>
76#endif
77
78#include <security/audit/audit.h>
79
80#ifdef __rtems__
81typedef long fd_mask;
82#include <vm/uma.h>
83#include <sys/mutex.h>
84#include <machine/rtems-bsd-symbols.h>
85#endif /* __rtems__ */
86
87static MALLOC_DEFINE(M_IOCTLOPS, "ioctlops", "ioctl data buffer");
88static MALLOC_DEFINE(M_SELECT, "select", "select() buffer");
89#ifndef __rtems__
90MALLOC_DEFINE(M_IOV, "iov", "large iov's");
91#endif /* __rtems__ */
92
93static int      pollout(struct thread *, struct pollfd *, struct pollfd *,
94                    u_int);
95static int      pollscan(struct thread *, struct pollfd *, u_int);
96static int      pollrescan(struct thread *);
97static int      selscan(struct thread *, fd_mask **, fd_mask **, int);
98static int      selrescan(struct thread *, fd_mask **, fd_mask **);
99static void     selfdalloc(struct thread *, void *);
100static void     selfdfree(struct seltd *, struct selfd *);
101static int      dofileread(struct thread *, int, struct file *, struct uio *,
102                    off_t, int);
103static int      dofilewrite(struct thread *, int, struct file *, struct uio *,
104                    off_t, int);
105static void     doselwakeup(struct selinfo *, int);
106static void     seltdinit(struct thread *);
107static int      seltdwait(struct thread *, int);
108static void     seltdclear(struct thread *);
109
110/*
111 * One seltd per-thread allocated on demand as needed.
112 *
113 *      t - protected by st_mtx
114 *      k - Only accessed by curthread or read-only
115 */
116struct seltd {
117        STAILQ_HEAD(, selfd)    st_selq;        /* (k) List of selfds. */
118        struct selfd            *st_free1;      /* (k) free fd for read set. */
119        struct selfd            *st_free2;      /* (k) free fd for write set. */
120        struct mtx              st_mtx;         /* Protects struct seltd */
121        struct cv               st_wait;        /* (t) Wait channel. */
122        int                     st_flags;       /* (t) SELTD_ flags. */
123};
124
125#define SELTD_PENDING   0x0001                  /* We have pending events. */
126#define SELTD_RESCAN    0x0002                  /* Doing a rescan. */
127
128/*
129 * One selfd allocated per-thread per-file-descriptor.
130 *      f - protected by sf_mtx
131 */
132struct selfd {
133        STAILQ_ENTRY(selfd)     sf_link;        /* (k) fds owned by this td. */
134        TAILQ_ENTRY(selfd)      sf_threads;     /* (f) fds on this selinfo. */
135        struct selinfo          *sf_si;         /* (f) selinfo when linked. */
136        struct mtx              *sf_mtx;        /* Pointer to selinfo mtx. */
137        struct seltd            *sf_td;         /* (k) owning seltd. */
138        void                    *sf_cookie;     /* (k) fd or pollfd. */
139};
140
141static uma_zone_t selfd_zone;
142static struct mtx_pool *mtxpool_select;
143
144#ifndef _SYS_SYSPROTO_H_
145struct read_args {
146        int     fd;
147        void    *buf;
148        size_t  nbyte;
149};
150#endif
151#ifndef __rtems__
152int
153read(td, uap)
154        struct thread *td;
155        struct read_args *uap;
156{
157        struct uio auio;
158        struct iovec aiov;
159        int error;
160
161        if (uap->nbyte > INT_MAX)
162                return (EINVAL);
163        aiov.iov_base = uap->buf;
164        aiov.iov_len = uap->nbyte;
165        auio.uio_iov = &aiov;
166        auio.uio_iovcnt = 1;
167        auio.uio_resid = uap->nbyte;
168        auio.uio_segflg = UIO_USERSPACE;
169        error = kern_readv(td, uap->fd, &auio);
170        return(error);
171}
172
173/*
174 * Positioned read system call
175 */
176#ifndef _SYS_SYSPROTO_H_
177struct pread_args {
178        int     fd;
179        void    *buf;
180        size_t  nbyte;
181        int     pad;
182        off_t   offset;
183};
184#endif
185int
186pread(td, uap)
187        struct thread *td;
188        struct pread_args *uap;
189{
190        struct uio auio;
191        struct iovec aiov;
192        int error;
193
194        if (uap->nbyte > INT_MAX)
195                return (EINVAL);
196        aiov.iov_base = uap->buf;
197        aiov.iov_len = uap->nbyte;
198        auio.uio_iov = &aiov;
199        auio.uio_iovcnt = 1;
200        auio.uio_resid = uap->nbyte;
201        auio.uio_segflg = UIO_USERSPACE;
202        error = kern_preadv(td, uap->fd, &auio, uap->offset);
203        return(error);
204}
205
206int
207freebsd6_pread(td, uap)
208        struct thread *td;
209        struct freebsd6_pread_args *uap;
210{
211        struct pread_args oargs;
212
213        oargs.fd = uap->fd;
214        oargs.buf = uap->buf;
215        oargs.nbyte = uap->nbyte;
216        oargs.offset = uap->offset;
217        return (pread(td, &oargs));
218}
219#endif /* __rtems__ */
220
221/*
222 * Scatter read system call.
223 */
224#ifndef _SYS_SYSPROTO_H_
225struct readv_args {
226        int     fd;
227        struct  iovec *iovp;
228        u_int   iovcnt;
229};
230#endif
231int
232readv(struct thread *td, struct readv_args *uap)
233{
234        struct uio *auio;
235        int error;
236
237        error = copyinuio(uap->iovp, uap->iovcnt, &auio);
238        if (error)
239                return (error);
240        error = kern_readv(td, uap->fd, auio);
241        free(auio, M_IOV);
242        return (error);
243}
244
245int
246kern_readv(struct thread *td, int fd, struct uio *auio)
247{
248        struct file *fp;
249        int error;
250
251        error = fget_read(td, fd, &fp);
252        if (error)
253                return (error);
254        error = dofileread(td, fd, fp, auio, (off_t)-1, 0);
255        fdrop(fp, td);
256        return (error);
257}
258
259/*
260 * Scatter positioned read system call.
261 */
262#ifndef _SYS_SYSPROTO_H_
263struct preadv_args {
264        int     fd;
265        struct  iovec *iovp;
266        u_int   iovcnt;
267        off_t   offset;
268};
269#endif
270int
271preadv(struct thread *td, struct preadv_args *uap)
272{
273        struct uio *auio;
274        int error;
275
276        error = copyinuio(uap->iovp, uap->iovcnt, &auio);
277        if (error)
278                return (error);
279        error = kern_preadv(td, uap->fd, auio, uap->offset);
280        free(auio, M_IOV);
281        return (error);
282}
283
284int
285kern_preadv(td, fd, auio, offset)
286        struct thread *td;
287        int fd;
288        struct uio *auio;
289        off_t offset;
290{
291        struct file *fp;
292        int error;
293
294        error = fget_read(td, fd, &fp);
295        if (error)
296                return (error);
297        if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE))
298                error = ESPIPE;
299#ifndef __rtems__
300        else if (offset < 0 && fp->f_vnode->v_type != VCHR)
301                error = EINVAL;
302#endif /* __rtems__ */
303        else
304                error = dofileread(td, fd, fp, auio, offset, FOF_OFFSET);
305        fdrop(fp, td);
306        return (error);
307}
308
309/*
310 * Common code for readv and preadv that reads data in
311 * from a file using the passed in uio, offset, and flags.
312 */
313static int
314dofileread(td, fd, fp, auio, offset, flags)
315        struct thread *td;
316        int fd;
317        struct file *fp;
318        struct uio *auio;
319        off_t offset;
320        int flags;
321{
322        ssize_t cnt;
323        int error;
324#ifdef KTRACE
325        struct uio *ktruio = NULL;
326#endif
327
328        /* Finish zero length reads right here */
329        if (auio->uio_resid == 0) {
330                td->td_retval[0] = 0;
331                return(0);
332        }
333        auio->uio_rw = UIO_READ;
334        auio->uio_offset = offset;
335        auio->uio_td = td;
336#ifdef KTRACE
337        if (KTRPOINT(td, KTR_GENIO)) 
338                ktruio = cloneuio(auio);
339#endif
340        cnt = auio->uio_resid;
341        if ((error = fo_read(fp, auio, td->td_ucred, flags, td))) {
342                if (auio->uio_resid != cnt && (error == ERESTART ||
343                    error == EINTR || error == EWOULDBLOCK))
344                        error = 0;
345        }
346        cnt -= auio->uio_resid;
347#ifdef KTRACE
348        if (ktruio != NULL) {
349                ktruio->uio_resid = cnt;
350                ktrgenio(fd, UIO_READ, ktruio, error);
351        }
352#endif
353        td->td_retval[0] = cnt;
354        return (error);
355}
356
357#ifndef __rtems__
358#ifndef _SYS_SYSPROTO_H_
359struct write_args {
360        int     fd;
361        const void *buf;
362        size_t  nbyte;
363};
364#endif
365int
366write(td, uap)
367        struct thread *td;
368        struct write_args *uap;
369{
370        struct uio auio;
371        struct iovec aiov;
372        int error;
373
374        if (uap->nbyte > INT_MAX)
375                return (EINVAL);
376        aiov.iov_base = (void *)(uintptr_t)uap->buf;
377        aiov.iov_len = uap->nbyte;
378        auio.uio_iov = &aiov;
379        auio.uio_iovcnt = 1;
380        auio.uio_resid = uap->nbyte;
381        auio.uio_segflg = UIO_USERSPACE;
382        error = kern_writev(td, uap->fd, &auio);
383        return(error);
384}
385
386/*
387 * Positioned write system call.
388 */
389#ifndef _SYS_SYSPROTO_H_
390struct pwrite_args {
391        int     fd;
392        const void *buf;
393        size_t  nbyte;
394        int     pad;
395        off_t   offset;
396};
397#endif
398int
399pwrite(td, uap)
400        struct thread *td;
401        struct pwrite_args *uap;
402{
403        struct uio auio;
404        struct iovec aiov;
405        int error;
406
407        if (uap->nbyte > INT_MAX)
408                return (EINVAL);
409        aiov.iov_base = (void *)(uintptr_t)uap->buf;
410        aiov.iov_len = uap->nbyte;
411        auio.uio_iov = &aiov;
412        auio.uio_iovcnt = 1;
413        auio.uio_resid = uap->nbyte;
414        auio.uio_segflg = UIO_USERSPACE;
415        error = kern_pwritev(td, uap->fd, &auio, uap->offset);
416        return(error);
417}
418
419int
420freebsd6_pwrite(td, uap)
421        struct thread *td;
422        struct freebsd6_pwrite_args *uap;
423{
424        struct pwrite_args oargs;
425
426        oargs.fd = uap->fd;
427        oargs.buf = uap->buf;
428        oargs.nbyte = uap->nbyte;
429        oargs.offset = uap->offset;
430        return (pwrite(td, &oargs));
431}
432
433/*
434 * Gather write system call.
435 */
436#ifndef _SYS_SYSPROTO_H_
437struct writev_args {
438        int     fd;
439        struct  iovec *iovp;
440        u_int   iovcnt;
441};
442#endif
443int
444writev(struct thread *td, struct writev_args *uap)
445{
446        struct uio *auio;
447        int error;
448
449        error = copyinuio(uap->iovp, uap->iovcnt, &auio);
450        if (error)
451                return (error);
452        error = kern_writev(td, uap->fd, auio);
453        free(auio, M_IOV);
454        return (error);
455}
456
457int
458kern_writev(struct thread *td, int fd, struct uio *auio)
459{
460        struct file *fp;
461        int error;
462
463        error = fget_write(td, fd, &fp);
464        if (error)
465                return (error);
466        error = dofilewrite(td, fd, fp, auio, (off_t)-1, 0);
467        fdrop(fp, td);
468        return (error);
469}
470
471/*
472 * Gather positioned write system call.
473 */
474#ifndef _SYS_SYSPROTO_H_
475struct pwritev_args {
476        int     fd;
477        struct  iovec *iovp;
478        u_int   iovcnt;
479        off_t   offset;
480};
481#endif
482int
483pwritev(struct thread *td, struct pwritev_args *uap)
484{
485        struct uio *auio;
486        int error;
487
488        error = copyinuio(uap->iovp, uap->iovcnt, &auio);
489        if (error)
490                return (error);
491        error = kern_pwritev(td, uap->fd, auio, uap->offset);
492        free(auio, M_IOV);
493        return (error);
494}
495
496int
497kern_pwritev(td, fd, auio, offset)
498        struct thread *td;
499        struct uio *auio;
500        int fd;
501        off_t offset;
502{
503        struct file *fp;
504        int error;
505
506        error = fget_write(td, fd, &fp);
507        if (error)
508                return (error);
509        if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE))
510                error = ESPIPE;
511        else if (offset < 0 && fp->f_vnode->v_type != VCHR)
512                error = EINVAL;
513        else
514                error = dofilewrite(td, fd, fp, auio, offset, FOF_OFFSET);
515        fdrop(fp, td);
516        return (error);
517}
518
519/*
520 * Common code for writev and pwritev that writes data to
521 * a file using the passed in uio, offset, and flags.
522 */
523static int
524dofilewrite(td, fd, fp, auio, offset, flags)
525        struct thread *td;
526        int fd;
527        struct file *fp;
528        struct uio *auio;
529        off_t offset;
530        int flags;
531{
532        ssize_t cnt;
533        int error;
534#ifdef KTRACE
535        struct uio *ktruio = NULL;
536#endif
537
538        auio->uio_rw = UIO_WRITE;
539        auio->uio_td = td;
540        auio->uio_offset = offset;
541#ifdef KTRACE
542        if (KTRPOINT(td, KTR_GENIO))
543                ktruio = cloneuio(auio);
544#endif
545        cnt = auio->uio_resid;
546        if (fp->f_type == DTYPE_VNODE)
547                bwillwrite();
548        if ((error = fo_write(fp, auio, td->td_ucred, flags, td))) {
549                if (auio->uio_resid != cnt && (error == ERESTART ||
550                    error == EINTR || error == EWOULDBLOCK))
551                        error = 0;
552                /* Socket layer is responsible for issuing SIGPIPE. */
553                if (fp->f_type != DTYPE_SOCKET && error == EPIPE) {
554                        PROC_LOCK(td->td_proc);
555                        tdksignal(td, SIGPIPE, NULL);
556                        PROC_UNLOCK(td->td_proc);
557                }
558        }
559        cnt -= auio->uio_resid;
560#ifdef KTRACE
561        if (ktruio != NULL) {
562                ktruio->uio_resid = cnt;
563                ktrgenio(fd, UIO_WRITE, ktruio, error);
564        }
565#endif
566        td->td_retval[0] = cnt;
567        return (error);
568}
569
570/*
571 * Truncate a file given a file descriptor.
572 *
573 * Can't use fget_write() here, since must return EINVAL and not EBADF if the
574 * descriptor isn't writable.
575 */
576int
577kern_ftruncate(td, fd, length)
578        struct thread *td;
579        int fd;
580        off_t length;
581{
582        struct file *fp;
583        int error;
584
585        AUDIT_ARG_FD(fd);
586        if (length < 0)
587                return (EINVAL);
588        error = fget(td, fd, &fp);
589        if (error)
590                return (error);
591        AUDIT_ARG_FILE(td->td_proc, fp);
592        if (!(fp->f_flag & FWRITE)) {
593                fdrop(fp, td);
594                return (EINVAL);
595        }
596        error = fo_truncate(fp, length, td->td_ucred, td);
597        fdrop(fp, td);
598        return (error);
599}
600
601#ifndef _SYS_SYSPROTO_H_
602struct ftruncate_args {
603        int     fd;
604        int     pad;
605        off_t   length;
606};
607#endif
608int
609ftruncate(td, uap)
610        struct thread *td;
611        struct ftruncate_args *uap;
612{
613
614        return (kern_ftruncate(td, uap->fd, uap->length));
615}
616
617#if defined(COMPAT_43)
618#ifndef _SYS_SYSPROTO_H_
619struct oftruncate_args {
620        int     fd;
621        long    length;
622};
623#endif
624int
625oftruncate(td, uap)
626        struct thread *td;
627        struct oftruncate_args *uap;
628{
629
630        return (kern_ftruncate(td, uap->fd, uap->length));
631}
632#endif /* COMPAT_43 */
633
634#ifndef _SYS_SYSPROTO_H_
635struct ioctl_args {
636        int     fd;
637        u_long  com;
638        caddr_t data;
639};
640#endif
641/* ARGSUSED */
642int
643ioctl(struct thread *td, struct ioctl_args *uap)
644{
645        u_long com;
646        int arg, error;
647        u_int size;
648        caddr_t data;
649
650        if (uap->com > 0xffffffff) {
651                printf(
652                    "WARNING pid %d (%s): ioctl sign-extension ioctl %lx\n",
653                    td->td_proc->p_pid, td->td_name, uap->com);
654                uap->com &= 0xffffffff;
655        }
656        com = uap->com;
657
658        /*
659         * Interpret high order word to find amount of data to be
660         * copied to/from the user's address space.
661         */
662        size = IOCPARM_LEN(com);
663        if ((size > IOCPARM_MAX) ||
664            ((com & (IOC_VOID  | IOC_IN | IOC_OUT)) == 0) ||
665#if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
666            ((com & IOC_OUT) && size == 0) ||
667#else
668            ((com & (IOC_IN | IOC_OUT)) && size == 0) ||
669#endif
670            ((com & IOC_VOID) && size > 0 && size != sizeof(int)))
671                return (ENOTTY);
672
673        if (size > 0) {
674                if (com & IOC_VOID) {
675                        /* Integer argument. */
676                        arg = (intptr_t)uap->data;
677                        data = (void *)&arg;
678                        size = 0;
679                } else
680                        data = malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
681        } else
682                data = (void *)&uap->data;
683        if (com & IOC_IN) {
684                error = copyin(uap->data, data, (u_int)size);
685                if (error) {
686                        if (size > 0)
687                                free(data, M_IOCTLOPS);
688                        return (error);
689                }
690        } else if (com & IOC_OUT) {
691                /*
692                 * Zero the buffer so the user always
693                 * gets back something deterministic.
694                 */
695                bzero(data, size);
696        }
697
698        error = kern_ioctl(td, uap->fd, com, data);
699
700        if (error == 0 && (com & IOC_OUT))
701                error = copyout(data, uap->data, (u_int)size);
702
703        if (size > 0)
704                free(data, M_IOCTLOPS);
705        return (error);
706}
707
708int
709kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data)
710{
711        struct file *fp;
712        struct filedesc *fdp;
713        int error;
714        int tmp;
715
716        AUDIT_ARG_FD(fd);
717        AUDIT_ARG_CMD(com);
718        if ((error = fget(td, fd, &fp)) != 0)
719                return (error);
720        if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
721                fdrop(fp, td);
722                return (EBADF);
723        }
724        fdp = td->td_proc->p_fd;
725        switch (com) {
726        case FIONCLEX:
727                FILEDESC_XLOCK(fdp);
728                fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
729                FILEDESC_XUNLOCK(fdp);
730                goto out;
731        case FIOCLEX:
732                FILEDESC_XLOCK(fdp);
733                fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
734                FILEDESC_XUNLOCK(fdp);
735                goto out;
736        case FIONBIO:
737                if ((tmp = *(int *)data))
738                        atomic_set_int(&fp->f_flag, FNONBLOCK);
739                else
740                        atomic_clear_int(&fp->f_flag, FNONBLOCK);
741                data = (void *)&tmp;
742                break;
743        case FIOASYNC:
744                if ((tmp = *(int *)data))
745                        atomic_set_int(&fp->f_flag, FASYNC);
746                else
747                        atomic_clear_int(&fp->f_flag, FASYNC);
748                data = (void *)&tmp;
749                break;
750        }
751
752        error = fo_ioctl(fp, com, data, td->td_ucred, td);
753out:
754        fdrop(fp, td);
755        return (error);
756}
757
758int
759poll_no_poll(int events)
760{
761        /*
762         * Return true for read/write.  If the user asked for something
763         * special, return POLLNVAL, so that clients have a way of
764         * determining reliably whether or not the extended
765         * functionality is present without hard-coding knowledge
766         * of specific filesystem implementations.
767         */
768        if (events & ~POLLSTANDARD)
769                return (POLLNVAL);
770
771        return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
772}
773
774int
775pselect(struct thread *td, struct pselect_args *uap)
776{
777        struct timespec ts;
778        struct timeval tv, *tvp;
779        sigset_t set, *uset;
780        int error;
781
782        if (uap->ts != NULL) {
783                error = copyin(uap->ts, &ts, sizeof(ts));
784                if (error != 0)
785                    return (error);
786                TIMESPEC_TO_TIMEVAL(&tv, &ts);
787                tvp = &tv;
788        } else
789                tvp = NULL;
790        if (uap->sm != NULL) {
791                error = copyin(uap->sm, &set, sizeof(set));
792                if (error != 0)
793                        return (error);
794                uset = &set;
795        } else
796                uset = NULL;
797        return (kern_pselect(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
798            uset, NFDBITS));
799}
800
801int
802kern_pselect(struct thread *td, int nd, fd_set *in, fd_set *ou, fd_set *ex,
803    struct timeval *tvp, sigset_t *uset, int abi_nfdbits)
804{
805        int error;
806
807        if (uset != NULL) {
808                error = kern_sigprocmask(td, SIG_SETMASK, uset,
809                    &td->td_oldsigmask, 0);
810                if (error != 0)
811                        return (error);
812                td->td_pflags |= TDP_OLDMASK;
813                /*
814                 * Make sure that ast() is called on return to
815                 * usermode and TDP_OLDMASK is cleared, restoring old
816                 * sigmask.
817                 */
818                thread_lock(td);
819                td->td_flags |= TDF_ASTPENDING;
820                thread_unlock(td);
821        }
822        error = kern_select(td, nd, in, ou, ex, tvp, abi_nfdbits);
823        return (error);
824}
825#endif /* __rtems__ */
826
827#ifndef _SYS_SYSPROTO_H_
828struct select_args {
829        int     nd;
830        fd_set  *in, *ou, *ex;
831        struct  timeval *tv;
832};
833#endif
834int
835select(struct thread *td, struct select_args *uap)
836{
837        struct timeval tv, *tvp;
838        int error;
839
840        if (uap->tv != NULL) {
841                error = copyin(uap->tv, &tv, sizeof(tv));
842                if (error)
843                        return (error);
844                tvp = &tv;
845        } else
846                tvp = NULL;
847
848        return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
849            NFDBITS));
850}
851
852int
853kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
854    fd_set *fd_ex, struct timeval *tvp, int abi_nfdbits)
855{
856        struct filedesc *fdp;
857        /*
858         * The magic 2048 here is chosen to be just enough for FD_SETSIZE
859         * infds with the new FD_SETSIZE of 1024, and more than enough for
860         * FD_SETSIZE infds, outfds and exceptfds with the old FD_SETSIZE
861         * of 256.
862         */
863        fd_mask s_selbits[howmany(2048, NFDBITS)];
864        fd_mask *ibits[3], *obits[3], *selbits, *sbp;
865        struct timeval atv, rtv, ttv;
866        int error, timo;
867        u_int nbufbytes, ncpbytes, ncpubytes, nfdbits;
868
869        if (nd < 0)
870                return (EINVAL);
871        fdp = td->td_proc->p_fd;
872        if (nd > fdp->fd_lastfile + 1)
873                nd = fdp->fd_lastfile + 1;
874
875        /*
876         * Allocate just enough bits for the non-null fd_sets.  Use the
877         * preallocated auto buffer if possible.
878         */
879        nfdbits = roundup(nd, NFDBITS);
880        ncpbytes = nfdbits / NBBY;
881        ncpubytes = roundup(nd, abi_nfdbits) / NBBY;
882        nbufbytes = 0;
883        if (fd_in != NULL)
884                nbufbytes += 2 * ncpbytes;
885        if (fd_ou != NULL)
886                nbufbytes += 2 * ncpbytes;
887        if (fd_ex != NULL)
888                nbufbytes += 2 * ncpbytes;
889        if (nbufbytes <= sizeof s_selbits)
890                selbits = &s_selbits[0];
891        else
892                selbits = malloc(nbufbytes, M_SELECT, M_WAITOK);
893
894        /*
895         * Assign pointers into the bit buffers and fetch the input bits.
896         * Put the output buffers together so that they can be bzeroed
897         * together.
898         */
899        sbp = selbits;
900#define getbits(name, x) \
901        do {                                                            \
902                if (name == NULL) {                                     \
903                        ibits[x] = NULL;                                \
904                        obits[x] = NULL;                                \
905                } else {                                                \
906                        ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp;   \
907                        obits[x] = sbp;                                 \
908                        sbp += ncpbytes / sizeof *sbp;                  \
909                        error = copyin(name, ibits[x], ncpubytes);      \
910                        if (error != 0)                                 \
911                                goto done;                              \
912                        bzero((char *)ibits[x] + ncpubytes,             \
913                            ncpbytes - ncpubytes);                      \
914                }                                                       \
915        } while (0)
916        getbits(fd_in, 0);
917        getbits(fd_ou, 1);
918        getbits(fd_ex, 2);
919#undef  getbits
920
921#if BYTE_ORDER == BIG_ENDIAN && defined(__LP64__)
922        /*
923         * XXX: swizzle_fdset assumes that if abi_nfdbits != NFDBITS,
924         * we are running under 32-bit emulation. This should be more
925         * generic.
926         */
927#define swizzle_fdset(bits)                                             \
928        if (abi_nfdbits != NFDBITS && bits != NULL) {                   \
929                int i;                                                  \
930                for (i = 0; i < ncpbytes / sizeof *sbp; i++)            \
931                        bits[i] = (bits[i] >> 32) | (bits[i] << 32);    \
932        }
933#else
934#define swizzle_fdset(bits)
935#endif
936
937        /* Make sure the bit order makes it through an ABI transition */
938        swizzle_fdset(ibits[0]);
939        swizzle_fdset(ibits[1]);
940        swizzle_fdset(ibits[2]);
941       
942        if (nbufbytes != 0)
943                bzero(selbits, nbufbytes / 2);
944
945        if (tvp != NULL) {
946                atv = *tvp;
947                if (itimerfix(&atv)) {
948                        error = EINVAL;
949                        goto done;
950                }
951                getmicrouptime(&rtv);
952                timevaladd(&atv, &rtv);
953        } else {
954                atv.tv_sec = 0;
955                atv.tv_usec = 0;
956        }
957        timo = 0;
958        seltdinit(td);
959        /* Iterate until the timeout expires or descriptors become ready. */
960        for (;;) {
961                error = selscan(td, ibits, obits, nd);
962                if (error || td->td_retval[0] != 0)
963                        break;
964                if (atv.tv_sec || atv.tv_usec) {
965                        getmicrouptime(&rtv);
966                        if (timevalcmp(&rtv, &atv, >=))
967                                break;
968                        ttv = atv;
969                        timevalsub(&ttv, &rtv);
970                        timo = ttv.tv_sec > 24 * 60 * 60 ?
971                            24 * 60 * 60 * hz : tvtohz(&ttv);
972                }
973                error = seltdwait(td, timo);
974                if (error)
975                        break;
976                error = selrescan(td, ibits, obits);
977                if (error || td->td_retval[0] != 0)
978                        break;
979        }
980        seltdclear(td);
981
982done:
983        /* select is not restarted after signals... */
984        if (error == ERESTART)
985                error = EINTR;
986        if (error == EWOULDBLOCK)
987                error = 0;
988
989        /* swizzle bit order back, if necessary */
990        swizzle_fdset(obits[0]);
991        swizzle_fdset(obits[1]);
992        swizzle_fdset(obits[2]);
993#undef swizzle_fdset
994
995#define putbits(name, x) \
996        if (name && (error2 = copyout(obits[x], name, ncpubytes))) \
997                error = error2;
998        if (error == 0) {
999                int error2;
1000
1001                putbits(fd_in, 0);
1002                putbits(fd_ou, 1);
1003                putbits(fd_ex, 2);
1004#undef putbits
1005        }
1006        if (selbits != &s_selbits[0])
1007                free(selbits, M_SELECT);
1008
1009        return (error);
1010}
1011#ifndef __rtems__
1012/*
1013 * Convert a select bit set to poll flags.
1014 *
1015 * The backend always returns POLLHUP/POLLERR if appropriate and we
1016 * return this as a set bit in any set.
1017 */
1018static int select_flags[3] = {
1019    POLLRDNORM | POLLHUP | POLLERR,
1020    POLLWRNORM | POLLHUP | POLLERR,
1021    POLLRDBAND | POLLERR
1022};
1023
1024/*
1025 * Compute the fo_poll flags required for a fd given by the index and
1026 * bit position in the fd_mask array.
1027 */
1028static __inline int
1029selflags(fd_mask **ibits, int idx, fd_mask bit)
1030{
1031        int flags;
1032        int msk;
1033
1034        flags = 0;
1035        for (msk = 0; msk < 3; msk++) {
1036                if (ibits[msk] == NULL)
1037                        continue;
1038                if ((ibits[msk][idx] & bit) == 0)
1039                        continue;
1040                flags |= select_flags[msk];
1041        }
1042        return (flags);
1043}
1044
1045/*
1046 * Set the appropriate output bits given a mask of fired events and the
1047 * input bits originally requested.
1048 */
1049static __inline int
1050selsetbits(fd_mask **ibits, fd_mask **obits, int idx, fd_mask bit, int events)
1051{
1052        int msk;
1053        int n;
1054
1055        n = 0;
1056        for (msk = 0; msk < 3; msk++) {
1057                if ((events & select_flags[msk]) == 0)
1058                        continue;
1059                if (ibits[msk] == NULL)
1060                        continue;
1061                if ((ibits[msk][idx] & bit) == 0)
1062                        continue;
1063                /*
1064                 * XXX Check for a duplicate set.  This can occur because a
1065                 * socket calls selrecord() twice for each poll() call
1066                 * resulting in two selfds per real fd.  selrescan() will
1067                 * call selsetbits twice as a result.
1068                 */
1069                if ((obits[msk][idx] & bit) != 0)
1070                        continue;
1071                obits[msk][idx] |= bit;
1072                n++;
1073        }
1074
1075        return (n);
1076}
1077#endif /* __rtems__ */
1078
1079/*
1080 * Traverse the list of fds attached to this thread's seltd and check for
1081 * completion.
1082 */
1083static int
1084selrescan(struct thread *td, fd_mask **ibits, fd_mask **obits)
1085{
1086#ifndef __rtems__
1087        struct filedesc *fdp;
1088        struct selinfo *si;
1089        struct seltd *stp;
1090        struct selfd *sfp;
1091        struct selfd *sfn;
1092        struct file *fp;
1093        fd_mask bit;
1094        int fd, ev, n, idx;
1095
1096        fdp = td->td_proc->p_fd;
1097        stp = td->td_sel;
1098        n = 0;
1099        STAILQ_FOREACH_SAFE(sfp, &stp->st_selq, sf_link, sfn) {
1100                fd = (int)(uintptr_t)sfp->sf_cookie;
1101                si = sfp->sf_si;
1102                selfdfree(stp, sfp);
1103                /* If the selinfo wasn't cleared the event didn't fire. */
1104                if (si != NULL)
1105                        continue;
1106                if ((fp = fget_unlocked(fdp, fd)) == NULL)
1107                        return (EBADF);
1108                idx = fd / NFDBITS;
1109                bit = (fd_mask)1 << (fd % NFDBITS);
1110                ev = fo_poll(fp, selflags(ibits, idx, bit), td->td_ucred, td);
1111                fdrop(fp, td);
1112                if (ev != 0)
1113                        n += selsetbits(ibits, obits, idx, bit, ev);
1114        }
1115        stp->st_flags = 0;
1116        td->td_retval[0] = n;
1117        return (0);
1118#else /* __rtems__ */
1119        return (ENOMEM);
1120#endif /* __rtems__ */
1121}
1122
1123/*
1124 * Perform the initial filedescriptor scan and register ourselves with
1125 * each selinfo.
1126 */
1127static int
1128selscan(td, ibits, obits, nfd)
1129        struct thread *td;
1130        fd_mask **ibits, **obits;
1131        int nfd;
1132{
1133#ifndef __rtems__
1134        struct filedesc *fdp;
1135        struct file *fp;
1136        fd_mask bit;
1137        int ev, flags, end, fd;
1138        int n, idx;
1139
1140        fdp = td->td_proc->p_fd;
1141        n = 0;
1142        for (idx = 0, fd = 0; fd < nfd; idx++) {
1143                end = imin(fd + NFDBITS, nfd);
1144                for (bit = 1; fd < end; bit <<= 1, fd++) {
1145                        /* Compute the list of events we're interested in. */
1146                        flags = selflags(ibits, idx, bit);
1147                        if (flags == 0)
1148                                continue;
1149                        if ((fp = fget_unlocked(fdp, fd)) == NULL)
1150                                return (EBADF);
1151                        selfdalloc(td, (void *)(uintptr_t)fd);
1152                        ev = fo_poll(fp, flags, td->td_ucred, td);
1153                        fdrop(fp, td);
1154                        if (ev != 0)
1155                                n += selsetbits(ibits, obits, idx, bit, ev);
1156                }
1157        }
1158
1159        td->td_retval[0] = n;
1160        return (0);
1161#else /* __rtems__ */
1162        return (ENOMEM);
1163#endif /* __rtems__ */
1164}
1165
1166#ifndef _SYS_SYSPROTO_H_
1167struct poll_args {
1168        struct pollfd *fds;
1169        u_int   nfds;
1170        int     timeout;
1171};
1172#endif
1173int
1174#ifdef __rtems__
1175kern_poll(td, uap)
1176#else
1177poll(td, uap)
1178#endif /* __rtems__ */
1179        struct thread *td;
1180        struct poll_args *uap;
1181{
1182        struct pollfd *bits;
1183        struct pollfd smallbits[32];
1184        struct timeval atv, rtv, ttv;
1185        int error = 0, timo;
1186        u_int nfds;
1187        size_t ni;
1188
1189        nfds = uap->nfds;
1190        if (nfds > maxfilesperproc && nfds > FD_SETSIZE) 
1191                return (EINVAL);
1192        ni = nfds * sizeof(struct pollfd);
1193        if (ni > sizeof(smallbits))
1194                bits = malloc(ni, M_TEMP, M_WAITOK);
1195        else
1196                bits = smallbits;
1197        error = copyin(uap->fds, bits, ni);
1198        if (error)
1199                goto done;
1200        if (uap->timeout != INFTIM) {
1201                atv.tv_sec = uap->timeout / 1000;
1202                atv.tv_usec = (uap->timeout % 1000) * 1000;
1203                if (itimerfix(&atv)) {
1204                        error = EINVAL;
1205                        goto done;
1206                }
1207                getmicrouptime(&rtv);
1208                timevaladd(&atv, &rtv);
1209        } else {
1210                atv.tv_sec = 0;
1211                atv.tv_usec = 0;
1212        }
1213        timo = 0;
1214        seltdinit(td);
1215        /* Iterate until the timeout expires or descriptors become ready. */
1216        for (;;) {
1217                error = pollscan(td, bits, nfds);
1218                if (error || td->td_retval[0] != 0)
1219                        break;
1220                if (atv.tv_sec || atv.tv_usec) {
1221                        getmicrouptime(&rtv);
1222                        if (timevalcmp(&rtv, &atv, >=))
1223                                break;
1224                        ttv = atv;
1225                        timevalsub(&ttv, &rtv);
1226                        timo = ttv.tv_sec > 24 * 60 * 60 ?
1227                            24 * 60 * 60 * hz : tvtohz(&ttv);
1228                }
1229                error = seltdwait(td, timo);
1230                if (error)
1231                        break;
1232                error = pollrescan(td);
1233                if (error || td->td_retval[0] != 0)
1234                        break;
1235        }
1236        seltdclear(td);
1237
1238done:
1239        /* poll is not restarted after signals... */
1240        if (error == ERESTART)
1241                error = EINTR;
1242        if (error == EWOULDBLOCK)
1243                error = 0;
1244        if (error == 0) {
1245                error = pollout(td, bits, uap->fds, nfds);
1246                if (error)
1247                        goto out;
1248        }
1249out:
1250        if (ni > sizeof(smallbits))
1251                free(bits, M_TEMP);
1252        return (error);
1253}
1254
1255static int
1256pollrescan(struct thread *td)
1257{
1258        struct seltd *stp;
1259        struct selfd *sfp;
1260        struct selfd *sfn;
1261        struct selinfo *si;
1262        struct filedesc *fdp;
1263        struct file *fp;
1264        struct pollfd *fd;
1265        int n;
1266
1267        n = 0;
1268        fdp = td->td_proc->p_fd;
1269        stp = td->td_sel;
1270        FILEDESC_SLOCK(fdp);
1271        STAILQ_FOREACH_SAFE(sfp, &stp->st_selq, sf_link, sfn) {
1272                fd = (struct pollfd *)sfp->sf_cookie;
1273                si = sfp->sf_si;
1274                selfdfree(stp, sfp);
1275                /* If the selinfo wasn't cleared the event didn't fire. */
1276                if (si != NULL)
1277                        continue;
1278                fp = fdp->fd_ofiles[fd->fd];
1279                if (fp == NULL) {
1280                        fd->revents = POLLNVAL;
1281                        n++;
1282                        continue;
1283                }
1284                /*
1285                 * Note: backend also returns POLLHUP and
1286                 * POLLERR if appropriate.
1287                 */
1288                fd->revents = fo_poll(fp, fd->events, td->td_ucred, td);
1289                if (fd->revents != 0)
1290                        n++;
1291        }
1292        FILEDESC_SUNLOCK(fdp);
1293        stp->st_flags = 0;
1294        td->td_retval[0] = n;
1295        return (0);
1296}
1297
1298
1299static int
1300pollout(td, fds, ufds, nfd)
1301        struct thread *td;
1302        struct pollfd *fds;
1303        struct pollfd *ufds;
1304        u_int nfd;
1305{
1306        int error = 0;
1307        u_int i = 0;
1308        u_int n = 0;
1309
1310        for (i = 0; i < nfd; i++) {
1311                error = copyout(&fds->revents, &ufds->revents,
1312                    sizeof(ufds->revents));
1313                if (error)
1314                        return (error);
1315                if (fds->revents != 0)
1316                        n++;
1317                fds++;
1318                ufds++;
1319        }
1320        td->td_retval[0] = n;
1321        return (0);
1322}
1323
1324static int
1325pollscan(td, fds, nfd)
1326        struct thread *td;
1327        struct pollfd *fds;
1328        u_int nfd;
1329{
1330        struct filedesc *fdp = td->td_proc->p_fd;
1331        int i;
1332        struct file *fp;
1333        int n = 0;
1334
1335        FILEDESC_SLOCK(fdp);
1336        for (i = 0; i < nfd; i++, fds++) {
1337                if (fds->fd >= fdp->fd_nfiles) {
1338                        fds->revents = POLLNVAL;
1339                        n++;
1340                } else if (fds->fd < 0) {
1341                        fds->revents = 0;
1342                } else {
1343                        fp = fdp->fd_ofiles[fds->fd];
1344                        if (fp == NULL) {
1345                                fds->revents = POLLNVAL;
1346                                n++;
1347                        } else {
1348                                /*
1349                                 * Note: backend also returns POLLHUP and
1350                                 * POLLERR if appropriate.
1351                                 */
1352                                selfdalloc(td, fds);
1353                                fds->revents = fo_poll(fp, fds->events,
1354                                    td->td_ucred, td);
1355                                /*
1356                                 * POSIX requires POLLOUT to be never
1357                                 * set simultaneously with POLLHUP.
1358                                 */
1359                                if ((fds->revents & POLLHUP) != 0)
1360                                        fds->revents &= ~POLLOUT;
1361
1362                                if (fds->revents != 0)
1363                                        n++;
1364                        }
1365                }
1366        }
1367        FILEDESC_SUNLOCK(fdp);
1368        td->td_retval[0] = n;
1369        return (0);
1370}
1371
1372/*
1373 * OpenBSD poll system call.
1374 *
1375 * XXX this isn't quite a true representation..  OpenBSD uses select ops.
1376 */
1377#ifndef _SYS_SYSPROTO_H_
1378struct openbsd_poll_args {
1379        struct pollfd *fds;
1380        u_int   nfds;
1381        int     timeout;
1382};
1383#endif
1384int
1385openbsd_poll(td, uap)
1386        register struct thread *td;
1387        register struct openbsd_poll_args *uap;
1388{
1389#ifdef __rtems__
1390        return (kern_poll(td, (struct poll_args *)uap));
1391#else
1392        return (poll(td, (struct poll_args *)uap));
1393#endif
1394}
1395
1396/*
1397 * XXX This was created specifically to support netncp and netsmb.  This
1398 * allows the caller to specify a socket to wait for events on.  It returns
1399 * 0 if any events matched and an error otherwise.  There is no way to
1400 * determine which events fired.
1401 */
1402int
1403selsocket(struct socket *so, int events, struct timeval *tvp, struct thread *td)
1404{
1405        struct timeval atv, rtv, ttv;
1406        int error, timo;
1407
1408        if (tvp != NULL) {
1409                atv = *tvp;
1410                if (itimerfix(&atv))
1411                        return (EINVAL);
1412                getmicrouptime(&rtv);
1413                timevaladd(&atv, &rtv);
1414        } else {
1415                atv.tv_sec = 0;
1416                atv.tv_usec = 0;
1417        }
1418
1419        timo = 0;
1420        seltdinit(td);
1421        /*
1422         * Iterate until the timeout expires or the socket becomes ready.
1423         */
1424        for (;;) {
1425                selfdalloc(td, NULL);
1426                error = sopoll(so, events, NULL, td);
1427                /* error here is actually the ready events. */
1428                if (error)
1429                        return (0);
1430                if (atv.tv_sec || atv.tv_usec) {
1431                        getmicrouptime(&rtv);
1432                        if (timevalcmp(&rtv, &atv, >=)) {
1433                                seltdclear(td);
1434                                return (EWOULDBLOCK);
1435                        }
1436                        ttv = atv;
1437                        timevalsub(&ttv, &rtv);
1438                        timo = ttv.tv_sec > 24 * 60 * 60 ?
1439                            24 * 60 * 60 * hz : tvtohz(&ttv);
1440                }
1441                error = seltdwait(td, timo);
1442                seltdclear(td);
1443                if (error)
1444                        break;
1445        }
1446        /* XXX Duplicates ncp/smb behavior. */
1447        if (error == ERESTART)
1448                error = 0;
1449        return (error);
1450}
1451
1452/*
1453 * Preallocate two selfds associated with 'cookie'.  Some fo_poll routines
1454 * have two select sets, one for read and another for write.
1455 */
1456static void
1457selfdalloc(struct thread *td, void *cookie)
1458{
1459        struct seltd *stp;
1460
1461        stp = td->td_sel;
1462        if (stp->st_free1 == NULL)
1463                stp->st_free1 = uma_zalloc(selfd_zone, M_WAITOK|M_ZERO);
1464        stp->st_free1->sf_td = stp;
1465        stp->st_free1->sf_cookie = cookie;
1466        if (stp->st_free2 == NULL)
1467                stp->st_free2 = uma_zalloc(selfd_zone, M_WAITOK|M_ZERO);
1468        stp->st_free2->sf_td = stp;
1469        stp->st_free2->sf_cookie = cookie;
1470}
1471
1472static void
1473selfdfree(struct seltd *stp, struct selfd *sfp)
1474{
1475        STAILQ_REMOVE(&stp->st_selq, sfp, selfd, sf_link);
1476        mtx_lock(sfp->sf_mtx);
1477        if (sfp->sf_si)
1478                TAILQ_REMOVE(&sfp->sf_si->si_tdlist, sfp, sf_threads);
1479        mtx_unlock(sfp->sf_mtx);
1480        uma_zfree(selfd_zone, sfp);
1481}
1482
1483/*
1484 * Record a select request.
1485 */
1486void
1487selrecord(selector, sip)
1488        struct thread *selector;
1489        struct selinfo *sip;
1490{
1491        struct selfd *sfp;
1492        struct seltd *stp;
1493        struct mtx *mtxp;
1494
1495        stp = selector->td_sel;
1496        /*
1497         * Don't record when doing a rescan.
1498         */
1499        if (stp->st_flags & SELTD_RESCAN)
1500                return;
1501        /*
1502         * Grab one of the preallocated descriptors.
1503         */
1504        sfp = NULL;
1505        if ((sfp = stp->st_free1) != NULL)
1506                stp->st_free1 = NULL;
1507        else if ((sfp = stp->st_free2) != NULL)
1508                stp->st_free2 = NULL;
1509        else
1510                panic("selrecord: No free selfd on selq");
1511        mtxp = sip->si_mtx;
1512        if (mtxp == NULL)
1513                mtxp = mtx_pool_find(mtxpool_select, sip);
1514        /*
1515         * Initialize the sfp and queue it in the thread.
1516         */
1517        sfp->sf_si = sip;
1518        sfp->sf_mtx = mtxp;
1519        STAILQ_INSERT_TAIL(&stp->st_selq, sfp, sf_link);
1520        /*
1521         * Now that we've locked the sip, check for initialization.
1522         */
1523        mtx_lock(mtxp);
1524        if (sip->si_mtx == NULL) {
1525                sip->si_mtx = mtxp;
1526                TAILQ_INIT(&sip->si_tdlist);
1527        }
1528        /*
1529         * Add this thread to the list of selfds listening on this selinfo.
1530         */
1531        TAILQ_INSERT_TAIL(&sip->si_tdlist, sfp, sf_threads);
1532        mtx_unlock(sip->si_mtx);
1533}
1534
1535/* Wake up a selecting thread. */
1536void
1537selwakeup(sip)
1538        struct selinfo *sip;
1539{
1540        doselwakeup(sip, -1);
1541}
1542
1543/* Wake up a selecting thread, and set its priority. */
1544void
1545selwakeuppri(sip, pri)
1546        struct selinfo *sip;
1547        int pri;
1548{
1549        doselwakeup(sip, pri);
1550}
1551
1552/*
1553 * Do a wakeup when a selectable event occurs.
1554 */
1555static void
1556doselwakeup(sip, pri)
1557        struct selinfo *sip;
1558        int pri;
1559{
1560        struct selfd *sfp;
1561        struct selfd *sfn;
1562        struct seltd *stp;
1563
1564        /* If it's not initialized there can't be any waiters. */
1565        if (sip->si_mtx == NULL)
1566                return;
1567        /*
1568         * Locking the selinfo locks all selfds associated with it.
1569         */
1570        mtx_lock(sip->si_mtx);
1571        TAILQ_FOREACH_SAFE(sfp, &sip->si_tdlist, sf_threads, sfn) {
1572                /*
1573                 * Once we remove this sfp from the list and clear the
1574                 * sf_si seltdclear will know to ignore this si.
1575                 */
1576                TAILQ_REMOVE(&sip->si_tdlist, sfp, sf_threads);
1577                sfp->sf_si = NULL;
1578                stp = sfp->sf_td;
1579                mtx_lock(&stp->st_mtx);
1580                stp->st_flags |= SELTD_PENDING;
1581                cv_broadcastpri(&stp->st_wait, pri);
1582                mtx_unlock(&stp->st_mtx);
1583        }
1584        mtx_unlock(sip->si_mtx);
1585}
1586
1587static void
1588seltdinit(struct thread *td)
1589{
1590        struct seltd *stp;
1591
1592        if ((stp = td->td_sel) != NULL)
1593                goto out;
1594        td->td_sel = stp = malloc(sizeof(*stp), M_SELECT, M_WAITOK|M_ZERO);
1595        mtx_init(&stp->st_mtx, "sellck", NULL, MTX_DEF);
1596        cv_init(&stp->st_wait, "select");
1597out:
1598        stp->st_flags = 0;
1599        STAILQ_INIT(&stp->st_selq);
1600}
1601
1602static int
1603seltdwait(struct thread *td, int timo)
1604{
1605        struct seltd *stp;
1606        int error;
1607
1608        stp = td->td_sel;
1609        /*
1610         * An event of interest may occur while we do not hold the seltd
1611         * locked so check the pending flag before we sleep.
1612         */
1613        mtx_lock(&stp->st_mtx);
1614        /*
1615         * Any further calls to selrecord will be a rescan.
1616         */
1617        stp->st_flags |= SELTD_RESCAN;
1618        if (stp->st_flags & SELTD_PENDING) {
1619                mtx_unlock(&stp->st_mtx);
1620                return (0);
1621        }
1622        if (timo > 0)
1623                error = cv_timedwait_sig(&stp->st_wait, &stp->st_mtx, timo);
1624        else
1625                error = cv_wait_sig(&stp->st_wait, &stp->st_mtx);
1626        mtx_unlock(&stp->st_mtx);
1627
1628        return (error);
1629}
1630
1631void
1632seltdfini(struct thread *td)
1633{
1634        struct seltd *stp;
1635
1636        stp = td->td_sel;
1637        if (stp == NULL)
1638                return;
1639        if (stp->st_free1)
1640                uma_zfree(selfd_zone, stp->st_free1);
1641        if (stp->st_free2)
1642                uma_zfree(selfd_zone, stp->st_free2);
1643        td->td_sel = NULL;
1644        free(stp, M_SELECT);
1645}
1646
1647/*
1648 * Remove the references to the thread from all of the objects we were
1649 * polling.
1650 */
1651static void
1652seltdclear(struct thread *td)
1653{
1654        struct seltd *stp;
1655        struct selfd *sfp;
1656        struct selfd *sfn;
1657
1658        stp = td->td_sel;
1659        STAILQ_FOREACH_SAFE(sfp, &stp->st_selq, sf_link, sfn)
1660                selfdfree(stp, sfp);
1661        stp->st_flags = 0;
1662}
1663
1664static void selectinit(void *);
1665SYSINIT(select, SI_SUB_SYSCALLS, SI_ORDER_ANY, selectinit, NULL);
1666static void
1667selectinit(void *dummy __unused)
1668{
1669
1670        selfd_zone = uma_zcreate("selfd", sizeof(struct selfd), NULL, NULL,
1671            NULL, NULL, UMA_ALIGN_PTR, 0);
1672        mtxpool_select = mtx_pool_create("select mtxpool", 128, MTX_DEF);
1673}
Note: See TracBrowser for help on using the repository browser.