You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
4.2 KiB

  1. /*****************************************************************************
  2. * FILE: dotprod_mutex.c
  3. * DESCRIPTION:
  4. * This example program illustrates the use of mutex variables
  5. * in a threads program. This version was obtained by modifying the
  6. * serial version of the program (dotprod_serial.c) which performs a
  7. * dot product. The main data is made available to all threads through
  8. * a globally accessible structure. Each thread works on a different
  9. * part of the data. The main thread waits for all the threads to complete
  10. * their computations, and then it prints the resulting sum.
  11. * SOURCE: Vijay Sonnad, IBM
  12. * LAST REVISED: 01/29/09 Blaise Barney
  13. * gcc -Wall -lpthread dotprod_mutex.c -o dotprod_mutex
  14. ******************************************************************************/
  15. #include <pthread.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. /*
  19. The following structure contains the necessary information
  20. to allow the function "dotprod" to access its input data and
  21. place its output into the structure. This structure is
  22. unchanged from the sequential version.
  23. */
  24. typedef struct
  25. {
  26. double *a;
  27. double *b;
  28. double sum;
  29. int veclen;
  30. } DOTDATA;
  31. /* Define globally accessible variables and a mutex */
  32. #define NUMTHRDS 10
  33. #define VECLEN 100000
  34. DOTDATA dotstr;
  35. pthread_t callThd[NUMTHRDS];
  36. pthread_mutex_t mutexsum;
  37. /*
  38. The function dotprod is activated when the thread is created.
  39. As before, all input to this routine is obtained from a structure
  40. of type DOTDATA and all output from this function is written into
  41. this structure. The benefit of this approach is apparent for the
  42. multi-threaded program: when a thread is created we pass a single
  43. argument to the activated function - typically this argument
  44. is a thread number. All the other information required by the
  45. function is accessed from the globally accessible structure.
  46. */
  47. void *dotprod(void *arg)
  48. {
  49. /* Define and use local variables for convenience */
  50. int i, start, end, len ;
  51. long offset;
  52. double mysum, *x, *y;
  53. offset = (long)arg;
  54. len = dotstr.veclen;
  55. start = offset*len;
  56. end = start + len;
  57. x = dotstr.a;
  58. y = dotstr.b;
  59. /*
  60. Perform the dot product and assign result
  61. to the appropriate variable in the structure.
  62. */
  63. mysum = 0;
  64. for (i=start; i<end ; i++)
  65. {
  66. mysum += (x[i] * y[i]);
  67. }
  68. /*
  69. Lock a mutex prior to updating the value in the shared
  70. structure, and unlock it upon updating.
  71. */
  72. pthread_mutex_lock (&mutexsum);
  73. dotstr.sum += mysum;
  74. printf("Thread %ld did %d to %d: mysum=%f global sum=%f\n",offset,start,end,mysum,dotstr.sum);
  75. pthread_mutex_unlock (&mutexsum);
  76. pthread_exit((void*) 0);
  77. }
  78. /*
  79. The main program creates threads which do all the work and then
  80. print out result upon completion. Before creating the threads,
  81. The input data is created. Since all threads update a shared structure, we
  82. need a mutex for mutual exclusion. The main thread needs to wait for
  83. all threads to complete, it waits for each one of the threads. We specify
  84. a thread attribute value that allow the main thread to join with the
  85. threads it creates. Note also that we free up handles when they are
  86. no longer needed.
  87. */
  88. int main (int argc, char *argv[])
  89. {
  90. long i;
  91. double *a, *b;
  92. void *status;
  93. pthread_attr_t attr;
  94. /* Assign storage and initialize values */
  95. a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
  96. b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
  97. for (i=0; i<VECLEN*NUMTHRDS; i++) {
  98. a[i]=1;
  99. b[i]=a[i];
  100. }
  101. dotstr.veclen = VECLEN;
  102. dotstr.a = a;
  103. dotstr.b = b;
  104. dotstr.sum=0;
  105. pthread_mutex_init(&mutexsum, NULL);
  106. /* Create threads to perform the dotproduct */
  107. pthread_attr_init(&attr);
  108. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  109. for(i=0;i<NUMTHRDS;i++)
  110. {
  111. /* Each thread works on a different set of data.
  112. * The offset is specified by 'i'. The size of
  113. * the data for each thread is indicated by VECLEN.
  114. */
  115. pthread_create(&callThd[i], &attr, dotprod, (void *)i);
  116. }
  117. pthread_attr_destroy(&attr);
  118. /* Wait on the other threads */
  119. for(i=0;i<NUMTHRDS;i++) {
  120. pthread_join(callThd[i], &status);
  121. }
  122. /* After joining, print out the results and cleanup */
  123. printf ("Sum = %f \n", dotstr.sum);
  124. free (a);
  125. free (b);
  126. pthread_mutex_destroy(&mutexsum);
  127. pthread_exit(NULL);
  128. }