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 */