Timer clean-ups.
This commit is contained in:
@@ -522,7 +522,7 @@ i420ex_speed_changed(void *priv)
|
||||
if (te)
|
||||
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);
|
||||
if (te)
|
||||
|
@@ -1541,10 +1541,10 @@ piix_speed_changed(void *priv)
|
||||
if (!dev)
|
||||
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);
|
||||
if (te)
|
||||
if (to)
|
||||
timer_on_auto(&dev->fast_off_timer, ((double) cpu_fast_off_val + 1) * dev->fast_off_period);
|
||||
}
|
||||
|
||||
|
@@ -497,7 +497,7 @@ sio_speed_changed(void *priv)
|
||||
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
|
||||
|
||||
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);
|
||||
if (te)
|
||||
|
@@ -369,7 +369,7 @@ exec386_2386(int cycs)
|
||||
}
|
||||
|
||||
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
|
||||
timer_process_inline();
|
||||
timer_process();
|
||||
|
||||
#ifdef USE_GDBSTUB
|
||||
if (gdbstub_instruction())
|
||||
|
@@ -256,7 +256,7 @@ update_tsc(void)
|
||||
|
||||
if (cycdiff > 0) {
|
||||
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 (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
|
||||
timer_process_inline();
|
||||
timer_process();
|
||||
}
|
||||
|
||||
# ifdef USE_GDBSTUB
|
||||
@@ -943,7 +943,7 @@ exec386(int cycs)
|
||||
}
|
||||
|
||||
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
|
||||
timer_process_inline();
|
||||
timer_process();
|
||||
|
||||
#ifdef USE_GDBSTUB
|
||||
if (gdbstub_instruction())
|
||||
|
@@ -363,7 +363,7 @@ serial_update_speed(serial_t *dev)
|
||||
if (dev->transmit_enabled & 3)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@@ -122,7 +122,7 @@ timer_is_enabled(pc_timer_t *timer)
|
||||
static __inline int
|
||||
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*/
|
||||
@@ -184,45 +184,8 @@ timer_set_p(pc_timer_t *timer, void *priv)
|
||||
|
||||
/* The API for big timer periods starts here. */
|
||||
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_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
|
||||
}
|
||||
#endif
|
||||
|
@@ -639,7 +639,8 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
|
||||
}
|
||||
} else {
|
||||
/*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_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) {
|
||||
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_loaded = 1;
|
||||
|
||||
@@ -679,7 +680,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
|
||||
ncr_dev->t128.status |= 0x04;
|
||||
}
|
||||
} 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));
|
||||
|
||||
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*/
|
||||
ncr->dma_mode = DMA_INITIATOR_RECEIVE;
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
} 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));
|
||||
|
||||
ncr_log("DMA receive timer start\n");
|
||||
|
@@ -1055,7 +1055,7 @@ spock_callback(void *priv)
|
||||
spock_process_scsi(scsi, scb);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@@ -1293,7 +1293,7 @@ x54x_cmd_callback(void *priv)
|
||||
}
|
||||
|
||||
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
|
||||
x54x_log("Temporary period: %lf us (%" PRIi64 " periods)\n", dev->timer.period, dev->temp_period);
|
||||
#endif
|
||||
|
138
src/timer.c
138
src/timer.c
@@ -15,10 +15,13 @@ pc_timer_t *timer_head = NULL;
|
||||
/* Are we initialized? */
|
||||
int timer_inited = 0;
|
||||
|
||||
static void timer_advance_ex(pc_timer_t *timer);
|
||||
|
||||
void
|
||||
timer_enable(pc_timer_t *timer)
|
||||
{
|
||||
pc_timer_t *timer_node = timer_head;
|
||||
int ret = 0;
|
||||
|
||||
if (!timer_inited || (timer == NULL))
|
||||
return;
|
||||
@@ -29,59 +32,63 @@ timer_enable(pc_timer_t *timer)
|
||||
if (timer->next || timer->prev)
|
||||
fatal("timer_enable - timer->next\n");
|
||||
|
||||
timer->flags |= TIMER_ENABLED;
|
||||
|
||||
/*List currently empty - add to head*/
|
||||
if (!timer_head) {
|
||||
timer_head = timer;
|
||||
timer->next = timer->prev = NULL;
|
||||
timer_target = timer_head->ts.ts32.integer;
|
||||
return;
|
||||
}
|
||||
|
||||
if (TIMER_LESS_THAN(timer, timer_head)) {
|
||||
ret = 1;
|
||||
} else if (TIMER_LESS_THAN(timer, timer_head)) {
|
||||
timer->next = timer_head;
|
||||
timer->prev = NULL;
|
||||
timer_head->prev = timer;
|
||||
timer_head = timer;
|
||||
timer_target = timer_head->ts.ts32.integer;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!timer_head->next) {
|
||||
ret = 1;
|
||||
} else if (!timer_head->next) {
|
||||
timer_head->next = timer;
|
||||
timer->prev = timer_head;
|
||||
return;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
pc_timer_t *prev = timer_head;
|
||||
timer_node = timer_head->next;
|
||||
if (ret == 0) {
|
||||
pc_timer_t *prev = timer_head;
|
||||
timer_node = timer_head->next;
|
||||
|
||||
while (1) {
|
||||
/*Timer expires before timer_node. Add to list in front of timer_node*/
|
||||
if (TIMER_LESS_THAN(timer, timer_node)) {
|
||||
timer->next = timer_node;
|
||||
timer->prev = prev;
|
||||
timer_node->prev = timer;
|
||||
prev->next = timer;
|
||||
return;
|
||||
while (1) {
|
||||
/*Timer expires before timer_node. Add to list in front of timer_node*/
|
||||
if (TIMER_LESS_THAN(timer, timer_node)) {
|
||||
timer->next = timer_node;
|
||||
timer->prev = prev;
|
||||
timer_node->prev = timer;
|
||||
prev->next = timer;
|
||||
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
|
||||
timer_disable(pc_timer_t *timer)
|
||||
{
|
||||
pc_timer_t *cur, *temp;
|
||||
|
||||
if (!timer_inited || (timer == NULL) || !(timer->flags & TIMER_ENABLED))
|
||||
return;
|
||||
|
||||
@@ -120,13 +127,15 @@ timer_process(void)
|
||||
timer->next = timer->prev = NULL;
|
||||
timer->flags &= ~TIMER_ENABLED;
|
||||
|
||||
timer->flags |= TIMER_PROCESS;
|
||||
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->flags |= TIMER_PROCESS;
|
||||
timer_advance_ex(timer); /* We're splitting a > 1 s period into
|
||||
multiple <= 1 s periods. */
|
||||
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->flags &= ~TIMER_PROCESS;
|
||||
}
|
||||
timer->flags &= ~TIMER_PROCESS;
|
||||
}
|
||||
|
||||
timer_target = timer_head->ts.ts32.integer;
|
||||
@@ -182,60 +191,47 @@ timer_stop(pc_timer_t *timer)
|
||||
return;
|
||||
|
||||
timer->period = 0.0;
|
||||
timer_disable(timer);
|
||||
if (timer_is_enabled(timer))
|
||||
timer_disable(timer);
|
||||
timer->flags &= ~TIMER_SPLIT;
|
||||
}
|
||||
|
||||
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))
|
||||
return;
|
||||
|
||||
if (start)
|
||||
timer_set_delay_u64(timer, period);
|
||||
else
|
||||
if (timer->flags & TIMER_PROCESS)
|
||||
timer_advance_u64(timer, period);
|
||||
else
|
||||
timer_set_delay_u64(timer, period);
|
||||
}
|
||||
|
||||
void
|
||||
timer_advance_ex(pc_timer_t *timer, int start)
|
||||
static void
|
||||
timer_advance_ex(pc_timer_t *timer)
|
||||
{
|
||||
if (!timer_inited || (timer == NULL))
|
||||
return;
|
||||
double dusec = ((double) TIMER_USEC);
|
||||
double period;
|
||||
|
||||
if (timer->period > MAX_USEC) {
|
||||
timer_do_period(timer, MAX_USEC64 * TIMER_USEC, start);
|
||||
timer->period -= MAX_USEC;
|
||||
timer->flags |= TIMER_SPLIT;
|
||||
} else {
|
||||
if (timer->period > 0.0)
|
||||
timer_do_period(timer, (uint64_t) (timer->period * ((double) TIMER_USEC)), start);
|
||||
else
|
||||
timer_disable(timer);
|
||||
timer->period = 0.0;
|
||||
period = (timer->period > MAX_USEC) ? MAX_USEC64 : timer->period;
|
||||
|
||||
if (timer->period > 0.0) {
|
||||
timer_do_period(timer, (uint64_t) (period * dusec));
|
||||
timer->period -= period;
|
||||
timer->flags = (timer->flags & ~TIMER_SPLIT) | ((timer->period > MAX_USEC) ? TIMER_SPLIT : 0);
|
||||
} else if (timer_is_enabled(timer)) {
|
||||
timer_disable(timer);
|
||||
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
|
||||
timer_on_auto(pc_timer_t *timer, double period)
|
||||
{
|
||||
if (!timer_inited || (timer == NULL))
|
||||
return;
|
||||
|
||||
if (period > 0.0)
|
||||
timer_on(timer, period, !(timer->flags & TIMER_PROCESS) && (timer->period <= 0.0));
|
||||
else
|
||||
if (period > 0.0) {
|
||||
timer->period = period;
|
||||
timer_advance_ex(timer);
|
||||
} else if (timer_is_on(timer))
|
||||
timer_stop(timer);
|
||||
}
|
||||
|
Reference in New Issue
Block a user