<< Chapter < Page Chapter >> Page >

We can explore this effect by substituting the following SpinFunc( ) function, replacing TestFunc( ) function in the pthread_create( ) call in the previous example:


void *SpinFunc(void *parm) { int me;me = (int) parm; printf("SpinFunc me=%d - sleeping %d seconds ...\n", me, me+1);sleep(me+1); printf("SpinFunc me=%d – wake globvar=%d...\n", me, globvar);globvar ++; printf("SpinFunc me=%d - spinning globvar=%d...\n", me, globvar);while(globvar<THREAD_COUNT ) ; printf("SpinFunc me=%d – done globvar=%d...\n", me, globvar);sleep(THREAD_COUNT+1); }

If you look at the function, each thread entering this function prints a message and goes to sleep for 1, 2, and 3 seconds. Then the function increments globvar (initially set to 0 in main) and begins a while-loop, continuously checking the value of globvar. As time passes, the second and third threads should finish their sleep( ) , increment the value for globvar , and begin the while-loop. When the last thread reaches the loop, the value for globvar is 3 and all the threads exit the loop. However, this isn’t what happens:


recs % create2&[1]23921 recs %Main - globvar=0 Main - creating i=0 tid=4 retval=0Main - creating i=1 tid=5 retval=0 Main - creating i=2 tid=6 retval=0Main thread - threads started globvar=0 Main - waiting for join 4SpinFunc me=0 - sleeping 1 seconds ... SpinFunc me=1 - sleeping 2 seconds ...SpinFunc me=2 - sleeping 3 seconds ... SpinFunc me=0 - wake globvar=0...SpinFunc me=0 - spinning globvar=1...recs % ps PID TTY TIME CMD23921 pts/35 0:09 create2 recs % psPID TTY TIME CMD 23921 pts/35 1:16 create2recs % kill -9 23921 [1]Killed create2 recs %

We run the program in the background Because we know it will hang and ignore interrupts. and everything seems to run fine. All the threads go to sleep for 1, 2, and 3 seconds. The first thread wakes up and starts the loop waiting for globvar to be incremented by the other threads. Unfortunately, with user space threads, there is no automatic time sharing. Because we are in a CPU loop that never makes a system call, the second and third threads never get scheduled so they can complete their sleep( ) call. To fix this problem, we need to make the following change to the code:

while(globvar<THREAD_COUNT ) sleep(1) ;

With this sleep Some thread libraries support a call to a routine sched_yield( ) that checks for runnable threads. If it finds a runnable thread, it runs the thread. If no thread is runnable, it returns immediately to the calling thread. This routine allows a thread that has the CPU to ensure that other threads make progress during CPU-intensive periods of its code. call, Threads 2 and 3 get a chance to be “scheduled.” They then finish their sleep calls, increment the globvar variable, and the program terminates properly.

You might ask the question, “Then what is the point of user space threads?” Well, when there is a high performance database server or Internet server, the multiple logical threads can overlap network I/O with database I/O and other background computations. This technique is not so useful when the threads all want to perform simultaneous CPU-intensive computations. To do this, you need threads that are created, managed, and scheduled by the operating system rather than a user library.

Get Jobilize Job Search Mobile App in your pocket Now!

Get it on Google Play Download on the App Store Now




Source:  OpenStax, High performance computing. OpenStax CNX. Aug 25, 2010 Download for free at http://cnx.org/content/col11136/1.5
Google Play and the Google Play logo are trademarks of Google Inc.

Notification Switch

Would you like to follow the 'High performance computing' conversation and receive update notifications?

Ask