-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
1,917 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
/***************************************************************************** | ||
* FILE: dotprod_mutex.c | ||
* DESCRIPTION: | ||
* This example program illustrates the use of mutex variables | ||
* in a threads program. This version was obtained by modifying the | ||
* serial version of the program (dotprod_serial.c) which performs a | ||
* dot product. The main data is made available to all threads through | ||
* a globally accessible structure. Each thread works on a different | ||
* part of the data. The main thread waits for all the threads to complete | ||
* their computations, and then it prints the resulting sum. | ||
* SOURCE: Vijay Sonnad, IBM | ||
* LAST REVISED: 01/29/09 Blaise Barney | ||
******************************************************************************/ | ||
#include <pthread.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
/* | ||
The following structure contains the necessary information | ||
to allow the function "dotprod" to access its input data and | ||
place its output into the structure. This structure is | ||
unchanged from the sequential version. | ||
*/ | ||
|
||
typedef struct | ||
{ | ||
double *a; | ||
double *b; | ||
double sum; | ||
int veclen; | ||
} DOTDATA; | ||
|
||
/* Define globally accessible variables and a mutex */ | ||
|
||
#define NUMTHRDS 4 | ||
#define VECLEN 100 | ||
DOTDATA dotstr; | ||
pthread_t callThd[NUMTHRDS]; | ||
pthread_mutex_t mutexsum; | ||
|
||
/* | ||
The function dotprod is activated when the thread is created. | ||
As before, all input to this routine is obtained from a structure | ||
of type DOTDATA and all output from this function is written into | ||
this structure. The benefit of this approach is apparent for the | ||
multi-threaded program: when a thread is created we pass a single | ||
argument to the activated function - typically this argument | ||
is a thread number. All the other information required by the | ||
function is accessed from the globally accessible structure. | ||
*/ | ||
|
||
void *dotprod(void *arg) | ||
{ | ||
|
||
/* Define and use local variables for convenience */ | ||
|
||
int i, start, end, len ; | ||
long offset; | ||
double mysum, *x, *y; | ||
offset = (long)arg; | ||
|
||
len = dotstr.veclen; | ||
start = offset*len; | ||
end = start + len; | ||
x = dotstr.a; | ||
y = dotstr.b; | ||
|
||
/* | ||
Perform the dot product and assign result | ||
to the appropriate variable in the structure. | ||
*/ | ||
|
||
mysum = 0; | ||
for (i=start; i<end ; i++) | ||
{ | ||
mysum += (x[i] * y[i]); | ||
} | ||
|
||
/* | ||
Lock a mutex prior to updating the value in the shared | ||
structure, and unlock it upon updating. | ||
*/ | ||
pthread_mutex_lock (&mutexsum); | ||
dotstr.sum += mysum; | ||
pthread_mutex_unlock (&mutexsum); | ||
|
||
pthread_exit((void*) 0); | ||
} | ||
|
||
/* | ||
The main program creates threads which do all the work and then | ||
print out result upon completion. Before creating the threads, | ||
The input data is created. Since all threads update a shared structure, we | ||
need a mutex for mutual exclusion. The main thread needs to wait for | ||
all threads to complete, it waits for each one of the threads. We specify | ||
a thread attribute value that allow the main thread to join with the | ||
threads it creates. Note also that we free up handles when they are | ||
no longer needed. | ||
*/ | ||
|
||
int main (int argc, char *argv[]) | ||
{ | ||
long i; | ||
double *a, *b; | ||
void *status; | ||
pthread_attr_t attr; | ||
|
||
/* Assign storage and initialize values */ | ||
|
||
a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double)); | ||
b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double)); | ||
|
||
for (i=0; i<VECLEN*NUMTHRDS; i++) { | ||
a[i]=1; | ||
b[i]=a[i]; | ||
} | ||
|
||
dotstr.veclen = VECLEN; | ||
dotstr.a = a; | ||
dotstr.b = b; | ||
dotstr.sum=0; | ||
|
||
pthread_mutex_init(&mutexsum, NULL); | ||
|
||
/* Create threads to perform the dotproduct */ | ||
pthread_attr_init(&attr); | ||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); | ||
|
||
for(i=0;i<NUMTHRDS;i++) | ||
{ | ||
/* Each thread works on a different set of data. | ||
* The offset is specified by 'i'. The size of | ||
* the data for each thread is indicated by VECLEN. | ||
*/ | ||
pthread_create(&callThd[i], &attr, dotprod, (void *)i); | ||
} | ||
|
||
pthread_attr_destroy(&attr); | ||
/* Wait on the other threads */ | ||
|
||
for(i=0;i<NUMTHRDS;i++) { | ||
pthread_join(callThd[i], &status); | ||
} | ||
/* After joining, print out the results and cleanup */ | ||
|
||
printf ("Sum = %f \n", dotstr.sum); | ||
free (a); | ||
free (b); | ||
pthread_mutex_destroy(&mutexsum); | ||
pthread_exit(NULL); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/****************************************************************************** | ||
* FILE: dotprod_serial.c | ||
* DESCRIPTION: | ||
* This is a simple serial program which computes the dot product of two | ||
* vectors. The threaded version can is dotprod_mutex.c. | ||
* SOURCE: Vijay Sonnad, IBM | ||
* LAST REVISED: 01/29/09 Blaise Barney | ||
******************************************************************************/ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
/* | ||
The following structure contains the necessary information | ||
to allow the function "dotprod" to access its input data and | ||
place its output so that it can be accessed later. | ||
*/ | ||
|
||
typedef struct | ||
{ | ||
double *a; | ||
double *b; | ||
double sum; | ||
int veclen; | ||
} DOTDATA; | ||
|
||
#define VECLEN 100 | ||
DOTDATA dotstr; | ||
|
||
/* | ||
We will use a function (dotprod) to perform the scalar product. | ||
All input to this routine is obtained through a structure of | ||
type DOTDATA and all output from this function is written into | ||
this same structure. While this is unnecessarily restrictive | ||
for a sequential program, it will turn out to be useful when | ||
we modify the program to compute in parallel. | ||
*/ | ||
|
||
void dotprod() | ||
{ | ||
|
||
/* Define and use local variables for convenience */ | ||
|
||
int start, end, i; | ||
double mysum, *x, *y; | ||
|
||
start=0; | ||
end = dotstr.veclen; | ||
x = dotstr.a; | ||
y = dotstr.b; | ||
|
||
/* | ||
Perform the dot product and assign result | ||
to the appropriate variable in the structure. | ||
*/ | ||
|
||
mysum = 0; | ||
for (i=start; i<end ; i++) | ||
{ | ||
mysum += (x[i] * y[i]); | ||
} | ||
dotstr.sum = mysum; | ||
|
||
} | ||
|
||
/* | ||
The main program initializes data and calls the dotprd() function. | ||
Finally, it prints the result. | ||
*/ | ||
|
||
int main (int argc, char *argv[]) | ||
{ | ||
int i,len; | ||
double *a, *b; | ||
|
||
/* Assign storage and initialize values */ | ||
len = VECLEN; | ||
a = (double*) malloc (len*sizeof(double)); | ||
b = (double*) malloc (len*sizeof(double)); | ||
|
||
for (i=0; i<len; i++) { | ||
a[i]=1; | ||
b[i]=a[i]; | ||
} | ||
|
||
dotstr.veclen = len; | ||
dotstr.a = a; | ||
dotstr.b = b; | ||
dotstr.sum=0; | ||
|
||
/* Perform the dotproduct */ | ||
dotprod (); | ||
|
||
/* Print result and release storage */ | ||
printf ("Sum = %f \n", dotstr.sum); | ||
free (a); | ||
free (b); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/***************************************************************************** | ||
* FILE: join.c | ||
* DESCRIPTION: | ||
* This example demonstrates how to "wait" for thread completions by using | ||
* the Pthread join routine. Threads are explicitly created in a joinable | ||
* state for portability reasons. Use of the pthread_exit status argument is | ||
* also shown. Compare to detached.c | ||
* AUTHOR: 8/98 Blaise Barney | ||
* LAST REVISED: 01/30/09 | ||
******************************************************************************/ | ||
#include <pthread.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#define NUM_THREADS 4 | ||
|
||
void *BusyWork(void *t) | ||
{ | ||
int i; | ||
long tid; | ||
double result=0.0; | ||
tid = (long)t; | ||
printf("Thread %ld starting...\n",tid); | ||
for (i=0; i<1000000; i++) | ||
{ | ||
result = result + sin(i) * tan(i); | ||
} | ||
printf("Thread %ld done. Result = %e\n",tid, result); | ||
pthread_exit((void*) t); | ||
} | ||
|
||
int main (int argc, char *argv[]) | ||
{ | ||
pthread_t thread[NUM_THREADS]; | ||
pthread_attr_t attr; | ||
int rc; | ||
long t; | ||
void *status; | ||
|
||
/* Initialize and set thread detached attribute */ | ||
pthread_attr_init(&attr); | ||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); | ||
|
||
for(t=0; t<NUM_THREADS; t++) { | ||
printf("Main: creating thread %ld\n", t); | ||
rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t); | ||
if (rc) { | ||
printf("ERROR; return code from pthread_create() is %d\n", rc); | ||
exit(-1); | ||
} | ||
} | ||
|
||
/* Free attribute and wait for the other threads */ | ||
pthread_attr_destroy(&attr); | ||
for(t=0; t<NUM_THREADS; t++) { | ||
rc = pthread_join(thread[t], &status); | ||
if (rc) { | ||
printf("ERROR; return code from pthread_join() is %d\n", rc); | ||
exit(-1); | ||
} | ||
printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status); | ||
} | ||
|
||
printf("Main: program completed. Exiting.\n"); | ||
pthread_exit(NULL); | ||
} | ||
|
Oops, something went wrong.