sem.c 4.0 KB

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