unified/arm: fix saving of registers in __pendsv()

The unified kernel calls a function (_get_next_ready_thread) to fetch
the next thread to run: it thus must save caller-saved registers that
are expected to hold a value before calling such function.

The callee-saved registers are available after saving them in the
outgoing thread's stack, so use some of those instead to reduce the
number of registers to save before calling _get_next_ready_thread. Also,
save caller-saved registers in callee-saved registers instead of on the
stack to reduce memory accesses.

This issue did not show up previously, probably because
_get_next_ready_thread did not use the regsiters that had to be saved,
but an upcoming optimization to that function stomps on them.

Change-Id: I27dcededace846e623c3870d907f0d4c464173bf
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
This commit is contained in:
Benjamin Walsh 2016-10-01 18:49:36 -04:00 committed by Maureen Helm
commit fc59e5b584

View file

@ -92,8 +92,8 @@ SECTION_FUNC(TEXT, __pendsv)
* to pend PendSV have been taken with the current kernel
* state and this is what we're handling currently.
*/
ldr ip, =_SCS_ICSR
ldr r3, =_SCS_ICSR_UNPENDSV
ldr v4, =_SCS_ICSR
ldr v3, =_SCS_ICSR_UNPENDSV
/* protect the kernel state while we play with the thread lists */
movs.n r0, #_EXC_IRQ_DEFAULT_PRIO
@ -102,9 +102,11 @@ SECTION_FUNC(TEXT, __pendsv)
/* find out incoming thread (fiber or task) */
#ifdef CONFIG_KERNEL_V2
push {lr}
mov.n v2, lr
movs.n v1, r1
blx _get_next_ready_thread
pop {lr}
movs.n r1, v1
mov.n lr, v2
movs.n r2, r0
#else
/* is there a fiber ready ? */
@ -137,8 +139,8 @@ SECTION_FUNC(TEXT, __pendsv)
* has been handled.
*/
/* _SCS_ICSR is still in ip and _SCS_ICSR_UNPENDSV in r3 */
str r3, [ip, #0]
/* _SCS_ICSR is still in v4 and _SCS_ICSR_UNPENDSV in v3 */
str v3, [v4, #0]
/* restore BASEPRI for the incoming thread */
ldr r0, [r2, #__tTCS_basepri_OFFSET]