"Fossies" - the Fresh Open Source Software Archive

Member "minidlna-1.3.0/select.c" (24 Nov 2020, 4307 Bytes) of package /linux/privat/minidlna-1.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "select.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (c) 2017 Gleb Smirnoff <glebius@FreeBSD.org>
    3  * Copyright (c) 2002-2017 Igor Sysoev
    4  * Copyright (c) 2011-2017 Nginx, Inc.
    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 
   29 #include <sys/types.h>
   30 #include <sys/select.h>
   31 #include <stdlib.h>
   32 #include <assert.h>
   33 #include <errno.h>
   34 #include <stdio.h>
   35 #include <string.h>
   36 
   37 #include "event.h"
   38 #include "log.h"
   39 
   40 static event_module_init_t select_init;
   41 static event_module_fini_t select_fini;
   42 static event_module_add_t select_add;
   43 static event_module_del_t select_del;
   44 static event_module_process_t select_process;
   45 
   46 static fd_set master_read_fd_set;
   47 static fd_set master_write_fd_set;
   48 static fd_set work_read_fd_set;
   49 static fd_set work_write_fd_set;
   50 
   51 static struct event **events;
   52 static int nevents;
   53 static int max_fd;
   54 
   55 struct event_module event_module = {
   56     .add =      select_add,
   57     .del =      select_del,
   58     .process =  select_process,
   59     .init =     select_init,
   60     .fini =     select_fini,
   61 };
   62 
   63 static int
   64 select_init(void)
   65 {
   66 
   67     events = calloc(FD_SETSIZE, sizeof(struct event *));
   68     if (events == NULL)
   69         return (ENOMEM);
   70 
   71     FD_ZERO(&master_read_fd_set);
   72     FD_ZERO(&master_write_fd_set);
   73     max_fd = 0;
   74     nevents = 0;
   75 
   76     return (0);
   77 }
   78 
   79 
   80 static void
   81 select_fini(void)
   82 {
   83 
   84     free(events);
   85     events = NULL;
   86 }
   87 
   88 static int
   89 select_add(struct event *ev)
   90 {
   91 
   92     assert(ev->fd < FD_SETSIZE);
   93 
   94     switch (ev->rdwr) {
   95     case EVENT_READ:
   96         FD_SET(ev->fd, &master_read_fd_set);
   97         break;
   98     case EVENT_WRITE:
   99         FD_SET(ev->fd, &master_write_fd_set);
  100         break;
  101     }
  102 
  103     if (max_fd != -1 && max_fd < ev->fd)
  104         max_fd = ev->fd;
  105 
  106     events[nevents] = ev;
  107     ev->index = nevents++;
  108 
  109     assert(nevents < FD_SETSIZE);
  110 
  111     return (0);
  112 }
  113 
  114 static int
  115 select_del(struct event *ev, int flags)
  116 {
  117 
  118     assert(ev->fd < FD_SETSIZE);
  119 
  120     switch (ev->rdwr) {
  121     case EVENT_READ:
  122         FD_CLR(ev->fd, &master_read_fd_set);
  123         break;
  124     case EVENT_WRITE:
  125         FD_CLR(ev->fd, &master_write_fd_set);
  126         break;
  127     }
  128 
  129     if (max_fd == ev->fd)
  130         max_fd = -1;
  131 
  132     if (ev->index < --nevents) {
  133         struct event *ev0;
  134 
  135         ev0 = events[nevents];
  136         events[ev->index] = ev0;
  137         ev0->index = ev->index;
  138     }
  139     ev->index = -1;
  140 
  141     return (0);
  142 }
  143 
  144 static int
  145 select_process(u_long msec)
  146 {
  147     struct timeval tv, *tp;
  148     struct event *ev;
  149     int ready, i;
  150 
  151     /* Need to rescan for max_fd. */
  152     if (max_fd == -1)
  153         for (i = 0; i < nevents; i++) {
  154             if (max_fd < events[i]->fd)
  155                 max_fd = events[i]->fd;
  156         }
  157 
  158     tv.tv_sec = (long) (msec / 1000);
  159     tv.tv_usec = (long) ((msec % 1000) * 1000);
  160     tp = &tv;
  161 
  162     work_read_fd_set = master_read_fd_set;
  163     work_write_fd_set = master_write_fd_set;
  164 
  165     ready = select(max_fd + 1, &work_read_fd_set, &work_write_fd_set, NULL, tp);
  166 
  167     if (ready == -1) {
  168         if (errno == EINTR)
  169             return (errno);
  170         DPRINTF(E_FATAL, L_GENERAL, "select(): %s. EXITING\n", strerror(errno));
  171     }
  172 
  173     if (ready == 0)
  174         return (0);
  175 
  176     for (i = 0; i < nevents; i++) {
  177         ev = events[i];
  178 
  179         switch (ev->rdwr) {
  180         case EVENT_READ:
  181             if (FD_ISSET(ev->fd, &work_read_fd_set))
  182                 ev->process(ev);
  183             break;
  184         case EVENT_WRITE:
  185             if (FD_ISSET(ev->fd, &work_write_fd_set))
  186                 ev->process(ev);
  187             break;
  188         }
  189     }
  190 
  191     return (0);
  192 }