Presentation is loading. Please wait.

Presentation is loading. Please wait.

Controlling concurrency A look at some techniques for process synchronization in the Linux environmemt.

Similar presentations


Presentation on theme: "Controlling concurrency A look at some techniques for process synchronization in the Linux environmemt."— Presentation transcript:

1 Controlling concurrency A look at some techniques for process synchronization in the Linux environmemt

2 What is a ‘race condition’ ? Without any ‘synchronization’ mechanism, multiprogramming is vulnerable to ‘races’ in which programs produce unpredictable and erroneous results, due to the relative timing of instruction-execution in separate threads or processes An example program demonstrates this phenomenon (see our ‘racedemo.cpp’)

3 Two tasks write to one terminal A parent-process forks a child-process, and both write messages to the screen, but without coordinating their efforts The operating system’s task-scheduler repeatedly preempts each of them The result is incomprehensible gibberish! Programs like this one are said to contain a ‘race condition’

4 The cure is communication What’s needed is some way for the tasks to be made aware of each other’s actions Various mechanisms for this exist in Linux One of the simplest ways is by ‘signaling’ (i.e., one task can wait for an ‘all clear’ signal to be sent to it by the other task) But ‘busy-waiting’ needs to be avoided, since it wastes CPU time and degrades the overall efficiency of the system

5 The ‘signal mask’ Each process has a ‘signal mask’ that can be used to ‘block’ certain specific signals The signal mask for each process is kept in its process control block (in the kernel) But a process can inspect and modify its signal mask by using special system-calls

6 The ‘sigset_t’ type Process Control Block struct task_struct blocked sigset_t The signal mask is a collection of flag-bits that indicates which signals are to be ‘blocked’

7 How to inspect ‘signal mask’ 1. Include the header-file: #include 2. Declare a ‘sigset_t’ object: sigset_t sigmask; 3. Call the ‘sigprocmask()’ library-function: sigprocmask( 0, NULL, &sigmask );

8 How to modify ‘signal mask’ 1. Declare two ‘sigset_t’ objects: sigset_tnset, oset; 2. Initialize the ‘new’ signal-set: sigemptyset( &nset ); sigaddset( &nset, SIGUSR1 ) sigaddset( &nset, SIGUSR2 ) 3. Call the ‘sigprocmask()’ library-function: sigprocmask( SIG_BLOCK, &nset, &oset );

9 How to wait for a signal 1. Declare and initialize a global variable: int done = 0; 2 Define your signal-handling function: void upon_signal( int signum ) { done = 1; }. 3. Install your signal-handler function: signal( SIGUSR1, upon_signal ); signal( SIGUSR2, upon_signal ); 4. Declare and initialize a ‘sigset_t’ object: sigset_t zeromask; sigemptyset( &zeromask ); 5. Then use ‘sigsuspend()’ to wait for your signal: while ( done == 0 ) sigsuspend( &zeromask );

10 Our ‘racecure.cpp’ demo These signal-handling library-functions are used by this demo-program to remove the ‘race condition’ without doing busy-waiting It’s based on ideas of W. Richard Stevens from his classic: “Advanced Programming in the UNIX Environment” (1993).

11 How it works done signal-mask signal-handler parent-process write-message; TELL_CHILD; WAIT_CHILD; done signal-mask signal-handler child-process WAIT_PARENT; write-message; TELL_PARENT; user kernel SIGUSR1 SIGUSR2

12 In-class exercises Modify ‘racedemo’ so that the parent forks twice (i.e., two child-processes), with three processes all writing to the ‘stdout’ stream Then add synchronization functions which will eliminate the race conditions and allow the parent-process to finish writing before either of the child-processes begins


Download ppt "Controlling concurrency A look at some techniques for process synchronization in the Linux environmemt."

Similar presentations


Ads by Google