From 0a4d77e919028c54f5e99fdc883ec04bae92d882 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 28 Apr 2009 20:31:59 +0200 Subject: [PATCH] Simplify checks whether player thread may sleep A player thread may sleep on input or output, except: (1) While it is executing a C_MOD command, it may only sleep on input. (2) While it is being aborted by the update or shutdown, it may not sleep at all. To find out whether a player thread may sleep on input, code has to check condition (2). It needs do to that in recvclient(). To find out whether it may sleep on output, it has to check both conditions. It needs to do that in pr_player() and upr_player(). The code tracked condition (1) in global variable play_lock_wanted. It checked condition (2) by examining struct player member command. Replace all that by new struct player member may_sleep. Initialize it in player_new(), update it in dispatch(), shutdwn() and update_run(). This makes the tests in recvclient(), pr_player() and upr_player() obvious. play_wrlock_wanted() is now unused, remove it. --- include/player.h | 5 +++++ include/server.h | 1 - src/lib/player/accept.c | 1 + src/lib/player/dispatch.c | 3 +++ src/lib/player/recvclient.c | 5 +++-- src/lib/subs/pr.c | 8 ++------ src/server/main.c | 9 +-------- src/server/update.c | 5 ++--- 8 files changed, 17 insertions(+), 20 deletions(-) diff --git a/include/player.h b/include/player.h index 8f8eb51b8..6d442e561 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 5b75aec8e..837e82d2f 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 638914875..1c8c60bc0 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 157ee1448..a75fda28d 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 74a704ce5..3b4f9feab 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 01fc13c8b..876c819e3 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 44a4f9a49..336eb6a65 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 704d6d3d2..7b4a4b676 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); } -- 2.43.0