Home | History | Annotate | Download | only in qemu
      1 #include "iolooper.h"
      2 #include "qemu-common.h"
      3 
      4 /* An implementation of iolooper.h based on Unix select() */
      5 #ifdef _WIN32
      6 #  include <winsock2.h>
      7 #else
      8 #  include <sys/types.h>
      9 #  include <sys/select.h>
     10 #endif
     11 
     12 struct IoLooper {
     13     fd_set   reads[1];
     14     fd_set   writes[1];
     15     fd_set   reads_result[1];
     16     fd_set   writes_result[1];
     17     int      max_fd;
     18     int      max_fd_valid;
     19 };
     20 
     21 IoLooper*
     22 iolooper_new(void)
     23 {
     24     IoLooper*  iol = qemu_malloc(sizeof(*iol));
     25     iolooper_reset(iol);
     26     return iol;
     27 }
     28 
     29 void
     30 iolooper_free( IoLooper*  iol )
     31 {
     32     qemu_free(iol);
     33 }
     34 
     35 void
     36 iolooper_reset( IoLooper*  iol )
     37 {
     38     FD_ZERO(iol->reads);
     39     FD_ZERO(iol->writes);
     40     iol->max_fd = -1;
     41     iol->max_fd_valid = 1;
     42 }
     43 
     44 static void
     45 iolooper_add_fd( IoLooper*  iol, int fd )
     46 {
     47     if (iol->max_fd_valid && fd > iol->max_fd) {
     48         iol->max_fd = fd;
     49     }
     50 }
     51 
     52 static void
     53 iolooper_del_fd( IoLooper*  iol, int fd )
     54 {
     55     if (iol->max_fd_valid && fd == iol->max_fd)
     56         iol->max_fd_valid = 0;
     57 }
     58 
     59 static int
     60 iolooper_fd_count( IoLooper*  iol )
     61 {
     62     int  max_fd = iol->max_fd;
     63     int  fd;
     64 
     65     if (iol->max_fd_valid)
     66         return max_fd + 1;
     67 
     68     /* recompute max fd */
     69     for (fd = 0; fd < FD_SETSIZE; fd++) {
     70         if (!FD_ISSET(fd, iol->reads) && !FD_ISSET(fd, iol->writes))
     71             continue;
     72 
     73         max_fd = fd;
     74     }
     75     iol->max_fd       = max_fd;
     76     iol->max_fd_valid = 1;
     77 
     78     return max_fd + 1;
     79 }
     80 
     81 void
     82 iolooper_add_read( IoLooper*  iol, int  fd )
     83 {
     84     if (fd >= 0) {
     85         iolooper_add_fd(iol, fd);
     86         FD_SET(fd, iol->reads);
     87     }
     88 }
     89 
     90 void
     91 iolooper_add_write( IoLooper*  iol, int  fd )
     92 {
     93     if (fd >= 0) {
     94         iolooper_add_fd(iol, fd);
     95         FD_SET(fd, iol->writes);
     96     }
     97 }
     98 
     99 void
    100 iolooper_del_read( IoLooper*  iol, int  fd )
    101 {
    102     if (fd >= 0) {
    103         iolooper_del_fd(iol, fd);
    104         FD_CLR(fd, iol->reads);
    105     }
    106 }
    107 
    108 void
    109 iolooper_del_write( IoLooper*  iol, int  fd )
    110 {
    111     if (fd >= 0) {
    112         iolooper_del_fd(iol, fd);
    113         FD_CLR(fd, iol->reads);
    114     }
    115 }
    116 
    117 int
    118 iolooper_poll( IoLooper*  iol )
    119 {
    120     int     count = iolooper_fd_count(iol);
    121     int     ret;
    122     fd_set  errs;
    123 
    124     if (count == 0)
    125         return 0;
    126 
    127     FD_ZERO(&errs);
    128 
    129     do {
    130         struct timeval  tv;
    131 
    132         tv.tv_sec = tv.tv_usec = 0;
    133 
    134         iol->reads_result[0]  = iol->reads[0];
    135         iol->writes_result[0] = iol->writes[0];
    136 
    137         ret = select( count, iol->reads_result, iol->writes_result, &errs, &tv);
    138     } while (ret < 0 && errno == EINTR);
    139 
    140     return ret;
    141 }
    142 
    143 int
    144 iolooper_wait( IoLooper*  iol, int64_t  duration )
    145 {
    146     int     count = iolooper_fd_count(iol);
    147     int     ret;
    148     fd_set  errs;
    149 
    150     if (count == 0)
    151         return 0;
    152 
    153     FD_ZERO(&errs);
    154 
    155     do {
    156         iol->reads_result[0]  = iol->reads[0];
    157         iol->writes_result[0] = iol->writes[0];
    158 
    159         ret = select( count, iol->reads_result, iol->writes_result, &errs, NULL);
    160     } while (ret < 0 && errno == EINTR);
    161 
    162     return ret;
    163 }
    164 
    165 
    166 int
    167 iolooper_is_read( IoLooper*  iol, int  fd )
    168 {
    169     return FD_ISSET(fd, iol->reads_result);
    170 }
    171 
    172 int
    173 iolooper_is_write( IoLooper*  iol, int  fd )
    174 {
    175     return FD_ISSET(fd, iol->writes_result);
    176 }
    177