LCOV - code coverage report
Current view: top level - ipc/chromium/src/third_party/libevent - select.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 112 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $       */
       2             : 
       3             : /*
       4             :  * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
       5             :  * Copyright 2007-2012 Niels Provos and Nick Mathewson
       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             :  * 3. The name of the author may not be used to endorse or promote products
      16             :  *    derived from this software without specific prior written permission.
      17             :  *
      18             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      19             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      20             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      21             :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      22             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      23             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      24             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      25             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      26             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      27             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      28             :  */
      29             : #include "event2/event-config.h"
      30             : #include "evconfig-private.h"
      31             : 
      32             : #ifdef EVENT__HAVE_SELECT
      33             : 
      34             : #ifdef __APPLE__
      35             : /* Apple wants us to define this if we might ever pass more than
      36             :  * FD_SETSIZE bits to select(). */
      37             : #define _DARWIN_UNLIMITED_SELECT
      38             : #endif
      39             : 
      40             : #include <sys/types.h>
      41             : #ifdef EVENT__HAVE_SYS_TIME_H
      42             : #include <sys/time.h>
      43             : #endif
      44             : #ifdef EVENT__HAVE_SYS_SELECT_H
      45             : #include <sys/select.h>
      46             : #endif
      47             : #include <sys/queue.h>
      48             : #include <signal.h>
      49             : #include <stdio.h>
      50             : #include <stdlib.h>
      51             : #include <string.h>
      52             : #include <unistd.h>
      53             : #include <errno.h>
      54             : 
      55             : #include "event-internal.h"
      56             : #include "evsignal-internal.h"
      57             : #include "event2/thread.h"
      58             : #include "evthread-internal.h"
      59             : #include "log-internal.h"
      60             : #include "evmap-internal.h"
      61             : 
      62             : #ifndef EVENT__HAVE_FD_MASK
      63             : /* This type is mandatory, but Android doesn't define it. */
      64             : typedef unsigned long fd_mask;
      65             : #endif
      66             : 
      67             : #ifndef NFDBITS
      68             : #define NFDBITS (sizeof(fd_mask)*8)
      69             : #endif
      70             : 
      71             : /* Divide positive x by y, rounding up. */
      72             : #define DIV_ROUNDUP(x, y)   (((x)+((y)-1))/(y))
      73             : 
      74             : /* How many bytes to allocate for N fds? */
      75             : #define SELECT_ALLOC_SIZE(n) \
      76             :         (DIV_ROUNDUP(n, NFDBITS) * sizeof(fd_mask))
      77             : 
      78             : struct selectop {
      79             :         int event_fds;          /* Highest fd in fd set */
      80             :         int event_fdsz;
      81             :         int resize_out_sets;
      82             :         fd_set *event_readset_in;
      83             :         fd_set *event_writeset_in;
      84             :         fd_set *event_readset_out;
      85             :         fd_set *event_writeset_out;
      86             : };
      87             : 
      88             : static void *select_init(struct event_base *);
      89             : static int select_add(struct event_base *, int, short old, short events, void*);
      90             : static int select_del(struct event_base *, int, short old, short events, void*);
      91             : static int select_dispatch(struct event_base *, struct timeval *);
      92             : static void select_dealloc(struct event_base *);
      93             : 
      94             : const struct eventop selectops = {
      95             :         "select",
      96             :         select_init,
      97             :         select_add,
      98             :         select_del,
      99             :         select_dispatch,
     100             :         select_dealloc,
     101             :         0, /* doesn't need reinit. */
     102             :         EV_FEATURE_FDS,
     103             :         0,
     104             : };
     105             : 
     106             : static int select_resize(struct selectop *sop, int fdsz);
     107             : static void select_free_selectop(struct selectop *sop);
     108             : 
     109             : static void *
     110           0 : select_init(struct event_base *base)
     111             : {
     112             :         struct selectop *sop;
     113             : 
     114           0 :         if (!(sop = mm_calloc(1, sizeof(struct selectop))))
     115           0 :                 return (NULL);
     116             : 
     117           0 :         if (select_resize(sop, SELECT_ALLOC_SIZE(32 + 1))) {
     118           0 :                 select_free_selectop(sop);
     119           0 :                 return (NULL);
     120             :         }
     121             : 
     122           0 :         evsig_init_(base);
     123             : 
     124           0 :         evutil_weakrand_seed_(&base->weakrand_seed, 0);
     125             : 
     126           0 :         return (sop);
     127             : }
     128             : 
     129             : #ifdef CHECK_INVARIANTS
     130             : static void
     131             : check_selectop(struct selectop *sop)
     132             : {
     133             :         /* nothing to be done here */
     134             : }
     135             : #else
     136             : #define check_selectop(sop) do { (void) sop; } while (0)
     137             : #endif
     138             : 
     139             : static int
     140           0 : select_dispatch(struct event_base *base, struct timeval *tv)
     141             : {
     142           0 :         int res=0, i, j, nfds;
     143           0 :         struct selectop *sop = base->evbase;
     144             : 
     145             :         check_selectop(sop);
     146           0 :         if (sop->resize_out_sets) {
     147           0 :                 fd_set *readset_out=NULL, *writeset_out=NULL;
     148           0 :                 size_t sz = sop->event_fdsz;
     149           0 :                 if (!(readset_out = mm_realloc(sop->event_readset_out, sz)))
     150           0 :                         return (-1);
     151           0 :                 sop->event_readset_out = readset_out;
     152           0 :                 if (!(writeset_out = mm_realloc(sop->event_writeset_out, sz))) {
     153             :                         /* We don't free readset_out here, since it was
     154             :                          * already successfully reallocated. The next time
     155             :                          * we call select_dispatch, the realloc will be a
     156             :                          * no-op. */
     157           0 :                         return (-1);
     158             :                 }
     159           0 :                 sop->event_writeset_out = writeset_out;
     160           0 :                 sop->resize_out_sets = 0;
     161             :         }
     162             : 
     163           0 :         memcpy(sop->event_readset_out, sop->event_readset_in,
     164           0 :                sop->event_fdsz);
     165           0 :         memcpy(sop->event_writeset_out, sop->event_writeset_in,
     166           0 :                sop->event_fdsz);
     167             : 
     168           0 :         nfds = sop->event_fds+1;
     169             : 
     170           0 :         EVBASE_RELEASE_LOCK(base, th_base_lock);
     171             : 
     172           0 :         res = select(nfds, sop->event_readset_out,
     173             :             sop->event_writeset_out, NULL, tv);
     174             : 
     175           0 :         EVBASE_ACQUIRE_LOCK(base, th_base_lock);
     176             : 
     177             :         check_selectop(sop);
     178             : 
     179           0 :         if (res == -1) {
     180           0 :                 if (errno != EINTR) {
     181           0 :                         event_warn("select");
     182           0 :                         return (-1);
     183             :                 }
     184             : 
     185           0 :                 return (0);
     186             :         }
     187             : 
     188           0 :         event_debug(("%s: select reports %d", __func__, res));
     189             : 
     190             :         check_selectop(sop);
     191           0 :         i = evutil_weakrand_range_(&base->weakrand_seed, nfds);
     192           0 :         for (j = 0; j < nfds; ++j) {
     193           0 :                 if (++i >= nfds)
     194           0 :                         i = 0;
     195           0 :                 res = 0;
     196           0 :                 if (FD_ISSET(i, sop->event_readset_out))
     197           0 :                         res |= EV_READ;
     198           0 :                 if (FD_ISSET(i, sop->event_writeset_out))
     199           0 :                         res |= EV_WRITE;
     200             : 
     201           0 :                 if (res == 0)
     202           0 :                         continue;
     203             : 
     204           0 :                 evmap_io_active_(base, i, res);
     205             :         }
     206             :         check_selectop(sop);
     207             : 
     208           0 :         return (0);
     209             : }
     210             : 
     211             : static int
     212           0 : select_resize(struct selectop *sop, int fdsz)
     213             : {
     214           0 :         fd_set *readset_in = NULL;
     215           0 :         fd_set *writeset_in = NULL;
     216             : 
     217           0 :         if (sop->event_readset_in)
     218             :                 check_selectop(sop);
     219             : 
     220           0 :         if ((readset_in = mm_realloc(sop->event_readset_in, fdsz)) == NULL)
     221           0 :                 goto error;
     222           0 :         sop->event_readset_in = readset_in;
     223           0 :         if ((writeset_in = mm_realloc(sop->event_writeset_in, fdsz)) == NULL) {
     224             :                 /* Note that this will leave event_readset_in expanded.
     225             :                  * That's okay; we wouldn't want to free it, since that would
     226             :                  * change the semantics of select_resize from "expand the
     227             :                  * readset_in and writeset_in, or return -1" to "expand the
     228             :                  * *set_in members, or trash them and return -1."
     229             :                  */
     230           0 :                 goto error;
     231             :         }
     232           0 :         sop->event_writeset_in = writeset_in;
     233           0 :         sop->resize_out_sets = 1;
     234             : 
     235           0 :         memset((char *)sop->event_readset_in + sop->event_fdsz, 0,
     236           0 :             fdsz - sop->event_fdsz);
     237           0 :         memset((char *)sop->event_writeset_in + sop->event_fdsz, 0,
     238           0 :             fdsz - sop->event_fdsz);
     239             : 
     240           0 :         sop->event_fdsz = fdsz;
     241             :         check_selectop(sop);
     242             : 
     243           0 :         return (0);
     244             : 
     245             :  error:
     246           0 :         event_warn("malloc");
     247           0 :         return (-1);
     248             : }
     249             : 
     250             : 
     251             : static int
     252           0 : select_add(struct event_base *base, int fd, short old, short events, void *p)
     253             : {
     254           0 :         struct selectop *sop = base->evbase;
     255             :         (void) p;
     256             : 
     257           0 :         EVUTIL_ASSERT((events & EV_SIGNAL) == 0);
     258             :         check_selectop(sop);
     259             :         /*
     260             :          * Keep track of the highest fd, so that we can calculate the size
     261             :          * of the fd_sets for select(2)
     262             :          */
     263           0 :         if (sop->event_fds < fd) {
     264           0 :                 int fdsz = sop->event_fdsz;
     265             : 
     266           0 :                 if (fdsz < (int)sizeof(fd_mask))
     267           0 :                         fdsz = (int)sizeof(fd_mask);
     268             : 
     269             :                 /* In theory we should worry about overflow here.  In
     270             :                  * reality, though, the highest fd on a unixy system will
     271             :                  * not overflow here. XXXX */
     272           0 :                 while (fdsz < (int) SELECT_ALLOC_SIZE(fd + 1))
     273           0 :                         fdsz *= 2;
     274             : 
     275           0 :                 if (fdsz != sop->event_fdsz) {
     276           0 :                         if (select_resize(sop, fdsz)) {
     277             :                                 check_selectop(sop);
     278           0 :                                 return (-1);
     279             :                         }
     280             :                 }
     281             : 
     282           0 :                 sop->event_fds = fd;
     283             :         }
     284             : 
     285           0 :         if (events & EV_READ)
     286           0 :                 FD_SET(fd, sop->event_readset_in);
     287           0 :         if (events & EV_WRITE)
     288           0 :                 FD_SET(fd, sop->event_writeset_in);
     289             :         check_selectop(sop);
     290             : 
     291           0 :         return (0);
     292             : }
     293             : 
     294             : /*
     295             :  * Nothing to be done here.
     296             :  */
     297             : 
     298             : static int
     299           0 : select_del(struct event_base *base, int fd, short old, short events, void *p)
     300             : {
     301           0 :         struct selectop *sop = base->evbase;
     302             :         (void)p;
     303             : 
     304           0 :         EVUTIL_ASSERT((events & EV_SIGNAL) == 0);
     305             :         check_selectop(sop);
     306             : 
     307           0 :         if (sop->event_fds < fd) {
     308             :                 check_selectop(sop);
     309           0 :                 return (0);
     310             :         }
     311             : 
     312           0 :         if (events & EV_READ)
     313           0 :                 FD_CLR(fd, sop->event_readset_in);
     314             : 
     315           0 :         if (events & EV_WRITE)
     316           0 :                 FD_CLR(fd, sop->event_writeset_in);
     317             : 
     318             :         check_selectop(sop);
     319           0 :         return (0);
     320             : }
     321             : 
     322             : static void
     323           0 : select_free_selectop(struct selectop *sop)
     324             : {
     325           0 :         if (sop->event_readset_in)
     326           0 :                 mm_free(sop->event_readset_in);
     327           0 :         if (sop->event_writeset_in)
     328           0 :                 mm_free(sop->event_writeset_in);
     329           0 :         if (sop->event_readset_out)
     330           0 :                 mm_free(sop->event_readset_out);
     331           0 :         if (sop->event_writeset_out)
     332           0 :                 mm_free(sop->event_writeset_out);
     333             : 
     334           0 :         memset(sop, 0, sizeof(struct selectop));
     335           0 :         mm_free(sop);
     336           0 : }
     337             : 
     338             : static void
     339           0 : select_dealloc(struct event_base *base)
     340             : {
     341           0 :         evsig_dealloc_(base);
     342             : 
     343           0 :         select_free_selectop(base->evbase);
     344           0 : }
     345             : 
     346             : #endif /* EVENT__HAVE_SELECT */

Generated by: LCOV version 1.13