First, make absolute times unsigned. This means that it's safe to
depend on their overflow behaviour (which is undefined for signed
integers). This requires a little extra care in handling comparisons,
but I think I've correctly adjusted them all.
Second, functions registered with schedule_timer() are guaranteed to be
called with precisely the time that was returned by schedule_timer().
Thus, it's only necessary to check these values for equality rather than
doing risky range checks, so do that.
The timing code still does lots that's undefined, unnecessary, or just
wrong, but this is a good start.
git-svn-id: svn://svn.tartarus.org/sgt/putty@9667
cda61777-01e9-0310-a592-
d414129be87e
16 files changed:
-long schedule_timer(int ticks, timer_fn_t fn, void *ctx)
+unsigned long schedule_timer(int ticks, timer_fn_t fn, void *ctx)
struct pinger_tag {
int interval;
int pending;
struct pinger_tag {
int interval;
int pending;
Backend *back;
void *backhandle;
};
static void pinger_schedule(Pinger pinger);
Backend *back;
void *backhandle;
};
static void pinger_schedule(Pinger pinger);
-static void pinger_timer(void *ctx, long now)
+static void pinger_timer(void *ctx, unsigned long now)
{
Pinger pinger = (Pinger)ctx;
{
Pinger pinger = (Pinger)ctx;
- if (pinger->pending && now - pinger->next >= 0) {
+ if (pinger->pending && now == pinger->next) {
pinger->back->special(pinger->backhandle, TS_PING);
pinger->pending = FALSE;
pinger_schedule(pinger);
pinger->back->special(pinger->backhandle, TS_PING);
pinger->pending = FALSE;
pinger_schedule(pinger);
* GETTICKCOUNT() and compare the result with the returned `next'
* value to find out how long you have to make your next wait().)
*/
* GETTICKCOUNT() and compare the result with the returned `next'
* value to find out how long you have to make your next wait().)
*/
-typedef void (*timer_fn_t)(void *ctx, long now);
-long schedule_timer(int ticks, timer_fn_t fn, void *ctx);
+typedef void (*timer_fn_t)(void *ctx, unsigned long now);
+unsigned long schedule_timer(int ticks, timer_fn_t fn, void *ctx);
void expire_timer_context(void *ctx);
void expire_timer_context(void *ctx);
-int run_timers(long now, long *next);
-void timer_change_notify(long next);
+int run_timers(unsigned long now, unsigned long *next);
+void timer_change_notify(unsigned long next);
/*
* Define no-op macros for the jump list functions, on platforms that
/*
* Define no-op macros for the jump list functions, on platforms that
static unsigned long ssh_pkt_getuint32(struct Packet *pkt);
static int ssh2_pkt_getbool(struct Packet *pkt);
static void ssh_pkt_getstring(struct Packet *pkt, char **p, int *length);
static unsigned long ssh_pkt_getuint32(struct Packet *pkt);
static int ssh2_pkt_getbool(struct Packet *pkt);
static void ssh_pkt_getstring(struct Packet *pkt, char **p, int *length);
-static void ssh2_timer(void *ctx, long now);
+static void ssh2_timer(void *ctx, unsigned long now);
static void do_ssh2_transport(Ssh ssh, void *vin, int inlen,
struct Packet *pktin);
static void ssh2_msg_unexpected(Ssh ssh, struct Packet *pktin);
static void do_ssh2_transport(Ssh ssh, void *vin, int inlen,
struct Packet *pktin);
static void ssh2_msg_unexpected(Ssh ssh, struct Packet *pktin);
unsigned long incoming_data_size, outgoing_data_size, deferred_data_size;
unsigned long max_data_size;
int kex_in_progress;
unsigned long incoming_data_size, outgoing_data_size, deferred_data_size;
unsigned long max_data_size;
int kex_in_progress;
- long next_rekey, last_rekey;
+ unsigned long next_rekey, last_rekey;
char *deferred_rekey_reason; /* points to STATIC string; don't free */
/*
char *deferred_rekey_reason; /* points to STATIC string; don't free */
/*
ssh->packet_dispatch[SSH2_MSG_DEBUG] = ssh2_msg_debug;
}
ssh->packet_dispatch[SSH2_MSG_DEBUG] = ssh2_msg_debug;
}
-static void ssh2_timer(void *ctx, long now)
+static void ssh2_timer(void *ctx, unsigned long now)
return;
if (!ssh->kex_in_progress && conf_get_int(ssh->conf, CONF_ssh_rekey_time) != 0 &&
return;
if (!ssh->kex_in_progress && conf_get_int(ssh->conf, CONF_ssh_rekey_time) != 0 &&
- now - ssh->next_rekey >= 0) {
+ now == ssh->next_rekey) {
do_ssh2_transport(ssh, "timeout", -1, NULL);
}
}
do_ssh2_transport(ssh, "timeout", -1, NULL);
}
}
rekey_time = conf_get_int(conf, CONF_ssh_rekey_time);
if (conf_get_int(ssh->conf, CONF_ssh_rekey_time) != rekey_time &&
rekey_time != 0) {
rekey_time = conf_get_int(conf, CONF_ssh_rekey_time);
if (conf_get_int(ssh->conf, CONF_ssh_rekey_time) != rekey_time &&
rekey_time != 0) {
- long new_next = ssh->last_rekey + rekey_time*60*TICKSPERSEC;
- long now = GETTICKCOUNT();
+ unsigned long new_next = ssh->last_rekey + rekey_time*60*TICKSPERSEC;
+ unsigned long now = GETTICKCOUNT();
- if (new_next - now < 0) {
+ if (now - ssh->last_rekey > rekey_time*60*TICKSPERSEC) {
rekeying = "timeout shortened";
} else {
ssh->next_rekey = schedule_timer(new_next - now, ssh2_timer, ssh);
rekeying = "timeout shortened";
} else {
ssh->next_rekey = schedule_timer(new_next - now, ssh2_timer, ssh);
-static void random_timer(void *ctx, long now)
+static void random_timer(void *ctx, unsigned long now)
- if (random_active > 0 && now - next_noise_collection >= 0) {
+ if (random_active > 0 && now == next_noise_collection) {
noise_regular();
next_noise_collection =
schedule_timer(NOISE_REGULAR_INTERVAL, random_timer, &pool);
noise_regular();
next_noise_collection =
schedule_timer(NOISE_REGULAR_INTERVAL, random_timer, &pool);
static void term_schedule_tblink(Terminal *term);
static void term_schedule_cblink(Terminal *term);
static void term_schedule_tblink(Terminal *term);
static void term_schedule_cblink(Terminal *term);
-static void term_timer(void *ctx, long now)
+static void term_timer(void *ctx, unsigned long now)
{
Terminal *term = (Terminal *)ctx;
int update = FALSE;
{
Terminal *term = (Terminal *)ctx;
int update = FALSE;
- if (term->tblink_pending && now - term->next_tblink >= 0) {
+ if (term->tblink_pending && now == term->next_tblink) {
term->tblinker = !term->tblinker;
term->tblink_pending = FALSE;
term_schedule_tblink(term);
update = TRUE;
}
term->tblinker = !term->tblinker;
term->tblink_pending = FALSE;
term_schedule_tblink(term);
update = TRUE;
}
- if (term->cblink_pending && now - term->next_cblink >= 0) {
+ if (term->cblink_pending && now == term->next_cblink) {
term->cblinker = !term->cblinker;
term->cblink_pending = FALSE;
term_schedule_cblink(term);
update = TRUE;
}
term->cblinker = !term->cblinker;
term->cblink_pending = FALSE;
term_schedule_cblink(term);
update = TRUE;
}
- if (term->in_vbell && now - term->vbell_end >= 0) {
+ if (term->in_vbell && now == term->vbell_end) {
term->in_vbell = FALSE;
update = TRUE;
}
if (update ||
term->in_vbell = FALSE;
update = TRUE;
}
if (update ||
- (term->window_update_pending && now - term->next_update >= 0))
+ (term->window_update_pending && now == term->next_update))
struct timer {
timer_fn_t fn;
void *ctx;
struct timer {
timer_fn_t fn;
void *ctx;
- long now;
- long when_set;
+ unsigned long now;
+ unsigned long when_set;
};
static tree234 *timers = NULL;
static tree234 *timer_contexts = NULL;
};
static tree234 *timers = NULL;
static tree234 *timer_contexts = NULL;
+static unsigned long now = 0L;
static int compare_timers(void *av, void *bv)
{
static int compare_timers(void *av, void *bv)
{
-long schedule_timer(int ticks, timer_fn_t fn, void *ctx)
+unsigned long schedule_timer(int ticks, timer_fn_t fn, void *ctx)
struct timer *t, *first;
init_timers();
struct timer *t, *first;
init_timers();
* Returns the time (in ticks) expected until the next timer after
* that triggers.
*/
* Returns the time (in ticks) expected until the next timer after
* that triggers.
*/
-int run_timers(long anow, long *next)
+int run_timers(unsigned long anow, unsigned long *next)
*/
delpos234(timers, 0);
sfree(first);
*/
delpos234(timers, 0);
sfree(first);
- } else if (first->now - now <= 0 ||
- now - (first->when_set - 10) < 0) {
+ } else if (now - first->when_set - 10 >
+ first->now - first->when_set - 10) {
/*
* This timer is active and has reached its running
* time. Run it.
/*
* This timer is active and has reached its running
* time. Run it.
static gint timer_trigger(gpointer data)
{
static gint timer_trigger(gpointer data)
{
- long now = GPOINTER_TO_LONG(data);
- long next;
+ unsigned long now = GPOINTER_TO_LONG(data);
+ unsigned long next, then;
long ticks;
if (run_timers(now, &next)) {
long ticks;
if (run_timers(now, &next)) {
- ticks = next - GETTICKCOUNT();
- timer_id = gtk_timeout_add(ticks > 0 ? ticks : 1, timer_trigger,
+ then = now;
+ now = GETTICKCOUNT();
+ if (now - then > next - then)
+ ticks = 0;
+ else
+ ticks = next - now;
+ timer_id = gtk_timeout_add(ticks, timer_trigger,
LONG_TO_GPOINTER(next));
}
LONG_TO_GPOINTER(next));
}
-void timer_change_notify(long next)
+void timer_change_notify(unsigned long next)
-void timer_change_notify(long next)
+void timer_change_notify(unsigned long next)
int errors;
int use_subsystem = 0;
int got_host = FALSE;
int errors;
int use_subsystem = 0;
int got_host = FALSE;
struct winsize size;
fdlist = NULL;
struct winsize size;
fdlist = NULL;
+ unsigned long next, then;
+ long ticks;
struct timeval tv, *ptv;
if (run_timers(now, &next)) {
struct timeval tv, *ptv;
if (run_timers(now, &next)) {
- ticks = next - GETTICKCOUNT();
- if (ticks < 0) ticks = 0; /* just in case */
+ then = now;
+ now = GETTICKCOUNT();
+ if (now - then > next - then)
+ ticks = 0;
+ else
+ ticks = next - now;
tv.tv_sec = ticks / 1000;
tv.tv_usec = ticks % 1000 * 1000;
ptv = &tv;
tv.tv_sec = ticks / 1000;
tv.tv_usec = ticks % 1000 * 1000;
ptv = &tv;
fd_set rset, wset, xset;
int i, fdcount, fdsize, *fdlist;
int fd, fdstate, rwx, ret, maxfd;
fd_set rset, wset, xset;
int i, fdcount, fdsize, *fdlist;
int fd, fdstate, rwx, ret, maxfd;
- long now = GETTICKCOUNT();
+ unsigned long now = GETTICKCOUNT();
fdlist = NULL;
fdcount = fdsize = 0;
fdlist = NULL;
fdcount = fdsize = 0;
FD_SET_MAX(0, maxfd, rset);
do {
FD_SET_MAX(0, maxfd, rset);
do {
+ unsigned long next, then;
+ long ticks;
struct timeval tv, *ptv;
if (run_timers(now, &next)) {
struct timeval tv, *ptv;
if (run_timers(now, &next)) {
- ticks = next - GETTICKCOUNT();
- if (ticks <= 0)
- ticks = 1; /* just in case */
+ then = now;
+ now = GETTICKCOUNT();
+ if (now - then > next - then)
+ ticks = 0;
+ else
+ ticks = next - now;
tv.tv_sec = ticks / 1000;
tv.tv_usec = ticks % 1000 * 1000;
ptv = &tv;
tv.tv_sec = ticks / 1000;
tv.tv_usec = ticks % 1000 * 1000;
ptv = &tv;
-void timer_change_notify(long next)
+void timer_change_notify(unsigned long next)
-void timer_change_notify(long next)
+void timer_change_notify(unsigned long next)
- long ticks = next - GETTICKCOUNT();
- if (ticks <= 0) ticks = 1; /* just in case */
+ unsigned long now = GETTICKCOUNT();
+ long ticks;
+ if (now - next < INT_MAX)
+ ticks = 0;
+ else
+ ticks = next - now;
KillTimer(hwnd, TIMING_TIMER_ID);
SetTimer(hwnd, TIMING_TIMER_ID, ticks, NULL);
timing_next_time = next;
KillTimer(hwnd, TIMING_TIMER_ID);
SetTimer(hwnd, TIMING_TIMER_ID, ticks, NULL);
timing_next_time = next;
switch (message) {
case WM_TIMER:
if ((UINT_PTR)wParam == TIMING_TIMER_ID) {
switch (message) {
case WM_TIMER:
if ((UINT_PTR)wParam == TIMING_TIMER_ID) {
KillTimer(hwnd, TIMING_TIMER_ID);
if (run_timers(timing_next_time, &next)) {
KillTimer(hwnd, TIMING_TIMER_ID);
if (run_timers(timing_next_time, &next)) {
* Timer for platforms where we must maintain window flashing manually
* (e.g., Win95).
*/
* Timer for platforms where we must maintain window flashing manually
* (e.g., Win95).
*/
-static void flash_window_timer(void *ctx, long now)
+static void flash_window_timer(void *ctx, unsigned long now)
- if (flashing && now - next_flash >= 0) {
+ if (flashing && now == next_flash) {
int errors;
int got_host = FALSE;
int use_subsystem = 0;
int errors;
int got_host = FALSE;
int use_subsystem = 0;
+ unsigned long now, next, then;
sklist = NULL;
skcount = sksize = 0;
sklist = NULL;
skcount = sksize = 0;
}
if (run_timers(now, &next)) {
}
if (run_timers(now, &next)) {
- ticks = next - GETTICKCOUNT();
- if (ticks < 0) ticks = 0; /* just in case */
+ then = now;
+ now = GETTICKCOUNT();
+ if (now - then > next - then)
+ ticks = 0;
+ else
+ ticks = next - now;
} else {
ticks = INFINITE;
}
} else {
ticks = INFINITE;
}
-static void serbreak_timer(void *ctx, long now)
+static void serbreak_timer(void *ctx, unsigned long now)
{
Serial serial = (Serial)ctx;
{
Serial serial = (Serial)ctx;
- if (now >= serial->clearbreak_time && serial->port) {
+ if (now == serial->clearbreak_time && serial->port) {
ClearCommBreak(serial->port);
serial->break_in_progress = FALSE;
logevent(serial->frontend, "Finished serial break");
ClearCommBreak(serial->port);
serial->break_in_progress = FALSE;
logevent(serial->frontend, "Finished serial break");
int do_eventsel_loop(HANDLE other_event)
{
int n, nhandles, nallhandles, netindex, otherindex;
int do_eventsel_loop(HANDLE other_event)
{
int n, nhandles, nallhandles, netindex, otherindex;
+ unsigned long next, then;
+ long ticks;
HANDLE *handles;
SOCKET *sklist;
int skcount;
HANDLE *handles;
SOCKET *sklist;
int skcount;
- long now = GETTICKCOUNT();
+ unsigned long now = GETTICKCOUNT();
if (run_timers(now, &next)) {
if (run_timers(now, &next)) {
- ticks = next - GETTICKCOUNT();
- if (ticks < 0) ticks = 0; /* just in case */
+ then = now;
+ now = GETTICKCOUNT();
+ if (now - then > next - then)
+ ticks = 0;
+ else
+ ticks = next - now;
} else {
ticks = INFINITE;
}
} else {
ticks = INFINITE;
}