errno and multithreading

Source: Internet
Author: User
Tags data structures mutex posix semaphore signal handler

Http://docs.sun.com/app/docs/doc/819-7051?l=zh "Multithreaded Programming Guide"

An excerpt from the "Apue"

POSIX and ISO c define errno as such a symbol, which expands into a modifiable integer left value (lvalue). This can be an integer that contains an error number, or a function that returns an error number pointer. Previously used definitions are:

However, in a thread-supporting environment, multiple threads share the process address space, and each thread has its own local errno to prevent one thread from interfering with another. For example, Linux supports multithreaded access errno, defined as:

You should know two rules for errno. The first rule is that if there is no error, its value is not purged by a routine. Therefore, the value is checked only when the return value of the function indicates an error. The second is that either function does not set the errno value to 0, and all constants defined in <errno.h> are not 0.

Ii. understanding of several concepts of reentrant, thread-safe, and asynchronous signaling security

Http://blog.chinaunix.net/u/12592/showart_1871048.html

Reentrant and asynchronous signal security
A reentrant function is simply a function that can be interrupted, that is, it can be interrupted at any point in time at which the function is executed, and transferred to the OS to execute another piece of code, and there is no error in returning control.
As defined in the Multithreaded Programming Guide, functions that can be invoked safely by a signal controller are called "Asynchronous signaling Security" functions.
Therefore, I think reentrant and asynchronous signal security is a concept.

I don't think it is correct to confuse a reentrant function with a thread-safe function.

Here, refer to the description in Csapp to illustrate:
--------------------------------------------------
Csapp
13.7.1 Thread Safety
A function is called thread-safe, and it always produces the correct result when it is called repeatedly by multiple concurrent threads.
13.7.2 can be reentrant
A class of important thread-safe functions, called reentrant functions, are characterized by the fact that they have an attribute that does not reference any shared data when they are called by multiple threads.

Although thread safety and reentrant can sometimes (incorrectly) be used as synonyms, there are clear technical differences between them. Reentrant functions are a true subset of thread-safe functions.
--------------------------------------------------

Re-entry means repeat access, first, it means that this function can be interrupted, and second, it means that it does not rely on any environment (including static) except to use variables on its own stack, such functions as Purecode (pure code) can be reentrant, allowing multiple copies of the function to be run, Because they use separate stacks, they don't interfere with each other.
reentrant functions are thread-safe functions, but in turn, thread-safe functions may not be reentrant functions.
In fact, there are few reentrant functions, Apue 10.6 Describes the reentrant functions that are described in single UNIX specification, and only 115, Apue 12.5 describes a function in posix.1 that does not guarantee thread safety, only 89.

Letter
Number, like a hardware interrupt, interrupts the sequence of instructions that are being executed. The signal processing function cannot determine where the process runs when the signal is captured. If the operation of the signal processing function is the operation of the interrupted function
Same, and this operation has a static data structure, etc., when the signal processing function returned (of course, this is discussed here is the signal processing function can return), restore the original execution sequence, may cause signal processing function
Overwrites the data in the previous normal operation.
The reason for the non-reentrant function is:
1> are known to use static data structures
2> they call malloc and free.
Because malloc typically maintains a linked table for the allocated store, the process may be modifying the linked table while inserting the execution signal processing function.
3> they are standard IO functions.
Because many implementations of the standard IO library use the global data structure

That
For reentrant functions, the use of signal processing functions also requires attention to a problem is errno. There is only one errno variable in a thread, and the reentrant function used in the signal processing function can also
Will modify the errno. For example, the Read function can be reentrant, but it may also modify the errno. Therefore, the correct approach is to start the signal processing function, first save the errno;
When the function exits, then restore the errno.

For example, the program is calling printf output, but when you invoke printf, a signal appears and the corresponding signal processing function has a printf statement that causes two printf outputs to be mixed together.
If it is for printf lock, the same is the case above will lead to deadlock. In this case, the method used is generally to block a certain signal in a specific area.
The method of shielding signal:
1> signal (sigpipe, sig_ign); Ignore some signals.
2> Sigprocmask ()
Sigprocmask is only defined for a single thread
3> Pthread_sigmask ()
Pthread_sigmasks can be used in multiple threads

Now it seems that the limits of asynchronous security and reentrant access seem to be the same, so here they equate

Thread Safety
Thread Safety: If a function can be invoked by multiple threads at the same time, it is called a thread-safe function.

When you do not need to share, provide a dedicated copy of your data for each thread. If sharing is important, provide an explicit synchronization to ensure that the program operates in a determined manner. By including a procedure in a statement to lock and unlock the mutex, the restless whole process can be turned into a line Cheng Ann whole process, and can be serialized.

Many functions are not thread-safe, because the data they return is stored in a static memory buffer. By modifying the interface, the caller itself provides the buffer to make these functions thread-safe.
When the operating system implements a thread-safe function, it provides some alternative thread-safe versions of some posix.1-safe functions in the application.
For example, gethostbyname () is thread insecure and provides a thread-safe implementation of Gethostbyname_r () in Linux.
The function name is followed by a "_r" to indicate that the version is reentrant (for a thread to be reentrant, that is, thread-safe, but not for a signal-processing function to be reentrant, or for the asynchronous signal to be secure).

Common negligence problems in multithreaded programs
1> passes the pointer to the caller stack as a parameter to the new thread.
2> a share that accesses global memory without a synchronization mechanism protection can change state.
3> A deadlock occurs when two threads attempt to gain permission on the same global resource in turn. One of the threads controls the first resource and another thread controls the second resource. No thread can continue until one of the threads is discarded
Operation.
4> attempts to regain the lock held (recursive deadlock).
5> creates a hidden interval in the synchronization protection. This interval occurs in protection if the protected code snippet contains functions that release the synchronization mechanism and then regain the synchronization mechanism before returning to the caller. The result is misleading. For the caller, the global data on the surface is protected and is not actually protected.
6> Use the sigwait (2) model to handle asynchronous signals when mixing UNIX signals with threads.
7> calls setjmp (3C) and longjmp (3C), and then jumps for a long time without releasing the mutex.
8> cannot be reassessed after returning from a call to *_cond_wait () or *_cond_timedwait ().

Summarize
To judge whether a function can be reentrant, it is to determine if it can be interrupted, and then resume operation after interruption to get the correct result. (Interrupt executing sequence of instructions does not change the function's data)
To determine whether a function is thread-safe is to determine if it can execute its sequence of commands at the same time as multiple threads, ensuring that each thread gets the correct result.

If a function is reentrant for multiple threads, the function is thread-safe, but that does not mean that the function is reentrant for the signal handler.
If the function is safe for the reentry of an asynchronous signal handler, then the function is "asynchronous-signal secure".

Reference:
Csapp
13.7.1 Thread Safety
13.7.2 can be reentrant
"Advanced Programming in the UNIX environment" 2nd Editon
10.6 reentrant Function
12.5 reentrant
Multithreaded Programming Guide
Signal processor and asynchronous signal security
Http://blog.chinaunix.net/u/25994/showart_369466.html

Third, reentrant functions and non -reentrant functions

Http://blog.chinaunix.net/u/25994/showart_369466.html

Mainly used in multitasking environments, a reentrant function is simply a function that can be interrupted, that is, to interrupt it at any point in the execution of the function, to move to the OS to execute another piece of code, and to return control without error, and a function that cannot be reentrant because of the use of some system resources, such as the global variable area, interrupt vector table, etc., so if it is interrupted, there may be problems, such functions can not run in a multitasking environment.

It can also be understood that reentry means repeated entry, first meaning that the function can be interrupted, and second, that it does not rely on any environment (including static) other than the variables on its own stack, so that the function is Purecode (pure code) can be reentrant, Multiple copies of the function can be allowed to run because they are using separate stacks, so they don't interfere with each other. If you do need to access global variables (including static), be careful to implement mutexes. Reentrant functions are important in parallel running environments, but typically pay a performance price for accessing global variables.

When writing reentrant functions, if global variables are used, they should be protected by means of turn-off interrupts, semaphores (i.e., p, v operations).

Note: If you do not protect the global variable you are using, this function is not reentrant, that is, when multiple processes call this function, it is very likely that the global variable becomes unknowable.

Example: Assuming exam is an int-type global variable, the function Squre_exam returns the exam squared value. Then the following function does not have a reentrant nature.

unsigned int example (int para)

{

    unsigned int temp;
        Exam = para;//(* *)
        temp = square_ex AM ();
        Return temp;
   }
    If this function is invoked by multiple processes, the result may be unknown, because when the (* *) statement is just finished, another process that uses this function may be activated exactly, then when the newly activated process executes to this function, the The Exam will be assigned a different para value, so when the control returns to "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;
[Application for semaphore operation]//(1)
Exam = para;
temp = Square_exam ();
[Release semaphore operation]
return temp;
}
(1) If a "semaphore" is not applied, stating that another process is in the process of assigning value to exam and calculating its square (that is, using this signal), this process must wait for it to release the signal before it can proceed. If you apply for a signal, you can continue, but the other process must wait for this process to release the semaphore before using this signal again.

Ways to ensure the reentrant nature of a function:
When writing functions to use local variables (such as registers, variables in the stack), for the global variables to be used to be protected (such as taking off interrupts, semaphores and other methods), so that the composition of the function must be a reentrant function.
The Reentrant technologies adopted in VxWorks are:
* Dynamic stack variable (each child function has its own separate stack space)
* Protected global variables and static variables
* Task variables

--------------------------------------------------
In
In the design of real-time systems, multiple tasks often invoke the same function. If this function is unfortunately designed to be a function that cannot be reentrant, then the different tasks that call this function may modify any other
The service calls this function's data, which leads to unpredictable consequences. So what is a reentrant function? A reentrant function is a procedure that can be invoked by multiple tasks without having to worry about the data being
No error will occur. Non-reentrant functions are considered unsafe functions in the design of real-time systems. Most of the functions that meet the following conditions are not reentrant:
1 The static data structure is used in the function body;
2 The function body calls the malloc () or free () function;
3 The standard I/O function is called in the function body.

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

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

B. Non-reentrant function 1
charctemp;//Global Variables
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;//statically local variable
CTEMP=*LPCX;
*lpcx=*lpcy;
lpcy=ctemp;//uses a static local variable
}

Question 1, how can I write a reentrant function.
A: Do not access those global variables in the function body, do not use static local variables, adhere to the use of only local variables, the written function will be reentrant. If you have to access global variables, remember to protect the global variables with mutually exclusive semaphores.

Question 2, how to rewrite a function that cannot be reentrant into a reentrant function.
A: The only way to turn a non reentrant function into reentrant is to override it with a reentrant rule. It's very simple, as long as you follow a few rules that are easy to understand, the functions you write are reentrant.
1 Do not use global variables. Because other code is likely to overwrite these variable values.
2 when interacting with the hardware, remember to perform such actions as Disinterrupt (), that is, to turn off the hardware interrupt. Complete the interaction remember to turn on interrupts, in some series, this is called "Enter/Exit Core".
3 cannot call any other functions that cannot be reentrant.
4 Use the stack carefully. It is best to os_enter_kernal first before using.

Stack operations involve memory allocations, and a little inattention can result in the benefit of overwriting data on other tasks, so use the stack with caution. It's best not to use it. Many hacker programs take advantage of this so that the system can execute illegal code to gain control of the system easily. There are some rules, in short, always remember a word: to ensure that the interruption is safe.

Instance problem: The following function has been designed to be alerted to bugs in the Code view because the function is not reentrant and 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 (or predictable), that is, the same output should be produced as long as the input data is the same. This function is unpredictable because the static variable is used in the function, because of the characteristics of the static variable, such functions are 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 the function, and use the principle that you don't have to do it as much as possible.
Modify the above function to a reentrant function, as long as you remove the static keyword from the sum variable, and the variable sum becomes a variable of type auto, and the function becomes a reentrant function.
Of course, there are times when you have to use a static variable in a function, such as when a function's return value is a pointer type, it must be the address of a static local variable as the return value and, if it is the auto type, return to the wrong pointer.



Reference: http://francislee.blogcn.com/articles/%E7%BD%91%E6%91%98errno%E4%B8%8E%E5%A4%9A%E7%BA%BF%E7%A8%8B.html

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.