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

          Line data    Source code
       1             : /*      $OpenBSD: poll.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_POLL
      33             : 
      34             : #include <sys/types.h>
      35             : #ifdef EVENT__HAVE_SYS_TIME_H
      36             : #include <sys/time.h>
      37             : #endif
      38             : #include <sys/queue.h>
      39             : #include <poll.h>
      40             : #include <signal.h>
      41             : #include <limits.h>
      42             : #include <stdio.h>
      43             : #include <stdlib.h>
      44             : #include <string.h>
      45             : #include <unistd.h>
      46             : #include <errno.h>
      47             : 
      48             : #include "event-internal.h"
      49             : #include "evsignal-internal.h"
      50             : #include "log-internal.h"
      51             : #include "evmap-internal.h"
      52             : #include "event2/thread.h"
      53             : #include "evthread-internal.h"
      54             : #include "time-internal.h"
      55             : 
      56             : struct pollidx {
      57             :         int idxplus1;
      58             : };
      59             : 
      60             : struct pollop {
      61             :         int event_count;                /* Highest number alloc */
      62             :         int nfds;                       /* Highest number used */
      63             :         int realloc_copy;               /* True iff we must realloc
      64             :                                          * event_set_copy */
      65             :         struct pollfd *event_set;
      66             :         struct pollfd *event_set_copy;
      67             : };
      68             : 
      69             : static void *poll_init(struct event_base *);
      70             : static int poll_add(struct event_base *, int, short old, short events, void *idx);
      71             : static int poll_del(struct event_base *, int, short old, short events, void *idx);
      72             : static int poll_dispatch(struct event_base *, struct timeval *);
      73             : static void poll_dealloc(struct event_base *);
      74             : 
      75             : const struct eventop pollops = {
      76             :         "poll",
      77             :         poll_init,
      78             :         poll_add,
      79             :         poll_del,
      80             :         poll_dispatch,
      81             :         poll_dealloc,
      82             :         0, /* doesn't need_reinit */
      83             :         EV_FEATURE_FDS,
      84             :         sizeof(struct pollidx),
      85             : };
      86             : 
      87             : static void *
      88           0 : poll_init(struct event_base *base)
      89             : {
      90             :         struct pollop *pollop;
      91             : 
      92           0 :         if (!(pollop = mm_calloc(1, sizeof(struct pollop))))
      93           0 :                 return (NULL);
      94             : 
      95           0 :         evsig_init_(base);
      96             : 
      97           0 :         evutil_weakrand_seed_(&base->weakrand_seed, 0);
      98             : 
      99           0 :         return (pollop);
     100             : }
     101             : 
     102             : #ifdef CHECK_INVARIANTS
     103             : static void
     104             : poll_check_ok(struct pollop *pop)
     105             : {
     106             :         int i, idx;
     107             :         struct event *ev;
     108             : 
     109             :         for (i = 0; i < pop->fd_count; ++i) {
     110             :                 idx = pop->idxplus1_by_fd[i]-1;
     111             :                 if (idx < 0)
     112             :                         continue;
     113             :                 EVUTIL_ASSERT(pop->event_set[idx].fd == i);
     114             :         }
     115             :         for (i = 0; i < pop->nfds; ++i) {
     116             :                 struct pollfd *pfd = &pop->event_set[i];
     117             :                 EVUTIL_ASSERT(pop->idxplus1_by_fd[pfd->fd] == i+1);
     118             :         }
     119             : }
     120             : #else
     121             : #define poll_check_ok(pop)
     122             : #endif
     123             : 
     124             : static int
     125           0 : poll_dispatch(struct event_base *base, struct timeval *tv)
     126             : {
     127             :         int res, i, j, nfds;
     128           0 :         long msec = -1;
     129           0 :         struct pollop *pop = base->evbase;
     130             :         struct pollfd *event_set;
     131             : 
     132             :         poll_check_ok(pop);
     133             : 
     134           0 :         nfds = pop->nfds;
     135             : 
     136             : #ifndef EVENT__DISABLE_THREAD_SUPPORT
     137           0 :         if (base->th_base_lock) {
     138             :                 /* If we're using this backend in a multithreaded setting,
     139             :                  * then we need to work on a copy of event_set, so that we can
     140             :                  * let other threads modify the main event_set while we're
     141             :                  * polling. If we're not multithreaded, then we'll skip the
     142             :                  * copy step here to save memory and time. */
     143           0 :                 if (pop->realloc_copy) {
     144           0 :                         struct pollfd *tmp = mm_realloc(pop->event_set_copy,
     145             :                             pop->event_count * sizeof(struct pollfd));
     146           0 :                         if (tmp == NULL) {
     147           0 :                                 event_warn("realloc");
     148           0 :                                 return -1;
     149             :                         }
     150           0 :                         pop->event_set_copy = tmp;
     151           0 :                         pop->realloc_copy = 0;
     152             :                 }
     153           0 :                 memcpy(pop->event_set_copy, pop->event_set,
     154             :                     sizeof(struct pollfd)*nfds);
     155           0 :                 event_set = pop->event_set_copy;
     156             :         } else {
     157           0 :                 event_set = pop->event_set;
     158             :         }
     159             : #else
     160             :         event_set = pop->event_set;
     161             : #endif
     162             : 
     163           0 :         if (tv != NULL) {
     164           0 :                 msec = evutil_tv_to_msec_(tv);
     165           0 :                 if (msec < 0 || msec > INT_MAX)
     166           0 :                         msec = INT_MAX;
     167             :         }
     168             : 
     169           0 :         EVBASE_RELEASE_LOCK(base, th_base_lock);
     170             : 
     171           0 :         res = poll(event_set, nfds, msec);
     172             : 
     173           0 :         EVBASE_ACQUIRE_LOCK(base, th_base_lock);
     174             : 
     175           0 :         if (res == -1) {
     176           0 :                 if (errno != EINTR) {
     177           0 :                         event_warn("poll");
     178           0 :                         return (-1);
     179             :                 }
     180             : 
     181           0 :                 return (0);
     182             :         }
     183             : 
     184           0 :         event_debug(("%s: poll reports %d", __func__, res));
     185             : 
     186           0 :         if (res == 0 || nfds == 0)
     187           0 :                 return (0);
     188             : 
     189           0 :         i = evutil_weakrand_range_(&base->weakrand_seed, nfds);
     190           0 :         for (j = 0; j < nfds; j++) {
     191             :                 int what;
     192           0 :                 if (++i == nfds)
     193           0 :                         i = 0;
     194           0 :                 what = event_set[i].revents;
     195           0 :                 if (!what)
     196           0 :                         continue;
     197             : 
     198           0 :                 res = 0;
     199             : 
     200             :                 /* If the file gets closed notify */
     201           0 :                 if (what & (POLLHUP|POLLERR|POLLNVAL))
     202           0 :                         what |= POLLIN|POLLOUT;
     203           0 :                 if (what & POLLIN)
     204           0 :                         res |= EV_READ;
     205           0 :                 if (what & POLLOUT)
     206           0 :                         res |= EV_WRITE;
     207           0 :                 if (res == 0)
     208           0 :                         continue;
     209             : 
     210           0 :                 evmap_io_active_(base, event_set[i].fd, res);
     211             :         }
     212             : 
     213           0 :         return (0);
     214             : }
     215             : 
     216             : static int
     217           0 : poll_add(struct event_base *base, int fd, short old, short events, void *idx_)
     218             : {
     219           0 :         struct pollop *pop = base->evbase;
     220           0 :         struct pollfd *pfd = NULL;
     221           0 :         struct pollidx *idx = idx_;
     222             :         int i;
     223             : 
     224           0 :         EVUTIL_ASSERT((events & EV_SIGNAL) == 0);
     225           0 :         if (!(events & (EV_READ|EV_WRITE)))
     226           0 :                 return (0);
     227             : 
     228             :         poll_check_ok(pop);
     229           0 :         if (pop->nfds + 1 >= pop->event_count) {
     230             :                 struct pollfd *tmp_event_set;
     231             :                 int tmp_event_count;
     232             : 
     233           0 :                 if (pop->event_count < 32)
     234           0 :                         tmp_event_count = 32;
     235             :                 else
     236           0 :                         tmp_event_count = pop->event_count * 2;
     237             : 
     238             :                 /* We need more file descriptors */
     239           0 :                 tmp_event_set = mm_realloc(pop->event_set,
     240             :                                  tmp_event_count * sizeof(struct pollfd));
     241           0 :                 if (tmp_event_set == NULL) {
     242           0 :                         event_warn("realloc");
     243           0 :                         return (-1);
     244             :                 }
     245           0 :                 pop->event_set = tmp_event_set;
     246             : 
     247           0 :                 pop->event_count = tmp_event_count;
     248           0 :                 pop->realloc_copy = 1;
     249             :         }
     250             : 
     251           0 :         i = idx->idxplus1 - 1;
     252             : 
     253           0 :         if (i >= 0) {
     254           0 :                 pfd = &pop->event_set[i];
     255             :         } else {
     256           0 :                 i = pop->nfds++;
     257           0 :                 pfd = &pop->event_set[i];
     258           0 :                 pfd->events = 0;
     259           0 :                 pfd->fd = fd;
     260           0 :                 idx->idxplus1 = i + 1;
     261             :         }
     262             : 
     263           0 :         pfd->revents = 0;
     264           0 :         if (events & EV_WRITE)
     265           0 :                 pfd->events |= POLLOUT;
     266           0 :         if (events & EV_READ)
     267           0 :                 pfd->events |= POLLIN;
     268             :         poll_check_ok(pop);
     269             : 
     270           0 :         return (0);
     271             : }
     272             : 
     273             : /*
     274             :  * Nothing to be done here.
     275             :  */
     276             : 
     277             : static int
     278           0 : poll_del(struct event_base *base, int fd, short old, short events, void *idx_)
     279             : {
     280           0 :         struct pollop *pop = base->evbase;
     281           0 :         struct pollfd *pfd = NULL;
     282           0 :         struct pollidx *idx = idx_;
     283             :         int i;
     284             : 
     285           0 :         EVUTIL_ASSERT((events & EV_SIGNAL) == 0);
     286           0 :         if (!(events & (EV_READ|EV_WRITE)))
     287           0 :                 return (0);
     288             : 
     289             :         poll_check_ok(pop);
     290           0 :         i = idx->idxplus1 - 1;
     291           0 :         if (i < 0)
     292           0 :                 return (-1);
     293             : 
     294             :         /* Do we still want to read or write? */
     295           0 :         pfd = &pop->event_set[i];
     296           0 :         if (events & EV_READ)
     297           0 :                 pfd->events &= ~POLLIN;
     298           0 :         if (events & EV_WRITE)
     299           0 :                 pfd->events &= ~POLLOUT;
     300             :         poll_check_ok(pop);
     301           0 :         if (pfd->events)
     302             :                 /* Another event cares about that fd. */
     303           0 :                 return (0);
     304             : 
     305             :         /* Okay, so we aren't interested in that fd anymore. */
     306           0 :         idx->idxplus1 = 0;
     307             : 
     308           0 :         --pop->nfds;
     309           0 :         if (i != pop->nfds) {
     310             :                 /*
     311             :                  * Shift the last pollfd down into the now-unoccupied
     312             :                  * position.
     313             :                  */
     314           0 :                 memcpy(&pop->event_set[i], &pop->event_set[pop->nfds],
     315             :                        sizeof(struct pollfd));
     316           0 :                 idx = evmap_io_get_fdinfo_(&base->io, pop->event_set[i].fd);
     317           0 :                 EVUTIL_ASSERT(idx);
     318           0 :                 EVUTIL_ASSERT(idx->idxplus1 == pop->nfds + 1);
     319           0 :                 idx->idxplus1 = i + 1;
     320             :         }
     321             : 
     322             :         poll_check_ok(pop);
     323           0 :         return (0);
     324             : }
     325             : 
     326             : static void
     327           0 : poll_dealloc(struct event_base *base)
     328             : {
     329           0 :         struct pollop *pop = base->evbase;
     330             : 
     331           0 :         evsig_dealloc_(base);
     332           0 :         if (pop->event_set)
     333           0 :                 mm_free(pop->event_set);
     334           0 :         if (pop->event_set_copy)
     335           0 :                 mm_free(pop->event_set_copy);
     336             : 
     337           0 :         memset(pop, 0, sizeof(struct pollop));
     338           0 :         mm_free(pop);
     339           0 : }
     340             : 
     341             : #endif /* EVENT__HAVE_POLL */

Generated by: LCOV version 1.13