網頁

2011年1月9日 星期日

Reentrant Function

Definition
reentrant function is one that can be used by more than one task concurrently without fear of data corruption. Conversely, a non-reentrant function is one that cannot be shared by more than one task unless mutual exclusion to the function is ensured either by using a semaphore or by disabling interrupts during critical sections of code. A reentrant function can be interrupted at any time and resumed at a later time without loss of data. Reentrant functions either use local variables or protect their data when global variables are used.
A reentrant function:
1) Does not hold static data over successive calls
2) 
Does not return a pointer to static data; all data is provided by the caller of the function
3) Uses local data or 
ensures protection of global data by making a local copy of it
4) 
Must not call any non-reentrant functions
Floating Point Reentrant for Keil C51 C compiler
Floating point operations the compiler generates code for (+ - * /) are fully reentrant. But only a few functions in math.h are reentrant.
Those that are not reentrant must be protected from interrupts. One way this can be accomplished is to put a wrapper that disables and re-enables interrupts around the floating point math calls. For example:
#pragma disable        // Disable Interrupts for this function
float ISR_sin (float x)
{
    return (sin(x));
}
Examples
void func(int* x, int* y)
{
    int tmp;
    tmp=*x;
    *x=*y;
    *y=tmp;
}

the above is reentrant or not?
Reentrant
Non-Reentrant to Reentrant
Non-reentrant version
char* FileName(char *name)
{
    static char fname[13];
    sprintf(fname, "%s", name);       // can't write fname = name
    return fname;
}
Reentrant versions
char* FileName1(char *name, char *fname_buf)      // use thread's own buffer
{
    sprintf(fname_buf, "%s", name);          // can write fname_buf = name
    return fname_buf;
}
char* FileName2(char *name)
{
    char *fname_buf = (char*)malloc(13);       // malloc will allocate memory every call
    sprintf(fname_buf, "%s", name);       // can write fname_buf = name
    return fname_buf;
}

The first one better, because second requires free() to release memory, and takes longer time to allocate memory.

沒有留言:

張貼留言