views:

1504

answers:

6

Recently, I asked a question, with title as "Is malloc thread safe?", and inside that I asked, "Is malloc re-entrant?"

I was under the impression that all re-entrant are thread-safe.

Is this assumption wrong?

+6  A: 

If your code is reentrant, then it is thread safe. The converse is not necessarily true, for example you could make yourself non-reentrant but thread safe by slapping a huge lock around the function.

1800 INFORMATION
+4  A: 

All re-entrant code is thread-safe. However, not all thread-safe code is re-entrant, for example a function that synchronizes access with a critical section is not re-entrant (because it cannot be entered by multiple threads) but it is thread-safe (because calling it from multiple threads will not cause any problems)

immibis
+2  A: 

Others have already given useful answers, but if you want additional detail, the wikipedia article on reentrant is worth a peek.

Brian Rasmussen
A: 

In addition to previous answers: two re-entrant functions can be not thread-safe if they handle shared data without locking.

stefaanv
Since re-entrant code shouldn't handle shared data, I stand corrected. re-entrant code is thread-safe as already stated by others.
stefaanv
+3  A: 

Re-entrant functions do not rely on global variables that are exposed in the C library headers .. take strtok() vs strtok_r() for example in C.

Some functions need a place to store a 'work in progress' , re-entrant functions allow you to specify this pointer within the thread's own storage, not in a global.

errno, however, is a slightly different case on POSIX systems :)

In short, reentrant means thread safe, but thread safe does not always mean re-entrant. Some functions do not rely on some exposed global variable that other threads could clobber.

malloc() has no need to be reentrant, it does not depend on anything out of the scope of the entry point for any given thread.

Functions that return statically allocated values are not thread safe without the use of a mutex, futex, or other atomic locking mechanism. Yet, they don't need to be reentrant.

i.e.:

static char *foo(unsigned int flags)
{
  static char ret[2] = { 0 };

  if (flags & FOO_BAR)
    ret[0] = 'c';
  else if (flags & BAR_FOO)
    ret[0] = 'd';
  else
    ret[0] = 'e';

  ret[1] = 'A';

  return ret;
}

So, as you can see, having multiple threads use that without some kind of locking would be a disaster .. but it has no purpose being re-entrant. You'll run into that when dynamically allocated memory is taboo on some embedded platform.

A better way to put 'thread safe' is 'safe for concurrent access' , which better illustrates the need.

Tim Post
@tinketim, Appreciate your clear and detailed response, thanks.
Alphaneo
+1  A: 

This is the definition that Qt uses:

  • A reentrant function can be called simultaneously by multiple threads provided that each invocation of the function references unique data.

  • A thread-safe function can be called simultaneously by multiple threads when each invocation references shared data. All access to the shared data is serialized.

By extension, a class is said to be reentrant if each and every one of its functions can be called simultaneously by multiple threads on different instances of the class. Similarly, the class is said to be thread-safe if the functions can be called by different threads on the same instance.

Georg