Revert "Upgrade to 2.1.8-stable (2017-01-22)." and "Probably Mac build fix?"
This reverts commits 2a572d125a91a4aafd3ad8ce87259fc640fa0763 and
af241a5c8c2cde0fab7d7d563276c1095b00e3b4, which break tombstoned.
Bug: http://b/64543673
Test: manual + treehugger
diff --git a/evport.c b/evport.c
index a014386..0d714d8 100644
--- a/evport.c
+++ b/evport.c
@@ -54,9 +54,6 @@
*/
#include "event2/event-config.h"
-#include "evconfig-private.h"
-
-#ifdef EVENT__HAVE_EVENT_PORTS
#include <sys/time.h>
#include <sys/queue.h>
@@ -78,8 +75,20 @@
#include "evsignal-internal.h"
#include "evmap-internal.h"
-#define INITIAL_EVENTS_PER_GETN 8
-#define MAX_EVENTS_PER_GETN 4096
+/*
+ * Default value for ed_nevents, which is the maximum file descriptor number we
+ * can handle. If an event comes in for a file descriptor F > nevents, we will
+ * grow the array of file descriptors, doubling its size.
+ */
+#define DEFAULT_NFDS 16
+
+
+/*
+ * EVENTS_PER_GETN is the maximum number of events to retrieve from port_getn on
+ * any particular call. You can speed things up by increasing this, but it will
+ * (obviously) require more memory.
+ */
+#define EVENTS_PER_GETN 8
/*
* Per-file-descriptor information about what events we're subscribed to. These
@@ -87,12 +96,7 @@
*/
struct fd_info {
- /* combinations of EV_READ and EV_WRITE */
- short fdi_what;
- /* Index of this fd within ed_pending, plus 1. Zero if this fd is
- * not in ed_pending. (The +1 is a hack so that memset(0) will set
- * it to a nil index. */
- int pending_idx_plus_1;
+ short fdi_what; /* combinations of EV_READ and EV_WRITE */
};
#define FDI_HAS_READ(fdi) ((fdi)->fdi_what & EV_READ)
@@ -103,15 +107,10 @@
struct evport_data {
int ed_port; /* event port for system events */
- /* How many elements of ed_pending should we look at? */
- int ed_npending;
- /* How many elements are allocated in ed_pending and pevtlist? */
- int ed_maxevents;
+ int ed_nevents; /* number of allocated fdi's */
+ struct fd_info *ed_fds; /* allocated fdi table */
/* fdi's that we need to reassoc */
- int *ed_pending;
- /* storage space for incoming events. */
- port_event_t *ed_pevtlist;
-
+ int ed_pending[EVENTS_PER_GETN]; /* fd's with pending events */
};
static void* evport_init(struct event_base *);
@@ -119,7 +118,6 @@
static int evport_del(struct event_base *, int fd, short old, short events, void *);
static int evport_dispatch(struct event_base *, struct timeval *);
static void evport_dealloc(struct event_base *);
-static int grow(struct evport_data *, int min_events);
const struct eventop evportops = {
"evport",
@@ -130,7 +128,7 @@
evport_dealloc,
1, /* need reinit */
0, /* features */
- sizeof(struct fd_info), /* fdinfo length */
+ 0, /* fdinfo length */
};
/*
@@ -141,6 +139,7 @@
evport_init(struct event_base *base)
{
struct evport_data *evpd;
+ int i;
if (!(evpd = mm_calloc(1, sizeof(struct evport_data))))
return (NULL);
@@ -150,47 +149,24 @@
return (NULL);
}
- if (grow(evpd, INITIAL_EVENTS_PER_GETN) < 0) {
+ /*
+ * Initialize file descriptor structure
+ */
+ evpd->ed_fds = mm_calloc(DEFAULT_NFDS, sizeof(struct fd_info));
+ if (evpd->ed_fds == NULL) {
close(evpd->ed_port);
mm_free(evpd);
- return NULL;
+ return (NULL);
}
-
- evpd->ed_npending = 0;
+ evpd->ed_nevents = DEFAULT_NFDS;
+ for (i = 0; i < EVENTS_PER_GETN; i++)
+ evpd->ed_pending[i] = -1;
- evsig_init_(base);
+ evsig_init(base);
return (evpd);
}
-static int
-grow(struct evport_data *data, int min_events)
-{
- int newsize;
- int *new_pending;
- port_event_t *new_pevtlist;
- if (data->ed_maxevents) {
- newsize = data->ed_maxevents;
- do {
- newsize *= 2;
- } while (newsize < min_events);
- } else {
- newsize = min_events;
- }
-
- new_pending = mm_realloc(data->ed_pending, sizeof(int)*newsize);
- if (new_pending == NULL)
- return -1;
- data->ed_pending = new_pending;
- new_pevtlist = mm_realloc(data->ed_pevtlist, sizeof(port_event_t)*newsize);
- if (new_pevtlist == NULL)
- return -1;
- data->ed_pevtlist = new_pevtlist;
-
- data->ed_maxevents = newsize;
- return 0;
-}
-
#ifdef CHECK_INVARIANTS
/*
* Checks some basic properties about the evport_data structure. Because it
@@ -202,7 +178,9 @@
check_evportop(struct evport_data *evpd)
{
EVUTIL_ASSERT(evpd);
+ EVUTIL_ASSERT(evpd->ed_nevents > 0);
EVUTIL_ASSERT(evpd->ed_port > 0);
+ EVUTIL_ASSERT(evpd->ed_fds > 0);
}
/*
@@ -218,6 +196,7 @@
* PORT_SOURCE_FD.
*/
EVUTIL_ASSERT(pevt->portev_source == PORT_SOURCE_FD);
+ EVUTIL_ASSERT(pevt->portev_user == NULL);
}
#else
@@ -226,6 +205,33 @@
#endif /* CHECK_INVARIANTS */
/*
+ * Doubles the size of the allocated file descriptor array.
+ */
+static int
+grow(struct evport_data *epdp, int factor)
+{
+ struct fd_info *tmp;
+ int oldsize = epdp->ed_nevents;
+ int newsize = factor * oldsize;
+ EVUTIL_ASSERT(factor > 1);
+
+ check_evportop(epdp);
+
+ tmp = mm_realloc(epdp->ed_fds, sizeof(struct fd_info) * newsize);
+ if (NULL == tmp)
+ return -1;
+ epdp->ed_fds = tmp;
+ memset((char*) (epdp->ed_fds + oldsize), 0,
+ (newsize - oldsize)*sizeof(struct fd_info));
+ epdp->ed_nevents = newsize;
+
+ check_evportop(epdp);
+
+ return 0;
+}
+
+
+/*
* (Re)associates the given file descriptor with the event port. The OS events
* are specified (implicitly) from the fd_info struct.
*/
@@ -236,7 +242,7 @@
if (sysevents != 0) {
if (port_associate(epdp->ed_port, PORT_SOURCE_FD,
- fd, sysevents, fdip) == -1) {
+ fd, sysevents, NULL) == -1) {
event_warn("port_associate");
return (-1);
}
@@ -257,12 +263,12 @@
{
int i, res;
struct evport_data *epdp = base->evbase;
- port_event_t *pevtlist = epdp->ed_pevtlist;
+ port_event_t pevtlist[EVENTS_PER_GETN];
/*
* port_getn will block until it has at least nevents events. It will
* also return how many it's given us (which may be more than we asked
- * for, as long as it's less than our maximum (ed_maxevents)) in
+ * for, as long as it's less than our maximum (EVENTS_PER_GETN)) in
* nevents.
*/
int nevents = 1;
@@ -285,25 +291,22 @@
* last time which need reassociation. See comment at the end of the
* loop below.
*/
- for (i = 0; i < epdp->ed_npending; ++i) {
+ for (i = 0; i < EVENTS_PER_GETN; ++i) {
struct fd_info *fdi = NULL;
- const int fd = epdp->ed_pending[i];
- if (fd != -1) {
- /* We might have cleared out this event; we need
- * to be sure that it's still set. */
- fdi = evmap_io_get_fdinfo_(&base->io, fd);
+ if (epdp->ed_pending[i] != -1) {
+ fdi = &(epdp->ed_fds[epdp->ed_pending[i]]);
}
if (fdi != NULL && FDI_HAS_EVENTS(fdi)) {
+ int fd = epdp->ed_pending[i];
reassociate(epdp, fdi, fd);
- /* epdp->ed_pending[i] = -1; */
- fdi->pending_idx_plus_1 = 0;
+ epdp->ed_pending[i] = -1;
}
}
EVBASE_RELEASE_LOCK(base, th_base_lock);
- res = port_getn(epdp->ed_port, pevtlist, epdp->ed_maxevents,
+ res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN,
(unsigned int *) &nevents, ts_p);
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
@@ -323,15 +326,13 @@
event_debug(("%s: port_getn reports %d events", __func__, nevents));
for (i = 0; i < nevents; ++i) {
+ struct fd_info *fdi;
port_event_t *pevt = &pevtlist[i];
int fd = (int) pevt->portev_object;
- struct fd_info *fdi = pevt->portev_user;
- /*EVUTIL_ASSERT(evmap_io_get_fdinfo_(&base->io, fd) == fdi);*/
check_evportop(epdp);
check_event(pevt);
epdp->ed_pending[i] = fd;
- fdi->pending_idx_plus_1 = i + 1;
/*
* Figure out what kind of event it was
@@ -353,16 +354,11 @@
if (pevt->portev_events & (POLLERR|POLLHUP|POLLNVAL))
res |= EV_READ|EV_WRITE;
- evmap_io_active_(base, fd, res);
- } /* end of all events gotten */
- epdp->ed_npending = nevents;
+ EVUTIL_ASSERT(epdp->ed_nevents > fd);
+ fdi = &(epdp->ed_fds[fd]);
- if (nevents == epdp->ed_maxevents &&
- epdp->ed_maxevents < MAX_EVENTS_PER_GETN) {
- /* we used all the space this time. We should be ready
- * for more events next time around. */
- grow(epdp, epdp->ed_maxevents * 2);
- }
+ evmap_io_active(base, fd, res);
+ } /* end of all events gotten */
check_evportop(epdp);
@@ -379,10 +375,27 @@
evport_add(struct event_base *base, int fd, short old, short events, void *p)
{
struct evport_data *evpd = base->evbase;
- struct fd_info *fdi = p;
+ struct fd_info *fdi;
+ int factor;
+ (void)p;
check_evportop(evpd);
+ /*
+ * If necessary, grow the file descriptor info table
+ */
+
+ factor = 1;
+ while (fd >= factor * evpd->ed_nevents)
+ factor *= 2;
+
+ if (factor > 1) {
+ if (-1 == grow(evpd, factor)) {
+ return (-1);
+ }
+ }
+
+ fdi = &evpd->ed_fds[fd];
fdi->fdi_what |= events;
return reassociate(evpd, fdi, fd);
@@ -396,12 +409,29 @@
evport_del(struct event_base *base, int fd, short old, short events, void *p)
{
struct evport_data *evpd = base->evbase;
- struct fd_info *fdi = p;
- int associated = ! fdi->pending_idx_plus_1;
+ struct fd_info *fdi;
+ int i;
+ int associated = 1;
+ (void)p;
check_evportop(evpd);
- fdi->fdi_what &= ~(events &(EV_READ|EV_WRITE));
+ if (evpd->ed_nevents < fd) {
+ return (-1);
+ }
+
+ for (i = 0; i < EVENTS_PER_GETN; ++i) {
+ if (evpd->ed_pending[i] == fd) {
+ associated = 0;
+ break;
+ }
+ }
+
+ fdi = &evpd->ed_fds[fd];
+ if (events & EV_READ)
+ fdi->fdi_what &= ~EV_READ;
+ if (events & EV_WRITE)
+ fdi->fdi_what &= ~EV_WRITE;
if (associated) {
if (!FDI_HAS_EVENTS(fdi) &&
@@ -421,10 +451,7 @@
}
} else {
if ((fdi->fdi_what & (EV_READ|EV_WRITE)) == 0) {
- const int i = fdi->pending_idx_plus_1 - 1;
- EVUTIL_ASSERT(evpd->ed_pending[i] == fd);
evpd->ed_pending[i] = -1;
- fdi->pending_idx_plus_1 = 0;
}
}
return 0;
@@ -436,16 +463,11 @@
{
struct evport_data *evpd = base->evbase;
- evsig_dealloc_(base);
+ evsig_dealloc(base);
close(evpd->ed_port);
- if (evpd->ed_pending)
- mm_free(evpd->ed_pending);
- if (evpd->ed_pevtlist)
- mm_free(evpd->ed_pevtlist);
-
+ if (evpd->ed_fds)
+ mm_free(evpd->ed_fds);
mm_free(evpd);
}
-
-#endif /* EVENT__HAVE_EVENT_PORTS */