#include "empthread.h"
+#define UPDATE_TIME_LEN 16
+
extern int shutdown_pending;
-extern int update_pending;
+extern empth_rwlock_t *play_lock;
+extern int play_wrlock_wanted;
extern int update_running;
-extern empth_rwlock_t *update_lock;
-#define UPDATE_TIME_LEN 16
extern time_t update_time[UPDATE_TIME_LEN];
void market_init(void);
* Mustn't block a player thread while update is pending, or else
* a malicous player could delay the update indefinitely
*/
- while (((n = io_output(iop, IO_NOWAIT)) > 0) && !update_pending) {
+ while ((n = io_output(iop, IO_NOWAIT)) > 0 && !play_wrlock_wanted)
empth_select(iop->fd, EMPTH_FD_WRITE);
- }
+
return n;
}
pr("Command not implemented\n");
return 0;
}
- empth_rwlock_rdlock(update_lock);
+ empth_rwlock_rdlock(play_lock);
if (redir) {
prredir(redir);
uprnf(buf);
logerror("%s: returned bad value", command->c_form);
break;
}
- empth_rwlock_unlock(update_lock);
+ empth_rwlock_unlock(play_lock);
player->command = 0;
return 0;
}
static void loc_NTTerm(void);
#endif
+/*
+ * Lock to synchronize player threads with update and shutdown.
+ * Update and shutdown takes it exclusive, commands take it shared.
+ */
+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. */
}
empth_wakeup(p->proc);
}
- empth_rwlock_wrlock(update_lock);
+ empth_rwlock_wrlock(play_lock);
/* rely on player_kill_idle() for killing hung player threads */
if (sig)
logerror("Server shutting down on signal %d", sig);
#include "prototypes.h"
#include "server.h"
-/*
- * Lock to synchronize player threads with the update.
- * Update takes it exclusive, commands take it shared.
- */
-empth_rwlock_t *update_lock;
-
-/*
- * Update is pending, player threads must give up update_lock ASAP.
- * This means they must not block while update_pending.
- */
-int update_pending;
-
/*
* Update is running.
* Can be used to suppress messages, or direct them to bulletins.
if (update_get_schedule() < 0)
exit(1);
- update_lock = empth_rwlock_create("Update");
- if (!update_lock)
+ play_lock = empth_rwlock_create("Update");
+ if (!play_lock)
exit_nomem();
dp = player_new(-1);
{
struct player *p;
- update_pending = 1;
+ play_wrlock_wanted = 1;
for (p = player_next(0); p != 0; p = player_next(p)) {
if (p->state != PS_PLAYING)
continue;
empth_wakeup(p->proc);
}
}
- empth_rwlock_wrlock(update_lock);
+ empth_rwlock_wrlock(play_lock);
if (*pre_update_hook) {
if (run_hook(pre_update_hook, "pre-update")) {
- update_pending = 0;
- empth_rwlock_unlock(update_lock);
+ play_wrlock_wanted = 0;
+ empth_rwlock_unlock(play_lock);
return;
}
}
update_running = 1;
update_main();
- update_pending = update_running = 0;
- empth_rwlock_unlock(update_lock);
+ play_wrlock_wanted = update_running = 0;
+ empth_rwlock_unlock(play_lock);
}
static int