/* reentrant function (a better solution) */ char *strtoupper_r(char *in_str,char *out_str) { int index; for (index = 0; in_str[index]; index++) out_str[index] = toupper(in_str[index]); out_str[index] = 0 return out_str; }
对我来说,这段代码不可重入,因为循环计数器的索引是在本地定义的.如果操作系统在循环中中断此线程,并且另一个线程调用此函数,则索引将丢失.我错过了什么?为什么这段代码被认为是可重入的?
操作系统在中断线程时是否将类似索引的局部变量的副本保存到线程的堆栈中,然后在处理继续时重新建立变量?
解决方法
not reentrant because index for the loop counter is being defined locally. Should the OS interrupt this thread inside the loop,and another thread call this function,index would be lost. What am I missing? Why is this code considered reentrant?
当发生中断时,cpu本身将至少保存当前指令指针(可能是标志寄存器和一些段和堆栈寄存器,但它依赖于cpu),例如,(对于x86)基于特定内存地址处的函数指针表调用代码.可以期望这些中断处理程序保存(例如,推送到堆栈)他们想要使用的其他寄存器,然后在返回之前恢复它们.
每个线程都有自己的堆栈,所以这一切都挂起来了.
Does the OS save a copy of local variables like index on to a thread’s stack when it interrupts the thread and then reestablishes the variables when processing continues?
通常……要么保存到堆栈,要么某些cpu(例如Sparc)有注册窗口 – 相同的cpu操作码在中断处理程序运行时寻址不同的寄存器,然后上下文切换回程序正在使用的寄存器.