Reentrant functions and memory allocation

M

Morris Dovey

For what I know, one of the rules to make a function reentrant is to
call only reentrant functions (obviously). This is the reason to know
if malloc() is or not reentrant.

That's true. In order to know, it's necessary to either examine
the code or ask someone in whose answer you have a high degree of
confidence.
 
F

fmassei

That's true. In order to know, it's necessary to either examine
the code or ask someone in whose answer you have a high degree of
confidence.
I think that I could easily read the code of one or two malloc()
implementations, but I was just asking if there is the needing or not
for that function to be reentrant in a conforming implementation.
 
E

Eric Sosman

I think that I could easily read the code of one or two malloc()
implementations, but I was just asking if there is the needing or not
for that function to be reentrant in a conforming implementation.

No. 7.1.4p4:

"The functions in the standard library are not
guaranteed to be reentrant and may modify objects
with static storage duration.158)

158) Thus, a signal handler cannot, in general,
call standard library functions."

Now, will you please go to comp.programming.threads for any
further questions? Please?
 
F

fmassei

No. 7.1.4p4:
"The functions in the standard library are not
guaranteed to be reentrant and may modify objects
with static storage duration.158)

158) Thus, a signal handler cannot, in general,
call standard library functions."

Now, will you please go to comp.programming.threads for any
further questions? Please?

Sure! And thank you very much for the help!
 
L

lawrence.jones

Tom?s ? h?ilidhe said:
Why are people talking about malloc being or not being re-entrant? We
don't see the definition of malloc, so we don't care if it calls
itself internally.

A function calling itself is recursion, not reentrancy.

Reentrancy means that multiple independent invocations of the function
can be executing concurrently. In the context of standard C, the only
way to have multiple concurrent invocations of a function is via signal
handlers, so the C Standard's statement that library functions aren't
reentrant means that you can't call any library function from a signal
handler that could possible be invoked while that library function is
running from a call in the mainline code.

Thread safety is a bit weaker than reentrancy since a non-reentrant
function can be made thread safe by adding synchronization primitives
that stop all but one thread from executing at a time.

-Larry Jones

We don't ATTEND parties, we just CRASH 'em. -- Calvin
 
C

CBFalconer

.... snip ...

For what I know, one of the rules to make a function reentrant
is to call only reentrant functions (obviously). This is the
reason to know if malloc() is or not reentrant.

malloc cannot ever be re-entrant. It needs to keep track of system
variables of some sort, to determine where to get memory to
allocate, or where to put memory that is freed. Wo it has to
update memory dedicated to keeping track of itself. There are
(awkward) ways of avoiding these problems, but that is another
subject.
 
G

Gordon Burditt

I still don't understand. Here's what I think I understand:
1) If a function is thread-safe, then it can be executed more than
once simultaneously without malfunctioning.

*FROM A DIFFERENT THREAD*. Think about calling malloc() from a signal
handler entered when the thread is already in malloc().
In general, to make a
function thread-safe, you avoid using static-duration objects and
instead opt for using automatic-duration objects.
2) If a function is re-entrant, then it can execute itself without
malfunctioning.

One definition of re-entrant (taken from Wikipedia, along with some
old OS/360 manuals from the 1970's that talked about "reentrant"
vs. "serially-reusable" code modules) says that it must not rely
on locks to singleton resources, and it must not call non-reentrant
routines.

Now, if multiple threads allocate out of the same pool of memory, then
malloc() must use locking, and that makes it non-reentrant. It also
makes anything that calls malloc() non-reentrant. (could still be
thread-safe, though).
If you have a multi-threaded program that uses malloc, then I can
definitely understand why you'd want malloc to be thread-safe. But I
fail to understand why you'd want it to be re-entrant.

Think about malloc() called from a signal handler. Especially in
a single-threaded program.
If you wanted malloc to be re-entrant, then that suggests to me that
you want to be able to call malloc from within malloc... which sounds
ridiculous to me because you shouldn't be going near the definition of
malloc.

But you might be in the middle of malloc() in your thread when, say,
SIGCHLD or SIGINT goes off, and your signal handler wants to allocate
memory to log the event (and perhaps tell the thread to do something
about it).
I'm not saying I'm right or wrong, but I do know that I don't fully
understand. So could someone please explain why we'd want malloc to be
re-entrant... ?

signals.
 
H

Herbert Rosenau

Dear all,
I'm trying to put some old code in a portable, cross-platform library
and I'm facing a big problem: is there a standard, platform-
independent way to write a reentrant function that allocate dynamic
memory? In other words: is it safe to use malloc() or free() in a
thread-safe function?

Ask your implementation. This is the only instance able to answer that
question.

Mine comes with 4 different answers to that question
- single threaded single processor
- single threaded but multiprocessor
- multiplr threaded but single processor
- multiple threaded and multiple processor

complile and linker flags defines the answer for a single program. The
standard knows nothing about multithreading and multiprocessing but
the implementation knows, so it serves different optimations based on
the requirement the program has.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
 
H

Herbert Rosenau

No. Because the malloc system will be operating on it's own memory
areas, and is not re-entrant. You have to ensure that all accesses
to the malloc package are done through appropriate guards.
Then your implementation is really bad, except your mashine knows
neither how to handle multiple threads nor multiple processors.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
 
H

Herbert Rosenau

Thank you all for the advice, I will write another post there. Anyway,
AFAIK any reentrant function is thread-safe. So, as long as I keep my
library functions reentrant there are no problems. Unfortunately there
are no standard c functions to allocate dynamic memory that are
assured to be reentrant. Is everything correct?

No, these are details known only by your implementation of C. The
standard knows nothing about multithreading and multiprocessing.
Reentrance has nothing to do with multithreading anyway. It is
possible to write reentrant functions who are failing on
multithreading. It is possible to write multithreaded code who fails
misreably on multiprocessing.

Anyway you must ask the documentation of your implementation about the
abilitirs of it to support them. The standard does neither allow nor
disallow it.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
 
H

Herbert Rosenau

What if during a call to malloc() from thread A, the system suspends the
thread and schedules thread B which calls malloc()? Shouldn't malloc()
be reentrant to function properly in this scenario?
No, not really. It is possible to write a function that is not
reentrant, but mutlithreadsave. It is possible to write a fuction that
is save against multiprocessing but not multithreadsave.

But having a function reentrant makes it easier to get it
multithreadsave too and having the fuctionin already multithreadsave
makes it much easier to get save against multiprocessing.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
 
A

Antoninus Twink

AFAIK any reentrant function is thread-safe. So, as long as I keep my
library functions reentrant there are no problems.

I think there might some weird corner-cases of
reentrant-but-not-threadsafe functions (the language lawyers here will
surely know), but basically, yes, if it's reentrant then it's going to
be threadsafe.
Unfortunately there are no standard c functions to allocate dynamic
memory that are assured to be reentrant. Is everything correct?

That's complete nonsense. The regulars here might worry about such
abysmal QoI on their DeathStations, but in practice all the threads
libraries you're ever likely to use will provide threadsafe malloc(),
stdio functions, and everything else you need to program C in a
multithreaded environment. If you apply some common sense (again, unlike
the regulars), what would be the point of providing a threads
implementation for C where the programmer couldn't safely do something
as fundamental as allocate memory?

For example, in the GNU setup, the C library behaves differently when
you link against libpthread: malloc becomes threadsafe (but slower),
fork does the necessary things to pass on the thread setup to the child
process it creates, and so on. I believe other Unices add extra
reentrant versions of standard library functions, e.g. strtok_r and the
like.

Don't be paralyzed by the regulars' paranoia.
 
R

Richard

Antoninus Twink said:
I think there might some weird corner-cases of
reentrant-but-not-threadsafe functions (the language lawyers here will
surely know), but basically, yes, if it's reentrant then it's going to
be threadsafe.


That's complete nonsense. The regulars here might worry about such
abysmal QoI on their DeathStations, but in practice all the threads
libraries you're ever likely to use will provide threadsafe malloc(),
stdio functions, and everything else you need to program C in a
multithreaded environment. If you apply some common sense (again, unlike
the regulars), what would be the point of providing a threads
implementation for C where the programmer couldn't safely do something
as fundamental as allocate memory?

For example, in the GNU setup, the C library behaves differently when
you link against libpthread: malloc becomes threadsafe (but slower),
fork does the necessary things to pass on the thread setup to the child
process it creates, and so on. I believe other Unices add extra
reentrant versions of standard library functions, e.g. strtok_r and the
like.

Don't be paralyzed by the regulars' paranoia.

Very well said.
 
A

Anonymous

I think there might some weird corner-cases of
reentrant-but-not-threadsafe functions (the language lawyers here will
surely know), but basically, yes, if it's reentrant then it's going to
be threadsafe.

Not quite accurate. It'd be better to say that if it's reentrant, it's
possible to use it in a thread-safe manner.

An example of a function that's reentrant but not threadsafe:

void foo(int *i)
{
(*i)++;
}

This function is reentrant, as it can concurrently be called, and no
2 calls can interfere with each other. However, it's not entirely thread
safe, as 2 calls with the same data will produce a race condition. To
make this function fully threadsafe, you'd need some form of lock around
the access to *i

nb: I've seen reentrant used in a few different senses across the
intarwebs, this one seems to be most common. Other senses could even end
up meaning "both thread and deadlock safe", "threadsafe and lockfree",
and a variety of others meanings.
 
C

christian.bau

An example of a function that's reentrant but not threadsafe:

void foo(int *i)
{
    (*i)++;

}

This function is reentrant, as it can concurrently be called, and no
2 calls can interfere with each other.

It is not reentrant. If I have a static variable int x; and I call foo
(&x); and in the middle of the call a signal is raised and the signal
handler calls foo (&x), then you don't know whether x is increased by
2, by 1, or whether you get a result that is just rubbish.
 
A

Anonymous

It is not reentrant. If I have a static variable int x; and I call foo
(&x); and in the middle of the call a signal is raised and the signal
handler calls foo (&x), then you don't know whether x is increased by 2,
by 1, or whether you get a result that is just rubbish.

That's what I said, and why I had the epilogue at the end of my post
about the varying definitions of reentrant. The one I was using, and have
seen used most often, is that *when called on independent data* the
reentrant function is thread safe. If you'd read the line just after you
snipped, you would have seen this.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,280
Latest member
BGBBrock56

Latest Threads

Top