ZHCU876Z July 2001 – October 2023 SM320F28335-EP
C 标准假定只有一个执行线程,唯一的例外是为信号处理程序提供有限的支持。可重入性问题通过禁止在信号处理程序中执行任何操作来加以避免。不过,SYS/BIOS 应用程序具有多个线程,这些线程都需要修改相同的全局程序状态,例如 CIO 缓冲器,因此可重入性是个问题。
可重入性问题仍要由您自行负责解决,但运行时支持环境确实通过为临界区提供支持,从而对多线程的可重入性提供了基本的支持。这个实现方案并不能帮助您避免可重入性问题,例如从内部中断调用运行时支持函数;这仍然是您的责任。
运行时支持环境提供了钩子程序来安装临界区基元。默认情况下,假定使用单线程模型,并且不采用临界区基元。在 SYS/BIOS 等多线程系统中,内核会安排在这些钩子程序中安装信号量锁基元函数,然后在运行时支持输入需要由临界区加以保护的代码时调用这些函数。
在整个运行时支持环境中,当因访问全局状态而需要由临界区加以保护时,会调用函数 _lock()。此操作会调用提供的基元(若已安装)并获取信号量,然后再继续。在临界区完成后,会调用 _unlock() 来释放信号量。
通常,SYS/BIOS 负责创建和安装基元,因此您无需采取任何操作。不过,这种机制可以在不使用 SYS/BIOS 锁定机制的多线程应用程序中使用。
您不应直接定义 _lock() 和 _unlock() 函数;相反,通过调用安装函数来指示运行时支持环境使用以下基元:
void _register_lock (void ( *lock)());
void _register_unlock(void (*unlock)());
_register_lock() 和 _register_unlock() 的参数应为无参数且不返回任何值的函数,此类函数会实现某种全局信号量锁定:
extern volatile sig_atomic_t *sema = SHARED_SEMAPHORE_LOCATION;
static int sema_depth = 0;
static void my_lock(void)
{
while (ATOMIC_TEST_AND_SET(sema, MY_UNIQUE_ID) != MY_UNIQUE_ID);
sema_depth++;
}
static void my_unlock(void)
{
if (!--sema_depth) ATOMIC_CLEAR(sema);
}
运行时支持会对 _lock() 的调用进行嵌套,因此基元必须跟踪嵌套级别。