Here's a snippet of code that IBM says is reentrant:
/* 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;
}
To me this code is 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?
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?
It seems to make this function reentrant Index would have to be part of the interface as storage provided by the caller.
Reentrant (multi-instance) code is a reusable routine that multiple programs can invoke, interrupt, and reinvoke simultaneously. When you want to reuse code, but associate each instance of the shared code with unique, preserved data, use reentrant code.
A reentrant function must not call non-reentrant functions. A non-reentrant function can often, but not always, be identified by its external interface and its usage. For example, the strtok subroutine is not reentrant, because it holds the string to be broken into tokens.
To be reentrant, a computer program or routine: Must hold no static (or global) non-constant data. Must not return the address to static (or global) non-constant data. Must work only on the data provided to it by the caller.
A function is said to be reentrant if there is a provision to interrupt the function in the course of execution, service the interrupt service routine and then resume the earlier going on function, without hampering its earlier course of action.
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?
The CPU itself will save at least the current instruction pointer (likely the flags register and a few segment and stack registers too but it's CPU dependent) when an interrupt occurs, then e.g. (for x86) invoke code based on a table of function pointers at a specific memory address. Those interrupt handlers can be expected to save (e.g. push to stack) other registers they want to use, then restore them before returning.
Each thread has it's own stack, so this all hangs together.
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?
Often... either saved to stack, or some CPUs (e.g. Sparcs) have register windows - the same CPU opcodes address different registers while the interrupt handler runs, then the context switches back to the registers the program was using.
It's the use of non-stack data that stops a function from being re-entrant, such as a variable that's static within the function body, or some global variable/buffer.
Non-static local variables are usually allocated on the stack or registers. Each thread has its own copy of the stack and registers (or at least the OS creates that illusion by saving and restoring the contents).
Therefore non-static local variables are thread safe, they don't "forget" their value when a context switch occurs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With