cond-perf.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #include <pthread.h>
  2. #include <stdbool.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include <atomic.h>
  8. static pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
  9. static pthread_mutex_t mut1 = PTHREAD_MUTEX_INITIALIZER;
  10. static pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
  11. static pthread_mutex_t mut2 = PTHREAD_MUTEX_INITIALIZER;
  12. static bool last_round;
  13. static int ntogo;
  14. static bool alldone;
  15. static void *
  16. cons (void *arg)
  17. {
  18. pthread_mutex_lock (&mut1);
  19. do
  20. {
  21. if (atomic_decrement_and_test (&ntogo))
  22. {
  23. pthread_mutex_lock (&mut2);
  24. alldone = true;
  25. pthread_cond_signal (&cond2);
  26. pthread_mutex_unlock (&mut2);
  27. }
  28. pthread_cond_wait (&cond1, &mut1);
  29. }
  30. while (! last_round);
  31. pthread_mutex_unlock (&mut1);
  32. return NULL;
  33. }
  34. int
  35. main (int argc, char *argv[])
  36. {
  37. int opt;
  38. int err;
  39. int nthreads = 10;
  40. int nrounds = 100;
  41. bool keeplock = false;
  42. while ((opt = getopt (argc, argv, "n:r:k")) != -1)
  43. switch (opt)
  44. {
  45. case 'n':
  46. nthreads = atol (optarg);
  47. break;
  48. case 'r':
  49. nrounds = atol (optarg);
  50. break;
  51. case 'k':
  52. keeplock = true;
  53. break;
  54. }
  55. ntogo = nthreads;
  56. pthread_t th[nthreads];
  57. int i;
  58. for (i = 0; __builtin_expect (i < nthreads, 1); ++i)
  59. if (__builtin_expect ((err = pthread_create (&th[i], NULL, cons, (void *) (long) i)) != 0, 0))
  60. printf ("pthread_create: %s\n", strerror (err));
  61. for (i = 0; __builtin_expect (i < nrounds, 1); ++i)
  62. {
  63. pthread_mutex_lock (&mut2);
  64. while (! alldone)
  65. pthread_cond_wait (&cond2, &mut2);
  66. pthread_mutex_unlock (&mut2);
  67. pthread_mutex_lock (&mut1);
  68. if (! keeplock)
  69. pthread_mutex_unlock (&mut1);
  70. ntogo = nthreads;
  71. alldone = false;
  72. if (i + 1 >= nrounds)
  73. last_round = true;
  74. pthread_cond_broadcast (&cond1);
  75. if (keeplock)
  76. pthread_mutex_unlock (&mut1);
  77. }
  78. for (i = 0; i < nthreads; ++i)
  79. if ((err = pthread_join (th[i], NULL)) != 0)
  80. printf ("pthread_create: %s\n", strerror (err));
  81. return 0;
  82. }