(player_kill_idle): Don't kill hung player threads. That code was
flawed. Firstly, when player_kill_idle() ran before the player thread
could react to being aborted by update or shutdown, player_kill_idle()
incorrectly diagnosed it as hung. Secondly, terminating hung threads
leaks resources and can leave a stale play_lock behind. It could
perhaps even corrupt game state. It might salvage some scenarios, but
makes others worse. Not worth it.
Remove the concept of thread priorities from empthread.h. Only LWP
supports priorities. Update synchronization used to rely on them,
which naturally worked only with LWP (#1504036). With that fixed, no
uses of priorities remained, but a minor bug did: players could starve
out threads with priorities below PP_PLAYER, i.e. delete_lostitems()
and player_kill_idle(). Closes #1458175:
(empth_create): Remove parameter prio. Callers changed. Also gets
rid of misleading comments in pthread.c and ntthread.c.
(PP_MAIN, PP_UPDATE, PP_SHUTDOWN, PP_SCHED, PP_TIMESTAMP, PP_PLAYER)
(PP_ACCEPT, PP_KILLIDLE): Remove.
(empth_init, empth_create) [EMPTH_LWP]: Pass priority 1.
(dispatch): Set player->command before acquiring play_lock, to make
sure the command is reliably aborted on update and shutdown. Before,
redirection output could block while player->command was still null,
letting players delay the update or shutdown indefinitely.
(dispatch): Rwlocks can hand out read locks while a write lock is
wanted. Unfair to writers, but possible. This lets commands run with
!player->aborted, which can then block on input and thus let players
delay the update or shutdown indefinitely. Avoid by spinning until
the update is done.
LWP failed to wake up threads sleeping in empth_sleep() while other
threads were runnable. This let players with a sufficiently fast
connection starve out system threads, including the update. Fix:
[EMPTH_LWP] (lwpWakeupSleep): External linkage.
[EMPTH_LWP] (lwpReschedule): Call it.
Replace incorrect uses of update_pending by update_running, fixing
buggy behavior while the update was trying to gain control:
(sct_do_upd_mob, shp_do_upd_mob, lnd_do_upd_mob, pln_do_upd_mob):
MOB_ACCESS mobility update was skipped.
(telegram_is_new): Fix recognition of new telegrams by timestamp.
(wu): Bulletins got misfiled as production reports.
(shp_nav): Sail path got ignored.
(setrel): Declaration of war failed silently with SLOW_WAR enabled.
Messages got suppressed.
(PR, mpr): Messages got misdirected to bulletins.
Use the new Empire clock for implementing MOB_ACCESS:
(lndstr, plnstr, sctstr, shpstr): Change timestamp members lnd_access,
pln_access, sct_access, shp_access from real time (time_t) to ETUs
within a turn (short).
(land_ca, plane_ca, sect_ca, ship_ca): Update accordingly.
(build_ship, build_land, build_bridge, build_plane, build_tower)
(explore, check_trade, bsanct, takeover, takeover_ship)
(takeover_land): Use game_tick_to_now() instead of time() to update
the timestamp. Change check_trade(), takeover_ship(), takeover_land()
to do that only when MOB_ACCESS is enabled, for consistency.
(lupgr, supgr, pupgr, takeover_ship): Don't touch the timestamp where
mobility isn't touched either.
(sct_do_upd_mob, shp_do_upd_mob, lnd_do_upd_mob, pln_do_upd_mob): Use
game_tick_to_now() instead of increase_mob() to compute ETUs since
the timestamp and update the timestamp. Closes #1012699.
(increase_mob): Remove.
(mob_sect, mob_ship, mob_land, mob_plane): sct_do_upd_mob() & friends
no longer do the right thing at the update. Use game_reset_tick() and
pass its result directly to do_mob_sect() & friends. This is only
correct when argument is etu_per_update, which it always is. Remove
parameter. Callers changed.
(do_mob_sect, do_mob_ship, do_mob_land, do_mob_plane): Oops on
negative argument.
(mob_acc_globals, timestampfil, mobupdate, updating_mob)
(update_all_mob, timestamp_fixing, update_timestamps, mobility_check):
The mobupdate command was important to let deities manually
synchronize mobility updating with updates. That's no longer needed.
The code behind it is somewhat hairy and ugly, and updating it to work
with the Empire clock is just not worth it. Remove. Users changed.
(player_coms): Update accordingly.
(upda): Remove display of mobility updating state.
(mobility_init): No need to fix up mobility on startup, as the Empire
clock runs normally even when the server is down. Remove. Caller
changed.
Use the new Empire clock for generating BTUs:
(natstr): New member nat_access.
(cou_ca): New selector access.
(grant_btus, accrued_btus): New.
(prod_nat, init_nat): Use grant_btus(). BTUs are now made at the
update in addition to login, because that lets us get away with a
simple ETU stamp (nat_access).
(nat_cap): Replaced by grant_btus(), remove.
Provide an Empire clock with ETU resolution that is properly
synchronized to updates (the one based on s_p_etu isn't synchronized):
(gamestr): New members game_turn, game_tick, game_rt.
(game_ca): New selectors for them. Restrict tick and rt to deity for
now. We'd need xdump update the Empire clock to make them safe for
players.
(game_record_update): New.
(update_main): Call it.
(game_tick_tick, game_tick_to_now, game_step_a_tick): New, not yet
used.
New Empire table game, to be used for global stuff:
(gamestr, EF_GAME, game_ca): New.
(empfile): Declare the table.
(ef_open_srv, ef_close_srv): Open and close it.
(main): Create it.
(empobj_storage): New member game.
Remove the demand update feature veto. It's virtually unused, flawed
by design (by voting last players can tactically vote no and thus
build up veto rights), and its implementation is buggy:
(update_missed): Remove.
(zdone): Don't show it.
(demand_check): Remove veto check.
(natstr, cou_ca): Remove member nat_missed and its selector.
(zdone): Don't clear and don't show it.
(update_removewants): Don't increment it. This was buggy anyway; it
incremented even on non-demand updates.
(prnat): Don't show it, remove key 'U'.
(docountry): Don't change it, deprecate the now useless key 'U'.
(do_mob_sect, do_mob_plane): Remove the special case for maxed out
mobility. The general case is fine.
(do_mob_ship): Move the special case for maxed out mobility into the
fuel conditional. The general non-fuel case is fine.
(do_mob_land): Likewise, but continue to call lnd_fortify() only when
needed.
New update scheduler:
(schedulefil): New.
(set_dirs, set_paths): Rename. Initialize schedulfil.
(read_schedule): New. Can read several updates, which will be used in
later changesets.
(update_time): Change to array. Will be used in later changesets.
(update_schedule_anchor): New.
(update_init): Initialize it.
(update_get_schedule): New.
(update_init): Call it to initialize update_time[].
(update_sched): Rewrite.
(update_forced, update_wanted): Replace.
(update_reschedule): New.
(main): Call it on SIGHUP to reload the schedule.
(update_trigger, update_force, force, player_coms): Drop force's
capability to schedule updates in the future, because it's not worth
the trouble to implement again. Deities can simply edit the schedule
file to schedule updates. Remove update_force() and
update_trigger()'s parameter.
(upda): Update for new scheduler. Take care to keep output the same
as far as possible, even though it's ugly, to avoid breaking clients.
(update_policy, adj_update, update_times, hourslop, blitz_time):
econfig keys removed.
(update_demand, UPD_DEMAND_NONE, UPD_DEMAND_SCHED, UPD_DEMAND_ASYNC)
(update_demandpolicy, UDP_NORMAL, UDP_TIMES, UDP_NORMAL, UDP_BLITZ)
(UDP_MAX, UDP_DEFAULT, UDDEM_TMCHECK, UDDEM_COMSET, UDDEM_DISABLE)
(UDDEM_MAX, UDDEM_DEFAULT): econfig key and values replaced. Users
changed. wantupd.h is now empty, remove.
(demand_check): External linkage.
(update_policy_check): Now pointless, remove.
(is_daytime_near, min_to_next_daytime, regular_update_time)
(scheduled_update_time, next_scheduled_time, updatetime)
(next_update_time, next_update_check_time): Unused, Remove.
(demand_check, demandupdatecheck): Move call of demand_update_time()
from demand_check(), which controls all demand updates, to
demandupdatecheck(), which controls only unscheduled ones. Fixes
update command not to lie about the next scheduled demand update.
(demandupdatecheck): Check updates_disabled() so that zdone no longer
claims to trigger an update when it can't.
Ron Koenderink [Sun, 11 Mar 2007 21:29:37 +0000 (21:29 +0000)]
(S_IRUSR, S_IWUSR, S_IEUSR, S_IRWXU,
S_IRGRP, S_IWGRP, S_IEGRP, S_IRWXG,
S_IROTH, S_IWOTH, S_IEOTH, S_IRWXO) [_WIN32]:
Add #ifndef for standard defines as the the MinGW environment has the
user defines already created. Correct EXEC permision to use S_IEXEC.
Set the group and other permssions to 0 as they do not exist in WIN32.
Ron Koenderink [Sat, 10 Mar 2007 16:29:51 +0000 (16:29 +0000)]
(add, disa, ef_open, logerror, main): Switch permissions to
standard defines instead of magic numbers to improve portability.
Also define WIN32 equivalents to the standard defines.
Rewrite how updates are triggered (closes #1504036):
(update_init, update_sched, update_run, update_wait): Don't create a
separate UpdateSched thread, run update_sched() in the Update thread.
Run the update by calling update_run() instead of by signalling its
thread. update_run() replaces update_wait(); it just runs the update
and returns instead of waiting for the signal to update in a loop.
Move initialization of the Update thread's *player to its new thread
entry point.
(update_sem, update_init): Remove update_sem.
(update_thread): New.
(update_init): Initialize it.
(update_forced): New.
(update_trigger, update_force): Wake up update_thread with
update_force set.
(update_sched): Reset it before sleep, test it after sleep so that
schedule checking is only done for scheduled updates, not forced
updates.
(update_sched, update_init): Move sanity test of s_p_etu to
update_init().
Make empth_wakeup() and empth_terminate() wake up empth_sleep(), and
empth_sleep() return whether that happened:
[EMPTH_LWP] (lwpWakeupSleep): New, factored out of lwpSelect().
[EMPTH_LWP] (lwpSelect): Use it.
[EMPTH_LWP] (lwpWakeup): New. Call lwpWakeupFd() if sleeping in
lwpSleepFd(), lwpWakeupSleep() if sleeping in lwpSleepUntil().
[EMPTH_LWP] (lwpTerminate, empth_wakeup): Use it rather than
lwpWakeupFd().
[EMPTH_LWP] (lwpWakeupFd): Internal linkage.
[EMPTH_LWP] (lwpSleepUntil): Reset member runtime, so that lwpWakeup()
can test it reliably. Return how sleep woke up.
[EMPTH_LWP] (empth_sleep): Return value of lwpSleepUntil().
[EMPTH_POSIX] (EMPTH_INTR): New.
[EMPTH_POSIX] (empth_wakeup): Set state to it.
[EMPTH_POSIX] (empth_restorectx): Clear state.
[EMPTH_POSIX] (empth_sleep): Don't re-seleep when state is not clear,
i.e. thread was woken up prematurely. Return how sleep woke up.
[EMPTH_W32] (empth_sleep): Implement by waiting on hThreadEvent with a
timeout rather than a straight Sleep(). Return how sleep woke up.
Simplify. Should also be more efficient.
(LwpSigCheck): New.
(lwpCatchAwaitedSig): Set it.
(lwpSigWait): Clear it.
(lwpSigWakeup): Test it.
(lwpSigWakeup): Unblock LwpSigWaiter without testing LwpSigCatched.
(lwpSigWait): Test LwpSigCatched after wakeup.
(LwpSigAwaited, LwpSigPtr): Remove.
(lwpCreate): Initialize members runtime and fd. Initializing fd is
necessary to make lwpWakeupFd() work reliably. Initializing runtime
isn't strictly necessary, as it is used only while the thread is on
LwpDelayq, and putting it there sets runtime.
Ron Koenderink [Sat, 27 Jan 2007 02:04:27 +0000 (02:04 +0000)]
(unit_view): New, create by expanding shp_view() to work for
land_unit as well.
(do_unit_move): Add view option for land units using unit_view().
Combine ship and land viewing using the unit_view().
(shp_view): Remove, not used any more, replaced by unit_view().
Ron Koenderink [Wed, 24 Jan 2007 23:24:37 +0000 (23:24 +0000)]
(unit_path): New, create by combining shp_path() and lnd_path().
(do_unit_move): Replace shp_path() and lnd_path() with unit_path().
(shp_path, lnd_path): Remove shp_path() and lnd_path(),
not used any more.