| #ifndef _GNU_SOURCE | |
| #define _GNU_SOURCE | |
| #endif | |
| #include <errno.h> | |
| #include <fcntl.h> | |
| #include <pthread.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <unistd.h> | |
| #include <sys/stat.h> | |
| #include <sys/types.h> | |
| static pthread_barrier_t barrier; | |
| static unsigned long extent_size; | |
| static unsigned long num_extents; | |
| struct dio_thread_data { | |
| int fd; | |
| int thread_id; | |
| }; | |
| static void *dio_thread(void *arg) | |
| { | |
| struct dio_thread_data *data = arg; | |
| off_t off; | |
| ssize_t ret; | |
| void *buf; | |
| if ((errno = posix_memalign(&buf, extent_size / 2, extent_size / 2))) { | |
| perror("malloc"); | |
| return NULL; | |
| } | |
| memset(buf, 0, extent_size / 2); | |
| off = (num_extents - 1) * extent_size; | |
| if (data->thread_id) | |
| off += extent_size / 2; | |
| while (off >= 0) { | |
| pthread_barrier_wait(&barrier); | |
| ret = pread(data->fd, buf, extent_size / 2, off); | |
| if (ret == -1) | |
| perror("pread"); | |
| off -= extent_size; | |
| } | |
| free(buf); | |
| return NULL; | |
| } | |
| int main(int argc, char **argv) | |
| { | |
| struct dio_thread_data data[2]; | |
| pthread_t thread; | |
| int fd; | |
| if (argc != 4) { | |
| fprintf(stderr, "usage: %s EXTENT_SIZE NUM_EXTENTS PATH\n", | |
| argv[0]); | |
| return EXIT_FAILURE; | |
| } | |
| extent_size = strtoul(argv[1], NULL, 0); | |
| num_extents = strtoul(argv[2], NULL, 0); | |
| errno = pthread_barrier_init(&barrier, NULL, 2); | |
| if (errno) { | |
| perror("pthread_barrier_init"); | |
| return EXIT_FAILURE; | |
| } | |
| fd = open(argv[3], O_RDONLY | O_DIRECT); | |
| if (fd == -1) { | |
| perror("open"); | |
| return EXIT_FAILURE; | |
| } | |
| data[0].fd = fd; | |
| data[0].thread_id = 0; | |
| errno = pthread_create(&thread, NULL, dio_thread, &data[0]); | |
| if (errno) { | |
| perror("pthread_create"); | |
| close(fd); | |
| return EXIT_FAILURE; | |
| } | |
| data[1].fd = fd; | |
| data[1].thread_id = 1; | |
| dio_thread(&data[1]); | |
| pthread_join(thread, NULL); | |
| close(fd); | |
| return EXIT_SUCCESS; | |
| } |