123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- #include <errno.h>
- #include <poll.h>
- #include <pthread.h>
- #include <signal.h>
- #include <stdarg.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/eventfd.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #define MAX_EFDS 3
- #define CLOSE_EFD_AND_EXIT(efd) \
- do { \
- close(efd); \
- return 1; \
- } while (0)
- #define EXIT_IF_ERROR(efd, bytes, prefix) \
- do { \
- if ((bytes) != sizeof(uint64_t)) { \
- perror(prefix); \
- printf("error at line-%d\n", __LINE__); \
- CLOSE_EFD_AND_EXIT(efd); \
- } \
- } while (0)
- int efds[MAX_EFDS] = {0};
- void* write_eventfd_thread(void* arg) {
- uint64_t count = 10;
- int* efds = (int*)arg;
- if (!arg) {
- printf("arg is NULL\n");
- return NULL;
- }
- printf("%s:got here\n", __func__);
- for (int i = 0; i < MAX_EFDS; i++) {
- printf("%s: efd = %d\n", __func__, efds[i]);
- }
- for (int i = 0; i < MAX_EFDS; i++) {
- sleep(1);
- write(efds[i], &count, sizeof(count));
- count += 1;
- }
- return NULL;
- }
- /* This function used to test polling on a group of eventfd descriptors.
- * To support regression testing, positive value returned for error case. */
- int eventfd_using_poll() {
- int ret = 0;
- struct pollfd pollfds[MAX_EFDS];
- pthread_t tid = 0;
- uint64_t count = 0;
- int poll_ret = 0;
- int nread_events = 0;
- for (int i = 0; i < MAX_EFDS; i++) {
- efds[i] = eventfd(0, 0);
- if (efds[i] < 0) {
- perror("eventfd failed");
- return 1;
- }
- printf("efd = %d\n", efds[i]);
- pollfds[i].fd = efds[i];
- pollfds[i].events = POLLIN;
- }
- ret = pthread_create(&tid, NULL, write_eventfd_thread, efds);
- if (ret != 0) {
- perror("error in thread creation\n");
- ret = 1;
- goto out;
- }
- while (1) {
- poll_ret = poll(pollfds, MAX_EFDS, 5000);
- if (poll_ret == 0) {
- printf("Poll timed out. Exiting.\n");
- break;
- }
- if (poll_ret < 0) {
- perror("error from poll");
- ret = 1;
- break;
- }
- for (int i = 0; i < MAX_EFDS; i++) {
- if (pollfds[i].revents & POLLIN) {
- pollfds[i].revents = 0;
- errno = 0;
- read(pollfds[i].fd, &count, sizeof(count));
- printf("fd set=%d\n", pollfds[i].fd);
- printf("efd = %d, count: %lu, errno=%d\n", pollfds[i].fd, count, errno);
- nread_events++;
- }
- }
- }
- if (nread_events == MAX_EFDS)
- printf("%s completed successfully\n", __func__);
- else
- printf("%s: nread_events=%d, MAX_EFDS=%d\n", __func__, nread_events, MAX_EFDS);
- pthread_join(tid, NULL);
- out:
- for (int i = 0; i < MAX_EFDS; i++) {
- close(efds[i]);
- }
- return ret;
- }
- /* This function used to test various flags supported while creating eventfd
- * descriptors.
- * To support regression testing, positive value returned for error case. */
- int eventfd_using_various_flags() {
- uint64_t count = 0;
- int efd = 0;
- ssize_t bytes = 0;
- int eventfd_flags[] = {0, EFD_SEMAPHORE, EFD_NONBLOCK, EFD_CLOEXEC};
- for (int i = 0; i < sizeof(eventfd_flags) / sizeof(int); i++) {
- printf("iteration #-%d, flags=%d\n", i, eventfd_flags[i]);
- efd = eventfd(0, eventfd_flags[i]);
- if (efd < 0) {
- perror("eventfd failed");
- printf("eventfd error for iteration #-%d, flags-%d\n", i, eventfd_flags[i]);
- return 1;
- }
- count = 5;
- bytes = write(efd, &count, sizeof(count));
- EXIT_IF_ERROR(efd, bytes, "write");
- bytes = write(efd, &count, sizeof(count));
- EXIT_IF_ERROR(efd, bytes, "write");
- count = 0;
- errno = 0;
- if (eventfd_flags[i] & EFD_SEMAPHORE) {
- uint64_t prev_count = 0;
- bytes = read(efd, &prev_count, sizeof(prev_count));
- EXIT_IF_ERROR(efd, bytes, "read");
- bytes = read(efd, &count, sizeof(count));
- EXIT_IF_ERROR(efd, bytes, "read");
- if (prev_count != 1 || count != 1) {
- printf("flag->EFD_SEMAPHORE, error, prev_count=%lu, new count=%lu\n", prev_count,
- count);
- close(efd);
- return 1;
- }
- continue;
- }
- count = 0;
- errno = 0;
- bytes = read(efd, &count, sizeof(count));
- EXIT_IF_ERROR(efd, bytes, "read");
- if (count != 10) {
- printf("%d: efd = %d, count: %lu, errno=%d\n", __LINE__, efd, count, errno);
- CLOSE_EFD_AND_EXIT(efd);
- }
- /* calling the second read would block if flags doesn't have EFD_NONBLOCK */
- if (eventfd_flags[i] & EFD_NONBLOCK) {
- count = 0;
- errno = 0;
- read(efd, &count, sizeof(count));
- printf("%d: efd = %d, count: %lu, errno=%d\n", __LINE__, efd, count, errno);
- }
- close(efd);
- }
- printf("%s completed successfully\n", __func__);
- return 0;
- }
- int eventfd_using_fork() {
- int status = 0;
- int efd = 0;
- uint64_t count = 0;
- efd = eventfd(0, EFD_NONBLOCK);
- if (efd < 0) {
- perror("eventfd failed");
- return 1;
- }
- pid_t pid = fork();
- if (pid == 0) {
- // child process
- count = 5;
- write(efd, &count, sizeof(count));
- exit(0);
- } else if (pid > 0) {
- // parent process
- waitpid(pid, &status, 0);
- if (WIFSIGNALED(status)) {
- perror("child was terminated by signal");
- CLOSE_EFD_AND_EXIT(efd);
- }
- count = 0;
- read(efd, &count, sizeof(count));
- if (count != 5) {
- printf("parent-pid=%d, efd = %d, count: %lu, errno=%d\n", getpid(), efd, count, errno);
- CLOSE_EFD_AND_EXIT(efd);
- }
- } else {
- perror("fork error");
- CLOSE_EFD_AND_EXIT(efd);
- }
- close(efd);
- printf("%s completed successfully\n", __func__);
- return 0;
- }
- int main(int argc, char* argv[]) {
- int ret = 0;
- ret = eventfd_using_poll();
- ret += eventfd_using_various_flags();
- ret += eventfd_using_fork();
- return ret;
- }
|