• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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*
iolooper_new(void)22 iolooper_new(void)
23 {
24     IoLooper*  iol = qemu_malloc(sizeof(*iol));
25     iolooper_reset(iol);
26     return iol;
27 }
28 
29 void
iolooper_free(IoLooper * iol)30 iolooper_free( IoLooper*  iol )
31 {
32     qemu_free(iol);
33 }
34 
35 void
iolooper_reset(IoLooper * iol)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
iolooper_add_fd(IoLooper * iol,int fd)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
iolooper_del_fd(IoLooper * iol,int fd)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
iolooper_fd_count(IoLooper * iol)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
iolooper_add_read(IoLooper * iol,int fd)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
iolooper_add_write(IoLooper * iol,int fd)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
iolooper_del_read(IoLooper * iol,int fd)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
iolooper_del_write(IoLooper * iol,int fd)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
iolooper_poll(IoLooper * iol)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
iolooper_wait(IoLooper * iol,int64_t duration)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
iolooper_is_read(IoLooper * iol,int fd)167 iolooper_is_read( IoLooper*  iol, int  fd )
168 {
169     return FD_ISSET(fd, iol->reads_result);
170 }
171 
172 int
iolooper_is_write(IoLooper * iol,int fd)173 iolooper_is_write( IoLooper*  iol, int  fd )
174 {
175     return FD_ISSET(fd, iol->writes_result);
176 }
177