From 03ad5eab59f7ca51099d7ccc60b27effc4d42383 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 12 May 2013 17:21:22 +0200 Subject: Use _DARWIN_UNLIMITED_SELECT in erl_poll This allows erl_poll to select() on file descriptors greater than FD_SETSIZE (1024) on Darwin. The fd sets are manually (re)allocated and freed. --- erts/emulator/beam/erl_alloc.types | 1 + erts/emulator/sys/common/erl_poll.c | 129 +++++++++++++++++++++++++++++++++--- erts/emulator/test/port_SUITE.erl | 2 +- 3 files changed, 120 insertions(+), 12 deletions(-) (limited to 'erts') diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types index 5e3615ccc2..a9cd779e1c 100644 --- a/erts/emulator/beam/erl_alloc.types +++ b/erts/emulator/beam/erl_alloc.types @@ -401,6 +401,7 @@ type POLLSET_UPDREQ SHORT_LIVED SYSTEM pollset_update_req type POLL_FDS LONG_LIVED SYSTEM poll_fds type POLL_RES_EVS LONG_LIVED SYSTEM poll_result_events type FD_STATUS LONG_LIVED SYSTEM fd_status +type SELECT_FDS LONG_LIVED SYSTEM select_fds +if unix diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c index a523d67158..556e8d05ad 100644 --- a/erts/emulator/sys/common/erl_poll.c +++ b/erts/emulator/sys/common/erl_poll.c @@ -40,6 +40,10 @@ # include "config.h" #endif +#if defined(__DARWIN__) || defined(__APPLE__) && defined(__MACH__) +# define _DARWIN_UNLIMITED_SELECT +#endif + #ifndef WANT_NONBLOCKING # define WANT_NONBLOCKING #endif @@ -90,6 +94,19 @@ #define HARD_DEBUG #endif +#ifdef _DARWIN_UNLIMITED_SELECT +# define FDS fd_set * +# define FDS_CLR FD_CLR +# define FDS_ISSET FD_ISSET +# define FDS_SET FD_SET +# define FDS_SIZE(n) ((((n)+NFDBITS-1)/NFDBITS)*sizeof(fd_mask)) +#else +# define FDS fd_set +# define FDS_CLR(fd, fds) FD_CLR((fd), &(fds)) +# define FDS_ISSET(fd, fds) FD_ISSET((fd), &(fds)) +# define FDS_SET(fd, fds) FD_SET((fd), &(fds)) +#endif + #define ERTS_POLL_USE_BATCH_UPDATE_POLLSET (ERTS_POLL_USE_DEVPOLL \ || ERTS_POLL_USE_KQUEUE) #define ERTS_POLL_USE_UPDATE_REQUESTS_QUEUE \ @@ -244,10 +261,14 @@ struct ErtsPollSet_ { #if ERTS_POLL_USE_FALLBACK int no_select_fds; #endif - fd_set input_fds; - fd_set res_input_fds; - fd_set output_fds; - fd_set res_output_fds; +#ifdef _DARWIN_UNLIMITED_SELECT + size_t select_fds_len; + char resize_res_sets; +#endif + FDS input_fds; + FDS res_input_fds; + FDS output_fds; + FDS res_output_fds; #endif #if ERTS_POLL_USE_UPDATE_REQUESTS_QUEUE ErtsPollSetUpdateRequestsBlock update_requests; @@ -624,6 +645,29 @@ grow_poll_fds(ErtsPollSet ps, int min_ix) } #endif +#ifdef _DARWIN_UNLIMITED_SELECT +static void +grow_select_fds(ErtsPollSet ps, int fd) +{ + int new_len = ERTS_POLL_EXPORT(erts_poll_get_table_len)(fd + 1); + if (new_len > max_fds) + new_len = max_fds; + new_len = FDS_SIZE(new_len); + ps->input_fds = ps->select_fds_len + ? erts_realloc(ERTS_ALC_T_SELECT_FDS, ps->input_fds, new_len) + : erts_alloc(ERTS_ALC_T_SELECT_FDS, new_len); + ps->output_fds = ps->select_fds_len + ? erts_realloc(ERTS_ALC_T_SELECT_FDS, ps->output_fds, new_len) + : erts_alloc(ERTS_ALC_T_SELECT_FDS, new_len); + memset((void *) ps->input_fds + ps->select_fds_len, 0, + new_len - ps->select_fds_len); + memset((void *) ps->output_fds + ps->select_fds_len, 0, + new_len - ps->select_fds_len); + ps->select_fds_len = new_len; + ps->resize_res_sets = 1; +} +#endif /* _DARWIN_UNLIMITED_SELECT */ + static void grow_fds_status(ErtsPollSet ps, int min_fd) { @@ -1290,22 +1334,26 @@ static int update_pollset(ErtsPollSet ps, int fd) #elif ERTS_POLL_USE_SELECT /* --- select ------------------------------ */ { ErtsPollEvents events = ps->fds_status[fd].events; +#ifdef _DARWIN_UNLIMITED_SELECT + if (FDS_SIZE(fd) > ps->select_fds_len) + grow_select_fds(ps, fd); +#endif if ((ERTS_POLL_EV_IN & events) != (ERTS_POLL_EV_IN & ps->fds_status[fd].used_events)) { if (ERTS_POLL_EV_IN & events) { - FD_SET(fd, &ps->input_fds); + FDS_SET(fd, ps->input_fds); } else { - FD_CLR(fd, &ps->input_fds); + FDS_CLR(fd, ps->input_fds); } } if ((ERTS_POLL_EV_OUT & events) != (ERTS_POLL_EV_OUT & ps->fds_status[fd].used_events)) { if (ERTS_POLL_EV_OUT & events) { - FD_SET(fd, &ps->output_fds); + FDS_SET(fd, ps->output_fds); } else { - FD_CLR(fd, &ps->output_fds); + FDS_CLR(fd, ps->output_fds); } } @@ -1789,7 +1837,7 @@ save_poll_result(ErtsPollSet ps, ErtsPollResFd pr[], int max_res, while (fd < end_fd && res < max_res) { pr[res].events = (ErtsPollEvents) 0; - if (FD_ISSET(fd, &ps->res_input_fds)) { + if (FDS_ISSET(fd, ps->res_input_fds)) { #if ERTS_POLL_USE_FALLBACK if (fd == ps->kp_fd) { res += get_kp_results(ps, &pr[res], max_res-res); @@ -1805,7 +1853,7 @@ save_poll_result(ErtsPollSet ps, ErtsPollResFd pr[], int max_res, #endif pr[res].events |= ERTS_POLL_EV_IN; } - if (FD_ISSET(fd, &ps->res_output_fds)) + if (FDS_ISSET(fd, ps->res_output_fds)) pr[res].events |= ERTS_POLL_EV_OUT; if (pr[res].events) { pr[res].fd = fd; @@ -1835,13 +1883,23 @@ save_poll_result(ErtsPollSet ps, ErtsPollResFd pr[], int max_res, fd_set *iset = NULL; fd_set *oset = NULL; if (ps->fds_status[fd].events & ERTS_POLL_EV_IN) { +#ifdef _DARWIN_UNLIMITED_SELECT + iset = ps->res_input_fds; + memset((void *) iset, 0, ps->select_fds_len); +#else iset = &ps->res_input_fds; FD_ZERO(iset); +#endif FD_SET(fd, iset); } if (ps->fds_status[fd].events & ERTS_POLL_EV_OUT) { +#ifdef _DARWIN_UNLIMITED_SELECT + oset = ps->res_output_fds; + memset((char *)oset, 0, ps->select_fds_len); +#else oset = &ps->res_output_fds; FD_ZERO(oset); +#endif FD_SET(fd, oset); } @@ -1992,16 +2050,37 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res) #elif ERTS_POLL_USE_SELECT /* --- select ------------------------------ */ SysTimeval to = *tv; +#ifdef _DARWIN_UNLIMITED_SELECT + if (ps->resize_res_sets) { + ps->res_input_fds = ps->res_input_fds + ? erts_realloc(ERTS_ALC_T_SELECT_FDS, ps->res_input_fds, + ps->select_fds_len) + : erts_alloc(ERTS_ALC_T_SELECT_FDS, ps->select_fds_len); + ps->res_output_fds = ps->res_output_fds + ? erts_realloc(ERTS_ALC_T_SELECT_FDS, ps->res_output_fds, + ps->select_fds_len) + : erts_alloc(ERTS_ALC_T_SELECT_FDS, ps->select_fds_len); + ps->resize_res_sets = 0; + } + memcpy(ps->res_input_fds, ps->input_fds, ps->select_fds_len); + memcpy(ps->res_output_fds, ps->output_fds, ps->select_fds_len); +#else ps->res_input_fds = ps->input_fds; ps->res_output_fds = ps->output_fds; +#endif #ifdef ERTS_SMP if (to.tv_sec || to.tv_usec) erts_thr_progress_prepare_wait(NULL); #endif res = select(ps->max_fd + 1, +#ifdef _DARWIN_UNLIMITED_SELECT + ps->res_input_fds, + ps->res_output_fds, +#else &ps->res_input_fds, &ps->res_output_fds, +#endif NULL, &to); #ifdef ERTS_SMP @@ -2028,8 +2107,13 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res) handle_update_requests(ps); ERTS_POLLSET_UNLOCK(ps); res = select(ps->max_fd + 1, +#ifdef _DARWIN_UNLIMITED_SELECT + ps->res_input_fds, + ps->res_output_fds, +#else &ps->res_input_fds, &ps->res_output_fds, +#endif NULL, &to); if (res == 0) { @@ -2233,7 +2317,8 @@ ERTS_POLL_EXPORT(erts_poll_init)(void) max_fds = OPEN_MAX; #endif -#if ERTS_POLL_USE_SELECT && defined(FD_SETSIZE) +#if ERTS_POLL_USE_SELECT && defined(FD_SETSIZE) && \ + !defined(_DARWIN_UNLIMITED_SELECT) if (max_fds > FD_SETSIZE) max_fds = FD_SETSIZE; #endif @@ -2301,11 +2386,20 @@ ERTS_POLL_EXPORT(erts_poll_create_pollset)(void) #if ERTS_POLL_USE_FALLBACK ps->no_select_fds = 0; #endif +#ifdef _DARWIN_UNLIMITED_SELECT + ps->select_fds_len = 0; + ps->resize_res_sets = 0; + ps->input_fds = NULL; + ps->res_input_fds = NULL; + ps->output_fds = NULL; + ps->res_output_fds = NULL; +#else FD_ZERO(&ps->input_fds); FD_ZERO(&ps->res_input_fds); FD_ZERO(&ps->output_fds); FD_ZERO(&ps->res_output_fds); #endif +#endif #if ERTS_POLL_USE_UPDATE_REQUESTS_QUEUE ps->update_requests.next = NULL; ps->update_requests.len = 0; @@ -2382,6 +2476,16 @@ ERTS_POLL_EXPORT(erts_poll_destroy_pollset)(ErtsPollSet ps) if (ps->poll_fds) erts_free(ERTS_ALC_T_POLL_FDS, (void *) ps->poll_fds); #elif ERTS_POLL_USE_SELECT +#ifdef _DARWIN_UNLIMITED_SELECT + if (ps->input_fds) + erts_free(ERTS_ALC_T_SELECT_FDS, (void *) ps->input_fds); + if (ps->res_input_fds) + erts_free(ERTS_ALC_T_SELECT_FDS, (void *) ps->res_input_fds); + if (ps->output_fds) + erts_free(ERTS_ALC_T_SELECT_FDS, (void *) ps->output_fds); + if (ps->res_output_fds) + erts_free(ERTS_ALC_T_SELECT_FDS, (void *) ps->res_output_fds); +#endif #endif #if ERTS_POLL_USE_UPDATE_REQUESTS_QUEUE { @@ -2445,6 +2549,9 @@ ERTS_POLL_EXPORT(erts_poll_info)(ErtsPollSet ps, ErtsPollInfo *pip) #if ERTS_POLL_USE_POLL size += ps->poll_fds_len*sizeof(struct pollfd); #elif ERTS_POLL_USE_SELECT +#ifdef _DARWIN_UNLIMITED_SELECT + size += ps->select_fds_len*4; +#endif #endif #if ERTS_POLL_USE_UPDATE_REQUESTS_QUEUE diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index 13aa0f4c00..4dd14877d5 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -628,7 +628,7 @@ iter_max_ports(Config) when is_list(Config) -> iter_max_ports_test(Config) -> - Dog = test_server:timetrap(test_server:minutes(20)), + Dog = test_server:timetrap(test_server:minutes(30)), PortTest = port_test(Config), Command = lists:concat([PortTest, " -h0 -q"]), Iters = case os:type() of -- cgit v1.2.3 From 32636da1c247fa350dc5331a8d9a3f43acf7fd08 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 28 May 2013 18:12:18 +0200 Subject: erts: Fix bug in unlimited fd_set patch --- erts/emulator/sys/common/erl_poll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts') diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c index 556e8d05ad..dffcf68df5 100644 --- a/erts/emulator/sys/common/erl_poll.c +++ b/erts/emulator/sys/common/erl_poll.c @@ -1335,7 +1335,7 @@ static int update_pollset(ErtsPollSet ps, int fd) { ErtsPollEvents events = ps->fds_status[fd].events; #ifdef _DARWIN_UNLIMITED_SELECT - if (FDS_SIZE(fd) > ps->select_fds_len) + if (FDS_SIZE(fd+1) > ps->select_fds_len) grow_select_fds(ps, fd); #endif if ((ERTS_POLL_EV_IN & events) -- cgit v1.2.3 From 5934be514bbc5118d2e8e2956e1abcd55dc72a74 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 28 May 2013 16:11:45 +0200 Subject: erts: Refactor unlimited select patch An attempt to beautify the code by reducing the amount of #ifdef's in the hot code path. --- erts/emulator/sys/common/erl_poll.c | 212 +++++++++++++++++------------------- 1 file changed, 101 insertions(+), 111 deletions(-) (limited to 'erts') diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c index dffcf68df5..37512bcb50 100644 --- a/erts/emulator/sys/common/erl_poll.c +++ b/erts/emulator/sys/common/erl_poll.c @@ -41,6 +41,9 @@ #endif #if defined(__DARWIN__) || defined(__APPLE__) && defined(__MACH__) +/* Setting _DARWIN_UNLIMITED_SELECT before including sys/select.h enables + * the version of select() that does not place a limit on the fd_set. + */ # define _DARWIN_UNLIMITED_SELECT #endif @@ -95,16 +98,46 @@ #endif #ifdef _DARWIN_UNLIMITED_SELECT -# define FDS fd_set * -# define FDS_CLR FD_CLR -# define FDS_ISSET FD_ISSET -# define FDS_SET FD_SET -# define FDS_SIZE(n) ((((n)+NFDBITS-1)/NFDBITS)*sizeof(fd_mask)) -#else -# define FDS fd_set -# define FDS_CLR(fd, fds) FD_CLR((fd), &(fds)) -# define FDS_ISSET(fd, fds) FD_ISSET((fd), &(fds)) -# define FDS_SET(fd, fds) FD_SET((fd), &(fds)) +typedef struct { + size_t sz; + fd_set* ptr; +}ERTS_fd_set; +# define ERTS_FD_CLR(fd, fds) do { ensure_select_fds((fd),(fds)); FD_CLR((fd), (fds)->ptr); }while(0) +# define ERTS_FD_SET(fd, fds) do { ensure_select_fds((fd),(fds)); FD_SET((fd), (fds)->ptr); }while(0) +# define ERTS_FD_ISSET(fd,fds) FD_ISSET((fd), (fds)->ptr) +# define ERTS_FD_ZERO(fds) memset((fds)->ptr, 0, (fds)->sz) +# define ERTS_FD_SIZE(n) ((((n)+NFDBITS-1)/NFDBITS)*sizeof(fd_mask)) + +static void ERTS_FD_COPY(ERTS_fd_set *src, ERTS_fd_set *dst) +{ + if (dst->sz != src->sz) { + dst->ptr = dst->ptr + ? erts_realloc(ERTS_ALC_T_SELECT_FDS, dst->ptr, src->sz) + : erts_alloc(ERTS_ALC_T_SELECT_FDS, src->sz); + dst->sz = src->sz; + } + memcpy(dst->ptr, src->ptr, src->sz); +} + +static ERTS_INLINE +int ERTS_SELECT(int nfds, ERTS_fd_set *readfds, ERTS_fd_set *writefds, + ERTS_fd_set *exceptfds, struct timeval *timeout) +{ + return select(nfds, + (readfds ? readfds->ptr : NULL ), + (writefds ? writefds->ptr : NULL), + (exceptfds ? exceptfds->ptr : NULL), + timeout); +} + +#else /* !_DARWIN_UNLIMITED_SELECT */ +# define ERTS_fd_set fd_set +# define ERTS_FD_CLR FD_CLR +# define ERTS_FD_ISSET FD_ISSET +# define ERTS_FD_SET FD_SET +# define ERTS_FD_ZERO FD_ZERO +# define ERTS_FD_COPY(src,dst) (*(dst) = *(src)) +# define ERTS_SELECT select #endif #define ERTS_POLL_USE_BATCH_UPDATE_POLLSET (ERTS_POLL_USE_DEVPOLL \ @@ -261,14 +294,10 @@ struct ErtsPollSet_ { #if ERTS_POLL_USE_FALLBACK int no_select_fds; #endif -#ifdef _DARWIN_UNLIMITED_SELECT - size_t select_fds_len; - char resize_res_sets; -#endif - FDS input_fds; - FDS res_input_fds; - FDS output_fds; - FDS res_output_fds; + ERTS_fd_set input_fds; + ERTS_fd_set res_input_fds; + ERTS_fd_set output_fds; + ERTS_fd_set res_output_fds; #endif #if ERTS_POLL_USE_UPDATE_REQUESTS_QUEUE ErtsPollSetUpdateRequestsBlock update_requests; @@ -647,24 +676,23 @@ grow_poll_fds(ErtsPollSet ps, int min_ix) #ifdef _DARWIN_UNLIMITED_SELECT static void -grow_select_fds(ErtsPollSet ps, int fd) +grow_select_fds(int fd, ERTS_fd_set* fds) { int new_len = ERTS_POLL_EXPORT(erts_poll_get_table_len)(fd + 1); if (new_len > max_fds) new_len = max_fds; - new_len = FDS_SIZE(new_len); - ps->input_fds = ps->select_fds_len - ? erts_realloc(ERTS_ALC_T_SELECT_FDS, ps->input_fds, new_len) + new_len = ERTS_FD_SIZE(new_len); + fds->ptr = fds->sz + ? erts_realloc(ERTS_ALC_T_SELECT_FDS, fds->ptr, new_len) : erts_alloc(ERTS_ALC_T_SELECT_FDS, new_len); - ps->output_fds = ps->select_fds_len - ? erts_realloc(ERTS_ALC_T_SELECT_FDS, ps->output_fds, new_len) - : erts_alloc(ERTS_ALC_T_SELECT_FDS, new_len); - memset((void *) ps->input_fds + ps->select_fds_len, 0, - new_len - ps->select_fds_len); - memset((void *) ps->output_fds + ps->select_fds_len, 0, - new_len - ps->select_fds_len); - ps->select_fds_len = new_len; - ps->resize_res_sets = 1; + memset((char*)fds->ptr + fds->sz, 0, new_len - fds->sz); + fds->sz = new_len; +} +static ERTS_INLINE void +ensure_select_fds(int fd, ERTS_fd_set* fds) +{ + if (ERTS_FD_SIZE(fd+1) > fds->sz) + grow_select_fds(fd, fds); } #endif /* _DARWIN_UNLIMITED_SELECT */ @@ -1334,26 +1362,22 @@ static int update_pollset(ErtsPollSet ps, int fd) #elif ERTS_POLL_USE_SELECT /* --- select ------------------------------ */ { ErtsPollEvents events = ps->fds_status[fd].events; -#ifdef _DARWIN_UNLIMITED_SELECT - if (FDS_SIZE(fd+1) > ps->select_fds_len) - grow_select_fds(ps, fd); -#endif if ((ERTS_POLL_EV_IN & events) != (ERTS_POLL_EV_IN & ps->fds_status[fd].used_events)) { if (ERTS_POLL_EV_IN & events) { - FDS_SET(fd, ps->input_fds); + ERTS_FD_SET(fd, &ps->input_fds); } else { - FDS_CLR(fd, ps->input_fds); + ERTS_FD_CLR(fd, &ps->input_fds); } } if ((ERTS_POLL_EV_OUT & events) != (ERTS_POLL_EV_OUT & ps->fds_status[fd].used_events)) { if (ERTS_POLL_EV_OUT & events) { - FDS_SET(fd, ps->output_fds); + ERTS_FD_SET(fd, &ps->output_fds); } else { - FDS_CLR(fd, ps->output_fds); + ERTS_FD_CLR(fd, &ps->output_fds); } } @@ -1837,7 +1861,7 @@ save_poll_result(ErtsPollSet ps, ErtsPollResFd pr[], int max_res, while (fd < end_fd && res < max_res) { pr[res].events = (ErtsPollEvents) 0; - if (FDS_ISSET(fd, ps->res_input_fds)) { + if (ERTS_FD_ISSET(fd, &ps->res_input_fds)) { #if ERTS_POLL_USE_FALLBACK if (fd == ps->kp_fd) { res += get_kp_results(ps, &pr[res], max_res-res); @@ -1853,7 +1877,7 @@ save_poll_result(ErtsPollSet ps, ErtsPollResFd pr[], int max_res, #endif pr[res].events |= ERTS_POLL_EV_IN; } - if (FDS_ISSET(fd, ps->res_output_fds)) + if (ERTS_FD_ISSET(fd, &ps->res_output_fds)) pr[res].events |= ERTS_POLL_EV_OUT; if (pr[res].events) { pr[res].fd = fd; @@ -1880,34 +1904,23 @@ save_poll_result(ErtsPollSet ps, ErtsPollResFd pr[], int max_res, while (fd < end_fd && res < max_res) { if (ps->fds_status[fd].events) { int sres; - fd_set *iset = NULL; - fd_set *oset = NULL; + ERTS_fd_set *iset = NULL; + ERTS_fd_set *oset = NULL; if (ps->fds_status[fd].events & ERTS_POLL_EV_IN) { -#ifdef _DARWIN_UNLIMITED_SELECT - iset = ps->res_input_fds; - memset((void *) iset, 0, ps->select_fds_len); -#else iset = &ps->res_input_fds; - FD_ZERO(iset); -#endif - FD_SET(fd, iset); + ERTS_FD_ZERO(iset); + ERTS_FD_SET(fd, iset); } if (ps->fds_status[fd].events & ERTS_POLL_EV_OUT) { -#ifdef _DARWIN_UNLIMITED_SELECT - oset = ps->res_output_fds; - memset((char *)oset, 0, ps->select_fds_len); -#else oset = &ps->res_output_fds; - FD_ZERO(oset); -#endif - FD_SET(fd, oset); - + ERTS_FD_ZERO(oset); + ERTS_FD_SET(fd, oset); } do { /* Initiate 'tv' each time; select() may modify it */ SysTimeval tv = {0, 0}; - sres = select(ps->max_fd+1, iset, oset, NULL, &tv); + sres = ERTS_SELECT(ps->max_fd+1, iset, oset, NULL, &tv); } while (sres < 0 && errno == EINTR); if (sres < 0) { #if ERTS_POLL_USE_FALLBACK @@ -1931,7 +1944,7 @@ save_poll_result(ErtsPollSet ps, ErtsPollResFd pr[], int max_res, } else if (sres > 0) { pr[res].fd = fd; - if (iset && FD_ISSET(fd, iset)) { + if (iset && ERTS_FD_ISSET(fd, iset)) { #if ERTS_POLL_USE_FALLBACK if (fd == ps->kp_fd) { res += get_kp_results(ps, @@ -1949,7 +1962,7 @@ save_poll_result(ErtsPollSet ps, ErtsPollResFd pr[], int max_res, #endif pr[res].events |= ERTS_POLL_EV_IN; } - if (oset && FD_ISSET(fd, oset)) { + if (oset && ERTS_FD_ISSET(fd, oset)) { pr[res].events |= ERTS_POLL_EV_OUT; } ASSERT(pr[res].events); @@ -2050,37 +2063,16 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res) #elif ERTS_POLL_USE_SELECT /* --- select ------------------------------ */ SysTimeval to = *tv; -#ifdef _DARWIN_UNLIMITED_SELECT - if (ps->resize_res_sets) { - ps->res_input_fds = ps->res_input_fds - ? erts_realloc(ERTS_ALC_T_SELECT_FDS, ps->res_input_fds, - ps->select_fds_len) - : erts_alloc(ERTS_ALC_T_SELECT_FDS, ps->select_fds_len); - ps->res_output_fds = ps->res_output_fds - ? erts_realloc(ERTS_ALC_T_SELECT_FDS, ps->res_output_fds, - ps->select_fds_len) - : erts_alloc(ERTS_ALC_T_SELECT_FDS, ps->select_fds_len); - ps->resize_res_sets = 0; - } - memcpy(ps->res_input_fds, ps->input_fds, ps->select_fds_len); - memcpy(ps->res_output_fds, ps->output_fds, ps->select_fds_len); -#else - ps->res_input_fds = ps->input_fds; - ps->res_output_fds = ps->output_fds; -#endif - + ERTS_FD_COPY(&ps->input_fds, &ps->res_input_fds); + ERTS_FD_COPY(&ps->output_fds, &ps->res_output_fds); + #ifdef ERTS_SMP if (to.tv_sec || to.tv_usec) erts_thr_progress_prepare_wait(NULL); #endif - res = select(ps->max_fd + 1, -#ifdef _DARWIN_UNLIMITED_SELECT - ps->res_input_fds, - ps->res_output_fds, -#else + res = ERTS_SELECT(ps->max_fd + 1, &ps->res_input_fds, &ps->res_output_fds, -#endif NULL, &to); #ifdef ERTS_SMP @@ -2106,14 +2098,9 @@ check_fd_events(ErtsPollSet ps, SysTimeval *tv, int max_res) ERTS_POLLSET_LOCK(ps); handle_update_requests(ps); ERTS_POLLSET_UNLOCK(ps); - res = select(ps->max_fd + 1, -#ifdef _DARWIN_UNLIMITED_SELECT - ps->res_input_fds, - ps->res_output_fds, -#else + res = ERTS_SELECT(ps->max_fd + 1, &ps->res_input_fds, &ps->res_output_fds, -#endif NULL, &to); if (res == 0) { @@ -2387,17 +2374,19 @@ ERTS_POLL_EXPORT(erts_poll_create_pollset)(void) ps->no_select_fds = 0; #endif #ifdef _DARWIN_UNLIMITED_SELECT - ps->select_fds_len = 0; - ps->resize_res_sets = 0; - ps->input_fds = NULL; - ps->res_input_fds = NULL; - ps->output_fds = NULL; - ps->res_output_fds = NULL; + ps->input_fds.sz = 0; + ps->input_fds.ptr = NULL; + ps->res_input_fds.sz = 0; + ps->res_input_fds.ptr = NULL; + ps->output_fds.sz = 0; + ps->output_fds.ptr = NULL; + ps->res_output_fds.sz = 0; + ps->res_output_fds.ptr = NULL; #else - FD_ZERO(&ps->input_fds); - FD_ZERO(&ps->res_input_fds); - FD_ZERO(&ps->output_fds); - FD_ZERO(&ps->res_output_fds); + ERTS_FD_ZERO(&ps->input_fds); + ERTS_FD_ZERO(&ps->res_input_fds); + ERTS_FD_ZERO(&ps->output_fds); + ERTS_FD_ZERO(&ps->res_output_fds); #endif #endif #if ERTS_POLL_USE_UPDATE_REQUESTS_QUEUE @@ -2477,14 +2466,14 @@ ERTS_POLL_EXPORT(erts_poll_destroy_pollset)(ErtsPollSet ps) erts_free(ERTS_ALC_T_POLL_FDS, (void *) ps->poll_fds); #elif ERTS_POLL_USE_SELECT #ifdef _DARWIN_UNLIMITED_SELECT - if (ps->input_fds) - erts_free(ERTS_ALC_T_SELECT_FDS, (void *) ps->input_fds); - if (ps->res_input_fds) - erts_free(ERTS_ALC_T_SELECT_FDS, (void *) ps->res_input_fds); - if (ps->output_fds) - erts_free(ERTS_ALC_T_SELECT_FDS, (void *) ps->output_fds); - if (ps->res_output_fds) - erts_free(ERTS_ALC_T_SELECT_FDS, (void *) ps->res_output_fds); + if (ps->input_fds.ptr) + erts_free(ERTS_ALC_T_SELECT_FDS, (void *) ps->input_fds.ptr); + if (ps->res_input_fds.ptr) + erts_free(ERTS_ALC_T_SELECT_FDS, (void *) ps->res_input_fds.ptr); + if (ps->output_fds.ptr) + erts_free(ERTS_ALC_T_SELECT_FDS, (void *) ps->output_fds.ptr); + if (ps->res_output_fds.ptr) + erts_free(ERTS_ALC_T_SELECT_FDS, (void *) ps->res_output_fds.ptr); #endif #endif #if ERTS_POLL_USE_UPDATE_REQUESTS_QUEUE @@ -2550,7 +2539,8 @@ ERTS_POLL_EXPORT(erts_poll_info)(ErtsPollSet ps, ErtsPollInfo *pip) size += ps->poll_fds_len*sizeof(struct pollfd); #elif ERTS_POLL_USE_SELECT #ifdef _DARWIN_UNLIMITED_SELECT - size += ps->select_fds_len*4; + size += ps->input_fds.sz + ps->res_input_fds.sz + + ps->output_fds.sz + ps->res_output_fds.sz; #endif #endif -- cgit v1.2.3 From aae984904cb79166c94a784cb6d1a4e6bfd3e7d7 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 4 Jun 2013 11:30:39 +0200 Subject: erts: Fix dynamic select for darwin Make sure the fd-sets (read and write) are of equal size. --- erts/emulator/sys/common/erl_poll.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'erts') diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c index 37512bcb50..7d292a304a 100644 --- a/erts/emulator/sys/common/erl_poll.c +++ b/erts/emulator/sys/common/erl_poll.c @@ -102,8 +102,8 @@ typedef struct { size_t sz; fd_set* ptr; }ERTS_fd_set; -# define ERTS_FD_CLR(fd, fds) do { ensure_select_fds((fd),(fds)); FD_CLR((fd), (fds)->ptr); }while(0) -# define ERTS_FD_SET(fd, fds) do { ensure_select_fds((fd),(fds)); FD_SET((fd), (fds)->ptr); }while(0) +# define ERTS_FD_CLR(fd, fds) FD_CLR((fd), (fds)->ptr) +# define ERTS_FD_SET(fd, fds) FD_SET((fd), (fds)->ptr) # define ERTS_FD_ISSET(fd,fds) FD_ISSET((fd), (fds)->ptr) # define ERTS_FD_ZERO(fds) memset((fds)->ptr, 0, (fds)->sz) # define ERTS_FD_SIZE(n) ((((n)+NFDBITS-1)/NFDBITS)*sizeof(fd_mask)) @@ -123,10 +123,13 @@ static ERTS_INLINE int ERTS_SELECT(int nfds, ERTS_fd_set *readfds, ERTS_fd_set *writefds, ERTS_fd_set *exceptfds, struct timeval *timeout) { + ASSERT(!readfds || readfds->sz >= nfds); + ASSERT(!writefds || writefds->sz >= nfds); + ASSERT(!exceptfds); return select(nfds, (readfds ? readfds->ptr : NULL ), (writefds ? writefds->ptr : NULL), - (exceptfds ? exceptfds->ptr : NULL), + NULL, timeout); } @@ -689,11 +692,16 @@ grow_select_fds(int fd, ERTS_fd_set* fds) fds->sz = new_len; } static ERTS_INLINE void -ensure_select_fds(int fd, ERTS_fd_set* fds) +ensure_select_fds(int fd, ERTS_fd_set* in, ERTS_fd_set* out) { - if (ERTS_FD_SIZE(fd+1) > fds->sz) - grow_select_fds(fd, fds); + ASSERT(in->sz == out->sz); + if (ERTS_FD_SIZE(fd+1) > in->sz) { + grow_select_fds(fd, in); + grow_select_fds(fd, out); + } } +#else +# define ensure_select_fds(fd, in, out) do {} while(0) #endif /* _DARWIN_UNLIMITED_SELECT */ static void @@ -1362,6 +1370,7 @@ static int update_pollset(ErtsPollSet ps, int fd) #elif ERTS_POLL_USE_SELECT /* --- select ------------------------------ */ { ErtsPollEvents events = ps->fds_status[fd].events; + ensure_select_fds(fd, &ps->input_fds, &ps->output_fds); if ((ERTS_POLL_EV_IN & events) != (ERTS_POLL_EV_IN & ps->fds_status[fd].used_events)) { if (ERTS_POLL_EV_IN & events) { -- cgit v1.2.3