void timer_adjust(mame_timer *which, double duration, int param, double period) { double time = get_relative_time(); /* if this is the callback timer, mark it modified */ if (which == callback_timer) callback_timer_modified = 1; /* compute the time of the next firing and insert into the list */ which->callback_param = param; which->enabled = 1; /* set the start and expire times */ which->start = time; which->expire = time + duration; 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 %08X to expire @ %.9f\n", (UINT32)which, which->expire)); if (which == timer_head && cpu_getexecutingcpu() >= 0) activecpu_abort_timeslice(); }
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(); }
static STATE_POSTLOAD( timer_postload ) { emu_timer *privlist = NULL; emu_timer *t; /* remove all timers and make a private list */ while (timer_head != NULL) { t = timer_head; /* temporary timers go away entirely */ if (t->temporary) timer_remove(t); /* permanent ones get added to our private list */ else { timer_list_remove(t); t->next = privlist; privlist = t; } } /* now add them all back in; this effectively re-sorts them by time */ while (privlist != NULL) { t = privlist; privlist = t->next; timer_list_insert(t); } }
void mame_timer_adjust(mame_timer *which, mame_time duration, int param, mame_time period) { mame_time time = get_current_time(); /* error if this is an inactive timer */ if (which->tag == -1) { printf("mame_timer_adjust: adjusting an inactive timer!\n"); logerror("mame_timer_adjust: adjusting an inactive timer!\n"); return; } /* if this is the callback timer, mark it modified */ if (which == callback_timer) callback_timer_modified = 1; /* compute the time of the next firing and insert into the list */ which->callback_param = param; which->enabled = 1; /* set the start and expire times */ which->start = time; which->expire = add_mame_times(time, duration); 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 %s:%d to expire @ %.9f\n", which->file, which->line, mame_time_to_double(which->expire))); if (which == timer_head && cpu_getexecutingcpu() >= 0) activecpu_abort_timeslice(); }
/**@brief Function for handling the timer list deletions. * * @return TRUE if Capture Compare register must be updated, FALSE otherwise. */ static bool list_deletions_handler(void) { timer_node_t * p_timer_old_head; uint8_t user_id; // Remember the old head, so as to decide if new compare needs to be set. p_timer_old_head = mp_timer_id_head; user_id = m_user_array_size; while (user_id--) { timer_user_t * p_user = &mp_users[user_id]; uint8_t user_ops_first = p_user->first; while (user_ops_first != p_user->last) { timer_node_t * p_timer; timer_user_op_t * p_user_op = &p_user->p_user_op_queue[user_ops_first]; // Traverse to next operation in queue. user_ops_first++; if (user_ops_first == p_user->user_op_queue_size) { user_ops_first = 0; } switch (p_user_op->op_type) { case TIMER_USER_OP_TYPE_STOP: // Delete node if timer is running. p_timer = p_user_op->p_node; if (p_timer->is_running) { timer_list_remove(p_user_op->p_node); p_timer->is_running = false; } break; case TIMER_USER_OP_TYPE_STOP_ALL: // Delete list of running timers, and mark all timers as not running. while (mp_timer_id_head != NULL) { timer_node_t * p_head = mp_timer_id_head; p_head->is_running = false; mp_timer_id_head = p_head->next; } break; default: // No implementation needed. break; } } } // Detect change in head of the list. return (mp_timer_id_head != p_timer_old_head); }
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 mame_timer_set_global_time(mame_time newbase) { mame_timer *timer; /* set the new global offset */ global_basetime = newbase; LOG(("mame_timer_set_global_time: new=%.9f head->expire=%.9f\n", mame_time_to_double(newbase), mame_time_to_double(timer_head->expire))); /* now process any timers that are overdue */ while (compare_mame_times(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 (compare_mame_times(timer->period, time_zero) == 0 || compare_mame_times(timer->period, time_never) == 0) timer->enabled = 0; /* set the global state of which callback we're in */ callback_timer_modified = 0; callback_timer = timer; callback_timer_expire_time = timer->expire; /* call the callback */ if (was_enabled && timer->callback) { LOG(("Timer %s:%d fired (expire=%.9f)\n", timer->file, timer->line, mame_time_to_double(timer->expire))); profiler_mark(PROFILER_TIMER_CALLBACK); (*timer->callback)(timer->callback_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 = add_mame_times(timer->expire, timer->period); timer_list_remove(timer); timer_list_insert(timer); } } } }
int timer_enable(emu_timer *which, int enable) { int old; /* set the enable flag */ old = which->enabled; which->enabled = enable; /* remove the timer and insert back into the list */ timer_list_remove(which); timer_list_insert(which); return old; }
static void timer_remove(emu_timer *which) { /* if this is a callback timer, note that */ if (which == callback_timer) callback_timer_modified = TRUE; /* remove it from the list */ timer_list_remove(which); /* free it up by adding it back to the free list */ if (timer_free_tail) timer_free_tail->next = which; else timer_free_head = which; which->next = NULL; timer_free_tail = which; }
RAW_OS_ERROR raw_timer_deactivate(RAW_TIMER *timer_ptr) { RAW_OS_ERROR mutex_ret; #if (RAW_TIMER_FUNCTION_CHECK > 0) if (timer_ptr == 0) { return RAW_NULL_OBJECT; } if (raw_int_nesting) { return RAW_NOT_CALLED_BY_ISR; } #endif if (timer_ptr->object_type != RAW_TIMER_OBJ_TYPE) { return RAW_ERROR_OBJECT_TYPE; } /*Timer state TIMER_DEACTIVE TIMER_DELETED is not allowed to delete*/ if (timer_ptr->timer_state == TIMER_DEACTIVE) { return RAW_TIMER_STATE_INVALID; } if (timer_ptr->timer_state == TIMER_DELETED) { return RAW_TIMER_STATE_INVALID; } mutex_ret = raw_mutex_get(&timer_mutex, RAW_WAIT_FOREVER); RAW_ASSERT(mutex_ret == RAW_SUCCESS); timer_list_remove(timer_ptr); timer_ptr->timer_state = TIMER_DEACTIVE; raw_mutex_put(&timer_mutex); return RAW_SUCCESS; }
static void timer_remove(emu_timer *which) { timer_private *global = which->machine->timer_data; /* if this is a callback timer, note that */ if (which == global->callback_timer) global->callback_timer_modified = TRUE; /* remove it from the list */ timer_list_remove(which); /* free it up by adding it back to the free list */ if (global->freelist_tail) global->freelist_tail->next = which; else global->freelist = which; which->next = NULL; global->freelist_tail = which; }
void timer_remove(mame_timer *which) { /* error if this is an inactive timer */ if (which->tag == -1) { logerror("timer_remove: removed an inactive timer!\n"); return; } /* remove it from the list */ timer_list_remove(which); /* mark it as dead */ which->tag = -1; /* free it up by adding it back to the free list */ if (timer_free_tail) timer_free_tail->next = which; else timer_free_head = which; which->next = NULL; timer_free_tail = which; }
/* ************************************************************************************************************************ * Timer task * * Description: This function is called to start a timer task. * * Arguments :pa is the parameters to task. * ----- * * * * Returns * * Note(s) :This function is called by internal, users shoud not touch this function. * * ************************************************************************************************************************ */ void timer_task(void *pa) { LIST *timer_head_ptr; LIST *iter; LIST *iter_temp; RAW_TIMER *timer_ptr; RAW_OS_ERROR mutex_ret; RAW_U16 callback_ret; /*reset the timer_sem count since it may not be 0 at this point, make it start here*/ raw_semaphore_set(&timer_sem, 0); pa = pa; while (1) { /*timer task will be blocked after call this function*/ raw_semaphore_get(&timer_sem, RAW_WAIT_FOREVER); mutex_ret = raw_mutex_get(&timer_mutex, RAW_WAIT_FOREVER); RAW_ASSERT(mutex_ret == RAW_SUCCESS); /*calculate which timer_head*/ raw_timer_count++; timer_head_ptr = &timer_head; iter = timer_head_ptr->next; while (RAW_TRUE) { /*if timer exits*/ if (iter != timer_head_ptr) { /*Must use iter_temp because iter may be remove later.*/ iter_temp = iter->next; timer_ptr = raw_list_entry(iter, RAW_TIMER, timer_list); /*if timeout*/ if (raw_timer_count == timer_ptr->match) { /*remove from timer list*/ timer_list_remove(timer_ptr); /*if timer is reschedulable*/ if (timer_ptr->reschedule_ticks) { /*Sort by remain time*/ timer_ptr->remain = timer_ptr->reschedule_ticks; timer_ptr->match = raw_timer_count + timer_ptr->remain; timer_ptr->to_head = &timer_head; timer_list_priority_insert(&timer_head, timer_ptr); } else { timer_ptr->timer_state = TIMER_DEACTIVE; } /*Any way both condition need to call registered timer function*/ /*the registered timer function should not touch any timer related API,otherwise system will be crashed*/ if (timer_ptr->raw_timeout_function) { callback_ret = timer_ptr->raw_timeout_function(timer_ptr->raw_timeout_param); if ((callback_ret == TIMER_CALLBACK_STOP) && (timer_ptr->timer_state != TIMER_DEACTIVE)) { /*remove from timer list*/ timer_list_remove(timer_ptr); timer_ptr->timer_state = TIMER_DEACTIVE; } } iter = iter_temp; } else { break; } } /*exit because timer is not exit*/ else { break; } } raw_mutex_put(&timer_mutex); } }
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); } } } }
void timer_adjust_global_time(double delta) { mame_timer *timer; /* add the delta to the global offset */ global_offset += delta; /* scan the list and adjust the times */ for (timer = timer_head; timer != NULL; timer = timer->next) { timer->start -= delta; timer->expire -= delta; } LOG(("timer_adjust_global_time: delta=%.9f head->expire=%.9f\n", delta, timer_head->expire)); /* now process any timers that are overdue */ while (timer_head->expire < TIME_IN_NSEC(1)) { int was_enabled = timer_head->enabled; /* if this is a one-shot timer, disable it now */ timer = timer_head; if (timer->period == 0) timer->enabled = 0; /* set the global state of which callback we're in */ callback_timer_modified = 0; callback_timer = timer; callback_timer_expire_time = timer->expire; /* call the callback */ if (was_enabled && timer->callback) { LOG(("Timer %08X fired (expire=%.9f)\n", (UINT32)timer, timer->expire)); profiler_mark(PROFILER_TIMER_CALLBACK); (*timer->callback)(timer->callback_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 += timer->period; timer_list_remove(timer); timer_list_insert(timer); } } } }