+void backend_plan_changed(struct io_conn *conn)
+{
+ struct pollfd *pfd;
+
+ /* This can happen with debugging and delayed free... */
+ if (conn->fd.backend_info == -1)
+ return;
+
+ pfd = &pollfds[conn->fd.backend_info];
+
+ if (pfd->events)
+ num_waiting--;
+
+ pfd->events = conn->plan.pollflag & (POLLIN|POLLOUT);
+ if (conn->duplex) {
+ int mask = conn->duplex->plan.pollflag & (POLLIN|POLLOUT);
+ /* You can't *both* read/write. */
+ assert(!mask || pfd->events != mask);
+ pfd->events |= mask;
+ }
+ if (pfd->events) {
+ num_waiting++;
+ pfd->fd = conn->fd.fd;
+ } else
+ pfd->fd = -conn->fd.fd;
+
+ if (!conn->plan.next)
+ num_closing++;
+
+ if (conn->plan.pollflag == POLLALWAYS)
+ some_always = true;
+}
+
+void backend_wait_changed(const void *wait)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_fds; i++) {
+ struct io_conn *c, *duplex;
+
+ /* Ignore listeners */
+ if (fds[i]->listener)
+ continue;
+ c = (void *)fds[i];
+ for (duplex = c->duplex; c; c = duplex, duplex = NULL) {
+ /* Ignore closing. */
+ if (!c->plan.next)
+ continue;
+ /* Not idle? */
+ if (c->plan.io)
+ continue;
+ /* Waiting on something else? */
+ if (c->plan.u1.const_vp != wait)
+ continue;
+ /* Make it do the next thing. */
+ c->plan = io_always_(c->plan.next, c->plan.next_arg);
+ backend_plan_changed(c);
+ }
+ }
+}
+