Another term you might run into is "thread-safe". It refers to whether it is safe to run a particular function in multiple threads. Banfa's link explains the subtle distinction between thread-safety and reentrancy. Evfery reentrant function is also thread-safe; but a thread-safe function is not necessarily reentrant.
As Banfa said, the real criteria for whether a function is reentrant is whether there are any portions of it where improper operation could occur if multiple instances of the function were running at once. These portions of the function are sometimes referred to as "critical regions".
For example, Function1 reads a global variable and returns that value plus one without changing the global variable. Multiple copies of Function1 will not interfere with each other -- the function appears to be reentrant. However, Function2 increments that same global variable. If Function1 and Function2 run simultaneously then it is possible for Function2 to increment the global after it has been read by Function1, but before Function1 returns. Does this make Function1 nonreentrant? It depends on the consequences of Function1 returning an out-of-date value. I suggest there is no critical region in Function1; the critical region is actually in Function1's callers, starting from just before the call to Function1 and extending to where it is finished using the return value from Function1.
For example, Function2 increments a global variable. The compiler might implement this operation by reading the global variable into a register, incrementing the register, and writing the new value back to the global variable. If so, then another instance of Function2 could interfere with itself if it occurs after the read operation, but before the write operation. The effect would be to nullify the second instance of Function2. This problem can be avoided if the compiler can be coerced into implementing the increment operation via an "atomically" (for example, via
read-modify-write. Unfortunately, there is no portable way to force the compiler to do this; if for no other reason, because some processors have no support for read-modify-write. Even if you can increment the global variable atomically, you have to look at the callers of Function2 to see if they would be adversely affected by multiple Function2 threads.