sem.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <sys/types.h>
  6. #include <sys/ipc.h>
  7. #include <sys/sem.h>
  8. #include <sys/time.h>
  9. #include <sys/wait.h>
  10. #define TEST_TIMES 1000
  11. #define DO_BENCH 1
  12. enum { PARALLEL, SERIAL, IN_PROCESS } mode = PARALLEL;
  13. int pipefds[2], key;
  14. /* server always sends messages */
  15. void server (void)
  16. {
  17. struct timeval tv1, tv2;
  18. int semid;
  19. struct sembuf buf;
  20. if ((semid = semget(key, 2, mode == SERIAL ? 0600|IPC_CREAT : 0)) < 0) {
  21. perror("semget");
  22. exit(1);
  23. }
  24. gettimeofday(&tv1, NULL);
  25. for (int i = 0 ; i < TEST_TIMES ; i++) {
  26. buf.sem_num = 0;
  27. buf.sem_op = 1;
  28. buf.sem_flg = 0;
  29. if (semop(semid, &buf, 1) < 0) {
  30. perror("semop");
  31. exit(1);
  32. }
  33. #ifndef DO_BENCH
  34. printf("Semaphore %d signaled\n", i);
  35. #endif
  36. }
  37. gettimeofday(&tv2, NULL);
  38. printf("time spent on %d semop (signal): %llu microsecond\n",
  39. TEST_TIMES,
  40. (tv2.tv_sec * 1000000ull + tv2.tv_usec) -
  41. (tv1.tv_sec * 1000000ull + tv1.tv_usec));
  42. if (mode == PARALLEL) {
  43. close(pipefds[0]);
  44. char byte = 0;
  45. write(pipefds[1], &byte, 1);
  46. buf.sem_num = 1;
  47. buf.sem_op = -1;
  48. buf.sem_flg = 0;
  49. if (semop(semid, &buf, 1) < 0) {
  50. perror("semop");
  51. exit(1);
  52. }
  53. semctl(semid, 0, IPC_RMID);
  54. }
  55. if (mode != IN_PROCESS)
  56. exit(0);
  57. }
  58. /* client always sends messages */
  59. void client (void)
  60. {
  61. struct timeval tv1, tv2;
  62. int semid;
  63. struct sembuf buf;
  64. if (mode == PARALLEL) {
  65. close(pipefds[1]);
  66. char byte = 0;
  67. read(pipefds[0], &byte, 1);
  68. }
  69. if ((semid = semget(key, 0, 0)) < 0) {
  70. perror("semget");
  71. exit(1);
  72. }
  73. gettimeofday(&tv1, NULL);
  74. for (int i = 0 ; i < TEST_TIMES ; i++) {
  75. buf.sem_num = 0;
  76. buf.sem_op = -1;
  77. buf.sem_flg = 0;
  78. if (semop(semid, &buf, 1) < 0) {
  79. perror("semop");
  80. exit(1);
  81. }
  82. #ifndef DO_BENCH
  83. printf("Semaphore %d wakened\n", i);
  84. #endif
  85. }
  86. gettimeofday(&tv2, NULL);
  87. if (mode == PARALLEL) {
  88. buf.sem_num = 1;
  89. buf.sem_op = 1;
  90. buf.sem_flg = 0;
  91. if (semop(semid, &buf, 1) < 0) {
  92. perror("semop");
  93. exit(1);
  94. }
  95. }
  96. else
  97. semctl(semid, 0, IPC_RMID);
  98. printf("time spent on %d semop (wait): %llu microsecond\n",
  99. TEST_TIMES,
  100. (tv2.tv_sec * 1000000ull + tv2.tv_usec) -
  101. (tv1.tv_sec * 1000000ull + tv1.tv_usec));
  102. if (mode != IN_PROCESS)
  103. exit(0);
  104. }
  105. int main (int argc, char ** argv)
  106. {
  107. int semid;
  108. key = rand();
  109. #ifndef DO_BENCH
  110. printf("Semaphore key: 0x%8x\n", key);
  111. #endif
  112. /* server run first and client run later */
  113. if (argc == 2 && strcmp(argv[1], "serial") == 0) {
  114. mode = SERIAL;
  115. if (fork() == 0)
  116. server();
  117. wait(NULL);
  118. if (fork() == 0)
  119. client();
  120. wait(NULL);
  121. }
  122. if ((semid = semget(key, 2, 0600|IPC_CREAT)) < 0) {
  123. perror("semget");
  124. exit(1);
  125. }
  126. /* server run first and client run later (in the same process) */
  127. if (argc == 2 && strcmp(argv[1], "in-process") == 0) {
  128. mode = IN_PROCESS;
  129. server();
  130. client();
  131. semctl(semid, 0, IPC_RMID);
  132. return 0;
  133. }
  134. pipe(pipefds);
  135. /* server to be the parent and client to be the child */
  136. if (argc == 1) {
  137. if (fork() == 0)
  138. client();
  139. else
  140. server();
  141. }
  142. /* client to be the parent and server to be the child */
  143. if (argc == 2 && strcmp(argv[1], "reverse") == 0) {
  144. if (fork() == 0)
  145. server();
  146. else
  147. client();
  148. }
  149. /* both client and server are children */
  150. if (argc == 2 && strcmp(argv[1], "children") == 0) {
  151. if (fork() == 0)
  152. server();
  153. if (fork() == 0)
  154. client();
  155. wait(NULL);
  156. wait(NULL);
  157. }
  158. semctl(semid, 0, IPC_RMID);
  159. return 0;
  160. }