eventfd.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. #include <errno.h>
  2. #include <poll.h>
  3. #include <pthread.h>
  4. #include <signal.h>
  5. #include <stdarg.h>
  6. #include <stdint.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <sys/eventfd.h>
  11. #include <sys/time.h>
  12. #include <sys/types.h>
  13. #include <sys/wait.h>
  14. #include <unistd.h>
  15. #define MAX_EFDS 3
  16. #define CLOSE_EFD_AND_EXIT(efd) \
  17. do { \
  18. close(efd); \
  19. return 1; \
  20. } while (0)
  21. #define EXIT_IF_ERROR(efd, bytes, prefix) \
  22. do { \
  23. if ((bytes) != sizeof(uint64_t)) { \
  24. perror(prefix); \
  25. printf("error at line-%d\n", __LINE__); \
  26. CLOSE_EFD_AND_EXIT(efd); \
  27. } \
  28. } while (0)
  29. int efds[MAX_EFDS] = {0};
  30. void* write_eventfd_thread(void* arg) {
  31. uint64_t count = 10;
  32. int* efds = (int*)arg;
  33. if (!arg) {
  34. printf("arg is NULL\n");
  35. return NULL;
  36. }
  37. printf("%s:got here\n", __func__);
  38. for (int i = 0; i < MAX_EFDS; i++) {
  39. printf("%s: efd = %d\n", __func__, efds[i]);
  40. }
  41. for (int i = 0; i < MAX_EFDS; i++) {
  42. sleep(1);
  43. if (write(efds[i], &count, sizeof(count)) != sizeof(count)) {
  44. perror("write error");
  45. return NULL;
  46. }
  47. count += 1;
  48. }
  49. return NULL;
  50. }
  51. /* This function used to test polling on a group of eventfd descriptors.
  52. * To support regression testing, positive value returned for error case. */
  53. int eventfd_using_poll() {
  54. int ret = 0;
  55. struct pollfd pollfds[MAX_EFDS];
  56. pthread_t tid = 0;
  57. uint64_t count = 0;
  58. int poll_ret = 0;
  59. int nread_events = 0;
  60. for (int i = 0; i < MAX_EFDS; i++) {
  61. efds[i] = eventfd(0, 0);
  62. if (efds[i] < 0) {
  63. perror("eventfd failed");
  64. return 1;
  65. }
  66. printf("efd = %d\n", efds[i]);
  67. pollfds[i].fd = efds[i];
  68. pollfds[i].events = POLLIN;
  69. }
  70. ret = pthread_create(&tid, NULL, write_eventfd_thread, efds);
  71. if (ret != 0) {
  72. perror("error in thread creation\n");
  73. ret = 1;
  74. goto out;
  75. }
  76. while (1) {
  77. poll_ret = poll(pollfds, MAX_EFDS, 5000);
  78. if (poll_ret == 0) {
  79. printf("Poll timed out. Exiting.\n");
  80. break;
  81. }
  82. if (poll_ret < 0) {
  83. perror("error from poll");
  84. ret = 1;
  85. break;
  86. }
  87. for (int i = 0; i < MAX_EFDS; i++) {
  88. if (pollfds[i].revents & POLLIN) {
  89. pollfds[i].revents = 0;
  90. errno = 0;
  91. if (read(pollfds[i].fd, &count, sizeof(count)) != sizeof(count)) {
  92. perror("read error");
  93. ret = 1;
  94. goto out;
  95. }
  96. printf("fd set=%d\n", pollfds[i].fd);
  97. printf("efd = %d, count: %lu, errno=%d\n", pollfds[i].fd, count, errno);
  98. nread_events++;
  99. }
  100. }
  101. }
  102. if (nread_events == MAX_EFDS)
  103. printf("%s completed successfully\n", __func__);
  104. else
  105. printf("%s: nread_events=%d, MAX_EFDS=%d\n", __func__, nread_events, MAX_EFDS);
  106. pthread_join(tid, NULL);
  107. out:
  108. for (int i = 0; i < MAX_EFDS; i++) {
  109. close(efds[i]);
  110. }
  111. return ret;
  112. }
  113. /* This function used to test various flags supported while creating eventfd
  114. * descriptors.
  115. * To support regression testing, positive value returned for error case. */
  116. int eventfd_using_various_flags() {
  117. uint64_t count = 0;
  118. int efd = 0;
  119. ssize_t bytes = 0;
  120. int eventfd_flags[] = {0, EFD_SEMAPHORE, EFD_NONBLOCK, EFD_CLOEXEC};
  121. for (int i = 0; i < sizeof(eventfd_flags) / sizeof(int); i++) {
  122. printf("iteration #-%d, flags=%d\n", i, eventfd_flags[i]);
  123. efd = eventfd(0, eventfd_flags[i]);
  124. if (efd < 0) {
  125. perror("eventfd failed");
  126. printf("eventfd error for iteration #-%d, flags-%d\n", i, eventfd_flags[i]);
  127. return 1;
  128. }
  129. count = 5;
  130. bytes = write(efd, &count, sizeof(count));
  131. EXIT_IF_ERROR(efd, bytes, "write");
  132. bytes = write(efd, &count, sizeof(count));
  133. EXIT_IF_ERROR(efd, bytes, "write");
  134. count = 0;
  135. errno = 0;
  136. if (eventfd_flags[i] & EFD_SEMAPHORE) {
  137. uint64_t prev_count = 0;
  138. bytes = read(efd, &prev_count, sizeof(prev_count));
  139. EXIT_IF_ERROR(efd, bytes, "read");
  140. bytes = read(efd, &count, sizeof(count));
  141. EXIT_IF_ERROR(efd, bytes, "read");
  142. if (prev_count != 1 || count != 1) {
  143. printf("flag->EFD_SEMAPHORE, error, prev_count=%lu, new count=%lu\n", prev_count,
  144. count);
  145. close(efd);
  146. return 1;
  147. }
  148. close(efd);
  149. continue;
  150. }
  151. count = 0;
  152. errno = 0;
  153. bytes = read(efd, &count, sizeof(count));
  154. EXIT_IF_ERROR(efd, bytes, "read");
  155. if (count != 10) {
  156. printf("%d: efd = %d, count: %lu, errno=%d\n", __LINE__, efd, count, errno);
  157. CLOSE_EFD_AND_EXIT(efd);
  158. }
  159. /* calling the second read would block if flags doesn't have EFD_NONBLOCK */
  160. if (eventfd_flags[i] & EFD_NONBLOCK) {
  161. count = 0;
  162. errno = 0;
  163. ssize_t ret = read(efd, &count, sizeof(count));
  164. if (ret != -1 || errno != EAGAIN) {
  165. printf("read that should return -1 with EAGAIN returned: %ld with errno=%d\n",
  166. ret,
  167. errno);
  168. close(efd);
  169. return 1;
  170. }
  171. printf("%d: efd = %d, count: %lu, errno=%d\n", __LINE__, efd, count, errno);
  172. }
  173. close(efd);
  174. }
  175. printf("%s completed successfully\n", __func__);
  176. return 0;
  177. }
  178. int eventfd_using_fork() {
  179. int status = 0;
  180. int efd = 0;
  181. uint64_t count = 0;
  182. efd = eventfd(0, EFD_NONBLOCK);
  183. if (efd < 0) {
  184. perror("eventfd failed");
  185. return 1;
  186. }
  187. pid_t pid = fork();
  188. if (pid == 0) {
  189. // child process
  190. count = 5;
  191. if (write(efd, &count, sizeof(count)) != sizeof(count)) {
  192. perror("write error");
  193. exit(1);
  194. }
  195. exit(0);
  196. } else if (pid > 0) {
  197. // parent process
  198. waitpid(pid, &status, 0);
  199. if (WIFSIGNALED(status)) {
  200. perror("child was terminated by signal");
  201. CLOSE_EFD_AND_EXIT(efd);
  202. }
  203. count = 0;
  204. if (read(efd, &count, sizeof(count)) != sizeof(count)) {
  205. perror("read error");
  206. close(efd);
  207. exit(1);
  208. }
  209. if (count != 5) {
  210. printf("parent-pid=%d, efd = %d, count: %lu, errno=%d\n", getpid(), efd, count, errno);
  211. CLOSE_EFD_AND_EXIT(efd);
  212. }
  213. } else {
  214. perror("fork error");
  215. CLOSE_EFD_AND_EXIT(efd);
  216. }
  217. close(efd);
  218. printf("%s completed successfully\n", __func__);
  219. return 0;
  220. }
  221. int main(int argc, char* argv[]) {
  222. int ret = 0;
  223. ret = eventfd_using_poll();
  224. ret += eventfd_using_various_flags();
  225. ret += eventfd_using_fork();
  226. return ret;
  227. }