diff options
Diffstat (limited to 'erts/emulator')
-rw-r--r-- | erts/emulator/sys/common/erl_poll.c | 212 |
1 files changed, 101 insertions, 111 deletions
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 |