diff options
Diffstat (limited to 'common/cyclic.c')
| -rw-r--r-- | common/cyclic.c | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/common/cyclic.c b/common/cyclic.c index ec952a01ee1..1cf5b25d1d8 100644 --- a/common/cyclic.c +++ b/common/cyclic.c @@ -22,17 +22,11 @@ DECLARE_GLOBAL_DATA_PTR; void hw_watchdog_reset(void); -struct hlist_head *cyclic_get_list(void) -{ - /* Silence "discards 'volatile' qualifier" warning. */ - return (struct hlist_head *)&gd->cyclic_list; -} - static bool cyclic_is_registered(const struct cyclic_info *cyclic) { const struct cyclic_info *c; - hlist_for_each_entry(c, cyclic_get_list(), list) { + hlist_for_each_entry(c, &gd->cyclic_list, list) { if (c == cyclic) return true; } @@ -41,7 +35,7 @@ static bool cyclic_is_registered(const struct cyclic_info *cyclic) } void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, - uint64_t delay_us, const char *name) + u64 delay_us, const char *name) { cyclic_unregister(cyclic); @@ -52,7 +46,7 @@ void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, cyclic->name = name; cyclic->delay_us = delay_us; cyclic->start_time_us = get_timer_us(0); - hlist_add_head(&cyclic->list, cyclic_get_list()); + hlist_add_head(&cyclic->list, &gd->cyclic_list); } void cyclic_unregister(struct cyclic_info *cyclic) @@ -67,26 +61,41 @@ static void cyclic_run(void) { struct cyclic_info *cyclic; struct hlist_node *tmp; - uint64_t now, cpu_time; + u64 now, after, cpu_time; + + /* + * Nothing to do if the list is empty. Also, schedule() can be + * called before timer infrastructure is ready, in which case + * calling get_timer_us() before the (empty) loop could cause + * a divide-by-0 or otherwise crash the system. No clients + * should be registered before the timer infrastructure is up, + * so the check for the list being empty should be + * ok. Otherwise, we would need a new GD_FLG_TIMERS_READY + * flag. + */ + if (hlist_empty(&gd->cyclic_list)) + return; /* Prevent recursion */ if (gd->flags & GD_FLG_CYCLIC_RUNNING) return; gd->flags |= GD_FLG_CYCLIC_RUNNING; - hlist_for_each_entry_safe(cyclic, tmp, cyclic_get_list(), list) { + now = get_timer_us(0); + hlist_for_each_entry_safe(cyclic, tmp, &gd->cyclic_list, list) { /* * Check if this cyclic function needs to get called, e.g. * do not call the cyclic func too often */ - now = get_timer_us(0); if (time_after_eq64(now, cyclic->next_call)) { /* Call cyclic function and account it's cpu-time */ cyclic->next_call = now + cyclic->delay_us; cyclic->func(cyclic); + after = get_timer_us(0); cyclic->run_cnt++; - cpu_time = get_timer_us(0) - now; + cpu_time = after - now; cyclic->cpu_time_us += cpu_time; + now = after; /* Check if cpu-time exceeds max allowed time */ if ((cpu_time > CONFIG_CYCLIC_MAX_CPU_TIME_US) && @@ -127,7 +136,7 @@ int cyclic_unregister_all(void) struct cyclic_info *cyclic; struct hlist_node *tmp; - hlist_for_each_entry_safe(cyclic, tmp, cyclic_get_list(), list) + hlist_for_each_entry_safe(cyclic, tmp, &gd->cyclic_list, list) cyclic_unregister(cyclic); return 0; |
