driver: timer: npcx: fix the racing condition when getting current uptime

In npcx_itim_evt_isr, it updates the cyc_sys_announced variable and
then calls sys_clock_announce() to update the kernel curr_tick variable.
If an ISR handler with higher priority preempts the timer ISR after the
sys_clock_announce is updated and before the sys_clock_announce() is
called, it will read the wrong time when calling k_uptime_get() because
the cyc_sys_announced and the curr_tick are not synchronized.
The commit fixes the problem by raising the timer's interrupt priority
to the highest one (i.e. 1 in npcx's configuration).

This commit also moves the computation of the delta cycle inside the
spinlock in sys_clock_elapsed() to prevent another potential racing
condition.

Signed-off-by: Jun Lin <CHLin56@nuvoton.com>
Signed-off-by: Wealian Liao <WHLIAO@nuvoton.com>
This commit is contained in:
Jun Lin 2022-01-04 14:16:29 +08:00 committed by Anas Nashif
commit 803a4ff620
3 changed files with 4 additions and 4 deletions

View file

@ -249,12 +249,12 @@ uint32_t sys_clock_elapsed(void)
}
k_spinlock_key_t key = k_spin_lock(&lock);
uint64_t current = npcx_itim_get_sys_cyc64();
uint64_t delta_cycle = npcx_itim_get_sys_cyc64() - cyc_sys_announced;
k_spin_unlock(&lock, key);
/* Return how many ticks elapsed since last sys_clock_announce() call */
return (uint32_t)((current - cyc_sys_announced) / SYS_CYCLES_PER_TICK);
return (uint32_t)(delta_cycle / SYS_CYCLES_PER_TICK);
}
uint32_t sys_clock_cycle_get_32(void)

View file

@ -68,7 +68,7 @@
reg-names = "evt_itim", "sys_itim";
clocks = <&pcc NPCX_CLOCK_BUS_LFCLK NPCX_PWDWN_CTL4 3
&pcc NPCX_CLOCK_BUS_APB2 NPCX_PWDWN_CTL7 5>;
interrupts = <46 2>; /* Event timer interrupt */
interrupts = <46 1>; /* Event timer interrupt */
label = "ITIM";
};

View file

@ -69,7 +69,7 @@
reg-names = "evt_itim", "sys_itim";
clocks = <&pcc NPCX_CLOCK_BUS_LFCLK NPCX_PWDWN_CTL4 0
&pcc NPCX_CLOCK_BUS_APB2 NPCX_PWDWN_CTL7 5>;
interrupts = <28 2>; /* Event timer interrupt */
interrupts = <28 1>; /* Event timer interrupt */
label = "ITIM";
};