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

4.115-freebsd-12freebsd-9.3
Last change on this file since 08264c8 was 08264c8, checked in by Sebastian Huber <sebastian.huber@…>, on Oct 28, 2013 at 8:54:33 AM

Use poll() from FreeBSD

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