void timer_adjust_periodic(emu_timer *which, attotime start_delay, INT32 param, attotime period) { attotime time = get_current_time(); /* if this is the callback timer, mark it modified */ if (which == callback_timer) callback_timer_modified = TRUE; /* compute the time of the next firing and insert into the list */ which->param = param; which->enabled = TRUE; /* clamp negative times to 0 */ if (start_delay.seconds < 0) start_delay = attotime_zero; /* set the start and expire times */ which->start = time; which->expire = attotime_add(time, start_delay); which->period = period; /* remove and re-insert the timer in its new order */ timer_list_remove(which); timer_list_insert(which); /* if this was inserted as the head, abort the current timeslice and resync */ LOG(("timer_adjust_oneshot %s.%s:%d to expire @ %s\n", which->file, which->func, which->line, attotime_string(which->expire, 9))); if (which == timer_head && cpu_getexecutingcpu() >= 0) activecpu_abort_timeslice(); }
void timer_set_global_time(attotime newbase) { emu_timer *timer; /* set the new global offset */ global_basetime = newbase; LOG(("timer_set_global_time: new=%s head->expire=%s\n", attotime_string(newbase, 9), attotime_string(timer_head->expire, 9))); /* now process any timers that are overdue */ while (attotime_compare(timer_head->expire, global_basetime) <= 0) { int was_enabled = timer_head->enabled; /* if this is a one-shot timer, disable it now */ timer = timer_head; if (attotime_compare(timer->period, attotime_zero) == 0 || attotime_compare(timer->period, attotime_never) == 0) timer->enabled = FALSE; /* set the global state of which callback we're in */ callback_timer_modified = FALSE; callback_timer = timer; callback_timer_expire_time = timer->expire; /* call the callback */ if (was_enabled && timer->callback != NULL) { LOG(("Timer %s:%d[%s] fired (expire=%s)\n", timer->file, timer->line, timer->func, attotime_string(timer->expire, 9))); profiler_mark(PROFILER_TIMER_CALLBACK); (*timer->callback)(Machine, timer->ptr, timer->param); profiler_mark(PROFILER_END); } /* clear the callback timer global */ callback_timer = NULL; /* reset or remove the timer, but only if it wasn't modified during the callback */ if (!callback_timer_modified) { /* if the timer is temporary, remove it now */ if (timer->temporary) timer_remove(timer); /* otherwise, reschedule it */ else { timer->start = timer->expire; timer->expire = attotime_add(timer->expire, timer->period); timer_list_remove(timer); timer_list_insert(timer); } } } }
void timer_add_scheduling_quantum(running_machine *machine, attoseconds_t quantum, attotime duration) { timer_private *global = machine->timer_data; attotime curtime = timer_get_time(machine); attotime expire = attotime_add(curtime, duration); int curr, blank = -1; /* a 0 request (minimum) needs to be non-zero to occupy a slot */ if (quantum == 0) quantum = 1; /* find an equal-duration slot or an empty slot */ for (curr = 1; curr < ARRAY_LENGTH(global->quantum_list); curr++) { quantum_slot *slot = &global->quantum_list[curr]; /* look for a matching quantum and extend it */ if (slot->requested == quantum) { slot->expire = attotime_max(slot->expire, expire); return; } /* remember any empty slots in case of no match */ if (slot->requested == 0) { if (blank == -1) blank = curr; } /* otherwise, expire any expired slots */ else if (attotime_compare(curtime, slot->expire) >= 0) slot->requested = 0; } /* fatal error if no slots left */ assert_always(blank != -1, "Out of scheduling quantum slots!"); /* fill in the item */ global->quantum_list[blank].requested = quantum; global->quantum_list[blank].actual = MAX(global->quantum_list[blank].requested, global->quantum_minimum); global->quantum_list[blank].expire = expire; /* update the minimum */ if (quantum < global->quantum_current->requested) { global->quantum_current = &global->quantum_list[blank]; global->exec.curquantum = global->quantum_current->actual; } }
/* Called via stream_update(stream). * This can be triggered by the core (based on emulated time) or via speaker_level_w(). */ static STREAM_UPDATE( speaker_sound_update ) { speaker_state *sp = (speaker_state *) param; stream_sample_t *buffer = outputs[0]; int volume = sp->levels[sp->level]; double filtered_volume; attotime sampled_time = attotime_zero; if (samples > 0) { /* Prepare to update time state */ sampled_time = attotime_make(0, sp->channel_sample_period); if (samples > 1) sampled_time = attotime_mul(sampled_time, samples); /* Note: since the stream is in the process of being updated, * stream_get_time() will return the time before the update! (MAME 0.130) * Avoid using it here in order to avoid a subtle dependence on the stream implementation. */ } if (samples-- > 0) { /* Note that first interm. sample may be composed... */ filtered_volume = update_interm_samples_get_filtered_volume(sp, volume); /* Composite volume is now quantized to the stream resolution */ *buffer++ = (stream_sample_t)filtered_volume; /* Any additional samples will be homogeneous, however may need filtering across samples: */ while (samples-- > 0) { filtered_volume = update_interm_samples_get_filtered_volume(sp, volume); *buffer++ = (stream_sample_t)filtered_volume; } /* Update the time state */ sp->channel_last_sample_time = attotime_add(sp->channel_last_sample_time, sampled_time); sp->channel_next_sample_time = attotime_add_attoseconds(sp->channel_last_sample_time, sp->channel_sample_period); sp->next_interm_sample_time = attotime_add_attoseconds(sp->channel_last_sample_time, sp->interm_sample_period); sp->last_update_time = sp->channel_last_sample_time; } } /* speaker_sound_update */
INLINE void count_states(int states) { attotime state_time = attotime_make(0, attotime_to_attoseconds(MICRO_STATE_CLOCK_PERIOD) * states); if (!micro.timer) { timer_adjust_oneshot(micro.timer, attotime_never, 0); micro.timer_active = 1; micro.endtime = state_time; } else if (attotime_compare(timer_timeelapsed(micro.timer), micro.endtime) > 0) { timer_adjust_oneshot(micro.timer, attotime_never, 0); micro.timer_active = 1; micro.endtime = state_time; } else micro.endtime = attotime_add(micro.endtime, state_time); }
void timer_execute_timers(running_machine *machine) { timer_private *global = machine->timer_data; emu_timer *timer; /* if the current quantum has expired, find a new one */ if (attotime_compare(global->exec.basetime, global->quantum_current->expire) >= 0) { int curr; global->quantum_current->requested = 0; global->quantum_current = &global->quantum_list[0]; for (curr = 1; curr < ARRAY_LENGTH(global->quantum_list); curr++) if (global->quantum_list[curr].requested != 0 && global->quantum_list[curr].requested < global->quantum_current->requested) global->quantum_current = &global->quantum_list[curr]; global->exec.curquantum = global->quantum_current->actual; } LOG(("timer_set_global_time: new=%s head->expire=%s\n", attotime_string(global->exec.basetime, 9), attotime_string(global->activelist->expire, 9))); /* now process any timers that are overdue */ while (attotime_compare(global->activelist->expire, global->exec.basetime) <= 0) { int was_enabled = global->activelist->enabled; /* if this is a one-shot timer, disable it now */ timer = global->activelist; if (attotime_compare(timer->period, attotime_zero) == 0 || attotime_compare(timer->period, attotime_never) == 0) timer->enabled = FALSE; /* set the global state of which callback we're in */ global->callback_timer_modified = FALSE; global->callback_timer = timer; global->callback_timer_expire_time = timer->expire; /* call the callback */ if (was_enabled && timer->callback != NULL) { LOG(("Timer %s:%d[%s] fired (expire=%s)\n", timer->file, timer->line, timer->func, attotime_string(timer->expire, 9))); profiler_mark_start(PROFILER_TIMER_CALLBACK); (*timer->callback)(machine, timer->ptr, timer->param); profiler_mark_end(); } /* clear the callback timer global */ global->callback_timer = NULL; /* reset or remove the timer, but only if it wasn't modified during the callback */ if (!global->callback_timer_modified) { /* if the timer is temporary, remove it now */ if (timer->temporary) timer_remove(timer); /* otherwise, reschedule it */ else { timer->start = timer->expire; timer->expire = attotime_add(timer->expire, timer->period); timer_list_remove(timer); timer_list_insert(timer); } } } }