Timer clean-ups.

This commit is contained in:
OBattler
2023-08-19 05:26:49 +02:00
parent 274b44ab00
commit 6c4a4be6be
11 changed files with 86 additions and 125 deletions

View File

@@ -522,7 +522,7 @@ i420ex_speed_changed(void *priv)
if (te) if (te)
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC); timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
te = timer_is_enabled(&dev->fast_off_timer); te = timer_is_on(&dev->fast_off_timer);
timer_stop(&dev->fast_off_timer); timer_stop(&dev->fast_off_timer);
if (te) if (te)

View File

@@ -1541,10 +1541,10 @@ piix_speed_changed(void *priv)
if (!dev) if (!dev)
return; return;
int te = timer_is_enabled(&dev->fast_off_timer); int to = timer_is_on(&dev->fast_off_timer);
timer_stop(&dev->fast_off_timer); timer_stop(&dev->fast_off_timer);
if (te) if (to)
timer_on_auto(&dev->fast_off_timer, ((double) cpu_fast_off_val + 1) * dev->fast_off_period); timer_on_auto(&dev->fast_off_timer, ((double) cpu_fast_off_val + 1) * dev->fast_off_period);
} }

View File

@@ -497,7 +497,7 @@ sio_speed_changed(void *priv)
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC); timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
if (dev->id == 0x03) { if (dev->id == 0x03) {
te = timer_is_enabled(&dev->fast_off_timer); te = timer_is_on(&dev->fast_off_timer);
timer_stop(&dev->fast_off_timer); timer_stop(&dev->fast_off_timer);
if (te) if (te)

View File

@@ -369,7 +369,7 @@ exec386_2386(int cycs)
} }
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
timer_process_inline(); timer_process();
#ifdef USE_GDBSTUB #ifdef USE_GDBSTUB
if (gdbstub_instruction()) if (gdbstub_instruction())

View File

@@ -256,7 +256,7 @@ update_tsc(void)
if (cycdiff > 0) { if (cycdiff > 0) {
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
timer_process_inline(); timer_process();
} }
} }
@@ -782,7 +782,7 @@ exec386_dynarec(int cycs)
if (cycdiff > 0) { if (cycdiff > 0) {
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
timer_process_inline(); timer_process();
} }
# ifdef USE_GDBSTUB # ifdef USE_GDBSTUB
@@ -943,7 +943,7 @@ exec386(int cycs)
} }
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
timer_process_inline(); timer_process();
#ifdef USE_GDBSTUB #ifdef USE_GDBSTUB
if (gdbstub_instruction()) if (gdbstub_instruction())

View File

@@ -363,7 +363,7 @@ serial_update_speed(serial_t *dev)
if (dev->transmit_enabled & 3) if (dev->transmit_enabled & 3)
timer_on_auto(&dev->transmit_timer, dev->transmit_period); timer_on_auto(&dev->transmit_timer, dev->transmit_period);
if (timer_is_enabled(&dev->timeout_timer)) if (timer_is_on(&dev->timeout_timer))
timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period);
} }

View File

@@ -122,7 +122,7 @@ timer_is_enabled(pc_timer_t *timer)
static __inline int static __inline int
timer_is_on(pc_timer_t *timer) timer_is_on(pc_timer_t *timer)
{ {
return ((timer->flags & TIMER_ENABLED) && (timer->period > 0.0)); return ((timer->flags & TIMER_SPLIT) && (timer->flags & TIMER_ENABLED));
} }
/*Return integer timestamp of timer*/ /*Return integer timestamp of timer*/
@@ -184,45 +184,8 @@ timer_set_p(pc_timer_t *timer, void *priv)
/* The API for big timer periods starts here. */ /* The API for big timer periods starts here. */
extern void timer_stop(pc_timer_t *timer); extern void timer_stop(pc_timer_t *timer);
extern void timer_advance_ex(pc_timer_t *timer, int start);
extern void timer_on(pc_timer_t *timer, double period, int start);
extern void timer_on_auto(pc_timer_t *timer, double period); extern void timer_on_auto(pc_timer_t *timer, double period);
extern void timer_remove_head(void);
extern pc_timer_t *timer_head;
extern int timer_inited;
static __inline void
timer_process_inline(void)
{
pc_timer_t *timer;
if (!timer_head)
return;
while (1) {
timer = timer_head;
if (!TIMER_LESS_THAN_VAL(timer, (uint32_t) tsc))
break;
timer_head = timer->next;
if (timer_head)
timer_head->prev = NULL;
timer->next = timer->prev = NULL;
timer->flags &= ~TIMER_ENABLED;
if (timer->flags & TIMER_SPLIT)
timer_advance_ex(timer, 0); /* We're splitting a > 1 s period into multiple <= 1 s periods. */
else if (timer->callback != NULL) /* Make sure it's no NULL, so that we can have a NULL callback when no operation is needed. */
timer->callback(timer->priv);
}
timer_target = timer_head->ts.ts32.integer;
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -639,7 +639,8 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
} }
} else { } else {
/*Don't stop the timer until it finishes the transfer*/ /*Don't stop the timer until it finishes the transfer*/
if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) &&
!timer_is_on(&ncr_dev->timer)) {
ncr_log("Continuing DMA mode\n"); ncr_log("Continuing DMA mode\n");
ncr_timer_on(ncr_dev, ncr, 0); ncr_timer_on(ncr_dev, ncr, 0);
} }
@@ -671,7 +672,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
if (dev->buffer_length > 0) { if (dev->buffer_length > 0) {
memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length)); memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length));
ncr_log("DMA send timer start, enabled? = %i\n", timer_is_enabled(&ncr_dev->timer)); ncr_log("DMA send timer start, enabled? = %i\n", timer_is_on(&ncr_dev->timer));
ncr_dev->t128.block_count = dev->buffer_length >> 9; ncr_dev->t128.block_count = dev->buffer_length >> 9;
ncr_dev->t128.block_loaded = 1; ncr_dev->t128.block_loaded = 1;
@@ -679,7 +680,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
ncr_dev->t128.status |= 0x04; ncr_dev->t128.status |= 0x04;
} }
} else { } else {
if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer)) {
memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length)); memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length));
ncr_log("DMA send timer on\n"); ncr_log("DMA send timer on\n");
@@ -693,7 +694,8 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
/*a Read 6/10 has occurred, start the timer when the block count is loaded*/ /*a Read 6/10 has occurred, start the timer when the block count is loaded*/
ncr->dma_mode = DMA_INITIATOR_RECEIVE; ncr->dma_mode = DMA_INITIATOR_RECEIVE;
if (ncr_dev->type == 3) { if (ncr_dev->type == 3) {
ncr_log("DMA receive timer start, enabled? = %i, cdb[0] = %02x, buflen = %i\n", timer_is_enabled(&ncr_dev->timer), ncr->command[0], dev->buffer_length); ncr_log("DMA receive timer start, enabled? = %i, cdb[0] = %02x, buflen = %i\n",
timer_is_on(&ncr_dev->timer), ncr->command[0], dev->buffer_length);
if (dev->buffer_length > 0) { if (dev->buffer_length > 0) {
memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length)); memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length));
@@ -709,7 +711,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
timer_on_auto(&ncr_dev->timer, 0.02); timer_on_auto(&ncr_dev->timer, 0.02);
} }
} else { } else {
if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer)) {
memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length)); memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length));
ncr_log("DMA receive timer start\n"); ncr_log("DMA receive timer start\n");

View File

@@ -1055,7 +1055,7 @@ spock_callback(void *priv)
spock_process_scsi(scsi, scb); spock_process_scsi(scsi, scb);
period = 0.2 * ((double) scsi->temp_period); period = 0.2 * ((double) scsi->temp_period);
timer_on(&scsi->callback_timer, (scsi->media_period + period + 10.0), 0); timer_on_auto(&scsi->callback_timer, (scsi->media_period + period + 10.0));
spock_log("Temporary period: %lf us (%" PRIi64 " periods)\n", scsi->callback_timer.period, scsi->temp_period); spock_log("Temporary period: %lf us (%" PRIi64 " periods)\n", scsi->callback_timer.period, scsi->temp_period);
} }

View File

@@ -1293,7 +1293,7 @@ x54x_cmd_callback(void *priv)
} }
period = (1000000.0 / dev->ha_bps) * ((double) dev->temp_period); period = (1000000.0 / dev->ha_bps) * ((double) dev->temp_period);
timer_on(&dev->timer, dev->media_period + period + 10.0, 0); timer_on_auto(&dev->timer, dev->media_period + period + 10.0);
#if 0 #if 0
x54x_log("Temporary period: %lf us (%" PRIi64 " periods)\n", dev->timer.period, dev->temp_period); x54x_log("Temporary period: %lf us (%" PRIi64 " periods)\n", dev->timer.period, dev->temp_period);
#endif #endif

View File

@@ -15,10 +15,13 @@ pc_timer_t *timer_head = NULL;
/* Are we initialized? */ /* Are we initialized? */
int timer_inited = 0; int timer_inited = 0;
static void timer_advance_ex(pc_timer_t *timer);
void void
timer_enable(pc_timer_t *timer) timer_enable(pc_timer_t *timer)
{ {
pc_timer_t *timer_node = timer_head; pc_timer_t *timer_node = timer_head;
int ret = 0;
if (!timer_inited || (timer == NULL)) if (!timer_inited || (timer == NULL))
return; return;
@@ -29,59 +32,63 @@ timer_enable(pc_timer_t *timer)
if (timer->next || timer->prev) if (timer->next || timer->prev)
fatal("timer_enable - timer->next\n"); fatal("timer_enable - timer->next\n");
timer->flags |= TIMER_ENABLED;
/*List currently empty - add to head*/ /*List currently empty - add to head*/
if (!timer_head) { if (!timer_head) {
timer_head = timer; timer_head = timer;
timer->next = timer->prev = NULL; timer->next = timer->prev = NULL;
timer_target = timer_head->ts.ts32.integer; timer_target = timer_head->ts.ts32.integer;
return; ret = 1;
} } else if (TIMER_LESS_THAN(timer, timer_head)) {
if (TIMER_LESS_THAN(timer, timer_head)) {
timer->next = timer_head; timer->next = timer_head;
timer->prev = NULL; timer->prev = NULL;
timer_head->prev = timer; timer_head->prev = timer;
timer_head = timer; timer_head = timer;
timer_target = timer_head->ts.ts32.integer; timer_target = timer_head->ts.ts32.integer;
return; ret = 1;
} } else if (!timer_head->next) {
if (!timer_head->next) {
timer_head->next = timer; timer_head->next = timer;
timer->prev = timer_head; timer->prev = timer_head;
return; ret = 1;
} }
pc_timer_t *prev = timer_head; if (ret == 0) {
timer_node = timer_head->next; pc_timer_t *prev = timer_head;
timer_node = timer_head->next;
while (1) { while (1) {
/*Timer expires before timer_node. Add to list in front of timer_node*/ /*Timer expires before timer_node. Add to list in front of timer_node*/
if (TIMER_LESS_THAN(timer, timer_node)) { if (TIMER_LESS_THAN(timer, timer_node)) {
timer->next = timer_node; timer->next = timer_node;
timer->prev = prev; timer->prev = prev;
timer_node->prev = timer; timer_node->prev = timer;
prev->next = timer; prev->next = timer;
return; ret = 1;
break;
}
/*timer_node is last in the list. Add timer to end of list*/
if (!timer_node->next) {
timer_node->next = timer;
timer->prev = timer_node;
ret = 1;
break;
}
prev = timer_node;
timer_node = timer_node->next;
} }
/*timer_node is last in the list. Add timer to end of list*/
if (!timer_node->next) {
timer_node->next = timer;
timer->prev = timer_node;
return;
}
prev = timer_node;
timer_node = timer_node->next;
} }
/* Do not mark it as enabled if it has failed every single condition. */
if (ret == 1)
timer->flags |= TIMER_ENABLED;
} }
void void
timer_disable(pc_timer_t *timer) timer_disable(pc_timer_t *timer)
{ {
pc_timer_t *cur, *temp;
if (!timer_inited || (timer == NULL) || !(timer->flags & TIMER_ENABLED)) if (!timer_inited || (timer == NULL) || !(timer->flags & TIMER_ENABLED))
return; return;
@@ -120,13 +127,15 @@ timer_process(void)
timer->next = timer->prev = NULL; timer->next = timer->prev = NULL;
timer->flags &= ~TIMER_ENABLED; timer->flags &= ~TIMER_ENABLED;
timer->flags |= TIMER_PROCESS;
if (timer->flags & TIMER_SPLIT) if (timer->flags & TIMER_SPLIT)
timer_advance_ex(timer, 0); /* We're splitting a > 1 s period into multiple <= 1 s periods. */ timer_advance_ex(timer); /* We're splitting a > 1 s period into
else if (timer->callback != NULL) {/* Make sure it's no NULL, so that we can have a NULL callback when no operation is needed. */ multiple <= 1 s periods. */
timer->flags |= TIMER_PROCESS; else if (timer->callback != NULL) /* Make sure it's not NULL, so that we can
have a NULL callback when no operation
is needed. */
timer->callback(timer->priv); timer->callback(timer->priv);
timer->flags &= ~TIMER_PROCESS; timer->flags &= ~TIMER_PROCESS;
}
} }
timer_target = timer_head->ts.ts32.integer; timer_target = timer_head->ts.ts32.integer;
@@ -182,60 +191,47 @@ timer_stop(pc_timer_t *timer)
return; return;
timer->period = 0.0; timer->period = 0.0;
timer_disable(timer); if (timer_is_enabled(timer))
timer_disable(timer);
timer->flags &= ~TIMER_SPLIT; timer->flags &= ~TIMER_SPLIT;
} }
static void static void
timer_do_period(pc_timer_t *timer, uint64_t period, int start) timer_do_period(pc_timer_t *timer, uint64_t period)
{ {
if (!timer_inited || (timer == NULL)) if (timer->flags & TIMER_PROCESS)
return;
if (start)
timer_set_delay_u64(timer, period);
else
timer_advance_u64(timer, period); timer_advance_u64(timer, period);
else
timer_set_delay_u64(timer, period);
} }
void static void
timer_advance_ex(pc_timer_t *timer, int start) timer_advance_ex(pc_timer_t *timer)
{ {
if (!timer_inited || (timer == NULL)) double dusec = ((double) TIMER_USEC);
return; double period;
if (timer->period > MAX_USEC) { period = (timer->period > MAX_USEC) ? MAX_USEC64 : timer->period;
timer_do_period(timer, MAX_USEC64 * TIMER_USEC, start);
timer->period -= MAX_USEC; if (timer->period > 0.0) {
timer->flags |= TIMER_SPLIT; timer_do_period(timer, (uint64_t) (period * dusec));
} else { timer->period -= period;
if (timer->period > 0.0) timer->flags = (timer->flags & ~TIMER_SPLIT) | ((timer->period > MAX_USEC) ? TIMER_SPLIT : 0);
timer_do_period(timer, (uint64_t) (timer->period * ((double) TIMER_USEC)), start); } else if (timer_is_enabled(timer)) {
else timer_disable(timer);
timer_disable(timer);
timer->period = 0.0;
timer->flags &= ~TIMER_SPLIT; timer->flags &= ~TIMER_SPLIT;
} }
} }
void
timer_on(pc_timer_t *timer, double period, int start)
{
if (!timer_inited || (timer == NULL))
return;
timer->period = period;
timer_advance_ex(timer, start);
}
void void
timer_on_auto(pc_timer_t *timer, double period) timer_on_auto(pc_timer_t *timer, double period)
{ {
if (!timer_inited || (timer == NULL)) if (!timer_inited || (timer == NULL))
return; return;
if (period > 0.0) if (period > 0.0) {
timer_on(timer, period, !(timer->flags & TIMER_PROCESS) && (timer->period <= 0.0)); timer->period = period;
else timer_advance_ex(timer);
} else if (timer_is_on(timer))
timer_stop(timer); timer_stop(timer);
} }