The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/linux/linux_event.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2007 Roman Divacky
    3  * Copyright (c) 2014 Dmitry Chagin
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD: releng/11.0/sys/compat/linux/linux_event.c 297297 2016-03-26 19:16:53Z dchagin $");
   30 
   31 #include "opt_compat.h"
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/imgact.h>
   36 #include <sys/kernel.h>
   37 #include <sys/limits.h>
   38 #include <sys/lock.h>
   39 #include <sys/mutex.h>
   40 #include <sys/capability.h>
   41 #include <sys/types.h>
   42 #include <sys/user.h>
   43 #include <sys/file.h>
   44 #include <sys/filedesc.h>
   45 #include <sys/filio.h>
   46 #include <sys/errno.h>
   47 #include <sys/event.h>
   48 #include <sys/poll.h>
   49 #include <sys/proc.h>
   50 #include <sys/selinfo.h>
   51 #include <sys/sx.h>
   52 #include <sys/syscallsubr.h>
   53 #include <sys/timespec.h>
   54 
   55 #ifdef COMPAT_LINUX32
   56 #include <machine/../linux32/linux.h>
   57 #include <machine/../linux32/linux32_proto.h>
   58 #else
   59 #include <machine/../linux/linux.h>
   60 #include <machine/../linux/linux_proto.h>
   61 #endif
   62 
   63 #include <compat/linux/linux_emul.h>
   64 #include <compat/linux/linux_event.h>
   65 #include <compat/linux/linux_file.h>
   66 #include <compat/linux/linux_util.h>
   67 
   68 /*
   69  * epoll defines 'struct epoll_event' with the field 'data' as 64 bits
   70  * on all architectures. But on 32 bit architectures BSD 'struct kevent' only
   71  * has 32 bit opaque pointer as 'udata' field. So we can't pass epoll supplied
   72  * data verbatuim. Therefore we allocate 64-bit memory block to pass
   73  * user supplied data for every file descriptor.
   74  */
   75 
   76 typedef uint64_t        epoll_udata_t;
   77 
   78 struct epoll_emuldata {
   79         uint32_t        fdc;            /* epoll udata max index */
   80         epoll_udata_t   udata[1];       /* epoll user data vector */
   81 };
   82 
   83 #define EPOLL_DEF_SZ            16
   84 #define EPOLL_SIZE(fdn)                 \
   85         (sizeof(struct epoll_emuldata)+(fdn) * sizeof(epoll_udata_t))
   86 
   87 struct epoll_event {
   88         uint32_t        events;
   89         epoll_udata_t   data;
   90 }
   91 #if defined(__amd64__)
   92 __attribute__((packed))
   93 #endif
   94 ;
   95 
   96 #define LINUX_MAX_EVENTS        (INT_MAX / sizeof(struct epoll_event))
   97 
   98 static void     epoll_fd_install(struct thread *td, int fd, epoll_udata_t udata);
   99 static int      epoll_to_kevent(struct thread *td, struct file *epfp,
  100                     int fd, struct epoll_event *l_event, int *kev_flags,
  101                     struct kevent *kevent, int *nkevents);
  102 static void     kevent_to_epoll(struct kevent *kevent, struct epoll_event *l_event);
  103 static int      epoll_kev_copyout(void *arg, struct kevent *kevp, int count);
  104 static int      epoll_kev_copyin(void *arg, struct kevent *kevp, int count);
  105 static int      epoll_delete_event(struct thread *td, struct file *epfp,
  106                     int fd, int filter);
  107 static int      epoll_delete_all_events(struct thread *td, struct file *epfp,
  108                     int fd);
  109 
  110 struct epoll_copyin_args {
  111         struct kevent   *changelist;
  112 };
  113 
  114 struct epoll_copyout_args {
  115         struct epoll_event      *leventlist;
  116         struct proc             *p;
  117         uint32_t                count;
  118         int                     error;
  119 };
  120 
  121 /* eventfd */
  122 typedef uint64_t        eventfd_t;
  123 
  124 static fo_rdwr_t        eventfd_read;
  125 static fo_rdwr_t        eventfd_write;
  126 static fo_truncate_t    eventfd_truncate;
  127 static fo_ioctl_t       eventfd_ioctl;
  128 static fo_poll_t        eventfd_poll;
  129 static fo_kqfilter_t    eventfd_kqfilter;
  130 static fo_stat_t        eventfd_stat;
  131 static fo_close_t       eventfd_close;
  132 static fo_fill_kinfo_t  eventfd_fill_kinfo;
  133 
  134 static struct fileops eventfdops = {
  135         .fo_read = eventfd_read,
  136         .fo_write = eventfd_write,
  137         .fo_truncate = eventfd_truncate,
  138         .fo_ioctl = eventfd_ioctl,
  139         .fo_poll = eventfd_poll,
  140         .fo_kqfilter = eventfd_kqfilter,
  141         .fo_stat = eventfd_stat,
  142         .fo_close = eventfd_close,
  143         .fo_chmod = invfo_chmod,
  144         .fo_chown = invfo_chown,
  145         .fo_sendfile = invfo_sendfile,
  146         .fo_fill_kinfo = eventfd_fill_kinfo,
  147         .fo_flags = DFLAG_PASSABLE
  148 };
  149 
  150 static void     filt_eventfddetach(struct knote *kn);
  151 static int      filt_eventfdread(struct knote *kn, long hint);
  152 static int      filt_eventfdwrite(struct knote *kn, long hint);
  153 
  154 static struct filterops eventfd_rfiltops = {
  155         .f_isfd = 1,
  156         .f_detach = filt_eventfddetach,
  157         .f_event = filt_eventfdread
  158 };
  159 static struct filterops eventfd_wfiltops = {
  160         .f_isfd = 1,
  161         .f_detach = filt_eventfddetach,
  162         .f_event = filt_eventfdwrite
  163 };
  164 
  165 struct eventfd {
  166         eventfd_t       efd_count;
  167         uint32_t        efd_flags;
  168         struct selinfo  efd_sel;
  169         struct mtx      efd_lock;
  170 };
  171 
  172 static int      eventfd_create(struct thread *td, uint32_t initval, int flags);
  173 
  174 
  175 static void
  176 epoll_fd_install(struct thread *td, int fd, epoll_udata_t udata)
  177 {
  178         struct linux_pemuldata *pem;
  179         struct epoll_emuldata *emd;
  180         struct proc *p;
  181 
  182         p = td->td_proc;
  183 
  184         pem = pem_find(p);
  185         KASSERT(pem != NULL, ("epoll proc emuldata not found.\n"));
  186 
  187         LINUX_PEM_XLOCK(pem);
  188         if (pem->epoll == NULL) {
  189                 emd = malloc(EPOLL_SIZE(fd), M_EPOLL, M_WAITOK);
  190                 emd->fdc = fd;
  191                 pem->epoll = emd;
  192         } else {
  193                 emd = pem->epoll;
  194                 if (fd > emd->fdc) {
  195                         emd = realloc(emd, EPOLL_SIZE(fd), M_EPOLL, M_WAITOK);
  196                         emd->fdc = fd;
  197                         pem->epoll = emd;
  198                 }
  199         }
  200         emd->udata[fd] = udata;
  201         LINUX_PEM_XUNLOCK(pem);
  202 }
  203 
  204 static int
  205 epoll_create_common(struct thread *td, int flags)
  206 {
  207         int error;
  208 
  209         error = kern_kqueue(td, flags, NULL);
  210         if (error)
  211                 return (error);
  212 
  213         epoll_fd_install(td, EPOLL_DEF_SZ, 0);
  214 
  215         return (0);
  216 }
  217 
  218 int
  219 linux_epoll_create(struct thread *td, struct linux_epoll_create_args *args)
  220 {
  221 
  222         /*
  223          * args->size is unused. Linux just tests it
  224          * and then forgets it as well.
  225          */
  226         if (args->size <= 0)
  227                 return (EINVAL);
  228 
  229         return (epoll_create_common(td, 0));
  230 }
  231 
  232 int
  233 linux_epoll_create1(struct thread *td, struct linux_epoll_create1_args *args)
  234 {
  235         int flags;
  236 
  237         if ((args->flags & ~(LINUX_O_CLOEXEC)) != 0)
  238                 return (EINVAL);
  239 
  240         flags = 0;
  241         if ((args->flags & LINUX_O_CLOEXEC) != 0)
  242                 flags |= O_CLOEXEC;
  243 
  244         return (epoll_create_common(td, flags));
  245 }
  246 
  247 /* Structure converting function from epoll to kevent. */
  248 static int
  249 epoll_to_kevent(struct thread *td, struct file *epfp,
  250     int fd, struct epoll_event *l_event, int *kev_flags,
  251     struct kevent *kevent, int *nkevents)
  252 {
  253         uint32_t levents = l_event->events;
  254         struct linux_pemuldata *pem;
  255         struct proc *p;
  256 
  257         /* flags related to how event is registered */
  258         if ((levents & LINUX_EPOLLONESHOT) != 0)
  259                 *kev_flags |= EV_ONESHOT;
  260         if ((levents & LINUX_EPOLLET) != 0)
  261                 *kev_flags |= EV_CLEAR;
  262         if ((levents & LINUX_EPOLLERR) != 0)
  263                 *kev_flags |= EV_ERROR;
  264         if ((levents & LINUX_EPOLLRDHUP) != 0)
  265                 *kev_flags |= EV_EOF;
  266 
  267         /* flags related to what event is registered */
  268         if ((levents & LINUX_EPOLL_EVRD) != 0) {
  269                 EV_SET(kevent++, fd, EVFILT_READ, *kev_flags, 0, 0, 0);
  270                 ++(*nkevents);
  271         }
  272         if ((levents & LINUX_EPOLL_EVWR) != 0) {
  273                 EV_SET(kevent++, fd, EVFILT_WRITE, *kev_flags, 0, 0, 0);
  274                 ++(*nkevents);
  275         }
  276 
  277         if ((levents & ~(LINUX_EPOLL_EVSUP)) != 0) {
  278                 p = td->td_proc;
  279 
  280                 pem = pem_find(p);
  281                 KASSERT(pem != NULL, ("epoll proc emuldata not found.\n"));
  282                 KASSERT(pem->epoll != NULL, ("epoll proc epolldata not found.\n"));
  283 
  284                 LINUX_PEM_XLOCK(pem);
  285                 if ((pem->flags & LINUX_XUNSUP_EPOLL) == 0) {
  286                         pem->flags |= LINUX_XUNSUP_EPOLL;
  287                         LINUX_PEM_XUNLOCK(pem);
  288                         linux_msg(td, "epoll_ctl unsupported flags: 0x%x\n",
  289                             levents);
  290                 } else
  291                         LINUX_PEM_XUNLOCK(pem);
  292                 return (EINVAL);
  293         }
  294 
  295         return (0);
  296 }
  297 
  298 /* 
  299  * Structure converting function from kevent to epoll. In a case
  300  * this is called on error in registration we store the error in
  301  * event->data and pick it up later in linux_epoll_ctl().
  302  */
  303 static void
  304 kevent_to_epoll(struct kevent *kevent, struct epoll_event *l_event)
  305 {
  306 
  307         if ((kevent->flags & EV_ERROR) != 0) {
  308                 l_event->events = LINUX_EPOLLERR;
  309                 return;
  310         }
  311 
  312         switch (kevent->filter) {
  313         case EVFILT_READ:
  314                 l_event->events = LINUX_EPOLLIN|LINUX_EPOLLRDNORM|LINUX_EPOLLPRI;
  315                 if ((kevent->flags & EV_EOF) != 0)
  316                         l_event->events |= LINUX_EPOLLRDHUP;
  317         break;
  318         case EVFILT_WRITE:
  319                 l_event->events = LINUX_EPOLLOUT|LINUX_EPOLLWRNORM;
  320         break;
  321         }
  322 }
  323 
  324 /* 
  325  * Copyout callback used by kevent. This converts kevent
  326  * events to epoll events and copies them back to the
  327  * userspace. This is also called on error on registering
  328  * of the filter.
  329  */
  330 static int
  331 epoll_kev_copyout(void *arg, struct kevent *kevp, int count)
  332 {
  333         struct epoll_copyout_args *args;
  334         struct linux_pemuldata *pem;
  335         struct epoll_emuldata *emd;
  336         struct epoll_event *eep;
  337         int error, fd, i;
  338 
  339         args = (struct epoll_copyout_args*) arg;
  340         eep = malloc(sizeof(*eep) * count, M_EPOLL, M_WAITOK | M_ZERO);
  341 
  342         pem = pem_find(args->p);
  343         KASSERT(pem != NULL, ("epoll proc emuldata not found.\n"));
  344         LINUX_PEM_SLOCK(pem);
  345         emd = pem->epoll;
  346         KASSERT(emd != NULL, ("epoll proc epolldata not found.\n"));
  347 
  348         for (i = 0; i < count; i++) {
  349                 kevent_to_epoll(&kevp[i], &eep[i]);
  350 
  351                 fd = kevp[i].ident;
  352                 KASSERT(fd <= emd->fdc, ("epoll user data vector"
  353                                                     " is too small.\n"));
  354                 eep[i].data = emd->udata[fd];
  355         }
  356         LINUX_PEM_SUNLOCK(pem);
  357 
  358         error = copyout(eep, args->leventlist, count * sizeof(*eep));
  359         if (error == 0) {
  360                 args->leventlist += count;
  361                 args->count += count;
  362         } else if (args->error == 0)
  363                 args->error = error;
  364 
  365         free(eep, M_EPOLL);
  366         return (error);
  367 }
  368 
  369 /*
  370  * Copyin callback used by kevent. This copies already
  371  * converted filters from kernel memory to the kevent 
  372  * internal kernel memory. Hence the memcpy instead of
  373  * copyin.
  374  */
  375 static int
  376 epoll_kev_copyin(void *arg, struct kevent *kevp, int count)
  377 {
  378         struct epoll_copyin_args *args;
  379 
  380         args = (struct epoll_copyin_args*) arg;
  381         
  382         memcpy(kevp, args->changelist, count * sizeof(*kevp));
  383         args->changelist += count;
  384 
  385         return (0);
  386 }
  387 
  388 /*
  389  * Load epoll filter, convert it to kevent filter
  390  * and load it into kevent subsystem.
  391  */
  392 int
  393 linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args)
  394 {
  395         struct file *epfp, *fp;
  396         struct epoll_copyin_args ciargs;
  397         struct kevent kev[2];
  398         struct kevent_copyops k_ops = { &ciargs,
  399                                         NULL,
  400                                         epoll_kev_copyin};
  401         struct epoll_event le;
  402         cap_rights_t rights;
  403         int kev_flags;
  404         int nchanges = 0;
  405         int error;
  406 
  407         if (args->op != LINUX_EPOLL_CTL_DEL) {
  408                 error = copyin(args->event, &le, sizeof(le));
  409                 if (error != 0)
  410                         return (error);
  411         }
  412 
  413         error = fget(td, args->epfd,
  414             cap_rights_init(&rights, CAP_KQUEUE_CHANGE), &epfp);
  415         if (error != 0)
  416                 return (error);
  417         if (epfp->f_type != DTYPE_KQUEUE)
  418                 goto leave1;
  419 
  420          /* Protect user data vector from incorrectly supplied fd. */
  421         error = fget(td, args->fd, cap_rights_init(&rights, CAP_POLL_EVENT), &fp);
  422         if (error != 0)
  423                 goto leave1;
  424 
  425         /* Linux disallows spying on himself */
  426         if (epfp == fp) {
  427                 error = EINVAL;
  428                 goto leave0;
  429         }
  430 
  431         ciargs.changelist = kev;
  432 
  433         switch (args->op) {
  434         case LINUX_EPOLL_CTL_MOD:
  435                 /*
  436                  * We don't memorize which events were set for this FD
  437                  * on this level, so just delete all we could have set:
  438                  * EVFILT_READ and EVFILT_WRITE, ignoring any errors
  439                  */
  440                 error = epoll_delete_all_events(td, epfp, args->fd);
  441                 if (error)
  442                         goto leave0;
  443                 /* FALLTHROUGH */
  444 
  445         case LINUX_EPOLL_CTL_ADD:
  446                         kev_flags = EV_ADD | EV_ENABLE;
  447                 break;
  448 
  449         case LINUX_EPOLL_CTL_DEL:
  450                 /* CTL_DEL means unregister this fd with this epoll */
  451                 error = epoll_delete_all_events(td, epfp, args->fd);
  452                 goto leave0;
  453 
  454         default:
  455                 error = EINVAL;
  456                 goto leave0;
  457         }
  458 
  459         error = epoll_to_kevent(td, epfp, args->fd, &le, &kev_flags,
  460             kev, &nchanges);
  461         if (error)
  462                 goto leave0;
  463 
  464         epoll_fd_install(td, args->fd, le.data);
  465 
  466         error = kern_kevent_fp(td, epfp, nchanges, 0, &k_ops, NULL);
  467 
  468 leave0:
  469         fdrop(fp, td);
  470 
  471 leave1:
  472         fdrop(epfp, td);
  473         return (error);
  474 }
  475 
  476 /*
  477  * Wait for a filter to be triggered on the epoll file descriptor.
  478  */
  479 static int
  480 linux_epoll_wait_common(struct thread *td, int epfd, struct epoll_event *events,
  481     int maxevents, int timeout, sigset_t *uset)
  482 {
  483         struct file *epfp;
  484         struct timespec ts, *tsp;
  485         cap_rights_t rights;
  486         struct epoll_copyout_args coargs;
  487         struct kevent_copyops k_ops = { &coargs,
  488                                         epoll_kev_copyout,
  489                                         NULL};
  490         int error;
  491 
  492         if (maxevents <= 0 || maxevents > LINUX_MAX_EVENTS)
  493                 return (EINVAL);
  494 
  495         if (uset != NULL) {
  496                 error = kern_sigprocmask(td, SIG_SETMASK, uset,
  497                     &td->td_oldsigmask, 0);
  498                 if (error != 0)
  499                         return (error);
  500                 td->td_pflags |= TDP_OLDMASK;
  501                 /*
  502                  * Make sure that ast() is called on return to
  503                  * usermode and TDP_OLDMASK is cleared, restoring old
  504                  * sigmask.
  505                  */
  506                 thread_lock(td);
  507                 td->td_flags |= TDF_ASTPENDING;
  508                 thread_unlock(td);
  509         }
  510 
  511         error = fget(td, epfd,
  512             cap_rights_init(&rights, CAP_KQUEUE_EVENT), &epfp);
  513         if (error != 0)
  514                 return (error);
  515 
  516         coargs.leventlist = events;
  517         coargs.p = td->td_proc;
  518         coargs.count = 0;
  519         coargs.error = 0;
  520 
  521         if (timeout != -1) {
  522                 if (timeout < 0) {
  523                         error = EINVAL;
  524                         goto leave;
  525                 }
  526                 /* Convert from milliseconds to timespec. */
  527                 ts.tv_sec = timeout / 1000;
  528                 ts.tv_nsec = (timeout % 1000) * 1000000;
  529                 tsp = &ts;
  530         } else {
  531                 tsp = NULL;
  532         }
  533 
  534         error = kern_kevent_fp(td, epfp, 0, maxevents, &k_ops, tsp);
  535         if (error == 0 && coargs.error != 0)
  536                 error = coargs.error;
  537 
  538         /* 
  539          * kern_kevent might return ENOMEM which is not expected from epoll_wait.
  540          * Maybe we should translate that but I don't think it matters at all.
  541          */
  542         if (error == 0)
  543                 td->td_retval[0] = coargs.count;
  544 leave:
  545         fdrop(epfp, td);
  546         return (error);
  547 }
  548 
  549 int
  550 linux_epoll_wait(struct thread *td, struct linux_epoll_wait_args *args)
  551 {
  552 
  553         return (linux_epoll_wait_common(td, args->epfd, args->events,
  554             args->maxevents, args->timeout, NULL));
  555 }
  556 
  557 int
  558 linux_epoll_pwait(struct thread *td, struct linux_epoll_pwait_args *args)
  559 {
  560         sigset_t mask, *pmask;
  561         l_sigset_t lmask;
  562         int error;
  563 
  564         if (args->mask != NULL) {
  565                 error = copyin(args->mask, &lmask, sizeof(l_sigset_t));
  566                 if (error != 0)
  567                         return (error);
  568                 linux_to_bsd_sigset(&lmask, &mask);
  569                 pmask = &mask;
  570         } else
  571                 pmask = NULL;
  572         return (linux_epoll_wait_common(td, args->epfd, args->events,
  573             args->maxevents, args->timeout, pmask));
  574 }
  575 
  576 static int
  577 epoll_delete_event(struct thread *td, struct file *epfp, int fd, int filter)
  578 {
  579         struct epoll_copyin_args ciargs;
  580         struct kevent kev;
  581         struct kevent_copyops k_ops = { &ciargs,
  582                                         NULL,
  583                                         epoll_kev_copyin};
  584         int error;
  585 
  586         ciargs.changelist = &kev;
  587         EV_SET(&kev, fd, filter, EV_DELETE | EV_DISABLE, 0, 0, 0);
  588 
  589         error = kern_kevent_fp(td, epfp, 1, 0, &k_ops, NULL);
  590 
  591         /*
  592          * here we ignore ENONT, because we don't keep track of events here
  593          */
  594         if (error == ENOENT)
  595                 error = 0;
  596         return (error);
  597 }
  598 
  599 static int
  600 epoll_delete_all_events(struct thread *td, struct file *epfp, int fd)
  601 {
  602         int error1, error2;
  603 
  604         error1 = epoll_delete_event(td, epfp, fd, EVFILT_READ);
  605         error2 = epoll_delete_event(td, epfp, fd, EVFILT_WRITE);
  606 
  607         /* report any errors we got */
  608         return (error1 == 0 ? error2 : error1);
  609 }
  610 
  611 static int
  612 eventfd_create(struct thread *td, uint32_t initval, int flags)
  613 {
  614         struct filedesc *fdp;
  615         struct eventfd *efd;
  616         struct file *fp;
  617         int fflags, fd, error;
  618 
  619         fflags = 0;
  620         if ((flags & LINUX_O_CLOEXEC) != 0)
  621                 fflags |= O_CLOEXEC;
  622 
  623         fdp = td->td_proc->p_fd;
  624         error = falloc(td, &fp, &fd, fflags);
  625         if (error)
  626                 return (error);
  627 
  628         efd = malloc(sizeof(*efd), M_EPOLL, M_WAITOK | M_ZERO);
  629         efd->efd_flags = flags;
  630         efd->efd_count = initval;
  631         mtx_init(&efd->efd_lock, "eventfd", NULL, MTX_DEF);
  632 
  633         knlist_init_mtx(&efd->efd_sel.si_note, &efd->efd_lock);
  634 
  635         fflags = FREAD | FWRITE; 
  636         if ((flags & LINUX_O_NONBLOCK) != 0)
  637                 fflags |= FNONBLOCK;
  638 
  639         finit(fp, fflags, DTYPE_LINUXEFD, efd, &eventfdops);
  640         fdrop(fp, td);
  641 
  642         td->td_retval[0] = fd;
  643         return (error);
  644 }
  645 
  646 int
  647 linux_eventfd(struct thread *td, struct linux_eventfd_args *args)
  648 {
  649 
  650         return (eventfd_create(td, args->initval, 0));
  651 }
  652 
  653 int
  654 linux_eventfd2(struct thread *td, struct linux_eventfd2_args *args)
  655 {
  656 
  657         if ((args->flags & ~(LINUX_O_CLOEXEC|LINUX_O_NONBLOCK|LINUX_EFD_SEMAPHORE)) != 0)
  658                 return (EINVAL);
  659 
  660         return (eventfd_create(td, args->initval, args->flags));
  661 }
  662 
  663 static int
  664 eventfd_close(struct file *fp, struct thread *td)
  665 {
  666         struct eventfd *efd;
  667 
  668         efd = fp->f_data;
  669         if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
  670                 return (EBADF);
  671 
  672         seldrain(&efd->efd_sel);
  673         knlist_destroy(&efd->efd_sel.si_note);
  674 
  675         fp->f_ops = &badfileops;
  676         mtx_destroy(&efd->efd_lock);
  677         free(efd, M_EPOLL);
  678 
  679         return (0);
  680 }
  681 
  682 static int
  683 eventfd_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
  684         int flags, struct thread *td)
  685 {
  686         struct eventfd *efd;
  687         eventfd_t count;
  688         int error;
  689 
  690         efd = fp->f_data;
  691         if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
  692                 return (EBADF);
  693 
  694         if (uio->uio_resid < sizeof(eventfd_t))
  695                 return (EINVAL);
  696 
  697         error = 0;
  698         mtx_lock(&efd->efd_lock);
  699 retry:
  700         if (efd->efd_count == 0) {
  701                 if ((efd->efd_flags & LINUX_O_NONBLOCK) != 0) {
  702                         mtx_unlock(&efd->efd_lock);
  703                         return (EAGAIN);
  704                 }
  705                 error = mtx_sleep(&efd->efd_count, &efd->efd_lock, PCATCH, "lefdrd", 0);
  706                 if (error == 0)
  707                         goto retry;
  708         }
  709         if (error == 0) {
  710                 if ((efd->efd_flags & LINUX_EFD_SEMAPHORE) != 0) {
  711                         count = 1;
  712                         --efd->efd_count;
  713                 } else {
  714                         count = efd->efd_count;
  715                         efd->efd_count = 0;
  716                 }
  717                 KNOTE_LOCKED(&efd->efd_sel.si_note, 0);
  718                 selwakeup(&efd->efd_sel);
  719                 wakeup(&efd->efd_count);
  720                 mtx_unlock(&efd->efd_lock);
  721                 error = uiomove(&count, sizeof(eventfd_t), uio);
  722         } else
  723                 mtx_unlock(&efd->efd_lock);
  724 
  725         return (error);
  726 }
  727 
  728 static int
  729 eventfd_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
  730          int flags, struct thread *td)
  731 {
  732         struct eventfd *efd;
  733         eventfd_t count;
  734         int error;
  735 
  736         efd = fp->f_data;
  737         if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
  738                 return (EBADF);
  739 
  740         if (uio->uio_resid < sizeof(eventfd_t))
  741                 return (EINVAL);
  742 
  743         error = uiomove(&count, sizeof(eventfd_t), uio);
  744         if (error)
  745                 return (error);
  746         if (count == UINT64_MAX)
  747                 return (EINVAL);
  748 
  749         mtx_lock(&efd->efd_lock);
  750 retry:
  751         if (UINT64_MAX - efd->efd_count <= count) {
  752                 if ((efd->efd_flags & LINUX_O_NONBLOCK) != 0) {
  753                         mtx_unlock(&efd->efd_lock);
  754                         /* Do not not return the number of bytes written */
  755                         uio->uio_resid += sizeof(eventfd_t);
  756                         return (EAGAIN);
  757                 }
  758                 error = mtx_sleep(&efd->efd_count, &efd->efd_lock,
  759                     PCATCH, "lefdwr", 0);
  760                 if (error == 0)
  761                         goto retry;
  762         }
  763         if (error == 0) {
  764                 efd->efd_count += count;
  765                 KNOTE_LOCKED(&efd->efd_sel.si_note, 0);
  766                 selwakeup(&efd->efd_sel);
  767                 wakeup(&efd->efd_count);
  768         }
  769         mtx_unlock(&efd->efd_lock);
  770 
  771         return (error);
  772 }
  773 
  774 static int
  775 eventfd_poll(struct file *fp, int events, struct ucred *active_cred,
  776         struct thread *td)
  777 {
  778         struct eventfd *efd;
  779         int revents = 0;
  780 
  781         efd = fp->f_data;
  782         if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
  783                 return (POLLERR);
  784 
  785         mtx_lock(&efd->efd_lock);
  786         if ((events & (POLLIN|POLLRDNORM)) && efd->efd_count > 0)
  787                 revents |= events & (POLLIN|POLLRDNORM);
  788         if ((events & (POLLOUT|POLLWRNORM)) && UINT64_MAX - 1 > efd->efd_count)
  789                 revents |= events & (POLLOUT|POLLWRNORM);
  790         if (revents == 0)
  791                 selrecord(td, &efd->efd_sel);
  792         mtx_unlock(&efd->efd_lock);
  793 
  794         return (revents);
  795 }
  796 
  797 /*ARGSUSED*/
  798 static int
  799 eventfd_kqfilter(struct file *fp, struct knote *kn)
  800 {
  801         struct eventfd *efd;
  802 
  803         efd = fp->f_data;
  804         if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
  805                 return (EINVAL);
  806 
  807         mtx_lock(&efd->efd_lock);
  808         switch (kn->kn_filter) {
  809         case EVFILT_READ:
  810                 kn->kn_fop = &eventfd_rfiltops;
  811                 break;
  812         case EVFILT_WRITE:
  813                 kn->kn_fop = &eventfd_wfiltops;
  814                 break;
  815         default:
  816                 mtx_unlock(&efd->efd_lock);
  817                 return (EINVAL);
  818         }
  819 
  820         kn->kn_hook = efd;
  821         knlist_add(&efd->efd_sel.si_note, kn, 1);
  822         mtx_unlock(&efd->efd_lock);
  823 
  824         return (0);
  825 }
  826 
  827 static void
  828 filt_eventfddetach(struct knote *kn)
  829 {
  830         struct eventfd *efd = kn->kn_hook;
  831 
  832         mtx_lock(&efd->efd_lock);
  833         knlist_remove(&efd->efd_sel.si_note, kn, 1);
  834         mtx_unlock(&efd->efd_lock);
  835 }
  836 
  837 /*ARGSUSED*/
  838 static int
  839 filt_eventfdread(struct knote *kn, long hint)
  840 {
  841         struct eventfd *efd = kn->kn_hook;
  842         int ret;
  843 
  844         mtx_assert(&efd->efd_lock, MA_OWNED);
  845         ret = (efd->efd_count > 0);
  846 
  847         return (ret);
  848 }
  849 
  850 /*ARGSUSED*/
  851 static int
  852 filt_eventfdwrite(struct knote *kn, long hint)
  853 {
  854         struct eventfd *efd = kn->kn_hook;
  855         int ret;
  856 
  857         mtx_assert(&efd->efd_lock, MA_OWNED);
  858         ret = (UINT64_MAX - 1 > efd->efd_count);
  859 
  860         return (ret);
  861 }
  862 
  863 /*ARGSUSED*/
  864 static int
  865 eventfd_truncate(struct file *fp, off_t length, struct ucred *active_cred,
  866         struct thread *td)
  867 {
  868 
  869         return (ENXIO);
  870 }
  871 
  872 /*ARGSUSED*/
  873 static int
  874 eventfd_ioctl(struct file *fp, u_long cmd, void *data,
  875         struct ucred *active_cred, struct thread *td)
  876 {
  877         struct eventfd *efd;
  878 
  879         efd = fp->f_data;
  880         if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
  881                 return (EINVAL);
  882 
  883         switch (cmd)
  884         {
  885         case FIONBIO:
  886                 if (*(int *)data)
  887                         efd->efd_flags |= LINUX_O_NONBLOCK;
  888                 else
  889                         efd->efd_flags &= ~LINUX_O_NONBLOCK;
  890         case FIOASYNC:
  891                 return (0);
  892         default:
  893                 return (ENXIO);
  894         }
  895 }
  896 
  897 /*ARGSUSED*/
  898 static int
  899 eventfd_stat(struct file *fp, struct stat *st, struct ucred *active_cred,
  900         struct thread *td)
  901 {
  902 
  903         return (ENXIO);
  904 }
  905 
  906 /*ARGSUSED*/
  907 static int
  908 eventfd_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
  909 {
  910 
  911         kif->kf_type = KF_TYPE_UNKNOWN;
  912         return (0);
  913 }

Cache object: 58823f6bf91909cb5a5d497fc806432e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.