REORG: fd: move the speculative I/O management from ev_sepoll

The speculative I/O will need to be ported to all pollers, so move
this to fd.c.
diff --git a/include/proto/fd.h b/include/proto/fd.h
index 240a2e2..f0265b7 100644
--- a/include/proto/fd.h
+++ b/include/proto/fd.h
@@ -30,6 +30,12 @@
 #include <common/config.h>
 #include <types/fd.h>
 
+/* public variables */
+extern int fd_nbspec;          // number of speculative events in the list
+extern int fd_nbupdt;          // number of updates in the list
+extern unsigned int *fd_spec;  // speculative I/O list
+extern unsigned int *fd_updt;  // FD updates list
+
 /* Deletes an FD from the fdsets, and recomputes the maxfd limit.
  * The file descriptor is also closed.
  */
@@ -70,7 +76,49 @@
  */
 void run_poller();
 
+/* Mark fd <fd> as updated and allocate an entry in the update list for this if
+ * it was not already there. This can be done at any time.
+ */
+static inline void updt_fd(const int fd)
+{
+	if (fdtab[fd].updated)
+		/* already scheduled for update */
+		return;
+	fd_updt[fd_nbupdt++] = fd;
+	fdtab[fd].updated = 1;
+}
+
+
+/* allocate an entry for a speculative event. This can be done at any time. */
+static inline void alloc_spec_entry(const int fd)
+{
+	if (fdtab[fd].spec_p)
+		/* FD already in speculative I/O list */
+		return;
+	fd_spec[fd_nbspec++] = fd;
+	fdtab[fd].spec_p = fd_nbspec;
+}
+
+/* Removes entry used by fd <fd> from the spec list and replaces it with the
+ * last one. The fdtab.spec is adjusted to match the back reference if needed.
+ * If the fd has no entry assigned, return immediately.
+ */
+static inline void release_spec_entry(int fd)
+{
+	unsigned int pos;
+
-#define EV_FD_ISSET(fd, ev)  (cur_poller.is_set((fd), (ev)))
+	pos = fdtab[fd].spec_p;
+	if (!pos)
+		return;
+	fdtab[fd].spec_p = 0;
+	fd_nbspec--;
+	if (pos <= fd_nbspec) {
+		/* was not the last entry */
+		fd = fd_spec[fd_nbspec];
+		fd_spec[pos - 1] = fd;
+		fdtab[fd].spec_p = pos;
+	}
+}
 
 /* event manipulation primitives for use by I/O callbacks */
 static inline void fd_want_recv(int fd)
diff --git a/include/types/fd.h b/include/types/fd.h
index a99c6bf..fab0c6c 100644
--- a/include/types/fd.h
+++ b/include/types/fd.h
@@ -25,13 +25,13 @@
 #include <common/config.h>
 #include <types/port_range.h>
 
+/* Direction for each FD event update */
 enum {
 	DIR_RD=0,
 	DIR_WR=1,
-	DIR_SIZE
 };
 
-/*
+/* Polling status flags returned in fdtab[].ev :
  * FD_POLL_IN remains set as long as some data is pending for read.
  * FD_POLL_OUT remains set as long as the fd accepts to write data.
  * FD_POLL_ERR and FD_POLL_ERR remain set forever (until processed).
@@ -45,6 +45,26 @@
 #define FD_POLL_DATA    (FD_POLL_IN  | FD_POLL_OUT)
 #define FD_POLL_STICKY  (FD_POLL_ERR | FD_POLL_HUP)
 
+/* Event state for an FD in each direction, as found in the 4 lower bits of
+ * fdtab[].spec_e, and in the 4 next bits.
+ */
+#define FD_EV_ACTIVE    1U
+#define FD_EV_POLLED    4U
+#define FD_EV_STATUS    (FD_EV_ACTIVE | FD_EV_POLLED)
+#define FD_EV_STATUS_R  (FD_EV_STATUS)
+#define FD_EV_STATUS_W  (FD_EV_STATUS << 1)
+
+#define FD_EV_POLLED_R  (FD_EV_POLLED)
+#define FD_EV_POLLED_W  (FD_EV_POLLED << 1)
+#define FD_EV_POLLED_RW (FD_EV_POLLED_R | FD_EV_POLLED_W)
+
+#define FD_EV_ACTIVE_R  (FD_EV_ACTIVE)
+#define FD_EV_ACTIVE_W  (FD_EV_ACTIVE << 1)
+#define FD_EV_ACTIVE_RW (FD_EV_ACTIVE_R | FD_EV_ACTIVE_W)
+
+#define FD_EV_CURR_MASK 0x0FU
+#define FD_EV_PREV_MASK 0xF0U
+
 /* info about one given fd */
 struct fdtab {
 	int (*iocb)(int fd);                 /* I/O handler, returns FD_WAIT_* */