From ac8ee8dcb7e4b5370e0c1be9f11e20c0f0a2014b Mon Sep 17 00:00:00 2001 From: Luis Gerhorst <privat@luisgerhorst.de> Date: Wed, 30 Dec 2020 10:28:20 +0100 Subject: [PATCH] per-cpu arm_arch_timer lock and last_cycle --- drivers/timer/arm_arch_timer.c | 51 +++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/drivers/timer/arm_arch_timer.c b/drivers/timer/arm_arch_timer.c index 871c4e659f9..bdc8b6f4cb9 100644 --- a/drivers/timer/arm_arch_timer.c +++ b/drivers/timer/arm_arch_timer.c @@ -15,8 +15,11 @@ #define MAX_TICKS INT32_MAX #define MIN_DELAY (1000) -static struct k_spinlock lock; -static volatile uint64_t last_cycle; +struct arm_arch_timer { + struct k_spinlock lock; + volatile uint64_t last_cycle; +}; +static struct arm_arch_timer timer[CONFIG_MP_NUM_CPUS]; static void arm_arch_timer_compare_isr(const void *arg) { @@ -24,15 +27,18 @@ static void arm_arch_timer_compare_isr(const void *arg) printk("%s on cpu%d\n", __func__, arch_curr_cpu()->id); - k_spinlock_key_t key = k_spin_lock(&lock); + int cpu = arch_curr_cpu()->id; + struct arm_arch_timer *cpu_timer = &timer[cpu]; + + k_spinlock_key_t key = k_spin_lock(&cpu_timer->lock); uint64_t curr_cycle = arm_arch_timer_count(); - uint32_t delta_ticks = (uint32_t)((curr_cycle - last_cycle) / CYC_PER_TICK); + uint32_t delta_ticks = (uint32_t)((curr_cycle - cpu_timer->last_cycle) / CYC_PER_TICK); - last_cycle += delta_ticks * CYC_PER_TICK; + cpu_timer->last_cycle += delta_ticks * CYC_PER_TICK; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { - uint64_t next_cycle = last_cycle + CYC_PER_TICK; + uint64_t next_cycle = cpu_timer->last_cycle + CYC_PER_TICK; if ((uint64_t)(next_cycle - curr_cycle) < MIN_DELAY) { next_cycle += CYC_PER_TICK; @@ -40,7 +46,7 @@ static void arm_arch_timer_compare_isr(const void *arg) arm_arch_timer_set_compare(next_cycle); } - k_spin_unlock(&lock, key); + k_spin_unlock(&cpu_timer->lock, key); z_clock_announce(IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? delta_ticks : 1); } @@ -71,21 +77,24 @@ void z_clock_set_timeout(int32_t ticks, bool idle) ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : \ MIN(MAX_TICKS, MAX(ticks - 1, 0)); - k_spinlock_key_t key = k_spin_lock(&lock); + int cpu = arch_curr_cpu()->id; + struct arm_arch_timer *cpu_timer = &timer[cpu]; + + k_spinlock_key_t key = k_spin_lock(&cpu_timer->lock); uint64_t curr_cycle = arm_arch_timer_count(); uint64_t req_cycle = ticks * CYC_PER_TICK; /* Round up to next tick boundary */ - req_cycle += (curr_cycle - last_cycle) + (CYC_PER_TICK - 1); + req_cycle += (curr_cycle - cpu_timer->last_cycle) + (CYC_PER_TICK - 1); req_cycle = (req_cycle / CYC_PER_TICK) * CYC_PER_TICK; - if ((req_cycle + last_cycle - curr_cycle) < MIN_DELAY) { + if ((req_cycle + cpu_timer->last_cycle - curr_cycle) < MIN_DELAY) { req_cycle += CYC_PER_TICK; } - arm_arch_timer_set_compare(req_cycle + last_cycle); - k_spin_unlock(&lock, key); + arm_arch_timer_set_compare(req_cycle + cpu_timer->last_cycle); + k_spin_unlock(&cpu_timer->lock, key); #endif } @@ -96,11 +105,15 @@ uint32_t z_clock_elapsed(void) return 0; } - k_spinlock_key_t key = k_spin_lock(&lock); - uint32_t ret = (uint32_t)((arm_arch_timer_count() - last_cycle) + /* TODO: irq_lock? */ + int cpu = arch_curr_cpu()->id; + struct arm_arch_timer *cpu_timer = &timer[cpu]; + + k_spinlock_key_t key = k_spin_lock(&cpu_timer->lock); + uint32_t ret = (uint32_t)((arm_arch_timer_count() - cpu_timer->last_cycle) / CYC_PER_TICK); - k_spin_unlock(&lock, key); + k_spin_unlock(&cpu_timer->lock, key); return ret; } @@ -112,9 +125,9 @@ uint32_t z_timer_cycle_get_32(void) #if defined(CONFIG_SMP) && CONFIG_MP_NUM_CPUS > 1 void smp_timer_init(void) { - printk("%s()\n", __func__); - /* arm_arch_timer_set_compare(arm_arch_timer_count() + CYC_PER_TICK); */ - /* arm_arch_timer_enable(true); */ - /* irq_enable(ARM_ARCH_TIMER_IRQ); */ + printk("%s() on cpu%d\n", __func__, arch_curr_cpu()->id); + arm_arch_timer_set_compare(arm_arch_timer_count() + CYC_PER_TICK); + arm_arch_timer_enable(true); + irq_enable(ARM_ARCH_TIMER_IRQ); } #endif -- GitLab