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