aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/sys/common/erl_poll.c212
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