root/kern/kern_event.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. kqueue_init
  2. filt_fileattach
  3. kqueue_kqfilter
  4. filt_kqdetach
  5. filt_kqueue
  6. filt_procattach
  7. filt_procdetach
  8. filt_proc
  9. filt_timerexpire
  10. filt_timerattach
  11. filt_timerdetach
  12. filt_timer
  13. filt_seltrue
  14. sys_kqueue
  15. sys_kevent
  16. kqueue_register
  17. kqueue_scan
  18. kqueue_read
  19. kqueue_write
  20. kqueue_ioctl
  21. kqueue_poll
  22. kqueue_stat
  23. kqueue_close
  24. kqueue_wakeup
  25. knote
  26. knote_remove
  27. knote_fdclose
  28. knote_attach
  29. knote_drop
  30. knote_enqueue
  31. knote_dequeue
  32. klist_invalidate

    1 /*      $OpenBSD: kern_event.c,v 1.31 2007/05/30 02:24:59 tedu Exp $    */
    2 
    3 /*-
    4  * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  * $FreeBSD: src/sys/kern/kern_event.c,v 1.22 2001/02/23 20:32:42 jlemon Exp $
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/kernel.h>
   34 #include <sys/proc.h>
   35 #include <sys/malloc.h>
   36 #include <sys/unistd.h>
   37 #include <sys/file.h>
   38 #include <sys/filedesc.h>
   39 #include <sys/fcntl.h>
   40 #include <sys/selinfo.h>
   41 #include <sys/queue.h>
   42 #include <sys/event.h>
   43 #include <sys/eventvar.h>
   44 #include <sys/pool.h>
   45 #include <sys/protosw.h>
   46 #include <sys/socket.h>
   47 #include <sys/socketvar.h>
   48 #include <sys/stat.h>
   49 #include <sys/uio.h>
   50 #include <sys/mount.h>
   51 #include <sys/poll.h>
   52 #include <sys/syscallargs.h>
   53 #include <sys/timeout.h>
   54 
   55 int     kqueue_scan(struct file *fp, int maxevents,
   56                     struct kevent *ulistp, const struct timespec *timeout,
   57                     struct proc *p, int *retval);
   58 
   59 int     kqueue_read(struct file *fp, off_t *poff, struct uio *uio,
   60                     struct ucred *cred);
   61 int     kqueue_write(struct file *fp, off_t *poff, struct uio *uio,
   62                     struct ucred *cred);
   63 int     kqueue_ioctl(struct file *fp, u_long com, caddr_t data,
   64                     struct proc *p);
   65 int     kqueue_poll(struct file *fp, int events, struct proc *p);
   66 int     kqueue_kqfilter(struct file *fp, struct knote *kn);
   67 int     kqueue_stat(struct file *fp, struct stat *st, struct proc *p);
   68 int     kqueue_close(struct file *fp, struct proc *p);
   69 void    kqueue_wakeup(struct kqueue *kq);
   70 
   71 struct fileops kqueueops = {
   72         kqueue_read,
   73         kqueue_write,
   74         kqueue_ioctl,
   75         kqueue_poll,
   76         kqueue_kqfilter,
   77         kqueue_stat,
   78         kqueue_close
   79 };
   80 
   81 void    knote_attach(struct knote *kn, struct filedesc *fdp);
   82 void    knote_drop(struct knote *kn, struct proc *p, struct filedesc *fdp);
   83 void    knote_enqueue(struct knote *kn);
   84 void    knote_dequeue(struct knote *kn);
   85 #define knote_alloc() ((struct knote *)pool_get(&knote_pool, PR_WAITOK))
   86 #define knote_free(kn) pool_put(&knote_pool, (kn))
   87 
   88 void    filt_kqdetach(struct knote *kn);
   89 int     filt_kqueue(struct knote *kn, long hint);
   90 int     filt_procattach(struct knote *kn);
   91 void    filt_procdetach(struct knote *kn);
   92 int     filt_proc(struct knote *kn, long hint);
   93 int     filt_fileattach(struct knote *kn);
   94 void    filt_timerexpire(void *knx);
   95 int     filt_timerattach(struct knote *kn);
   96 void    filt_timerdetach(struct knote *kn);
   97 int     filt_timer(struct knote *kn, long hint);
   98 
   99 struct filterops kqread_filtops =
  100         { 1, NULL, filt_kqdetach, filt_kqueue };
  101 struct filterops proc_filtops =
  102         { 0, filt_procattach, filt_procdetach, filt_proc };
  103 struct filterops file_filtops =
  104         { 1, filt_fileattach, NULL, NULL };
  105 struct filterops timer_filtops =
  106         { 0, filt_timerattach, filt_timerdetach, filt_timer };
  107 
  108 struct  pool knote_pool;
  109 struct  pool kqueue_pool;
  110 int kq_ntimeouts = 0;
  111 int kq_timeoutmax = (4 * 1024);
  112 
  113 #define KNOTE_ACTIVATE(kn) do {                                         \
  114         kn->kn_status |= KN_ACTIVE;                                     \
  115         if ((kn->kn_status & (KN_QUEUED | KN_DISABLED)) == 0)           \
  116                 knote_enqueue(kn);                                      \
  117 } while(0)
  118 
  119 #define KN_HASHSIZE             64              /* XXX should be tunable */
  120 #define KN_HASH(val, mask)      (((val) ^ (val >> 8)) & (mask))
  121 
  122 extern struct filterops sig_filtops;
  123 #ifdef notyet
  124 extern struct filterops aio_filtops;
  125 #endif
  126 
  127 /*
  128  * Table for for all system-defined filters.
  129  */
  130 struct filterops *sysfilt_ops[] = {
  131         &file_filtops,                  /* EVFILT_READ */
  132         &file_filtops,                  /* EVFILT_WRITE */
  133         NULL, /*&aio_filtops,*/         /* EVFILT_AIO */
  134         &file_filtops,                  /* EVFILT_VNODE */
  135         &proc_filtops,                  /* EVFILT_PROC */
  136         &sig_filtops,                   /* EVFILT_SIGNAL */
  137         &timer_filtops,                 /* EVFILT_TIMER */
  138 };
  139 
  140 void kqueue_init(void);
  141 
  142 void
  143 kqueue_init(void)
  144 {
  145 
  146         pool_init(&kqueue_pool, sizeof(struct kqueue), 0, 0, 0, "kqueuepl",
  147             &pool_allocator_nointr);
  148         pool_init(&knote_pool, sizeof(struct knote), 0, 0, 0, "knotepl",
  149             &pool_allocator_nointr);
  150 }
  151 
  152 int
  153 filt_fileattach(struct knote *kn)
  154 {
  155         struct file *fp = kn->kn_fp;
  156 
  157         return ((*fp->f_ops->fo_kqfilter)(fp, kn));
  158 }
  159 
  160 int
  161 kqueue_kqfilter(struct file *fp, struct knote *kn)
  162 {
  163         struct kqueue *kq = (struct kqueue *)kn->kn_fp->f_data;
  164 
  165         if (kn->kn_filter != EVFILT_READ)
  166                 return (1);
  167 
  168         kn->kn_fop = &kqread_filtops;
  169         SLIST_INSERT_HEAD(&kq->kq_sel.si_note, kn, kn_selnext);
  170         return (0);
  171 }
  172 
  173 void
  174 filt_kqdetach(struct knote *kn)
  175 {
  176         struct kqueue *kq = (struct kqueue *)kn->kn_fp->f_data;
  177 
  178         SLIST_REMOVE(&kq->kq_sel.si_note, kn, knote, kn_selnext);
  179 }
  180 
  181 /*ARGSUSED*/
  182 int
  183 filt_kqueue(struct knote *kn, long hint)
  184 {
  185         struct kqueue *kq = (struct kqueue *)kn->kn_fp->f_data;
  186 
  187         kn->kn_data = kq->kq_count;
  188         return (kn->kn_data > 0);
  189 }
  190 
  191 int
  192 filt_procattach(struct knote *kn)
  193 {
  194         struct proc *p;
  195 
  196         p = pfind(kn->kn_id);
  197         if (p == NULL)
  198                 return (ESRCH);
  199 
  200         /*
  201          * Fail if it's not owned by you, or the last exec gave us
  202          * setuid/setgid privs (unless you're root).
  203          */
  204         if ((p->p_cred->p_ruid != curproc->p_cred->p_ruid ||
  205             (p->p_flag & P_SUGID)) && suser(curproc, 0) != 0)
  206                 return (EACCES);
  207 
  208         kn->kn_ptr.p_proc = p;
  209         kn->kn_flags |= EV_CLEAR;               /* automatically set */
  210 
  211         /*
  212          * internal flag indicating registration done by kernel
  213          */
  214         if (kn->kn_flags & EV_FLAG1) {
  215                 kn->kn_data = kn->kn_sdata;             /* ppid */
  216                 kn->kn_fflags = NOTE_CHILD;
  217                 kn->kn_flags &= ~EV_FLAG1;
  218         }
  219 
  220         /* XXX lock the proc here while adding to the list? */
  221         SLIST_INSERT_HEAD(&p->p_klist, kn, kn_selnext);
  222 
  223         return (0);
  224 }
  225 
  226 /*
  227  * The knote may be attached to a different process, which may exit,
  228  * leaving nothing for the knote to be attached to.  So when the process
  229  * exits, the knote is marked as DETACHED and also flagged as ONESHOT so
  230  * it will be deleted when read out.  However, as part of the knote deletion,
  231  * this routine is called, so a check is needed to avoid actually performing
  232  * a detach, because the original process does not exist any more.
  233  */
  234 void
  235 filt_procdetach(struct knote *kn)
  236 {
  237         struct proc *p = kn->kn_ptr.p_proc;
  238 
  239         if (kn->kn_status & KN_DETACHED)
  240                 return;
  241 
  242         /* XXX locking?  this might modify another process. */
  243         SLIST_REMOVE(&p->p_klist, kn, knote, kn_selnext);
  244 }
  245 
  246 int
  247 filt_proc(struct knote *kn, long hint)
  248 {
  249         u_int event;
  250 
  251         /*
  252          * mask off extra data
  253          */
  254         event = (u_int)hint & NOTE_PCTRLMASK;
  255 
  256         /*
  257          * if the user is interested in this event, record it.
  258          */
  259         if (kn->kn_sfflags & event)
  260                 kn->kn_fflags |= event;
  261 
  262         /*
  263          * process is gone, so flag the event as finished.
  264          */
  265         if (event == NOTE_EXIT) {
  266                 kn->kn_status |= KN_DETACHED;
  267                 kn->kn_flags |= (EV_EOF | EV_ONESHOT);
  268                 return (1);
  269         }
  270 
  271         /*
  272          * process forked, and user wants to track the new process,
  273          * so attach a new knote to it, and immediately report an
  274          * event with the parent's pid.
  275          */
  276         if ((event == NOTE_FORK) && (kn->kn_sfflags & NOTE_TRACK)) {
  277                 struct kevent kev;
  278                 int error;
  279 
  280                 /*
  281                  * register knote with new process.
  282                  */
  283                 kev.ident = hint & NOTE_PDATAMASK;      /* pid */
  284                 kev.filter = kn->kn_filter;
  285                 kev.flags = kn->kn_flags | EV_ADD | EV_ENABLE | EV_FLAG1;
  286                 kev.fflags = kn->kn_sfflags;
  287                 kev.data = kn->kn_id;                   /* parent */
  288                 kev.udata = kn->kn_kevent.udata;        /* preserve udata */
  289                 error = kqueue_register(kn->kn_kq, &kev, NULL);
  290                 if (error)
  291                         kn->kn_fflags |= NOTE_TRACKERR;
  292         }
  293 
  294         return (kn->kn_fflags != 0);
  295 }
  296 
  297 void
  298 filt_timerexpire(void *knx)
  299 {
  300         struct knote *kn = knx;
  301         struct timeval tv;
  302         int tticks;
  303 
  304         kn->kn_data++;
  305         KNOTE_ACTIVATE(kn);
  306 
  307         if ((kn->kn_flags & EV_ONESHOT) == 0) {
  308                 tv.tv_sec = kn->kn_sdata / 1000;
  309                 tv.tv_usec = (kn->kn_sdata % 1000) * 1000;
  310                 tticks = tvtohz(&tv);
  311                 timeout_add((struct timeout *)kn->kn_hook, tticks);
  312         }
  313 }
  314 
  315 
  316 /*
  317  * data contains amount of time to sleep, in milliseconds
  318  */ 
  319 int
  320 filt_timerattach(struct knote *kn)
  321 {
  322         struct timeout *to;
  323         struct timeval tv;
  324         int tticks;
  325 
  326         if (kq_ntimeouts > kq_timeoutmax)
  327                 return (ENOMEM);
  328         kq_ntimeouts++;
  329 
  330         tv.tv_sec = kn->kn_sdata / 1000;
  331         tv.tv_usec = (kn->kn_sdata % 1000) * 1000;
  332         tticks = tvtohz(&tv);
  333 
  334         kn->kn_flags |= EV_CLEAR;       /* automatically set */
  335         MALLOC(to, struct timeout *, sizeof(*to), M_KEVENT, 0);
  336         timeout_set(to, filt_timerexpire, kn);
  337         timeout_add(to, tticks);
  338         kn->kn_hook = to;
  339 
  340         return (0);
  341 }
  342 
  343 void
  344 filt_timerdetach(struct knote *kn)
  345 {
  346         struct timeout *to;
  347 
  348         to = (struct timeout *)kn->kn_hook;
  349         timeout_del(to);
  350         FREE(to, M_KEVENT);
  351         kq_ntimeouts--;
  352 }
  353 
  354 int
  355 filt_timer(struct knote *kn, long hint)
  356 {
  357         return (kn->kn_data != 0);
  358 }
  359 
  360 
  361 /*
  362  * filt_seltrue:
  363  *
  364  *      This filter "event" routine simulates seltrue().
  365  */
  366 int
  367 filt_seltrue(struct knote *kn, long hint)
  368 {
  369 
  370         /*
  371          * We don't know how much data can be read/written,
  372          * but we know that it *can* be.  This is about as
  373          * good as select/poll does as well.
  374          */
  375         kn->kn_data = 0;
  376         return (1);
  377 }
  378 
  379 int
  380 sys_kqueue(struct proc *p, void *v, register_t *retval)
  381 {
  382         struct filedesc *fdp = p->p_fd;
  383         struct kqueue *kq;
  384         struct file *fp;
  385         int fd, error;
  386 
  387         error = falloc(p, &fp, &fd);
  388         if (error)
  389                 return (error);
  390         fp->f_flag = FREAD | FWRITE;
  391         fp->f_type = DTYPE_KQUEUE;
  392         fp->f_ops = &kqueueops;
  393         kq = pool_get(&kqueue_pool, PR_WAITOK);
  394         bzero(kq, sizeof(*kq));
  395         TAILQ_INIT(&kq->kq_head);
  396         fp->f_data = (caddr_t)kq;
  397         *retval = fd;
  398         if (fdp->fd_knlistsize < 0)
  399                 fdp->fd_knlistsize = 0;         /* this process has a kq */
  400         kq->kq_fdp = fdp;
  401         FILE_SET_MATURE(fp);
  402         return (0);
  403 }
  404 
  405 int
  406 sys_kevent(struct proc *p, void *v, register_t *retval)
  407 {
  408         struct filedesc* fdp = p->p_fd;
  409         struct sys_kevent_args /* {
  410                 syscallarg(int) fd;
  411                 syscallarg(const struct kevent *) changelist;
  412                 syscallarg(int) nchanges;
  413                 syscallarg(struct kevent *) eventlist;
  414                 syscallarg(int) nevents;
  415                 syscallarg(const struct timespec *) timeout;
  416         } */ *uap = v;
  417         struct kevent *kevp;
  418         struct kqueue *kq;
  419         struct file *fp;
  420         struct timespec ts;
  421         int i, n, nerrors, error;
  422 
  423         if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL ||
  424             (fp->f_type != DTYPE_KQUEUE))
  425                 return (EBADF);
  426 
  427         FREF(fp);
  428 
  429         if (SCARG(uap, timeout) != NULL) {
  430                 error = copyin(SCARG(uap, timeout), &ts, sizeof(ts));
  431                 if (error)
  432                         goto done;
  433                 SCARG(uap, timeout) = &ts;
  434         }
  435 
  436         kq = (struct kqueue *)fp->f_data;
  437         nerrors = 0;
  438 
  439         while (SCARG(uap, nchanges) > 0) {
  440                 n = SCARG(uap, nchanges) > KQ_NEVENTS
  441                         ? KQ_NEVENTS : SCARG(uap, nchanges);
  442                 error = copyin(SCARG(uap, changelist), kq->kq_kev,
  443                     n * sizeof(struct kevent));
  444                 if (error)
  445                         goto done;
  446                 for (i = 0; i < n; i++) {
  447                         kevp = &kq->kq_kev[i];
  448                         kevp->flags &= ~EV_SYSFLAGS;
  449                         error = kqueue_register(kq, kevp, p);
  450                         if (error) {
  451                                 if (SCARG(uap, nevents) != 0) {
  452                                         kevp->flags = EV_ERROR;
  453                                         kevp->data = error;
  454                                         (void) copyout((caddr_t)kevp,
  455                                             (caddr_t)SCARG(uap, eventlist),
  456                                             sizeof(*kevp));
  457                                         SCARG(uap, eventlist)++;
  458                                         SCARG(uap, nevents)--;
  459                                         nerrors++;
  460                                 } else {
  461                                         goto done;
  462                                 }
  463                         }
  464                 }
  465                 SCARG(uap, nchanges) -= n;
  466                 SCARG(uap, changelist) += n;
  467         }
  468         if (nerrors) {
  469                 *retval = nerrors;
  470                 error = 0;
  471                 goto done;
  472         }
  473 
  474         error = kqueue_scan(fp, SCARG(uap, nevents), SCARG(uap, eventlist),
  475                             SCARG(uap, timeout), p, &n);
  476         *retval = n;
  477  done:
  478         FRELE(fp);
  479         return (error);
  480 }
  481 
  482 int
  483 kqueue_register(struct kqueue *kq, struct kevent *kev, struct proc *p)
  484 {
  485         struct filedesc *fdp = kq->kq_fdp;
  486         struct filterops *fops = NULL;
  487         struct file *fp = NULL;
  488         struct knote *kn = NULL;
  489         int s, error = 0;
  490 
  491         if (kev->filter < 0) {
  492                 if (kev->filter + EVFILT_SYSCOUNT < 0)
  493                         return (EINVAL);
  494                 fops = sysfilt_ops[~kev->filter];       /* to 0-base index */
  495         }
  496 
  497         if (fops == NULL) {
  498                 /*
  499                  * XXX
  500                  * filter attach routine is responsible for ensuring that
  501                  * the identifier can be attached to it.
  502                  */
  503                 return (EINVAL);
  504         }
  505 
  506         if (fops->f_isfd) {
  507                 /* validate descriptor */
  508                 if ((fp = fd_getfile(fdp, kev->ident)) == NULL)
  509                         return (EBADF);
  510                 FREF(fp);
  511                 fp->f_count++;
  512 
  513                 if (kev->ident < fdp->fd_knlistsize) {
  514                         SLIST_FOREACH(kn, &fdp->fd_knlist[kev->ident], kn_link)
  515                                 if (kq == kn->kn_kq &&
  516                                     kev->filter == kn->kn_filter)
  517                                         break;
  518                 }
  519         } else {
  520                 if (fdp->fd_knhashmask != 0) {
  521                         struct klist *list;
  522 
  523                         list = &fdp->fd_knhash[
  524                             KN_HASH((u_long)kev->ident, fdp->fd_knhashmask)];
  525                         SLIST_FOREACH(kn, list, kn_link)
  526                                 if (kev->ident == kn->kn_id &&
  527                                     kq == kn->kn_kq &&
  528                                     kev->filter == kn->kn_filter)
  529                                         break;
  530                 }
  531         }
  532 
  533         if (kn == NULL && ((kev->flags & EV_ADD) == 0)) {
  534                 error = ENOENT;
  535                 goto done;
  536         }
  537 
  538         /*
  539          * kn now contains the matching knote, or NULL if no match
  540          */
  541         if (kev->flags & EV_ADD) {
  542 
  543                 if (kn == NULL) {
  544                         kn = knote_alloc();
  545                         if (kn == NULL) {
  546                                 error = ENOMEM;
  547                                 goto done;
  548                         }
  549                         kn->kn_fp = fp;
  550                         kn->kn_kq = kq;
  551                         kn->kn_fop = fops;
  552 
  553                         /*
  554                          * apply reference count to knote structure, and
  555                          * do not release it at the end of this routine.
  556                          */
  557                         if (fp != NULL)
  558                                 FRELE(fp);
  559                         fp = NULL;
  560 
  561                         kn->kn_sfflags = kev->fflags;
  562                         kn->kn_sdata = kev->data;
  563                         kev->fflags = 0;
  564                         kev->data = 0;
  565                         kn->kn_kevent = *kev;
  566 
  567                         knote_attach(kn, fdp);
  568                         if ((error = fops->f_attach(kn)) != 0) {
  569                                 knote_drop(kn, p, fdp);
  570                                 goto done;
  571                         }
  572                 } else {
  573                         /*
  574                          * The user may change some filter values after the
  575                          * initial EV_ADD, but doing so will not reset any
  576                          * filters which have already been triggered.
  577                          */
  578                         kn->kn_sfflags = kev->fflags;
  579                         kn->kn_sdata = kev->data;
  580                         kn->kn_kevent.udata = kev->udata;
  581                 }
  582 
  583                 s = splhigh();
  584                 if (kn->kn_fop->f_event(kn, 0))
  585                         KNOTE_ACTIVATE(kn);
  586                 splx(s);
  587 
  588         } else if (kev->flags & EV_DELETE) {
  589                 kn->kn_fop->f_detach(kn);
  590                 knote_drop(kn, p, p->p_fd);
  591                 goto done;
  592         }
  593 
  594         if ((kev->flags & EV_DISABLE) &&
  595             ((kn->kn_status & KN_DISABLED) == 0)) {
  596                 s = splhigh();
  597                 kn->kn_status |= KN_DISABLED;
  598                 splx(s);
  599         }
  600 
  601         if ((kev->flags & EV_ENABLE) && (kn->kn_status & KN_DISABLED)) {
  602                 s = splhigh();
  603                 kn->kn_status &= ~KN_DISABLED;
  604                 if ((kn->kn_status & KN_ACTIVE) &&
  605                     ((kn->kn_status & KN_QUEUED) == 0))
  606                         knote_enqueue(kn);
  607                 splx(s);
  608         }
  609 
  610 done:
  611         if (fp != NULL)
  612                 closef(fp, p);
  613         return (error);
  614 }
  615 
  616 int
  617 kqueue_scan(struct file *fp, int maxevents, struct kevent *ulistp,
  618         const struct timespec *tsp, struct proc *p, int *retval)
  619 {
  620         struct kqueue *kq = (struct kqueue *)fp->f_data;
  621         struct kevent *kevp;
  622         struct timeval atv, rtv, ttv;
  623         struct knote *kn, marker;
  624         int s, count, timeout, nkev = 0, error = 0;
  625 
  626         count = maxevents;
  627         if (count == 0)
  628                 goto done;
  629 
  630         if (tsp != NULL) {
  631                 TIMESPEC_TO_TIMEVAL(&atv, tsp);
  632                 if (tsp->tv_sec == 0 && tsp->tv_nsec == 0) {
  633                         /* No timeout, just poll */
  634                         timeout = -1;
  635                         goto start;
  636                 }
  637                 if (itimerfix(&atv)) {
  638                         error = EINVAL;
  639                         goto done;
  640                 }
  641 
  642                 timeout = atv.tv_sec > 24 * 60 * 60 ?
  643                         24 * 60 * 60 * hz : tvtohz(&atv);
  644 
  645                 getmicrouptime(&rtv);
  646                 timeradd(&atv, &rtv, &atv);
  647         } else {
  648                 atv.tv_sec = 0;
  649                 atv.tv_usec = 0;
  650                 timeout = 0;
  651         }
  652         goto start;
  653 
  654 retry:
  655         if (atv.tv_sec || atv.tv_usec) {
  656                 getmicrouptime(&rtv);
  657                 if (timercmp(&rtv, &atv, >=))
  658                         goto done;
  659                 ttv = atv;
  660                 timersub(&ttv, &rtv, &ttv);
  661                 timeout = ttv.tv_sec > 24 * 60 * 60 ?
  662                         24 * 60 * 60 * hz : tvtohz(&ttv);
  663         }
  664 
  665 start:
  666         kevp = kq->kq_kev;
  667         s = splhigh();
  668         if (kq->kq_count == 0) {
  669                 if (timeout < 0) {
  670                         error = EWOULDBLOCK;
  671                 } else {
  672                         kq->kq_state |= KQ_SLEEP;
  673                         error = tsleep(kq, PSOCK | PCATCH, "kqread", timeout);
  674                 }
  675                 splx(s);
  676                 if (error == 0)
  677                         goto retry;
  678                 /* don't restart after signals... */
  679                 if (error == ERESTART)
  680                         error = EINTR;
  681                 else if (error == EWOULDBLOCK)
  682                         error = 0;
  683                 goto done;
  684         }
  685 
  686         TAILQ_INSERT_TAIL(&kq->kq_head, &marker, kn_tqe);
  687         while (count) {
  688                 kn = TAILQ_FIRST(&kq->kq_head);
  689                 TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe);
  690                 if (kn == &marker) {
  691                         splx(s);
  692                         if (count == maxevents)
  693                                 goto retry;
  694                         goto done;
  695                 }
  696                 if (kn->kn_status & KN_DISABLED) {
  697                         kn->kn_status &= ~KN_QUEUED;
  698                         kq->kq_count--;
  699                         continue;
  700                 }
  701                 if ((kn->kn_flags & EV_ONESHOT) == 0 &&
  702                     kn->kn_fop->f_event(kn, 0) == 0) {
  703                         kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE);
  704                         kq->kq_count--;
  705                         continue;
  706                 }
  707                 *kevp = kn->kn_kevent;
  708                 kevp++;
  709                 nkev++;
  710                 if (kn->kn_flags & EV_ONESHOT) {
  711                         kn->kn_status &= ~KN_QUEUED;
  712                         kq->kq_count--;
  713                         splx(s);
  714                         kn->kn_fop->f_detach(kn);
  715                         knote_drop(kn, p, p->p_fd);
  716                         s = splhigh();
  717                 } else if (kn->kn_flags & EV_CLEAR) {
  718                         kn->kn_data = 0;
  719                         kn->kn_fflags = 0;
  720                         kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE);
  721                         kq->kq_count--;
  722                 } else {
  723                         TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
  724                 }
  725                 count--;
  726                 if (nkev == KQ_NEVENTS) {
  727                         splx(s);
  728                         error = copyout((caddr_t)&kq->kq_kev, (caddr_t)ulistp,
  729                             sizeof(struct kevent) * nkev);
  730                         ulistp += nkev;
  731                         nkev = 0;
  732                         kevp = kq->kq_kev;
  733                         s = splhigh();
  734                         if (error)
  735                                 break;
  736                 }
  737         }
  738         TAILQ_REMOVE(&kq->kq_head, &marker, kn_tqe);
  739         splx(s);
  740 done:
  741         if (nkev != 0)
  742                 error = copyout((caddr_t)&kq->kq_kev, (caddr_t)ulistp,
  743                     sizeof(struct kevent) * nkev);
  744         *retval = maxevents - count;
  745         return (error);
  746 }
  747 
  748 /*
  749  * XXX
  750  * This could be expanded to call kqueue_scan, if desired.
  751  */
  752 /*ARGSUSED*/
  753 int
  754 kqueue_read(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
  755 {
  756         return (ENXIO);
  757 }
  758 
  759 /*ARGSUSED*/
  760 int
  761 kqueue_write(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
  762 
  763 {
  764         return (ENXIO);
  765 }
  766 
  767 /*ARGSUSED*/
  768 int
  769 kqueue_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p)
  770 {
  771         return (ENOTTY);
  772 }
  773 
  774 /*ARGSUSED*/
  775 int
  776 kqueue_poll(struct file *fp, int events, struct proc *p)
  777 {
  778         struct kqueue *kq = (struct kqueue *)fp->f_data;
  779         int revents = 0;
  780         int s = splhigh();
  781 
  782         if (events & (POLLIN | POLLRDNORM)) {
  783                 if (kq->kq_count) {
  784                         revents |= events & (POLLIN | POLLRDNORM);
  785                 } else {
  786                         selrecord(p, &kq->kq_sel);
  787                         kq->kq_state |= KQ_SEL;
  788                 }
  789         }
  790         splx(s);
  791         return (revents);
  792 }
  793 
  794 /*ARGSUSED*/
  795 int
  796 kqueue_stat(struct file *fp, struct stat *st, struct proc *p)
  797 {
  798         struct kqueue *kq = (struct kqueue *)fp->f_data;
  799 
  800         bzero((void *)st, sizeof(*st));
  801         st->st_size = kq->kq_count;
  802         st->st_blksize = sizeof(struct kevent);
  803         st->st_mode = S_IFIFO;
  804         return (0);
  805 }
  806 
  807 /*ARGSUSED*/
  808 int
  809 kqueue_close(struct file *fp, struct proc *p)
  810 {
  811         struct kqueue *kq = (struct kqueue *)fp->f_data;
  812         struct filedesc *fdp = p->p_fd;
  813         struct knote **knp, *kn, *kn0;
  814         int i;
  815 
  816         for (i = 0; i < fdp->fd_knlistsize; i++) {
  817                 knp = &SLIST_FIRST(&fdp->fd_knlist[i]);
  818                 kn = *knp;
  819                 while (kn != NULL) {
  820                         kn0 = SLIST_NEXT(kn, kn_link);
  821                         if (kq == kn->kn_kq) {
  822                                 FREF(kn->kn_fp);
  823                                 kn->kn_fop->f_detach(kn);
  824                                 closef(kn->kn_fp, p);
  825                                 knote_free(kn);
  826                                 *knp = kn0;
  827                         } else {
  828                                 knp = &SLIST_NEXT(kn, kn_link);
  829                         }
  830                         kn = kn0;
  831                 }
  832         }
  833         if (fdp->fd_knhashmask != 0) {
  834                 for (i = 0; i < fdp->fd_knhashmask + 1; i++) {
  835                         knp = &SLIST_FIRST(&fdp->fd_knhash[i]);
  836                         kn = *knp;
  837                         while (kn != NULL) {
  838                                 kn0 = SLIST_NEXT(kn, kn_link);
  839                                 if (kq == kn->kn_kq) {
  840                                         kn->kn_fop->f_detach(kn);
  841                 /* XXX non-fd release of kn->kn_ptr */
  842                                         knote_free(kn);
  843                                         *knp = kn0;
  844                                 } else {
  845                                         knp = &SLIST_NEXT(kn, kn_link);
  846                                 }
  847                                 kn = kn0;
  848                         }
  849                 }
  850         }
  851         pool_put(&kqueue_pool, kq);
  852         fp->f_data = NULL;
  853 
  854         return (0);
  855 }
  856 
  857 void
  858 kqueue_wakeup(struct kqueue *kq)
  859 {
  860 
  861         if (kq->kq_state & KQ_SLEEP) {
  862                 kq->kq_state &= ~KQ_SLEEP;
  863                 wakeup(kq);
  864         }
  865         if (kq->kq_state & KQ_SEL) {
  866                 kq->kq_state &= ~KQ_SEL;
  867                 selwakeup(&kq->kq_sel);
  868         }
  869         KNOTE(&kq->kq_sel.si_note, 0);
  870 }
  871 
  872 /*
  873  * walk down a list of knotes, activating them if their event has triggered.
  874  */
  875 void
  876 knote(struct klist *list, long hint)
  877 {
  878         struct knote *kn;
  879 
  880         SLIST_FOREACH(kn, list, kn_selnext)
  881                 if (kn->kn_fop->f_event(kn, hint))
  882                         KNOTE_ACTIVATE(kn);
  883 }
  884 
  885 /*
  886  * remove all knotes from a specified klist
  887  */
  888 void
  889 knote_remove(struct proc *p, struct klist *list)
  890 {
  891         struct knote *kn;
  892 
  893         while ((kn = SLIST_FIRST(list)) != NULL) {
  894                 kn->kn_fop->f_detach(kn);
  895                 knote_drop(kn, p, p->p_fd);
  896         }
  897 }
  898 
  899 /*
  900  * remove all knotes referencing a specified fd
  901  */
  902 void
  903 knote_fdclose(struct proc *p, int fd)
  904 {
  905         struct filedesc *fdp = p->p_fd;
  906         struct klist *list = &fdp->fd_knlist[fd];
  907 
  908         knote_remove(p, list);
  909 }
  910 
  911 void
  912 knote_attach(struct knote *kn, struct filedesc *fdp)
  913 {
  914         struct klist *list;
  915         int size;
  916 
  917         if (! kn->kn_fop->f_isfd) {
  918                 if (fdp->fd_knhashmask == 0)
  919                         fdp->fd_knhash = hashinit(KN_HASHSIZE, M_TEMP,
  920                             M_WAITOK, &fdp->fd_knhashmask);
  921                 list = &fdp->fd_knhash[KN_HASH(kn->kn_id, fdp->fd_knhashmask)];
  922                 goto done;
  923         }
  924 
  925         if (fdp->fd_knlistsize <= kn->kn_id) {
  926                 size = fdp->fd_knlistsize;
  927                 while (size <= kn->kn_id)
  928                         size += KQEXTENT;
  929                 list = malloc(size * sizeof(struct klist *), M_TEMP, M_WAITOK);
  930                 bcopy((caddr_t)fdp->fd_knlist, (caddr_t)list,
  931                     fdp->fd_knlistsize * sizeof(struct klist *));
  932                 bzero((caddr_t)list +
  933                     fdp->fd_knlistsize * sizeof(struct klist *),
  934                     (size - fdp->fd_knlistsize) * sizeof(struct klist *));
  935                 if (fdp->fd_knlist != NULL)
  936                         free(fdp->fd_knlist, M_TEMP);
  937                 fdp->fd_knlistsize = size;
  938                 fdp->fd_knlist = list;
  939         }
  940         list = &fdp->fd_knlist[kn->kn_id];
  941 done:
  942         SLIST_INSERT_HEAD(list, kn, kn_link);
  943         kn->kn_status = 0;
  944 }
  945 
  946 /*
  947  * should be called at spl == 0, since we don't want to hold spl
  948  * while calling closef and free.
  949  */
  950 void
  951 knote_drop(struct knote *kn, struct proc *p, struct filedesc *fdp)
  952 {
  953         struct klist *list;
  954 
  955         if (kn->kn_fop->f_isfd)
  956                 list = &fdp->fd_knlist[kn->kn_id];
  957         else
  958                 list = &fdp->fd_knhash[KN_HASH(kn->kn_id, fdp->fd_knhashmask)];
  959 
  960         SLIST_REMOVE(list, kn, knote, kn_link);
  961         if (kn->kn_status & KN_QUEUED)
  962                 knote_dequeue(kn);
  963         if (kn->kn_fop->f_isfd) {
  964                 FREF(kn->kn_fp);
  965                 closef(kn->kn_fp, p);
  966         }
  967         knote_free(kn);
  968 }
  969 
  970 
  971 void
  972 knote_enqueue(struct knote *kn)
  973 {
  974         struct kqueue *kq = kn->kn_kq;
  975         int s = splhigh();
  976 
  977         KASSERT((kn->kn_status & KN_QUEUED) == 0);
  978 
  979         TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
  980         kn->kn_status |= KN_QUEUED;
  981         kq->kq_count++;
  982         splx(s);
  983         kqueue_wakeup(kq);
  984 }
  985 
  986 void
  987 knote_dequeue(struct knote *kn)
  988 {
  989         struct kqueue *kq = kn->kn_kq;
  990         int s = splhigh();
  991 
  992         KASSERT(kn->kn_status & KN_QUEUED);
  993 
  994         TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe);
  995         kn->kn_status &= ~KN_QUEUED;
  996         kq->kq_count--;
  997         splx(s);
  998 }
  999 
 1000 void
 1001 klist_invalidate(struct klist *list)
 1002 {
 1003         struct knote *kn;
 1004 
 1005         SLIST_FOREACH(kn, list, kn_selnext) {
 1006                 kn->kn_status |= KN_DETACHED;
 1007                 kn->kn_flags |= EV_EOF | EV_ONESHOT;
 1008         }
 1009 }

/* [<][>][^][v][top][bottom][index][help] */