The concept of reentrant function and non-reentrant function and the writing specification

Source: Internet
Author: User
Tags semaphore

1. Definition

A reentrant function is simply a function that can be interrupted , that is, it can be interrupted at any moment of the execution of the function, and go to the OS Scheduler to execute another piece of code, and return control without error; The non-reentrant function can cause problems if it is interrupted, because it uses some system resources, such as the global variable area, the interrupt vector table , and so on, so the function cannot be run in a multi-tasking environment.

In other words, we can also understand that re-entry means that the function can be interrupted, and the second means that it does not depend on any environment (including static) other than the variable on its own stack, so that the function is Purecode (pure code) reentrant, You can allow multiple copies of the function to run, because they use separate stacks, so they do not interfere with each other. If you do need to access global variables (including static), be aware of implementing mutually exclusive means. Reentrant functions are important in a parallel run environment, but there is a general need to pay some performance cost for accessing global variables.

When you write a reentrant function, if you use a global variable, you should protect it by turning off interrupts, semaphores (that is, p, v operations), and so on.  

Description: If the global variable being used is not protected, then this function is not reentrant, that is, when multiple processes call this function, it is likely that the global variable becomes unknowable.

2. Case

void Swap1 (int* x, int* y) {    tmp=*x;     *x=*y;     *y=tmp;} void Swap2 (int* x, int* y) {    int tmp;     tmp=*x;     *x=*y;     *y=tmp;}


The Swap1 is non-reentrant, and swap is reentrant. Because under multithreaded conditions, the operating system switches to another thread if the SWAP1 is not finished, and that thread may call Swap1 again, so the state is wrong.

If we introduce a global variable into a reentrant function such as the following, this case

unsigned int example (int para) {    unsigned int temp;        Exam = para; (* *)        temp = Square_exam ();        return temp;    }    If this function is called by more than one process, the result may be unknown, because when the (*) statement has just been executed, another process using this function may be just activated, then when the newly activated process executes to this function, the exam will be assigned a different para value, so when the control returns to the "Temp = Square_exam () ", the computed temp is probably not the expected result. This function should be improved as follows.    unsigned int example (int para) {        unsigned int temp;        [Request semaphore operation]//(1)        Exam = para;        temp = Square_exam ();        [Release semaphore operation]        return temp;    }


If the above Square_exam () is still a reentrant function, in the execution process, continue to call example this function (function recursion), but because the main function does not immediately release the semaphore, it is easy to create a deadlock (http://blog.csdn.net /xy010902100449/article/details/45896055).
 A method to guarantee the reentrant nature of a function:

  try to use local variables when writing functions(such as registers, variables in the stack),protect the global variables you want to use (such as closing interrupts, semaphores, etc.), the function that makes up is necessarily a reentrant function.
The reentrant Technologies taken in the VxWorks are:
* Dynamic stack variables (each child function has its own independent stack space)
* Protected global variables and static variables
* Task Variables


--------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------- -----------------------------------------------------

3, non-reentrant How to change to re-enter the function

in the design of real-time systems , there are often cases where multiple tasks call the same function. If this function is unfortunately designed to be a non-reentrant function, then different tasks calling this function may modify the data of other tasks invoking the function, which can lead to unpredictable consequences. So what is reentrant function? The so-called reentrant function refers to a procedure that can be called by multiple tasks The task does not have to worry about data errors when it is called     1) The function body uses a static data structure;
    2) The function body calls the malloc () or free () function; The
    3) function calls standard I/O functions within the body.

    The following examples illustrate.
    A. reentrant function
    void strcpy (char *lpszdest, char *lpszsrc)

  {
        while (*lpszdest++=*lpszsrc++);
        *dest=0;
   }

    b.       Charctemp; //global variable
    void SwapChar1 ( Char *lpcx, char *lpcy)

{
CTEMP=*LPCX;
*lpcx=*lpcy;
lpcy=ctemp;// access to global variables
}

C. Non-reentrant function 2
void SwapChar2 (char *lpcx,char *lpcy)

 {
Static char ctemp;//Static Local Variables
CTEMP=*LPCX;
*lpcx=*lpcy;
lpcy=ctemp;//uses static local variables
}

Question 1, how can I write a reentrant function?
For: in the function body does not access those global variables, do not use static local variables, persist in using only local variables, the written function will be reentrant. If you must access global variables, remember to protect global variables with mutually exclusive semaphores .

Question 2, how can I overwrite a non-reentrant function into a reentrant function?
A: The only way to turn a non-reentrant function into reentrant is to rewrite it with reentrant rules. In fact it is very simple, as long as you follow a few very easy to understand the rules, then the written function is reentrant.
1)do not use global variables。 Because other code is likely to overwrite these variable values.
2)in the event of interaction with the hardware, remember to perform operations like Disinterrupt (), which isturn off hardware interrupts。 Complete the interaction remember to open the interrupt, on some series, this is called "Enter/Exit Core".
3)You cannot call any other function that is not reentrant.
4)use the stack with caution。 It is best to os_enter_kernal first before use.

The stack operation involves memory allocation, and a little inattention can cause data to be overwritten by other tasks, so use the stack with caution! Better not use it! Many hacking programs take advantage of this so that the system can easily gain control of the system by executing illegal code. There are some rules, in short, always remember a word: to ensure that the interruption is safe!

Example problem: Once designed the following function, in the Code view is reminded of a bug, because this function is not reentrant, why?
unsigned int sum_int (unsigned int base)

{
unsigned int index;
static unsigned int sum = 0; // Note that the static type
for (index = 1; index <= base; index++)
sum + = index;
return sum;
}

Analysis: The so-called function is reentrant (It can also be said to be predictable.), which should produce the same output as long as the input data is the same. This function is unpredictable because a static variable is used in the function because of the characteristics of the static variable, such a function is called:functions with "internal memory" function。 So if you need a reentrant function, be sure to avoid using the static variable in the function, the static variable in this function, using the principle that you can not use as much as possible.
Modify the above function to a reentrant function, as long as the static keyword declared in the sum variable is removed, the variable sum becomes a variable of type auto, and the function becomes a reentrant function.
Of course, there are times when a static variable must be used in a function, such as when the return value of a function is a pointer type, the address of a static local variable must be the return value, and if it is the auto type, it is returned as the wrong pointer.



The concept of reentrant function and non-reentrant function and the writing specification

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.