Created
April 12, 2020 20:01
-
-
Save bgaff/9a8fbbe8af79c0e18502430d416df77e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE | |
#include <stdio.h> | |
#include <errno.h> | |
#include <unistd.h> | |
#include <assert.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <sys/types.h> | |
#include <fcntl.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <time.h> | |
#include <poll.h> | |
#include <sys/mman.h> | |
#include <sys/syscall.h> | |
#include <sys/ioctl.h> | |
#include <pthread.h> | |
#include <linux/userfaultfd.h> | |
struct test_data { | |
int uffd; | |
int timeout; | |
int poll_res; | |
int poll_errno; | |
int poll_revents; | |
}; | |
static void *uffd_poll_thread(void *arg) | |
{ | |
struct test_data* data = (struct test_data*)arg; | |
int res; | |
struct pollfd pfd; | |
pfd.fd = data->uffd; | |
pfd.events = POLLIN; | |
pfd.revents = 0; | |
/* Wait for an event or timeout */ | |
res = poll(&pfd, 1, data->timeout); | |
data->poll_res = res; | |
data->poll_errno = errno; | |
data->poll_revents = pfd.revents; | |
return NULL; | |
} | |
static int test_userfaultfd_closing(int close_timeout, int poll_timeout) | |
{ | |
struct test_data data; | |
struct uffdio_api uffdio_api; | |
pthread_t poll_thread; | |
int uffd = syscall(__NR_userfaultfd, O_NONBLOCK); | |
assert(uffd != -1); | |
uffdio_api.api = UFFD_API; | |
uffdio_api.features = 0; | |
assert(ioctl(uffd, UFFDIO_API, &uffdio_api) != -1); | |
data.uffd = uffd; | |
data.poll_revents = 0; | |
data.timeout = poll_timeout; | |
assert(pthread_create(&poll_thread, NULL, | |
uffd_poll_thread, (void *)&data) == 0); | |
/* Wait for the other thread to enter the poll */ | |
usleep(1000*close_timeout); | |
assert(close(uffd) != -1); | |
assert(fcntl(uffd, F_GETFD) == -1 && errno == EBADF); | |
pthread_join(poll_thread, NULL); | |
/* We should be woken up about the fd being closed */ | |
fprintf(stderr, "poll_res = %d, poll_revents = %X, poll_errno=%d\n", | |
data.poll_res, data.poll_revents, data.poll_errno); | |
assert(data.poll_res == 1); | |
assert(data.poll_revents & POLLERR); | |
return 0; | |
} | |
int main(int argc, char **argv) | |
{ | |
if (argc < 3) { | |
return 1; | |
} | |
return test_userfaultfd_closing(atoi(argv[1]), atoi(argv[2])); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment