% % This file was automatically produced at Feb 27 2003, 22:51:56 by % c2latex -c condvar2.c % \documentclass[11pt,a4paper]{article} \setlength{\textwidth}{15cm} \setlength{\textheight}{22.5cm} \setlength{\hoffset}{-2cm} \setlength{\voffset}{-2cm} \begin{document} \expandafter\ifx\csname indentation\endcsname\relax% \newlength{\indentation}\fi \setlength{\indentation}{0.5em} \begin{flushleft} {$/\ast$\it{}$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$\mbox{}\\ $\ast$ FILE: condvar2.c\mbox{}\\ $\ast$ DESCRIPTION:\mbox{}\\ $\ast$ This example has a BUG! It is a variation on the condvar1.c example. \mbox{}\\ $\ast$ Instead of just one thread waiting for the condition signal, there are\mbox{}\\ $\ast$ four threads waiting for the same signal. Find out how to fix the\mbox{}\\ $\ast$ program. The solution program is condvar2\_sol.c.\mbox{}\\ $\ast$\mbox{}\\ $\ast$ SOURCE: Adapted from example code in "Pthreads Programming", B. Nichols\mbox{}\\ $\ast$ et al. O'Reilly and Associates.\mbox{}\\ $\ast$ LAST REVISED: 01/07/2003 Blaise Barney\mbox{}\\ $\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast/$}\mbox{}\\ \mbox{}\\ {\tt \#include} $<${\tt{}pthread.h}$>$\mbox{}\\ {\tt \#include} $<${\tt{}stdio.h}$>$\mbox{}\\ \mbox{}\\ {\tt \#define} NUM\_THREADS 6\mbox{}\\ {\tt \#define} TCOUNT 10\mbox{}\\ {\tt \#define} COUNT\_LIMIT 12\mbox{}\\ \mbox{}\\ {\bf int} count = 0;\mbox{}\\ {\bf int} thread\_ids[6] = \{0,1,2,3,4,5\};\mbox{}\\ pthread\_mutex\_t count\_mutex;\mbox{}\\ pthread\_cond\_t count\_threshold\_cv;\mbox{}\\ \mbox{}\\ {\bf void} $\ast$inc\_count({\bf void} $\ast$idp) \mbox{}\\ \{\mbox{}\\ \hspace*{2\indentation}{\bf int} j,i;\mbox{}\\ \hspace*{2\indentation}{\bf double} result=0.0;\mbox{}\\ \hspace*{2\indentation}{\bf int} $\ast$my\_id = idp;\mbox{}\\ \hspace*{2\indentation}{\bf for} (i=0; i $<$ TCOUNT; i++) \{\mbox{}\\ \hspace*{4\indentation}pthread\_mutex\_lock(\&count\_mutex);\mbox{}\\ \hspace*{4\indentation}count++;\mbox{}\\ \mbox{}\\ \hspace*{4\indentation}{$/\ast$\it{} \mbox{}\\ \hspace*{4\indentation}Check the value of count and signal waiting thread when condition is\mbox{}\\ \hspace*{4\indentation}reached. Note that this occurs while mutex is locked. \mbox{}\\ \hspace*{4\indentation}$\ast/$}\mbox{}\\ \hspace*{4\indentation}{\bf if} (count == COUNT\_LIMIT) \{\mbox{}\\ \hspace*{6\indentation}pthread\_cond\_signal(\&count\_threshold\_cv);\mbox{}\\ \hspace*{6\indentation}printf({\tt"inc\_count(): thread \%d, count $=$ \%d Threshold reached.$\backslash$n"}, \mbox{}\\ \hspace*{13\indentation}$\ast$my\_id, count);\mbox{}\\ \hspace*{6\indentation}\}\mbox{}\\ \hspace*{4\indentation}printf({\tt"inc\_count(): thread \%d, count $=$ \%d, unlocking mutex$\backslash$n"}, \mbox{}\\ \hspace*{11\indentation}$\ast$my\_id, count);\mbox{}\\ \hspace*{4\indentation}pthread\_mutex\_unlock(\&count\_mutex);\mbox{}\\ \mbox{}\\ \hspace*{4\indentation}{$/\ast$\it{} Do some work so threads can alternate on mutex lock $\ast/$}\mbox{}\\ \hspace*{4\indentation}{\bf for} (j=0; j $<$ 1000; j++)\mbox{}\\ \hspace*{6\indentation}result = result + ({\bf double})random();\mbox{}\\ \hspace*{4\indentation}\}\mbox{}\\ \hspace*{2\indentation}pthread\_exit(NULL);\mbox{}\\ \}\mbox{}\\ \mbox{}\\ {\bf void} $\ast$watch\_count({\bf void} $\ast$idp) \mbox{}\\ \{\mbox{}\\ \hspace*{2\indentation}{\bf int} $\ast$my\_id = idp;\mbox{}\\ \mbox{}\\ \hspace*{2\indentation}printf({\tt"Starting watch\_count(): thread \%d$\backslash$n"}, $\ast$my\_id);\mbox{}\\ \mbox{}\\ \hspace*{2\indentation}{$/\ast$\it{}\mbox{}\\ \hspace*{2\indentation}Lock mutex and wait for signal. Note that the pthread\_cond\_wait routine\mbox{}\\ \hspace*{2\indentation}will automatically and atomically unlock mutex while it waits. \mbox{}\\ \hspace*{2\indentation}Also, note that if COUNT\_LIMIT is reached before this routine is run by\mbox{}\\ \hspace*{2\indentation}the waiting thread, the loop will be skipped to prevent pthread\_cond\_wait\mbox{}\\ \hspace*{2\indentation}from never returning.\mbox{}\\ \hspace*{2\indentation}$\ast/$}\mbox{}\\ \hspace*{2\indentation}pthread\_mutex\_lock(\&count\_mutex);\mbox{}\\ \hspace*{4\indentation}printf({\tt"$\ast$$\ast$$\ast$Before cond\_wait: thread \%d$\backslash$n"}, $\ast$my\_id);\mbox{}\\ \hspace*{4\indentation}pthread\_cond\_wait(\&count\_threshold\_cv, \&count\_mutex);\mbox{}\\ \hspace*{4\indentation}printf({\tt"$\ast$$\ast$$\ast$Thread \%d Condition signal received.$\backslash$n"}, $\ast$my\_id);\mbox{}\\ \hspace*{2\indentation}pthread\_mutex\_unlock(\&count\_mutex);\mbox{}\\ \hspace*{2\indentation}pthread\_exit(NULL);\mbox{}\\ \}\mbox{}\\ \mbox{}\\ {\bf int} main({\bf int} argc, {\bf char} $\ast$argv[])\mbox{}\\ \{\mbox{}\\ \hspace*{2\indentation}{\bf int} i, rc;\mbox{}\\ \hspace*{2\indentation}pthread\_t threads[6];\mbox{}\\ \hspace*{2\indentation}pthread\_attr\_t attr;\mbox{}\\ \mbox{}\\ \hspace*{2\indentation}{$/\ast$\it{} Initialize mutex and condition variable objects $\ast/$}\mbox{}\\ \hspace*{2\indentation}pthread\_mutex\_init(\&count\_mutex, NULL);\mbox{}\\ \hspace*{2\indentation}pthread\_cond\_init (\&count\_threshold\_cv, NULL);\mbox{}\\ \mbox{}\\ \hspace*{2\indentation}{$/\ast$\it{}\mbox{}\\ \hspace*{2\indentation}For portability, explicitly create threads in a joinable state \mbox{}\\ \hspace*{2\indentation}$\ast/$}\mbox{}\\ \hspace*{2\indentation}pthread\_attr\_init(\&attr);\mbox{}\\ \hspace*{2\indentation}pthread\_attr\_setdetachstate(\&attr, PTHREAD\_CREATE\_JOINABLE);\mbox{}\\ \hspace*{2\indentation}pthread\_create(\&threads[2], \&attr, watch\_count, ({\bf void} $\ast$)\&thread\_ids[2]);\mbox{}\\ \hspace*{2\indentation}pthread\_create(\&threads[3], \&attr, watch\_count, ({\bf void} $\ast$)\&thread\_ids[3]);\mbox{}\\ \hspace*{2\indentation}pthread\_create(\&threads[4], \&attr, watch\_count, ({\bf void} $\ast$)\&thread\_ids[4]);\mbox{}\\ \hspace*{2\indentation}pthread\_create(\&threads[5], \&attr, watch\_count, ({\bf void} $\ast$)\&thread\_ids[5]);\mbox{}\\ \hspace*{2\indentation}pthread\_create(\&threads[0], \&attr, inc\_count, ({\bf void} $\ast$)\&thread\_ids[0]);\mbox{}\\ \hspace*{2\indentation}pthread\_create(\&threads[1], \&attr, inc\_count, ({\bf void} $\ast$)\&thread\_ids[1]);\mbox{}\\ \mbox{}\\ \hspace*{2\indentation}{$/\ast$\it{} Wait for all threads to complete $\ast/$}\mbox{}\\ \hspace*{2\indentation}{\bf for} (i = 0; i $<$ NUM\_THREADS; i++) \{\mbox{}\\ \hspace*{4\indentation}pthread\_join(threads[i], NULL);\mbox{}\\ \hspace*{2\indentation}\}\mbox{}\\ \hspace*{2\indentation}printf ({\tt"Main(): Waited on \%d threads. Done.$\backslash$n"}, NUM\_THREADS);\mbox{}\\ \mbox{}\\ \hspace*{2\indentation}{$/\ast$\it{} Clean up and exit $\ast/$}\mbox{}\\ \hspace*{2\indentation}pthread\_attr\_destroy(\&attr);\mbox{}\\ \hspace*{2\indentation}pthread\_mutex\_destroy(\&count\_mutex);\mbox{}\\ \hspace*{2\indentation}pthread\_cond\_destroy(\&count\_threshold\_cv);\mbox{}\\ \hspace*{2\indentation}pthread\_exit (NULL);\mbox{}\\ \mbox{}\\ \}\mbox{}\\ \mbox{}\\ \end{flushleft} \end{document}