X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Fio%2Fio.c;h=b3c4c760eb445f4ed6c188de08dd7bbad4cd2b22;hp=8d43922351d51ba131e4c087b600bbdc013993c0;hb=e2ce04eac30ec613c858bd4cd2ca12e1c464edb8;hpb=d0458a433876acc01b48f74c1c3b966bbc29de57 diff --git a/ccan/io/io.c b/ccan/io/io.c index 8d439223..b3c4c760 100644 --- a/ccan/io/io.c +++ b/ccan/io/io.c @@ -12,6 +12,45 @@ void *io_loop_return; +#ifdef DEBUG +bool io_plan_for_other; +struct io_conn *current; +bool (*io_debug)(struct io_conn *conn); +bool io_debug_wakeup; + +void io_plan_debug(struct io_plan *plan) +{ + if (io_plan_for_other) { + io_plan_for_other = false; + return; + } + + if (!io_debug || !current) + return; + + if (!io_debug(current) && !io_debug_wakeup) + return; + + io_debug_wakeup = false; + current->plan = *plan; + backend_plan_changed(current); + + /* Call back into the loop immediately. */ + io_loop_return = io_loop(); +} + +static void debug_io_wake(struct io_conn *conn) +{ + /* We want linear if we wake a debugged connection, too. */ + if (io_debug && io_debug(conn)) + io_debug_wakeup = true; +} +#else +static void debug_io_wake(struct io_conn *conn) +{ +} +#endif + struct io_listener *io_new_listener_(int fd, void (*init)(int fd, void *arg), void *arg) @@ -138,6 +177,8 @@ struct io_plan io_write_(const void *data, size_t len, plan.next = cb; plan.next_arg = arg; plan.pollflag = POLLOUT; + + io_plan_debug(&plan); return plan; } @@ -169,6 +210,8 @@ struct io_plan io_read_(void *data, size_t len, plan.next = cb; plan.next_arg = arg; plan.pollflag = POLLIN; + + io_plan_debug(&plan); return plan; } @@ -200,6 +243,7 @@ struct io_plan io_read_partial_(void *data, size_t *len, plan.next_arg = arg; plan.pollflag = POLLIN; + io_plan_debug(&plan); return plan; } @@ -231,6 +275,7 @@ struct io_plan io_write_partial_(const void *data, size_t *len, plan.next_arg = arg; plan.pollflag = POLLOUT; + io_plan_debug(&plan); return plan; } @@ -243,10 +288,11 @@ struct io_plan io_idle(void) /* Never called (overridded by io_wake), but NULL means closing */ plan.next = io_close; + io_plan_debug(&plan); return plan; } -void io_wake(struct io_conn *conn, struct io_plan plan) +void io_wake_(struct io_conn *conn, struct io_plan plan) { /* It might be closing, but we haven't called its finish() yet. */ @@ -256,15 +302,19 @@ void io_wake(struct io_conn *conn, struct io_plan plan) assert(!conn->plan.io); conn->plan = plan; backend_plan_changed(conn); + + debug_io_wake(conn); } void io_ready(struct io_conn *conn) { if (conn->plan.io(conn->fd.fd, &conn->plan)) { + set_current(conn); if (timeout_active(conn)) backend_del_timeout(conn); conn->plan = conn->plan.next(conn, conn->plan.next_arg); backend_plan_changed(conn); + set_current(NULL); } } @@ -278,11 +328,12 @@ struct io_plan io_close(struct io_conn *conn, void *arg) /* This means we're closing. */ plan.next = NULL; + io_plan_debug(&plan); return plan; } /* Exit the loop, returning this (non-NULL) arg. */ -struct io_plan io_break(void *ret, struct io_plan plan) +struct io_plan io_break_(void *ret, struct io_plan plan) { assert(ret); io_loop_return = ret;