source: CIVL/examples/pthread/dotprod_mutex.cvl@ 325d439

1.23 2.0 main test-branch
Last change on this file since 325d439 was 6fe2cd9, checked in by John Edenhofner <johneden@…>, 12 years ago

Almost done

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@1040 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 4.8 KB
Line 
1/*****************************************************************************
2* SOURCE: This is a translation of a Pthread program from the Lawrence Livermore
3* Computing Center POSIX Threads Programming Exercise at:
4* https://computing.llnl.gov/tutorials/pthreads/exercise.html
5* FILE: dotprod_mutex.cvl
6* DESCRIPTION:
7* This example program illustrates the use of mutex variables
8* in a threads program. This version was obtained by modifying the
9* serial version of the program (dotprod_serial.c) which performs a
10* dot product. The main data is made available to all threads through
11* a globally accessible structure. Each thread works on a different
12* part of the data. The main thread waits for all the threads to complete
13* their computations, and then it prints the resulting sum.
14* Command line execution:
15* civl verify -inputNUMTHRDS=4 -inputVECLEN=100000 dotprod_mutex.cvl
16******************************************************************************/
17
18#include "pthread.cvh"
19#include <civlc.h>
20#include <stdio.h>
21#include <stdlib.h>
22
23/*
24The following structure contains the necessary information
25to allow the function "dotprod" to access its input data and
26place its output into the structure. This structure is
27unchanged from the sequential version.
28*/
29
30typedef struct
31{
32 double *a;
33 double *b;
34 double sum;
35 int veclen;
36} DOTDATA;
37
38/* Define globally accessible variables and a mutex */
39
40$input int NUMTHRDS;
41$input int VECLEN;
42
43DOTDATA dotstr;
44pthread_t callThd[NUMTHRDS];
45pthread_mutex_t mutexsum;
46
47/*
48The function dotprod is activated when the thread is created.
49As before, all input to this routine is obtained from a structure
50of type DOTDATA and all output from this function is written into
51this structure. The benefit of this approach is apparent for the
52multi-threaded program: when a thread is created we pass a single
53argument to the activated function - typically this argument
54is a thread number. All the other information required by the
55function is accessed from the globally accessible structure.
56*/
57
58void *dotprod(void *arg)
59{
60 /* Define and use local variables for convenience */
61 int i, start, end, len ;
62 long offset;
63 double mysum, *x, *y;
64 offset = (long)*arg; // Dereference rather than direct conv
65
66 len = dotstr.veclen;
67 start = offset*len;
68 end = start + len;
69 x = dotstr.a;
70 y = dotstr.b;
71
72 /*
73 Perform the dot product and assign result
74 to the appropriate variable in the structure.
75 */
76 mysum = 0;
77 for (i=start; i<end ; i++) {
78 mysum += (x[i] * y[i]);
79 }
80
81 /*
82 Lock a mutex prior to updating the value in the shared
83 structure, and unlock it upon updating.
84 */
85 pthread_mutex_lock (&mutexsum);
86 dotstr.sum += mysum;
87 printf("Thread %d did %d to %d: mysum=%f global sum=%f\n",offset,start,end,mysum,dotstr.sum); //Removed l from %ld, unsupported
88 pthread_mutex_unlock (&mutexsum);
89
90 pthread_exit(NULL, false, NULL, 0); //Different parameters
91}
92
93/*
94The main program creates threads which do all the work and then
95print out result upon completion. Before creating the threads,
96The input data is created. Since all threads update a shared structure, we
97need a mutex for mutual exclusion. The main thread needs to wait for
98all threads to complete, it waits for each one of the threads. We specify
99a thread attribute value that allow the main thread to join with the
100threads it creates. Note also that we free up handles when they are
101no longer needed.
102*/
103
104int main (void)
105{
106 long i;
107 long j[NUMTHRDS];
108 double *a, *b;
109 void *status;
110 pthread_attr_t attr;
111
112 /* Assign storage and initialize values */
113
114 a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
115 b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
116
117 for (i=0; i<VECLEN*NUMTHRDS; i++) {
118 a[i]=1;
119 b[i]=a[i];
120 }
121
122 dotstr.veclen = VECLEN;
123 dotstr.a = a;
124 dotstr.b = b;
125 dotstr.sum=0;
126
127 pthread_mutex_init(&mutexsum, NULL);
128
129 /* Create threads to perform the dotproduct */
130 pthread_attr_init(&attr);
131 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
132
133 for(i=0;i<NUMTHRDS;i++){
134 /* Each thread works on a different set of data.
135 * The offset is specified by 'i'. The size of
136 * the data for each thread is indicated by VECLEN.
137 */
138 //Add values into array and use address so that each value is unique as int to void * conversion is not supported
139 j[i] = (long)i;
140 pthread_create(&callThd[i], &attr, dotprod, (void *)&j[i]);
141 }
142
143 pthread_attr_destroy(&attr);
144 /* Wait on the other threads */
145
146 for(i=0;i<NUMTHRDS;i++) {
147 pthread_join(callThd[i], &status);
148 }
149 /* After joining, print out the results and cleanup */
150
151 printf ("Sum = %f \n", dotstr.sum);
152 free (a);
153 free (b);
154 pthread_mutex_destroy(&mutexsum);
155 pthread_exit(NULL, true, NULL, 0); //Different parameters
156}
Note: See TracBrowser for help on using the repository browser.