iolooper-select.c revision 9a33e8554225c82cd900208f88e8965bb085ab87
15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "iolooper.h" 25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h" 35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* An implementation of iolooper.h based on Unix select() */ 55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32 65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# include <winsock2.h> 75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# include <sys/types.h> 95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# include <sys/select.h> 105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct IoLooper { 135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd_set reads[1]; 145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd_set writes[1]; 155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd_set reads_result[1]; 165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd_set writes_result[1]; 175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int max_fd; 185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int max_fd_valid; 195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}; 205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerIoLooper* 225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneriolooper_new(void) 235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 249a33e8554225c82cd900208f88e8965bb085ab87Vladimir Chtchetkine IoLooper* iol = malloc(sizeof(*iol)); 255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iolooper_reset(iol); 265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return iol; 275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid 305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneriolooper_free( IoLooper* iol ) 315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 329a33e8554225c82cd900208f88e8965bb085ab87Vladimir Chtchetkine free(iol); 335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid 365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneriolooper_reset( IoLooper* iol ) 375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_ZERO(iol->reads); 395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_ZERO(iol->writes); 405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iol->max_fd = -1; 415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iol->max_fd_valid = 1; 425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneriolooper_add_fd( IoLooper* iol, int fd ) 465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (iol->max_fd_valid && fd > iol->max_fd) { 485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iol->max_fd = fd; 495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneriolooper_del_fd( IoLooper* iol, int fd ) 545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (iol->max_fd_valid && fd == iol->max_fd) 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iol->max_fd_valid = 0; 575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int 605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneriolooper_fd_count( IoLooper* iol ) 615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int max_fd = iol->max_fd; 635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (iol->max_fd_valid) 665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return max_fd + 1; 675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* recompute max fd */ 695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (fd = 0; fd < FD_SETSIZE; fd++) { 705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!FD_ISSET(fd, iol->reads) && !FD_ISSET(fd, iol->writes)) 715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner max_fd = fd; 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iol->max_fd = max_fd; 765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iol->max_fd_valid = 1; 775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return max_fd + 1; 795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid 825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneriolooper_add_read( IoLooper* iol, int fd ) 835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd >= 0) { 855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iolooper_add_fd(iol, fd); 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_SET(fd, iol->reads); 875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneriolooper_add_write( IoLooper* iol, int fd ) 925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd >= 0) { 945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iolooper_add_fd(iol, fd); 955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_SET(fd, iol->writes); 965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid 1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneriolooper_del_read( IoLooper* iol, int fd ) 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd >= 0) { 1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iolooper_del_fd(iol, fd); 1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_CLR(fd, iol->reads); 1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid 1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneriolooper_del_write( IoLooper* iol, int fd ) 1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd >= 0) { 1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iolooper_del_fd(iol, fd); 1139a33e8554225c82cd900208f88e8965bb085ab87Vladimir Chtchetkine FD_CLR(fd, iol->writes); 1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint 1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneriolooper_poll( IoLooper* iol ) 1195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int count = iolooper_fd_count(iol); 1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd_set errs; 1235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (count == 0) 1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_ZERO(&errs); 1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner do { 1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct timeval tv; 1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tv.tv_sec = tv.tv_usec = 0; 1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iol->reads_result[0] = iol->reads[0]; 1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iol->writes_result[0] = iol->writes[0]; 1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = select( count, iol->reads_result, iol->writes_result, &errs, &tv); 1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } while (ret < 0 && errno == EINTR); 1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret; 1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint 1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneriolooper_wait( IoLooper* iol, int64_t duration ) 1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int count = iolooper_fd_count(iol); 1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd_set errs; 1499b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner struct timeval tm0, *tm = NULL; 1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (count == 0) 1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1549b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner if (duration < 0) 1559b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner tm = NULL; 1569b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner else { 1579b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner tm = &tm0; 1589b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner tm->tv_sec = duration / 1000; 1599b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner tm->tv_usec = (duration - 1000*tm->tv_sec) * 1000; 1609b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner } 1619b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner 1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_ZERO(&errs); 1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner do { 1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iol->reads_result[0] = iol->reads[0]; 1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iol->writes_result[0] = iol->writes[0]; 1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1689b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner ret = select( count, iol->reads_result, iol->writes_result, &errs, tm); 1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } while (ret < 0 && errno == EINTR); 1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret; 1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint 1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneriolooper_is_read( IoLooper* iol, int fd ) 1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return FD_ISSET(fd, iol->reads_result); 1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint 1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneriolooper_is_write( IoLooper* iol, int fd ) 1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return FD_ISSET(fd, iol->writes_result); 1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 186cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thije 187cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thijeint 188cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thijeiolooper_has_operations( IoLooper* iol ) 189cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thije{ 190cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thije return iolooper_fd_count(iol) > 0; 191cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thije} 192