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