=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/cmd-wait-for.c,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- src/usr.bin/tmux/cmd-wait-for.c 2016/10/10 21:51:39 1.14 +++ src/usr.bin/tmux/cmd-wait-for.c 2016/10/16 17:55:14 1.15 @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-wait-for.c,v 1.14 2016/10/10 21:51:39 nicm Exp $ */ +/* $OpenBSD: cmd-wait-for.c,v 1.15 2016/10/16 17:55:14 nicm Exp $ */ /* * Copyright (c) 2013 Nicholas Marriott @@ -41,13 +41,18 @@ .exec = cmd_wait_for_exec }; +struct wait_item { + struct cmd_q *cmdq; + TAILQ_ENTRY(wait_item) entry; +}; + struct wait_channel { const char *name; int locked; int woken; - TAILQ_HEAD(, cmd_q) waiters; - TAILQ_HEAD(, cmd_q) lockers; + TAILQ_HEAD(, wait_item) waiters; + TAILQ_HEAD(, wait_item) lockers; RB_ENTRY(wait_channel) entry; }; @@ -135,7 +140,7 @@ cmd_wait_for_signal(__unused struct cmd_q *cmdq, const char *name, struct wait_channel *wc) { - struct cmd_q *wq, *wq1; + struct wait_item *wi, *wi1; if (wc == NULL) wc = cmd_wait_for_add(name); @@ -147,10 +152,11 @@ } log_debug("signal wait channel %s, with waiters", wc->name); - TAILQ_FOREACH_SAFE(wq, &wc->waiters, waitentry, wq1) { - TAILQ_REMOVE(&wc->waiters, wq, waitentry); - if (!cmdq_free(wq)) - cmdq_continue(wq); + TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) { + wi->cmdq->flags &= ~CMD_Q_WAITING; + + TAILQ_REMOVE(&wc->waiters, wi, entry); + free(wi); } cmd_wait_for_remove(wc); @@ -158,10 +164,10 @@ } static enum cmd_retval -cmd_wait_for_wait(struct cmd_q *cmdq, const char *name, - struct wait_channel *wc) +cmd_wait_for_wait(struct cmd_q *cmdq, const char *name, struct wait_channel *wc) { - struct client *c = cmdq->client; + struct client *c = cmdq->client; + struct wait_item *wi; if (c == NULL || c->session != NULL) { cmdq_error(cmdq, "not able to wait"); @@ -178,16 +184,18 @@ } log_debug("wait channel %s not woken (%p)", wc->name, c); - TAILQ_INSERT_TAIL(&wc->waiters, cmdq, waitentry); - cmdq->references++; + wi = xcalloc(1, sizeof *wi); + wi->cmdq = cmdq; + TAILQ_INSERT_TAIL(&wc->waiters, wi, entry); return (CMD_RETURN_WAIT); } static enum cmd_retval -cmd_wait_for_lock(struct cmd_q *cmdq, const char *name, - struct wait_channel *wc) +cmd_wait_for_lock(struct cmd_q *cmdq, const char *name, struct wait_channel *wc) { + struct wait_item *wi; + if (cmdq->client == NULL || cmdq->client->session != NULL) { cmdq_error(cmdq, "not able to lock"); return (CMD_RETURN_ERROR); @@ -197,8 +205,9 @@ wc = cmd_wait_for_add(name); if (wc->locked) { - TAILQ_INSERT_TAIL(&wc->lockers, cmdq, waitentry); - cmdq->references++; + wi = xcalloc(1, sizeof *wi); + wi->cmdq = cmdq; + TAILQ_INSERT_TAIL(&wc->lockers, wi, entry); return (CMD_RETURN_WAIT); } wc->locked = 1; @@ -210,17 +219,17 @@ cmd_wait_for_unlock(struct cmd_q *cmdq, const char *name, struct wait_channel *wc) { - struct cmd_q *wq; + struct wait_item *wi; if (wc == NULL || !wc->locked) { cmdq_error(cmdq, "channel %s not locked", name); return (CMD_RETURN_ERROR); } - if ((wq = TAILQ_FIRST(&wc->lockers)) != NULL) { - TAILQ_REMOVE(&wc->lockers, wq, waitentry); - if (!cmdq_free(wq)) - cmdq_continue(wq); + if ((wi = TAILQ_FIRST(&wc->lockers)) != NULL) { + wi->cmdq->flags &= ~CMD_Q_WAITING; + TAILQ_REMOVE(&wc->lockers, wi, entry); + free(wi); } else { wc->locked = 0; cmd_wait_for_remove(wc); @@ -233,19 +242,19 @@ cmd_wait_for_flush(void) { struct wait_channel *wc, *wc1; - struct cmd_q *wq, *wq1; + struct wait_item *wi, *wi1; RB_FOREACH_SAFE(wc, wait_channels, &wait_channels, wc1) { - TAILQ_FOREACH_SAFE(wq, &wc->waiters, waitentry, wq1) { - TAILQ_REMOVE(&wc->waiters, wq, waitentry); - if (!cmdq_free(wq)) - cmdq_continue(wq); + TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) { + wi->cmdq->flags &= ~CMD_Q_WAITING; + TAILQ_REMOVE(&wc->waiters, wi, entry); + free(wi); } wc->woken = 1; - TAILQ_FOREACH_SAFE(wq, &wc->lockers, waitentry, wq1) { - TAILQ_REMOVE(&wc->lockers, wq, waitentry); - if (!cmdq_free(wq)) - cmdq_continue(wq); + TAILQ_FOREACH_SAFE(wi, &wc->lockers, entry, wi1) { + wi->cmdq->flags &= ~CMD_Q_WAITING; + TAILQ_REMOVE(&wc->lockers, wi, entry); + free(wi); } wc->locked = 0; cmd_wait_for_remove(wc);