ARMv7-A小系统实践(五):两个线程怎样真正切换起来

本章记录什么

这一章实现两个任务之间的协同式切换。重点不在调度算法,而在“暂停的计算怎样被表示”:哪些寄存器属于普通函数边界上的长期状态,任务栈与上下文对象分别保存什么,新任务从未运行过又怎样伪造出第一次恢复所需的现场。

在这一章之前做了什么

启动代码已经建立 SVC 栈并进入 C 环境,AAPCS32 也给出了 r4-r11splr 的保存责任。于是可以先在没有中断的情况下做最小闭环:任务 A 主动调用切换函数,汇编保存 A 的 callee-saved 状态,恢复 B 的状态;B 再切回 A,A 从原调用点之后继续执行。

这种主动切换故意避开 IRQ。原因是它把问题缩小到普通调用边界,容易观察、容易回退。下一章再处理任意指令点被打断时所需的完整异常现场。

ARMv7-A小系统实践(三):AAPCS32、栈与上下文汇编

本章记录什么

这一章讨论 C 函数与汇编函数如何彼此信任。处理器不会自动知道哪几个寄存器应该由调用者保存,也不会自动保证栈满足编译器要求;这些规则来自 AAPCS32。只有把参数、返回值、caller-saved、callee-saved、栈对齐和 lr 的含义连起来,才能安全地从启动汇编调用 C、从 IRQ 入口调用分发器,或者实现一个与编译器兼容的上下文切换函数。

在这一章之前做了什么

上一章已经说明模式切换如何改变 splr 和 SPSR 的可见版本。那属于处理器架构。普通函数调用则通常不改变处理器模式,它依赖的是软件合同。两者都在操作寄存器,但保存集合、返回方式和错误症状完全不同。本章先把这条边界画清楚,再进入多寄存器访存和实际函数边界。

文章中的示例会从一个普通五参数函数开始,逐步走到汇编调用 C、C 调用汇编以及结构体偏移校验。读完后,即使没有工程源码,也应能独立判断一段汇编是否破坏了 ABI。


:D 一言句子获取中...