From: Rusty Russell Date: Mon, 14 Oct 2013 11:03:07 +0000 (+1030) Subject: ccan/io: flatten debug callchain. X-Git-Url: https://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=9e02685a6216720d37848a332187e3745b7f981e;hp=d4af94ec86618e89b449a27590a7b4f8e4365943 ccan/io: flatten debug callchain. Don't call from the plan-construction function, call after it returns. Signed-off-by: Rusty Russell --- diff --git a/ccan/io/backend.h b/ccan/io/backend.h index fa4cf8ee..df168d9f 100644 --- a/ccan/io/backend.h +++ b/ccan/io/backend.h @@ -55,7 +55,7 @@ static inline void set_current(struct io_conn *conn) } static inline bool doing_debug(void) { - return io_debug != NULL; + return io_debug_conn != NULL; } #else static inline void set_current(struct io_conn *conn) diff --git a/ccan/io/io.c b/ccan/io/io.c index b6ae56ac..a4489ee8 100644 --- a/ccan/io/io.c +++ b/ccan/io/io.c @@ -13,42 +13,56 @@ void *io_loop_return; #ifdef DEBUG -bool io_plan_for_other; +/* Set to skip the next plan. */ +bool io_plan_nodebug; +/* The current connection to apply plan to. */ struct io_conn *current; -bool (*io_debug)(struct io_conn *conn); +/* User-defined function to select which connection(s) to debug. */ +bool (*io_debug_conn)(struct io_conn *conn); +/* Set when we wake up an connection we are debugging. */ bool io_debug_wakeup; -void io_plan_debug(struct io_plan *plan) +struct io_plan io_debug(struct io_plan plan) { - if (io_plan_for_other) { - io_plan_for_other = false; - return; + if (io_plan_nodebug) { + io_plan_nodebug = false; + return plan; } - if (!io_debug || !current) - return; + if (!io_debug_conn || !current) + return plan; - if (!io_debug(current) && !io_debug_wakeup) - return; + if (!io_debug_conn(current) && !io_debug_wakeup) + return plan; io_debug_wakeup = false; - current->plan = *plan; + current->plan = plan; backend_plan_changed(current); /* Call back into the loop immediately. */ io_loop_return = io_loop(); + return plan; } 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)) + if (io_debug_conn && io_debug_conn(conn)) io_debug_wakeup = true; } + +/* Counterpart to io_plan_no_debug(), called in macros in io.h */ +static void io_plan_debug_again(void) +{ + io_plan_nodebug = false; +} #else static void debug_io_wake(struct io_conn *conn) { } +static void io_plan_debug_again(void) +{ +} #endif struct io_listener *io_new_listener_(int fd, @@ -82,6 +96,8 @@ struct io_conn *io_new_conn_(int fd, struct io_plan plan) { struct io_conn *conn = malloc(sizeof(*conn)); + io_plan_debug_again(); + if (!conn) return NULL; @@ -111,6 +127,8 @@ struct io_conn *io_duplex_(struct io_conn *old, struct io_plan plan) { struct io_conn *conn; + io_plan_debug_again(); + assert(!old->duplex); conn = malloc(sizeof(*conn)); @@ -177,7 +195,6 @@ struct io_plan io_write_(const void *data, size_t len, plan.next_arg = arg; plan.pollflag = POLLOUT; - io_plan_debug(&plan); return plan; } @@ -207,7 +224,6 @@ struct io_plan io_read_(void *data, size_t len, plan.next_arg = arg; plan.pollflag = POLLIN; - io_plan_debug(&plan); return plan; } @@ -236,7 +252,6 @@ struct io_plan io_read_partial_(void *data, size_t *len, plan.next_arg = arg; plan.pollflag = POLLIN; - io_plan_debug(&plan); return plan; } @@ -265,26 +280,26 @@ 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; } -struct io_plan io_idle(void) +struct io_plan io_idle_(void) { struct io_plan plan; plan.pollflag = 0; plan.io = NULL; /* Never called (overridden by io_wake), but NULL means closing */ - plan.next = (void *)io_idle; + plan.next = (void *)io_idle_; - io_plan_debug(&plan); return plan; } void io_wake_(struct io_conn *conn, struct io_plan plan) { + io_plan_debug_again(); + /* It might be closing, but we haven't called its finish() yet. */ if (!conn->plan.next) return; @@ -318,7 +333,7 @@ void io_ready(struct io_conn *conn) } /* Close the connection, we're done. */ -struct io_plan io_close(void) +struct io_plan io_close_(void) { struct io_plan plan; @@ -327,7 +342,6 @@ struct io_plan io_close(void) plan.next = NULL; plan.u.close.saved_errno = errno; - io_plan_debug(&plan); return plan; } @@ -339,6 +353,8 @@ struct io_plan io_close_cb(struct io_conn *conn, void *arg) /* Exit the loop, returning this (non-NULL) arg. */ struct io_plan io_break_(void *ret, struct io_plan plan) { + io_plan_debug_again(); + assert(ret); io_loop_return = ret; diff --git a/ccan/io/io.h b/ccan/io/io.h index 828fb666..c85a5b8c 100644 --- a/ccan/io/io.h +++ b/ccan/io/io.h @@ -18,7 +18,7 @@ * Returns NULL on error (and sets errno). */ #define io_new_conn(fd, plan) \ - (io_plan_other(), io_new_conn_((fd), (plan))) + (io_plan_no_debug(), io_new_conn_((fd), (plan))) struct io_conn *io_new_conn_(int fd, struct io_plan plan); /** @@ -83,10 +83,10 @@ void io_close_listener(struct io_listener *listener); * Note that the I/O may actually be done immediately. */ #define io_write(data, len, cb, arg) \ - io_write_((data), (len), \ - typesafe_cb_preargs(struct io_plan, void *, \ - (cb), (arg), struct io_conn *), \ - (arg)) + io_debug(io_write_((data), (len), \ + typesafe_cb_preargs(struct io_plan, void *, \ + (cb), (arg), struct io_conn *), \ + (arg))) struct io_plan io_write_(const void *data, size_t len, struct io_plan (*cb)(struct io_conn *, void *), void *arg); @@ -105,10 +105,10 @@ struct io_plan io_write_(const void *data, size_t len, * Note that the I/O may actually be done immediately. */ #define io_read(data, len, cb, arg) \ - io_read_((data), (len), \ - typesafe_cb_preargs(struct io_plan, void *, \ - (cb), (arg), struct io_conn *), \ - (arg)) + io_debug(io_read_((data), (len), \ + typesafe_cb_preargs(struct io_plan, void *, \ + (cb), (arg), struct io_conn *), \ + (arg))) struct io_plan io_read_(void *data, size_t len, struct io_plan (*cb)(struct io_conn *, void *), void *arg); @@ -128,10 +128,11 @@ struct io_plan io_read_(void *data, size_t len, * Note that the I/O may actually be done immediately. */ #define io_read_partial(data, len, cb, arg) \ - io_read_partial_((data), (len), \ - typesafe_cb_preargs(struct io_plan, void *, \ - (cb), (arg), struct io_conn *), \ - (arg)) + io_debug(io_read_partial_((data), (len), \ + typesafe_cb_preargs(struct io_plan, void *, \ + (cb), (arg), \ + struct io_conn *), \ + (arg))) struct io_plan io_read_partial_(void *data, size_t *len, struct io_plan (*cb)(struct io_conn *, void *), void *arg); @@ -150,10 +151,11 @@ struct io_plan io_read_partial_(void *data, size_t *len, * Note that the I/O may actually be done immediately. */ #define io_write_partial(data, len, cb, arg) \ - io_write_partial_((data), (len), \ - typesafe_cb_preargs(struct io_plan, void *, \ - (cb), (arg), struct io_conn *), \ - (arg)) + io_debug(io_write_partial_((data), (len), \ + typesafe_cb_preargs(struct io_plan, void *, \ + (cb), (arg), \ + struct io_conn *), \ + (arg))) struct io_plan io_write_partial_(const void *data, size_t *len, struct io_plan (*cb)(struct io_conn *, void*), void *arg); @@ -164,7 +166,8 @@ struct io_plan io_write_partial_(const void *data, size_t *len, * This indicates the connection is idle: io_wake() will be called later do * give the connection a new plan. */ -struct io_plan io_idle(void); +#define io_idle() io_debug(io_idle_()) +struct io_plan io_idle_(void); /** * io_timeout - set timeout function if the callback doesn't complete. @@ -202,7 +205,7 @@ bool io_timeout_(struct io_conn *conn, struct timespec ts, * You must io_close() both of them to close the fd. */ #define io_duplex(conn, plan) \ - (io_plan_other(), io_duplex_((conn), (plan))) + (io_plan_no_debug(), io_duplex_((conn), (plan))) struct io_conn *io_duplex_(struct io_conn *conn, struct io_plan plan); /** @@ -212,7 +215,7 @@ struct io_conn *io_duplex_(struct io_conn *conn, struct io_plan plan); * * This makes @conn ready to do I/O the next time around the io_loop(). */ -#define io_wake(conn, plan) (io_plan_other(), io_wake_((conn), (plan))) +#define io_wake(conn, plan) (io_plan_no_debug(), io_wake_((conn), (plan))) void io_wake_(struct io_conn *conn, struct io_plan plan); /** @@ -226,7 +229,7 @@ void io_wake_(struct io_conn *conn, struct io_plan plan); * * If io_loop() is called again, then @plan will be carried out. */ -#define io_break(ret, plan) (io_plan_other(), io_break_((ret), (plan))) +#define io_break(ret, plan) (io_plan_no_debug(), io_break_((ret), (plan))) struct io_plan io_break_(void *ret, struct io_plan plan); /* FIXME: io_recvfrom/io_sendto */ @@ -236,7 +239,8 @@ struct io_plan io_break_(void *ret, struct io_plan plan); * * On return to io_loop, the connection will be closed. */ -struct io_plan io_close(void); +#define io_close() io_debug(io_close_()) +struct io_plan io_close_(void); /** * io_close_cb - helper callback to close a connection. diff --git a/ccan/io/io_plan.h b/ccan/io/io_plan.h index e87011e7..86be1d70 100644 --- a/ccan/io/io_plan.h +++ b/ccan/io/io_plan.h @@ -63,38 +63,43 @@ struct io_plan { #ifdef DEBUG /** - * io_debug - routine to select connection(s) to debug. + * io_debug_conn - routine to select connection(s) to debug. * * If this is set, the routine should return true if the connection is a * debugging candidate. If so, the callchain for I/O operations on this * connection will be linear, for easier use of a debugger. */ -extern bool (*io_debug)(struct io_conn *conn); +extern bool (*io_debug_conn)(struct io_conn *conn); /** - * io_plan_other - mark the next plan not being for the current connection + * io_debug - if we're debugging the current connection, call immediately. * - * Most routines which take a plan are about to apply it to the current - * connection. We (ab)use this pattern for debugging: as soon as such a - * plan is created, it is called, to create a linear call chain. - * - * Some routines, like io_break() and io_wake() take an io_plan, but they - * must not be applied immediately to the current connection, so we call this - * first. + * This determines if we are debugging the current connection: if so, + * it immediately applies the plan and calls back into io_loop() to + * create a linear call chain. */ -#define io_plan_other() ((io_plan_for_other = true)) +struct io_plan io_debug(struct io_plan plan); /** - * io_plan_debug - hook for debugging a plan. + * io_plan_no_debug - mark the next plan not to be called immediately. * - * After constructing a plan, call this. If the current connection is being - * debugged, then it will be immediately serviced with this plan. + * Most routines which take a plan are about to apply it to the current + * connection. We (ab)use this pattern for debugging: as soon as such a + * plan is created it is called, to create a linear call chain. + * + * Some routines, like io_break(), io_duplex() and io_wake() take an + * io_plan, but they must not be applied immediately to the current + * connection, so we call this first. */ -void io_plan_debug(struct io_plan *plan); -extern bool io_plan_for_other; +#define io_plan_no_debug() ((io_plan_nodebug = true)) + +extern bool io_plan_nodebug; #else -#define io_plan_other() (void)0 -static inline void io_plan_debug(struct io_plan *plan) { } +static inline struct io_plan io_debug(struct io_plan plan) +{ + return plan; +} +#define io_plan_no_debug() (void)0 #endif #endif /* CCAN_IO_PLAN_H */ diff --git a/ccan/io/test/run-01-start-finish-DEBUG.c b/ccan/io/test/run-01-start-finish-DEBUG.c index 48f0f3e5..9e33f2bc 100644 --- a/ccan/io/test/run-01-start-finish-DEBUG.c +++ b/ccan/io/test/run-01-start-finish-DEBUG.c @@ -5,4 +5,4 @@ int real_main(void); #include "run-01-start-finish.c" #undef main static bool always_debug(struct io_conn *conn) { return true; } -int main(void) { io_debug = always_debug; return real_main(); } +int main(void) { io_debug_conn = always_debug; return real_main(); } diff --git a/ccan/io/test/run-02-read-DEBUG.c b/ccan/io/test/run-02-read-DEBUG.c index d48260cf..5ca27818 100644 --- a/ccan/io/test/run-02-read-DEBUG.c +++ b/ccan/io/test/run-02-read-DEBUG.c @@ -5,4 +5,4 @@ int real_main(void); #include "run-02-read.c" #undef main static bool always_debug(struct io_conn *conn) { return true; } -int main(void) { io_debug = always_debug; return real_main(); } +int main(void) { io_debug_conn = always_debug; return real_main(); } diff --git a/ccan/io/test/run-03-readpartial-DEBUG.c b/ccan/io/test/run-03-readpartial-DEBUG.c index f23cc312..c473b65c 100644 --- a/ccan/io/test/run-03-readpartial-DEBUG.c +++ b/ccan/io/test/run-03-readpartial-DEBUG.c @@ -5,4 +5,4 @@ int real_main(void); #include "run-03-readpartial.c" #undef main static bool always_debug(struct io_conn *conn) { return true; } -int main(void) { io_debug = always_debug; return real_main(); } +int main(void) { io_debug_conn = always_debug; return real_main(); } diff --git a/ccan/io/test/run-04-writepartial-DEBUG.c b/ccan/io/test/run-04-writepartial-DEBUG.c index 515bd466..fa65bcf5 100644 --- a/ccan/io/test/run-04-writepartial-DEBUG.c +++ b/ccan/io/test/run-04-writepartial-DEBUG.c @@ -5,4 +5,4 @@ int real_main(void); #include "run-04-writepartial.c" #undef main static bool always_debug(struct io_conn *conn) { return true; } -int main(void) { io_debug = always_debug; return real_main(); } +int main(void) { io_debug_conn = always_debug; return real_main(); } diff --git a/ccan/io/test/run-05-write-DEBUG.c b/ccan/io/test/run-05-write-DEBUG.c index ae5eb107..831e6719 100644 --- a/ccan/io/test/run-05-write-DEBUG.c +++ b/ccan/io/test/run-05-write-DEBUG.c @@ -5,4 +5,4 @@ int real_main(void); #include "run-05-write.c" #undef main static bool always_debug(struct io_conn *conn) { return true; } -int main(void) { io_debug = always_debug; return real_main(); } +int main(void) { io_debug_conn = always_debug; return real_main(); } diff --git a/ccan/io/test/run-06-idle-DEBUG.c b/ccan/io/test/run-06-idle-DEBUG.c index f2ed1d47..298ce234 100644 --- a/ccan/io/test/run-06-idle-DEBUG.c +++ b/ccan/io/test/run-06-idle-DEBUG.c @@ -5,4 +5,4 @@ int real_main(void); #include "run-06-idle.c" #undef main static bool always_debug(struct io_conn *conn) { return true; } -int main(void) { io_debug = always_debug; return real_main(); } +int main(void) { io_debug_conn = always_debug; return real_main(); } diff --git a/ccan/io/test/run-07-break-DEBUG.c b/ccan/io/test/run-07-break-DEBUG.c index 7309594e..602d7c2f 100644 --- a/ccan/io/test/run-07-break-DEBUG.c +++ b/ccan/io/test/run-07-break-DEBUG.c @@ -5,4 +5,4 @@ int real_main(void); #include "run-07-break.c" #undef main static bool always_debug(struct io_conn *conn) { return true; } -int main(void) { io_debug = always_debug; return real_main(); } +int main(void) { io_debug_conn = always_debug; return real_main(); } diff --git a/ccan/io/test/run-08-hangup-on-idle-DEBUG.c b/ccan/io/test/run-08-hangup-on-idle-DEBUG.c index 589dc267..f916b8e1 100644 --- a/ccan/io/test/run-08-hangup-on-idle-DEBUG.c +++ b/ccan/io/test/run-08-hangup-on-idle-DEBUG.c @@ -4,4 +4,4 @@ int real_main(void); #include "run-08-hangup-on-idle.c" #undef main static bool always_debug(struct io_conn *conn) { return true; } -int main(void) { io_debug = always_debug; return real_main(); } +int main(void) { io_debug_conn = always_debug; return real_main(); } diff --git a/ccan/io/test/run-08-read-after-hangup-DEBUG.c b/ccan/io/test/run-08-read-after-hangup-DEBUG.c index 189a3eaf..8c602891 100644 --- a/ccan/io/test/run-08-read-after-hangup-DEBUG.c +++ b/ccan/io/test/run-08-read-after-hangup-DEBUG.c @@ -4,4 +4,4 @@ int real_main(void); #include "run-08-read-after-hangup.c" #undef main static bool always_debug(struct io_conn *conn) { return true; } -int main(void) { io_debug = always_debug; return real_main(); } +int main(void) { io_debug_conn = always_debug; return real_main(); } diff --git a/ccan/io/test/run-10-many-DEBUG.c b/ccan/io/test/run-10-many-DEBUG.c index 3b18596e..675c7952 100644 --- a/ccan/io/test/run-10-many-DEBUG.c +++ b/ccan/io/test/run-10-many-DEBUG.c @@ -9,4 +9,4 @@ static bool debug_one(struct io_conn *conn) { return conn == buf[1].reader; } -int main(void) { io_debug = debug_one; return real_main(); } +int main(void) { io_debug_conn = debug_one; return real_main(); } diff --git a/ccan/io/test/run-12-bidir-DEBUG.c b/ccan/io/test/run-12-bidir-DEBUG.c index d2c886d5..55c4cf72 100644 --- a/ccan/io/test/run-12-bidir-DEBUG.c +++ b/ccan/io/test/run-12-bidir-DEBUG.c @@ -5,4 +5,4 @@ int real_main(void); #include "run-12-bidir.c" #undef main static bool always_debug(struct io_conn *conn) { return true; } -int main(void) { io_debug = always_debug; return real_main(); } +int main(void) { io_debug_conn = always_debug; return real_main(); } diff --git a/ccan/io/test/run-13-all-idle-DEBUG.c b/ccan/io/test/run-13-all-idle-DEBUG.c index 1ef1db6d..2969a13b 100644 --- a/ccan/io/test/run-13-all-idle-DEBUG.c +++ b/ccan/io/test/run-13-all-idle-DEBUG.c @@ -5,4 +5,4 @@ int real_main(void); #include "run-13-all-idle.c" #undef main static bool always_debug(struct io_conn *conn) { return true; } -int main(void) { io_debug = always_debug; return real_main(); } +int main(void) { io_debug_conn = always_debug; return real_main(); } diff --git a/ccan/io/test/run-15-timeout-DEBUG.c b/ccan/io/test/run-15-timeout-DEBUG.c index 8ada4c00..d5114862 100644 --- a/ccan/io/test/run-15-timeout-DEBUG.c +++ b/ccan/io/test/run-15-timeout-DEBUG.c @@ -5,4 +5,4 @@ int real_main(void); #include "run-15-timeout.c" #undef main static bool always_debug(struct io_conn *conn) { return true; } -int main(void) { io_debug = always_debug; return real_main(); } +int main(void) { io_debug_conn = always_debug; return real_main(); } diff --git a/ccan/io/test/run-17-homemade-io-DEBUG.c b/ccan/io/test/run-17-homemade-io-DEBUG.c index 40105d6f..5c44ce08 100644 --- a/ccan/io/test/run-17-homemade-io-DEBUG.c +++ b/ccan/io/test/run-17-homemade-io-DEBUG.c @@ -5,4 +5,4 @@ int real_main(void); #include "run-17-homemade-io.c" #undef main static bool always_debug(struct io_conn *conn) { return true; } -int main(void) { io_debug = always_debug; return real_main(); } +int main(void) { io_debug_conn = always_debug; return real_main(); } diff --git a/ccan/io/test/run-17-homemade-io.c b/ccan/io/test/run-17-homemade-io.c index 07794fa9..00fbf223 100644 --- a/ccan/io/test/run-17-homemade-io.c +++ b/ccan/io/test/run-17-homemade-io.c @@ -81,7 +81,6 @@ static struct io_plan io_read_packet(struct packet *pkt, plan.next_arg = arg; plan.pollflag = POLLIN; - io_plan_debug(&plan); return plan; } diff --git a/ccan/io/test/run-18-errno-DEBUG.c b/ccan/io/test/run-18-errno-DEBUG.c index bfa66157..863d1ae1 100644 --- a/ccan/io/test/run-18-errno-DEBUG.c +++ b/ccan/io/test/run-18-errno-DEBUG.c @@ -5,4 +5,4 @@ int real_main(void); #include "run-18-errno.c" #undef main static bool always_debug(struct io_conn *conn) { return true; } -int main(void) { io_debug = always_debug; return real_main(); } +int main(void) { io_debug_conn = always_debug; return real_main(); }