 |
|
 |
|
03-25-05 12:56 PM
I'm beginning to study posix threads (using linux as development and
test system), and I have some doubts, so don't be surprised if some of
my questions make little or no sense.
1) Are the issues that arise inside signal handlers the same as those
that come up when using threads? ie, a function that cannot be safely
invoked inside a signal handler cannot also be safely invoked inside a
thread, and viceversa?
2) My understanding is that, unless otherwise specified, all the
library calls are to be considered thread-unsafe. In particular, it's
very likely that malloc() uses global variables, so it should not be
called (at least, without some kind of protection for mutual
exclusion). But, if we assume this, then every other library call
becomes unsafe, since the implementation could potentially call
malloc() internally (unless, as usual, the function is explicitly
marked thread-safe, such as those ending in _r (correct?)).
So, how can this problem be solved, and what are the issues to be
aware of when calling library functions inside a thread?
Thanks in advance.
[ Post a follow-up to this message ]
|
|
|
 |
|
 |
|
 |
|
03-25-05 12:56 PM
"subnet" <sunglo@katamail.com> wrote in message
news:9dcfb2af.0503250205.243b6836@posting.google.com...
> I'm beginning to study posix threads (using linux as development and
> test system), and I have some doubts, so don't be surprised if some of
> my questions make little or no sense.
>
> 1) Are the issues that arise inside signal handlers the same as those
> that come up when using threads? ie, a function that cannot be safely
> invoked inside a signal handler cannot also be safely invoked inside a
> thread, and viceversa?
No, they're not the same at all.
> 2) My understanding is that, unless otherwise specified, all the
> library calls are to be considered thread-unsafe. In particular, it's
> very likely that malloc() uses global variables, so it should not be
> called (at least, without some kind of protection for mutual
> exclusion). But, if we assume this, then every other library call
> becomes unsafe, since the implementation could potentially call
> malloc() internally (unless, as usual, the function is explicitly
> marked thread-safe, such as those ending in _r (correct?)).
> So, how can this problem be solved, and what are the issues to be
> aware of when calling library functions inside a thread?
Have you ever heard of POSIX pthreads? Pretty much every modern UNIX
supports it, and it solves all these problems. It's an open standard.
DS
[ Post a follow-up to this message ]
|
|
|
 |
|
 |
|
 |
|
03-25-05 12:56 PM
> No, they're not the same at all.
<irony>Why waste all those words? Just say "No".</hirony>
> Have you ever heard of POSIX pthreads? Pretty much every modern UNIX
> supports it, and it solves all these problems. It's an open standard.
Did you actually read my post? It started with "I'm beginning to study
posix threads".
And so what? Do you mean that many threads can all call malloc() at the
same time?
[ Post a follow-up to this message ]
|
|
|
 |
|
 |
|
 |
|
03-25-05 11:03 PM
sunglo@katamail.com writes:
>
> Did you actually read my post? It started with "I'm beginning to study
> posix threads".
> And so what? Do you mean that many threads can all call malloc() at the
> same time?
It obviously depends on your libc, but any reasonable libc including
pthreads should allow it. Rather few functions are unsafe for
concurrent calls. Most of them have a note in the manual stating if
this is the case.
--
Måns Rullgård
mru@inprovide.com
[ Post a follow-up to this message ]
|
|
|
 |
|
 |
|
 |
|
03-25-05 11:03 PM
sunglo@katamail.com wrote:
>
>
> <irony>Why waste all those words? Just say "No".</hirony>
>
>
> Did you actually read my post? It started with "I'm beginning to study
> posix threads".
> And so what? Do you mean that many threads can all call malloc() at the
> same time?
Yes. If an environment supports POSIX threads,
then its supporting library(s) (where 'malloc()'
and other functions reside) are "thread-safe" as
well.
Generally, library functions in a threaded
environment act transparently - i.e., you don't
have to do anything special to use these functions
in a threaded application.
Consider the library function 'strcat()'.
You can call 'strcat()' from many threads at
the same time just as you would in a single
threaded application. However, if more than
one thread is attempting to 'strcat()' to the
_same_ string (the same physical location in
memory) at the same time, the resultant string
would be undefined.
So, while 'strcat()' is a thread-safe reentrant
function, it's _data_ is not. You control
concurrency to data structures in a threaded
application using pthread functions
'pthread_mutex_lock()'/'pthread_mutex_unlock()',
for example.
There are exceptions (as another poster has
stated) and their man page would indicate which
functions are unsafe in a threaded application.
A simple example is the function 'strtok()' in
which the alternate function 'strtok_r()' is
provided for multi-threaded applications.
Depending on your architecture, you have to set
you build environment correctly. On Solaris, for
example, "man pthreads" provides a discussion
on what's needed to build (compile & link)
a threaded application.
HTH,
--
Stephen
[ Post a follow-up to this message ]
|
|
|
 |
|
 |
|
 |
|
03-25-05 11:03 PM
Stephen wrote:
> Yes. If an environment supports POSIX threads,
> then its supporting library(s) (where 'malloc()'
> and other functions reside) are "thread-safe" as
> well.
Thank you. I just did not find this stated clearly in my google
searches.
> Consider the library function 'strcat()'.
> You can call 'strcat()' from many threads at
> the same time just as you would in a single
> threaded application. However, if more than
> one thread is attempting to 'strcat()' to the
> _same_ string (the same physical location in
> memory) at the same time, the resultant string
> would be undefined.
Of course. I was only referring to thread safety wrt data that is not
under the programmer's control (that is, possible global/static data
manipulation inside the library function implementation).
> So, while 'strcat()' is a thread-safe reentrant
Although this is not exactly what I originally asked, let me elaborate
on this and ask you to confirm if my understanding is correct, since
the two concepts you mention are often confused (perhaps because often
a function has both properties), and I'm still not 100% sure of the
difference.
I think that "thread-safe" and "reentrant" are not exactly the same
thing (correct me if I'm wrong), because a "reentrant" function is also
"thread-safe", but the opposite is not necessarily true.
>From what I understand, "reentrancy" means that the function can be
safely interrupted anywhere in the middle, and re-entered (re-executed
from the start).
This could happen, for example, if the function is a signal handler and
another signal of the same kind arrives in the middle. This means that,
for the second execution, another activation frame is created *on the
same stack* (since the two invocations are part of *the same* scheduler
execution unit).
This implies that:
- to be re-entrant, a function must not modify static/global data (and
must not use locks), and
- if a function is re-entrant, it's of course also thread-safe (if it
works correctly with many invocations on a single stack, it must
therefore work correctly when executed from different threads, since
each thread is a different scheduler execution unit, and has its own
stack).
Thread-safety, on the other hand, is a weaker concept: this just mean
that the function can be safely executed concurrently by many threads
(each with its own stack). So, a simple function that uses a mutex to
protect shared data may be thread-safe (assuming the mutex is used
correctly), but is *not* re-entrant (if the same thread re-entered it
while it holds the lock this would cause a deadlock).
Am I correct in saying that what differentiates a thread-safe function
from a re-entrant one is that the latter can be re-entered without
problems by the same schedulable entity (eg, thread), while the former
can not (needs to be executed, although concurrently, by different
schedulable entities/stacks)? Is there something I'm missing?
And, to end, are the library functions used in a multi-threaded
environment (like POSIX pthreads) guaranteed (unless noted otherwise)
to be re-entrant or just thread-safe?
> There are exceptions (as another poster has
> stated) and their man page would indicate which
> functions are unsafe in a threaded application.
Yes, I just thought it was the other way around.
> HTH,
Many thanks for your help.
[ Post a follow-up to this message ]
|
|
|
 |
|
 |
|
 |
|
03-26-05 01:50 AM
<sunglo@katamail.com> wrote in message
news:1111748309.582768.63040@g14g2000cwa.googlegroups.com...
>
> <irony>Why waste all those words? Just say "No".</hirony>
>
[vbcol=seagreen]
> Did you actually read my post? It started with "I'm beginning to study
> posix threads".
Ahh, now your post makes *much* less sense.
> And so what? Do you mean that many threads can all call malloc() at the
> same time?
Of course. It would be impossible to use 'malloc' if it wasn't unless
all the code that might ever get called from any function was developed
under full coordination or called under the same lock.
DS
[ Post a follow-up to this message ]
|
|
|
 |
|
 |
|
 |
|
03-26-05 12:57 PM
sunglo@katamail.com wrote:
> I think that "thread-safe" and "reentrant" are not exactly the same
> thing (correct me if I'm wrong), because a "reentrant" function is also
> "thread-safe", but the opposite is not necessarily true.
This is what SUSv3 has to say about these two terms:
http://www.opengroup.org/onlinepubs...xbd_chap03.html
> And, to end, are the library functions used in a multi-threaded
> environment (like POSIX pthreads) guaranteed (unless noted otherwise)
> to be re-entrant or just thread-safe?
From the above URL on thread-safety:
"Each function defined in the System Interfaces volume of IEEE Std
1003.1-2001 is thread-safe unless explicitly stated otherwise."
--
mail1dotstofanetdotdk
[ Post a follow-up to this message ]
|
|
|
 |
|
 |
|
 |
|
03-26-05 12:57 PM
sunglo@katamail.com wrote:
>
> Stephen wrote:
>
>
> Thank you. I just did not find this stated clearly in my google
> searches.
>
>
> Of course. I was only referring to thread safety wrt data that is not
> under the programmer's control (that is, possible global/static data
> manipulation inside the library function implementation).
>
>
> Although this is not exactly what I originally asked, let me elaborate
> on this and ask you to confirm if my understanding is correct, since
> the two concepts you mention are often confused (perhaps because often
> a function has both properties), and I'm still not 100% sure of the
> difference.
>
> I think that "thread-safe" and "reentrant" are not exactly the same
> thing (correct me if I'm wrong), because a "reentrant" function is also
> "thread-safe", but the opposite is not necessarily true.
I don't claim to offer a definitive answer, but a little
Google research _seems_ to shows that reentrant is an older
term and seems to be 1st applied to complete programs - i.e.,
a program is reentrant if more than one user can run it
without affecting the other(s). I think (IMHO) nowadays,
the two terms are safely interchangeable. There might be an
argument that "thread-safe" means (more of a) "parallel
execution" model, and reentrant means able to be called
"safely from itself" model.
Note, that the scope of a reentrant function can extend
beyond the function itself.
Consider the 'strtok()' example. The function 'strtok()',
even in a non-threaded application, is _not_ reentrant.
Once you start a 'strtok()' function, you cannot start
another 'strtok()' function until the 1st is completed.
This is because 'strtok()' maintains internal state
information used between successive calls to itself.
>
> safely interrupted anywhere in the middle, and re-entered (re-executed
> from the start).
> This could happen, for example, if the function is a signal handler and
> another signal of the same kind arrives in the middle. This means that,
> for the second execution, another activation frame is created *on the
> same stack* (since the two invocations are part of *the same* scheduler
> execution unit).
> This implies that:
>
> - to be re-entrant, a function must not modify static/global data (and
> must not use locks), and
> - if a function is re-entrant, it's of course also thread-safe (if it
> works correctly with many invocations on a single stack, it must
> therefore work correctly when executed from different threads, since
> each thread is a different scheduler execution unit, and has its own
> stack).
>
> Thread-safety, on the other hand, is a weaker concept: this just mean
> that the function can be safely executed concurrently by many threads
> (each with its own stack). So, a simple function that uses a mutex to
> protect shared data may be thread-safe (assuming the mutex is used
> correctly), but is *not* re-entrant (if the same thread re-entered it
> while it holds the lock this would cause a deadlock).
>
Not necessarily. The _same_ thread can acquire the _same_
mutex, if the programmer so desires. A recursive algorithm
can be used in a threaded program and have its data
protected by a mutex as needed (man 'pthread_mutex_lock()').
The multiple locking/unlocking of the mutex simply adjusts a
reference count for owner the mutex (the original locking thread).
> Am I correct in saying that what differentiates a thread-safe function
> from a re-entrant one is that the latter can be re-entered without
> problems by the same schedulable entity (eg, thread), while the former
> can not (needs to be executed, although concurrently, by different
> schedulable entities/stacks)? Is there something I'm missing?
>
> And, to end, are the library functions used in a multi-threaded
> environment (like POSIX pthreads) guaranteed (unless noted otherwise)
> to be re-entrant or just thread-safe?
It's been my experience that this is where most
mis-understandings occur and I guess it can't be
helped. The label REENTRANT/THREAD-SAFE doesn't
apply to a function's instruction _code_ (unless we
go back to assembler days when functions could
modify themselves). The label applies to the
changeable data (this does not apply to the stack
because it's impossible for two simultaneous
functions to occupy the same position on the stack)
a function manages.
For example, we know that the 'strcat()' function
by itself is reentrant/thread-safe. However, if more
than 1 thread is attempting a 'strcat()' to the
_same_ memory location, the results are undefined
unless that memory is protected against concurrent
access through a mutex.
Note, 'strcat()' is a trivial function. But replace
it with 'snprintf()'. In my environment, 'snprintf()'
is described as a safe in multi-threaded programs.
But that only means that and internal data structures
used by 'snprintf()' are protected inside the function
itself. Again, if more than 1 thread is 'snprintf()'ing
to the same memory location, the results are undefined.
>
>
> Yes, I just thought it was the other way around.
>
>
> Many thanks for your help.
--
Stephen
[ Post a follow-up to this message ]
|
|
|
 |
|
 |
|
 |
|
03-26-05 11:05 PM
Bjorn Reese wrote:
> This is what SUSv3 has to say about these two terms:
>
>
http://www.opengroup.org/onlinepubs...xbd_chap03.html
Their definition of "reentrant function" is a bit vague.
It says nothing about the case in which the function is executed
more than once *by the same thread* (on the same stack), as it
could happen for example in an interrupt handler or a signal handler.
In the common use and in many textbooks, such functions are also
referred as "reentrant" functions (and can only call other reentrant
- in the same meaning - functions).
> "Each function defined in the System Interfaces volume of IEEE Std
> 1003.1-2001 is thread-safe unless explicitly stated otherwise."
Thanks.
[ Post a follow-up to this message ]
|
|
|
 |
|
|
|
|
Sponsored Links |
 |
 |
|
|
 |
All times are GMT. The time now is 11:14 PM. |
 |
|
|
 |
|
 |
|
|
 |
|
Forum Rules:
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
|
HTML code is OFF
vB code is ON
Smilies are ON
[IMG] code is OFF
|
|
|
|
|
 |
|
 |
|