%
% This file was automatically produced at Feb 27 2003, 22:51:56 by
% c2latex -c dotprod_mutex.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$\mbox{}\\
$\ast$ FILE: dotprod\_mutex.c\mbox{}\\
$\ast$ DESCRIPTION:\mbox{}\\
$\ast$   This example program illustrates the use of mutex variables \mbox{}\\
$\ast$   in a threads program. This version was obtained by modifying the\mbox{}\\
$\ast$   serial version of the program (dotprod\_serial.c) which performs a \mbox{}\\
$\ast$   dot product. The main data is made available to all threads through \mbox{}\\
$\ast$   a globally accessible  structure. Each thread works on a different \mbox{}\\
$\ast$   part of the data. The main thread waits for all the threads to complete \mbox{}\\
$\ast$   their computations, and then it prints the resulting sum.\mbox{}\\
$\ast$\mbox{}\\
$\ast$ SOURCE: Vijay Sonnad, IBM\mbox{}\\
$\ast$ LAST REVISED: 9/20/98 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{}\\
{\tt \#include} $<${\tt{}malloc.h}$>$\mbox{}\\
\mbox{}\\
{$/\ast$\it{}   \mbox{}\\
The following structure contains the necessary information  \mbox{}\\
to allow the function "dotprod" to access its input data and \mbox{}\\
place its output into the structure.  This structure is \mbox{}\\
unchanged from the sequential version.\mbox{}\\
$\ast/$}\mbox{}\\
\mbox{}\\
{\bf typedef} {\bf struct} \mbox{}\\
\hspace*{1\indentation}\{\mbox{}\\
\hspace*{3\indentation}{\bf double}      $\ast$a;\mbox{}\\
\hspace*{3\indentation}{\bf double}      $\ast$b;\mbox{}\\
\hspace*{3\indentation}{\bf double}     sum; \mbox{}\\
\hspace*{3\indentation}{\bf int}     veclen; \mbox{}\\
\hspace*{1\indentation}\} DOTDATA;\mbox{}\\
\mbox{}\\
{$/\ast$\it{} Define globally accessible variables and a mutex $\ast/$}\mbox{}\\
\mbox{}\\
{\tt \#define} NUMTHRDS 4\mbox{}\\
{\tt \#define} VECLEN 100\mbox{}\\
\hspace*{3\indentation}DOTDATA dotstr; \mbox{}\\
\hspace*{3\indentation}pthread\_t callThd[NUMTHRDS];\mbox{}\\
\hspace*{3\indentation}pthread\_mutex\_t mutexsum;\mbox{}\\
\mbox{}\\
{$/\ast$\it{}\mbox{}\\
The function dotprod is activated when the thread is created.\mbox{}\\
As before, all input to this routine is obtained from a structure \mbox{}\\
of type DOTDATA and all output from this function is written into\mbox{}\\
this structure. The benefit of this approach is apparent for the \mbox{}\\
multi$-$threaded program: when a thread is created we pass a single\mbox{}\\
argument to the activated function $-$ typically this argument\mbox{}\\
is a thread number. All  the other information required by the \mbox{}\\
function is accessed from the globally accessible structure. \mbox{}\\
$\ast/$}\mbox{}\\
\mbox{}\\
{\bf void} $\ast$dotprod({\bf void} $\ast$arg)\mbox{}\\
\{\mbox{}\\
\mbox{}\\
{$/\ast$\it{} Define and use local variables for convenience $\ast/$}\mbox{}\\
\mbox{}\\
\hspace*{3\indentation}{\bf int} i, start, end, offset, len ;\mbox{}\\
\hspace*{3\indentation}{\bf double} mysum, $\ast$x, $\ast$y;\mbox{}\\
\hspace*{3\indentation}offset = ({\bf int})arg;\mbox{}\\
\hspace*{5\indentation}\mbox{}\\
\hspace*{3\indentation}len = dotstr.veclen;\mbox{}\\
\hspace*{3\indentation}start = offset$\ast$len;\mbox{}\\
\hspace*{3\indentation}end   = start + len;\mbox{}\\
\hspace*{3\indentation}x = dotstr.a;\mbox{}\\
\hspace*{3\indentation}y = dotstr.b;\mbox{}\\
\mbox{}\\
{$/\ast$\it{}\mbox{}\\
Perform the dot product and assign result\mbox{}\\
to the appropriate variable in the structure. \mbox{}\\
$\ast/$}\mbox{}\\
\mbox{}\\
\hspace*{3\indentation}mysum = 0;\mbox{}\\
\hspace*{3\indentation}{\bf for} (i=start; i$<$end ; i++) \mbox{}\\
\hspace*{4\indentation}\{\mbox{}\\
\hspace*{6\indentation}mysum += (x[i] $\ast$ y[i]);\mbox{}\\
\hspace*{4\indentation}\}\mbox{}\\
\mbox{}\\
{$/\ast$\it{}\mbox{}\\
Lock a mutex prior to updating the value in the shared\mbox{}\\
structure, and unlock it upon updating.\mbox{}\\
$\ast/$}\mbox{}\\
\hspace*{3\indentation}pthread\_mutex\_lock (\&mutexsum);\mbox{}\\
\hspace*{3\indentation}dotstr.sum += mysum;\mbox{}\\
\hspace*{3\indentation}pthread\_mutex\_unlock (\&mutexsum);\mbox{}\\
\mbox{}\\
\hspace*{3\indentation}pthread\_exit(({\bf void}$\ast$) 0);\mbox{}\\
\}\mbox{}\\
\mbox{}\\
{$/\ast$\it{} \mbox{}\\
The main program creates threads which do all the work and then \mbox{}\\
print out result upon completion. Before creating the threads,\mbox{}\\
The input data is created. Since all threads update a shared structure, we\mbox{}\\
need a mutex for mutual exclusion. The main thread needs to wait for\mbox{}\\
all threads to complete, it waits for each one of the threads. We specify\mbox{}\\
a thread attribute value that allow the main thread to join with the\mbox{}\\
threads it creates. Note also that we free up handles  when they are\mbox{}\\
no longer needed.\mbox{}\\
$\ast/$}\mbox{}\\
\mbox{}\\
{\bf int} main ({\bf int} argc, {\bf char} $\ast$argv[])\mbox{}\\
\{\mbox{}\\
\hspace*{3\indentation}{\bf int} i;\mbox{}\\
\hspace*{3\indentation}{\bf double} $\ast$a, $\ast$b;\mbox{}\\
\hspace*{3\indentation}{\bf int} status;\mbox{}\\
\hspace*{3\indentation}pthread\_attr\_t attr;\mbox{}\\
\mbox{}\\
{$/\ast$\it{} Assign storage and initialize values $\ast/$}\mbox{}\\
\mbox{}\\
\hspace*{3\indentation}a = ({\bf double}$\ast$) malloc (NUMTHRDS$\ast$VECLEN$\ast${\bf sizeof}({\bf double}));\mbox{}\\
\hspace*{3\indentation}b = ({\bf double}$\ast$) malloc (NUMTHRDS$\ast$VECLEN$\ast${\bf sizeof}({\bf double}));\mbox{}\\
\hspace*{2\indentation}\mbox{}\\
\hspace*{3\indentation}{\bf for} (i=0; i$<$VECLEN$\ast$NUMTHRDS; i++)\mbox{}\\
\hspace*{4\indentation}\{\mbox{}\\
\hspace*{5\indentation}a[i]=1;\mbox{}\\
\hspace*{5\indentation}b[i]=a[i];\mbox{}\\
\hspace*{4\indentation}\}\mbox{}\\
\mbox{}\\
\hspace*{3\indentation}dotstr.veclen = VECLEN; \mbox{}\\
\hspace*{3\indentation}dotstr.a = a; \mbox{}\\
\hspace*{3\indentation}dotstr.b = b; \mbox{}\\
\hspace*{3\indentation}dotstr.sum=0;\mbox{}\\
\mbox{}\\
\hspace*{3\indentation}pthread\_mutex\_init(\&mutexsum, NULL);\mbox{}\\
\hspace*{9\indentation}\mbox{}\\
{$/\ast$\it{} Create threads to perform the dotproduct  $\ast/$}\mbox{}\\
\hspace*{3\indentation}pthread\_attr\_init(\&attr);\mbox{}\\
\hspace*{3\indentation}pthread\_attr\_setdetachstate(\&attr, PTHREAD\_CREATE\_JOINABLE);\mbox{}\\
\mbox{}\\
\hspace*{8\indentation}{\bf for}(i=0;i$<$NUMTHRDS;i++)\mbox{}\\
\hspace*{8\indentation}\{\mbox{}\\
\hspace*{16\indentation}{$/\ast$\it{} \mbox{}\\
\hspace*{16\indentation}$\ast$$\ast$ Each thread works on a different set of data.\mbox{}\\
\hspace*{16\indentation}$\ast$$\ast$ The offset is specified by 'i'. The size of\mbox{}\\
\hspace*{16\indentation}$\ast$$\ast$ the data for each thread is indicated by VECLEN.\mbox{}\\
\hspace*{16\indentation}$\ast/$}\mbox{}\\
\hspace*{16\indentation}pthread\_create( \&callThd[i], \&attr, dotprod, ({\bf void} $\ast$)i); \mbox{}\\
\hspace*{8\indentation}\}\mbox{}\\
\mbox{}\\
\hspace*{8\indentation}pthread\_attr\_destroy(\&attr);\mbox{}\\
{$/\ast$\it{} Wait on the other threads $\ast/$}\mbox{}\\
\mbox{}\\
\hspace*{8\indentation}{\bf for}(i=0;i$<$NUMTHRDS;i++)\mbox{}\\
\hspace*{8\indentation}\{\mbox{}\\
\hspace*{10\indentation}pthread\_join( callThd[i], ({\bf void} $\ast$$\ast$)\&status);\mbox{}\\
\hspace*{8\indentation}\}\mbox{}\\
{$/\ast$\it{} After joining, print out the results and cleanup $\ast/$}\mbox{}\\
\mbox{}\\
\hspace*{3\indentation}printf ({\tt"Sum $=$  \%f $\backslash$n"}, dotstr.sum);\mbox{}\\
\hspace*{3\indentation}free (a);\mbox{}\\
\hspace*{3\indentation}free (b);\mbox{}\\
\hspace*{3\indentation}pthread\_mutex\_destroy(\&mutexsum);\mbox{}\\
\hspace*{3\indentation}pthread\_exit(NULL);\mbox{}\\
\}   \mbox{}\\
\mbox{}\\
\end{flushleft}
\end{document}
