MEDIUM: polling: prepare to call the iocb() function when defined.

We will need this to centralize I/O callbacks. Nobody sets it right
now so the code should have no impact.
diff --git a/src/ev_epoll.c b/src/ev_epoll.c
index 482992e..589932f 100644
--- a/src/ev_epoll.c
+++ b/src/ev_epoll.c
@@ -260,15 +260,20 @@
 			if (!fdtab[fd].owner)
 				continue;
 			if (fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP|FD_POLL_ERR))
-				fdtab[fd].cb[DIR_RD].f(fd);
+				if (fdtab[fd].cb[DIR_RD].f)
+					fdtab[fd].cb[DIR_RD].f(fd);
 		}
 
 		if ((fd_evts[FD2OFS(fd)] >> FD2BIT(fd)) & DIR2MSK(DIR_WR)) {
 			if (!fdtab[fd].owner)
 				continue;
 			if (fdtab[fd].ev & (FD_POLL_OUT|FD_POLL_ERR|FD_POLL_HUP))
-				fdtab[fd].cb[DIR_WR].f(fd);
+				if (fdtab[fd].cb[DIR_WR].f)
+					fdtab[fd].cb[DIR_WR].f(fd);
 		}
+
+		if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev)
+			fdtab[fd].iocb(fd);
 	}
 }
 
diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c
index b27f372..556abcc 100644
--- a/src/ev_kqueue.c
+++ b/src/ev_kqueue.c
@@ -138,21 +138,27 @@
 
 	for (count = 0; count < status; count++) {
 		fd = kev[count].ident;
+
+		fdtab[fd].ev &= FD_POLL_STICKY;
 		if (kev[count].filter ==  EVFILT_READ) {
 			if (FD_ISSET(fd, fd_evts[DIR_RD])) {
 				if (!fdtab[fd].owner)
 					continue;
 				fdtab[fd].ev |= FD_POLL_IN;
-				fdtab[fd].cb[DIR_RD].f(fd);
+				if (fdtab[fd].cb[DIR_RD].f)
+					fdtab[fd].cb[DIR_RD].f(fd);
 			}
 		} else if (kev[count].filter ==  EVFILT_WRITE) {
 			if (FD_ISSET(fd, fd_evts[DIR_WR])) {
 				if (!fdtab[fd].owner)
 					continue;
 				fdtab[fd].ev |= FD_POLL_OUT;
-				fdtab[fd].cb[DIR_WR].f(fd);
+				if (fdtab[fd].cb[DIR_WR].f)
+					fdtab[fd].cb[DIR_WR].f(fd)
 			}
 		}
+		if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev)
+			fdtab[fd].iocb(fd);
 	}
 }
 
diff --git a/src/ev_poll.c b/src/ev_poll.c
index 6351a72..015ff76 100644
--- a/src/ev_poll.c
+++ b/src/ev_poll.c
@@ -163,15 +163,20 @@
 			if (!fdtab[fd].owner)
 				continue;
 			if (fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP|FD_POLL_ERR))
-				fdtab[fd].cb[DIR_RD].f(fd);
+				if (fdtab[fd].cb[DIR_RD].f)
+					fdtab[fd].cb[DIR_RD].f(fd);
 		}
 	  
 		if (FD_ISSET(fd, fd_evts[DIR_WR])) {
 			if (!fdtab[fd].owner)
 				continue;
 			if (fdtab[fd].ev & (FD_POLL_OUT|FD_POLL_ERR|FD_POLL_HUP))
-				fdtab[fd].cb[DIR_WR].f(fd);
+				if (fdtab[fd].cb[DIR_WR].f)
+					fdtab[fd].cb[DIR_WR].f(fd);
 		}
+
+		if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev)
+			fdtab[fd].iocb(fd);
 	}
 
 }
diff --git a/src/ev_select.c b/src/ev_select.c
index 64031cc..b1c41bc 100644
--- a/src/ev_select.c
+++ b/src/ev_select.c
@@ -146,19 +146,25 @@
 			/* if we specify read first, the accepts and zero reads will be
 			 * seen first. Moreover, system buffers will be flushed faster.
 			 */
+			fdtab[fd].ev &= FD_POLL_STICKY;
 			if (FD_ISSET(fd, tmp_evts[DIR_RD])) {
 				if (!fdtab[fd].owner)
 					continue;
 				fdtab[fd].ev |= FD_POLL_IN;
-				fdtab[fd].cb[DIR_RD].f(fd);
+				if (fdtab[fd].cb[DIR_RD].f)
+					fdtab[fd].cb[DIR_RD].f(fd);
 			}
 
 			if (FD_ISSET(fd, tmp_evts[DIR_WR])) {
 				if (!fdtab[fd].owner)
 					continue;
 				fdtab[fd].ev |= FD_POLL_OUT;
-				fdtab[fd].cb[DIR_WR].f(fd);
+				if (fdtab[fd].cb[DIR_WR].f)
+					fdtab[fd].cb[DIR_WR].f(fd);
 			}
+
+			if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev)
+				fdtab[fd].iocb(fd);
 		}
 	}
 }
diff --git a/src/ev_sepoll.c b/src/ev_sepoll.c
index 049eb30..55c81ea 100644
--- a/src/ev_sepoll.c
+++ b/src/ev_sepoll.c
@@ -413,15 +413,20 @@
 			if (!fdtab[fd].owner)
 				continue;
 			if (fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP|FD_POLL_ERR))
-				fdtab[fd].cb[DIR_RD].f(fd);
+				if (fdtab[fd].cb[DIR_RD].f)
+					fdtab[fd].cb[DIR_RD].f(fd);
 		}
 
 		if ((fdtab[fd].spec.e & FD_EV_MASK_W) == FD_EV_WAIT_W) {
 			if (!fdtab[fd].owner)
 				continue;
 			if (fdtab[fd].ev & (FD_POLL_OUT|FD_POLL_ERR))
-				fdtab[fd].cb[DIR_WR].f(fd);
+				if (fdtab[fd].cb[DIR_WR].f)
+					fdtab[fd].cb[DIR_WR].f(fd);
 		}
+
+		if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev)
+			fdtab[fd].iocb(fd);
 	}
 
 	/* now process speculative events if any */
@@ -454,7 +459,7 @@
 			/* The owner is interested in reading from this FD */
 			/* Pretend there is something to read */
 			fdtab[fd].ev |= FD_POLL_IN;
-			if (!fdtab[fd].cb[DIR_RD].f(fd))
+			if (fdtab[fd].cb[DIR_RD].f && !fdtab[fd].cb[DIR_RD].f(fd))
 				fdtab[fd].spec.e ^= (FD_EV_WAIT_R ^ FD_EV_SPEC_R);
 		}
 
@@ -462,7 +467,21 @@
 			/* The owner is interested in writing to this FD */
 			/* Pretend there is something to write */
 			fdtab[fd].ev |= FD_POLL_OUT;
-			if (!fdtab[fd].cb[DIR_WR].f(fd))
+			if (fdtab[fd].cb[DIR_WR].f && !fdtab[fd].cb[DIR_WR].f(fd))
+				fdtab[fd].spec.e ^= (FD_EV_WAIT_W ^ FD_EV_SPEC_W);
+		}
+
+		if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev) {
+			int wait = fdtab[fd].iocb(fd);
+
+			/* FIXME: warning, this will not work if both old and new
+			 * callbacks are used at the same time ! This is only a
+			 * temporary measure during the migration.
+			 */
+			if (wait & FD_WAIT_READ)
+				fdtab[fd].spec.e ^= (FD_EV_WAIT_R ^ FD_EV_SPEC_R);
+
+			if (wait & FD_WAIT_WRITE)
 				fdtab[fd].spec.e ^= (FD_EV_WAIT_W ^ FD_EV_SPEC_W);
 		}