sem.c 4.3 KB

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