diff --git a/include/player.h b/include/player.h index 8f8eb51b..6d442e56 100644 --- a/include/player.h +++ b/include/player.h @@ -51,6 +51,10 @@ #define CAP bit(6) #define MONEY bit(7) +enum player_sleep { + PLAYER_SLEEP_NEVER, PLAYER_SLEEP_ON_INPUT, PLAYER_SLEEP_FREELY +}; + struct player { struct emp_qelem queue; empth_t *proc; @@ -76,6 +80,7 @@ struct player { int simulation; /* e.g. budget command */ double dolcost; time_t curup; /* when last input was received */ + enum player_sleep may_sleep; /* when may thread sleep? */ int aborted; /* interrupt cookie or EOF received? */ int eof; /* EOF (cookie or real) received? */ int recvfail; /* #recvclient() failures */ diff --git a/include/server.h b/include/server.h index 5b75aec8..837e82d2 100644 --- a/include/server.h +++ b/include/server.h @@ -40,7 +40,6 @@ extern int shutdown_pending; extern empth_rwlock_t *play_lock; -extern int play_wrlock_wanted; extern int update_running; extern time_t update_time[UPDATE_TIME_LEN]; diff --git a/src/lib/player/accept.c b/src/lib/player/accept.c index 63891487..1c8c60bc 100644 --- a/src/lib/player/accept.c +++ b/src/lib/player/accept.c @@ -89,6 +89,7 @@ player_new(int s) } emp_insque(&lp->queue, &Players); lp->cnum = NATID_BAD; + lp->may_sleep = PLAYER_SLEEP_FREELY; lp->curid = -1; time(&lp->curup); } diff --git a/src/lib/player/dispatch.c b/src/lib/player/dispatch.c index 157ee144..a75fda28 100644 --- a/src/lib/player/dispatch.c +++ b/src/lib/player/dispatch.c @@ -85,6 +85,8 @@ dispatch(char *buf, char *redir) pr("Command not implemented\n"); return 0; } + player->may_sleep = command->c_flags & C_MOD + ? PLAYER_SLEEP_ON_INPUT : PLAYER_SLEEP_FREELY; player->command = command; empth_rwlock_rdlock(play_lock); if (redir) { @@ -109,5 +111,6 @@ dispatch(char *buf, char *redir) } empth_rwlock_unlock(play_lock); player->command = NULL; + player->may_sleep = PLAYER_SLEEP_FREELY; return 0; } diff --git a/src/lib/player/recvclient.c b/src/lib/player/recvclient.c index 74a704ce..3b4f9fea 100644 --- a/src/lib/player/recvclient.c +++ b/src/lib/player/recvclient.c @@ -39,7 +39,6 @@ #include "journal.h" #include "player.h" #include "prototypes.h" -#include "server.h" /* * Receive a line of input from the current player. @@ -80,7 +79,9 @@ recvclient(char *cmd, int size) * Flush all queued output before potentially sleeping in * io_input(), to make sure player sees the prompt. */ - while (io_output(player->iop, !play_wrlock_wanted) > 0) ; + while (io_output(player->iop, + player->may_sleep >= PLAYER_SLEEP_ON_INPUT) > 0) + ; /* * If io_output_all() blocked and got unblocked by command diff --git a/src/lib/subs/pr.c b/src/lib/subs/pr.c index 01fc13c8..876c819e 100644 --- a/src/lib/subs/pr.c +++ b/src/lib/subs/pr.c @@ -244,9 +244,7 @@ pr_player(struct player *pl, int id, char *buf) if (player == pl) { while (io_output_if_queue_long(pl->iop, - !play_wrlock_wanted - && !(pl->command && (pl->command->c_flags & C_MOD))) - > 0) + pl->may_sleep == PLAYER_SLEEP_FREELY) > 0) ; } } @@ -302,9 +300,7 @@ upr_player(struct player *pl, int id, char *buf) if (player == pl) { while (io_output_if_queue_long(pl->iop, - !play_wrlock_wanted - && !(pl->command && (pl->command->c_flags & C_MOD))) - > 0) + pl->may_sleep == PLAYER_SLEEP_FREELY) > 0) ; } } diff --git a/src/server/main.c b/src/server/main.c index 44a4f9a4..336eb6a6 100644 --- a/src/server/main.c +++ b/src/server/main.c @@ -86,13 +86,6 @@ static void loc_NTTerm(void); */ empth_rwlock_t *play_lock; -/* - * Is a thread attempting to take an exclusive play_lock? - * Threads holding a shared play_lock must not sleep while this is - * true. - */ -int play_wrlock_wanted; - static char pidfname[] = "server.pid"; /* Run as daemon? If yes, detach from controlling terminal etc. */ @@ -421,12 +414,12 @@ shutdwn(int sig) logerror("Shutdown commencing (cleaning up threads.)"); - play_wrlock_wanted = 1; for (p = player_next(NULL); p; p = player_next(p)) { if (p->state != PS_PLAYING) continue; pr_flash(p, "Server shutting down...\n"); p->state = PS_SHUTDOWN; + p->may_sleep = PLAYER_SLEEP_NEVER; p->aborted++; if (p->command) { pr_flash(p, "Shutdown aborting command\n"); diff --git a/src/server/update.c b/src/server/update.c index 704d6d3d..7b4a4b67 100644 --- a/src/server/update.c +++ b/src/server/update.c @@ -193,12 +193,12 @@ update_run(void) { struct player *p; - play_wrlock_wanted = 1; for (p = player_next(NULL); p; p = player_next(p)) { if (p->state != PS_PLAYING) continue; if (p->command) { pr_flash(p, "Update aborting command\n"); + p->may_sleep = PLAYER_SLEEP_NEVER; p->aborted = 1; empth_wakeup(p->proc); } @@ -206,14 +206,13 @@ update_run(void) empth_rwlock_wrlock(play_lock); if (*pre_update_hook) { if (run_hook(pre_update_hook, "pre-update")) { - play_wrlock_wanted = 0; empth_rwlock_unlock(play_lock); return; } } update_running = 1; update_main(); - play_wrlock_wanted = update_running = 0; + update_running = 0; empth_rwlock_unlock(play_lock); }