re-entrant function????????

D

dandelion

Eltee said:
So you guys always use synchronized wrappers around stdlib functions? I mean, common
"operations" such as malloc, sprintf?

Nope. I try to avoid calling them alltogether in any part of the system that
is eligable to have multiple threads of execution running.
That's news to me, cause I haven't written a synchronized wrapper around a malloc, yet.
Consequently, my entire "c opus" ;-) is useless as far as
multi-threadedness is concerned?

Hmmm... Without knowing your "Magnus Opus", not all is lost.

Writing wrappers for the functions you need isn't all that hard and usually
a multithreaded app has one main thread taking care of all the mallocing,
sprintffing etc. and a number of "small" threads with a very limited task .

That makes it easy to avoid calling the standard lib in the "small" threads
and thus, reentrancy is not really a problem.
 
C

CBFalconer

Eltee said:
.... snip ...

Now, as we established that reentrancy is not entirely off topic,
may I inquire as to which implementations of a standard library
are, in fact, reentrant inspite of the above ISO "not guaranteed"
guideline? GNU? Intel? M$? Borland? etc?

Who knows. You would have to examine each function of each
library. What we can say is that some are inherently
non-reentrant, e.g. strtok. putchar specifies a file, and thus is
non-reentrant, while putc does not, and thus can be reentrant. The
better implementations will make everything possible reentrant.

When you have the library source you can make these decisions, if
you know what you are doing and can spend the time.
 
L

Lawrence Kirby

On Tue, 11 Jan 2005 16:43:03 +0100, Eltee wrote:

....
So you guys always use synchronized wrappers around stdlib functions? I mean,
common "operations" such as malloc, sprintf? That's news to me, cause I haven't
written a synchronized wrapper around a malloc, yet. Consequently, my entire "c
opus" ;-) is useless as far as multi-threadedness is concerned? Bummer!

If you use threads you will be using an environment that supports them as
an extension. That environment is also likely to support reentrant use of
various standard library functions as a related extension.

Lawrence
 
R

Robert Gamble

So you guys always use synchronized wrappers around stdlib functions? I
mean, common "operations" such as malloc, sprintf? That's news to me,
cause I haven't written a synchronized wrapper around a malloc, yet.
Consequently, my entire "c opus" ;-) is useless as far as
multi-threadedness is concerned? Bummer!

If you are writing multi-threaded programs you will probably be trying to
adhere to a standard such a POSIX threads. If this is the case you will
probably be working with a pthreads complaint standard c library in which
case you won't need wrapper functions for most standard functions the
library provides. GNU provides a posix-compliant standard library
including pthreads.

Rob Gamble
 
X

xarax

hi,

can anyone of C masters siting out there suggest any 1 example of
re-entrnt function just to show what is the significance of that
property and how we can exploit it ....

sushant

The correct terminology is "recursive" function. Reentrant
means something else entirely.
 
R

Robert Gamble

The correct terminology is "recursive" function. Reentrant
means something else entirely.

And exactly what makes you think that he meant recursive?

Rob Gamble
 
R

Richard Tobin

Maybe. Or maybe it's just an involuntary function call. It depends
on your interrupts.
[/QUOTE]
Again, it doesn't matter. It's still a particular order of executing
instructions.

So is a function call a "thread of execution"? If so, you're just
referring to something different from the rest of us.

-- Richard
 
E

E. Robert Tisdale

Trent said:
This is re-entrant

int f(int x) {
int y = x*x;
return y;
}

This is not

int y;

int f (int x) {
y = x*x;
return y;
}

Another example of re-entrant vs. non-reentrant functions
is strtok_r vs. strtok.
As the OP said, it becomes an issue
when you have multiple threads (lightweight processes)
in a single process, because (some) state is shared
between multiple threads of execution.

The canonical example is

int x;
void f (void) { x++; }

with two threads executing f(). The ++ operation (typically) resolves
into three assembly instructions: copy-memory-to-register,
increment-register, and copy-register-to-memory.

Consider, for example, the situation where first thread executes
the first two instructions, then the second thread executes all three,
then the first thread executes the last instruction.
The second thread's change will be lost
and the contents of memory at that address will be incorrect.

This class of bugs are a PITA to locate
because symptoms are intermittent
and therefore difficult to reproduce.

The ANSI/ISO standards do *not* guarantee
that the first example above will be reentrant.
Implementations are allowed to copy local variables
into static storage where they may be corrupted by other threads
but, to my knowledge, there are no viable ANSI/ISO compliant
implementations which do so.
So the first example is, in *fact*, thread safe.
 
N

Neil Kurzman

hi,

can anyone of C masters siting out there suggest any 1 example of
re-entrnt function just to show what is the significance of that
property and how we can exploit it ....

sushant

Look up the "tower of Honoi " The computer solution is very simple if
recursion is used.
recursive function are re-entrant.

Otherwise function used by multitasking, multithread, and interrupts
may have to be re-entrant.
since they may be paused in the middle and then call again.
 
E

Eltee

Lawrence said:
On Tue, 11 Jan 2005 16:43:03 +0100, Eltee wrote:

...




If you use threads you will be using an environment that supports them as
an extension. That environment is also likely to support reentrant use of
various standard library functions as a related extension.

What worries me is something else. I have a lot of utility functions packed in
.... <cough /> ... shared objects. Those functions in turn, utilize standard
library functions, but without taking any care of (non)reentrancy. Now, I make
it a rule not to use any variables (dynamic or static) outside those functions.
Everything in a particular <cough /> so (dll) is either a parameter or a local
variable. Bottom line: if someone calls my functions from multiple threads
without synchronizing, the outcome might not be as expected. I'll have to take
care of synchronizing myself and not leave it to the caller.
 
L

Lawrence Kirby

Look up the "tower of Honoi " The computer solution is very simple if
recursion is used.
recursive function are re-entrant.

Sometimes they are, but not always. Recursive functions call themselves
under very controlled circumstances. Reentrancy is a more general
principle than that.
Otherwise function used by multitasking, multithread, and interrupts
may have to be re-entrant.
since they may be paused in the middle and then call again.

Or maybe executed my multiple threads simultaneously.

Lawrence
 
G

Guillaume

recursive function are re-entrant.
Sometimes they are, but not always.

Huh? Give me one example of a recursive function that is not reentrant.
By definition, a recursive function will call itself at one point;
which makes it reentrant.
Recursive functions call themselves
under very controlled circumstances.

Which doesn't make them any more non-reentrant. ;-)
Reentrancy is a more general
principle than that.

That's right, of course! You named the multithreading case.
But there is more. A function can become recursive in a non-obvious
way (and that is one pitfall that some programmers will fall into
at one point or another): if it calls a function that calls another
function that... that ends up calling the first function.

In some programming languages, it could also be as simple as a
function calling itself in one of its arguments, such as:

array(array(1, 2), 3)

in some language that would construct a multi-dimensional array.

C does evaluate all of the arguments before calling the function, but
not all languages are like that.
 
C

Chris Torek

Huh? Give me one example of a recursive function that is not reentrant.

It is easy to construct an artificial example, although this sort
of thing is much less likely to occur in real code.
By definition, a recursive function will call itself at one point;
which makes it reentrant.

Not necessarily. Here is one example:

void pointless(int recurselevel, unsigned char c) {
static char *p;

if (recurselevel == 0)
p = malloc(UCHAR_MAX + 1);
if (c == 'Z') {
p[recurselevel] = '\0';
puts(p);
free(p);
} else {
p[recurselevel] = c;
pointless(recurselevel + 1, c + 1);
}
}
Which doesn't make them any more non-reentrant. ;-)

Unless, by accident or (as above) on purpose, they do something
"non-reentrant" at certain recursion levels.
 
X

Xenos

Guillaume said:
Huh? Give me one example of a recursive function that is not reentrant.
By definition, a recursive function will call itself at one point;
which makes it reentrant.
void foo()
{
static int i = 10;

/* do wacky stuff here */

if (--i > 0)
foo();
}

this ugly function is recursive, but not reentrant.
 
G

Guillaume

void foo()
{
static int i = 10;

/* do wacky stuff here */

if (--i > 0)
foo();
}

this ugly function is recursive, but not reentrant.

It is reentrant, since it will reenter itself while still being inside
itself at a higher level. Whether it's harmful or not in this special
case is another story entirely. I don't see your point?

What is your definition of reentrancy?
 
A

Alan Balmer

It is reentrant, since it will reenter itself while still being inside
itself at a higher level.
Sounds like a definition of recursive, not reentrant.
Whether it's harmful or not in this special
case is another story entirely. I don't see your point?
By that definition, all functions are reentrant, since they can be
called twice.
What is your definition of reentrancy?
http://en.wikipedia.org/wiki/Reentrant
 
X

Xenos

Guillaume said:
It is reentrant, since it will reenter itself while still being inside
itself at a higher level. Whether it's harmful or not in this special
case is another story entirely. I don't see your point?

What is your definition of reentrancy?
Just because the function calls itself does not make it reentrant. If it
were, it could be called by multiple threads, interrupts or whatever without
them affecting any other invocation. That is not the same as recursion.
 
K

Keith Thompson

Guillaume said:
Huh? Give me one example of a recursive function that is not reentrant.
By definition, a recursive function will call itself at one point;
which makes it reentrant.

Here's a contrived example:

#include <stdio.h>

static int recursive_but_not_reentrant(int n)
{
static int count = 0;
if (n <= 0) {
return count;
}
else {
count ++;
return recursive_but_not_reentrant(n - 1);
}
}

int main(void)
{
printf("recursive_but_not_reentrant(10) = %d\n",
recursive_but_not_reentrant(10));
printf("recursive_but_not_reentrant(10) = %d\n",
recursive_but_not_reentrant(10));
return 0;
}

Output:

recursive_but_not_reentrant(10) = 10
recursive_but_not_reentrant(10) = 20
 
R

Richard Tobin

Guillaume said:
It is reentrant, since it will reenter itself while still being inside
itself at a higher level.

Usage varies, but re-entrant is commonly used to refer to code that
can safely be re-entered at any time (subject perhaps to locks). A
function that re-enters itself from certain fixed points (ie a recursive
function) may not be safely callable from another thread, and so may
not be re-entrant by this definition.

There doesn't even need another thread to be involved. Consider
a function sort() that works recursively, by calling itself on parts
of the array of items to sort. Such a function might not be designed
to work if the user-supplied comparison function itself calls sort(),
in which case it would not be re-entrant.

-- Richard
 

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

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top