rendered paste body#define _GNU_SOURCE#include <ctype.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/mman.h>#include <unistd.h>#define LARGE_CHUNK (32 * 1024)#define SMALL_CHUNK (1024)typedef unsigned long ulong;static char file_name[] = "test-mmio.bin";static ulong file_size = 32 * 1024 * 1024;static ulong page_size;static voiderror(const char *s){ perror(s); exit(EXIT_FAILURE);}static intopen_file(int flags){ int fd = open(file_name, flags, 0666); if (fd < 0) { error(NULL); } return fd;}static void *mmap_file(int fd){ void *mm = mmap(0, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (mm == MAP_FAILED) { error(NULL); } return mm;}static voidsync_file(int fd){#ifdef F_FULLFSYNC fcntl(fd, F_FULLFSYNC, 0);#else fdatasync(fd);#endif}static voidsync_range(int fd, void *ptr, ulong off, ulong len){#ifdef __linux__ sync_file_range(fd, off, len, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER);#else msync(((char *) ptr) + off, len, MS_SYNC);#endif}voiddo_write(int fd, int len){ void *buf = alloca(len); memset(buf, 0, len); if (write(fd, buf, len) != len) { error(NULL); }}voiddo_mcopy(void *ptr, int len){ void *buf = alloca(len); memset(buf, 0, len); memcpy(ptr, buf, len);}voidtest(int fd, void *mm, int chunk, int sync, int advise){ ulong size; for (size = 0; size < file_size; size += chunk) { if (!mm) { do_write(fd, chunk); } else { do_mcopy(((char*) mm) + size, chunk); } if (sync == 1) { sync_file(fd); } else if (mm && sync == 2) { sync_range(fd, mm, size, chunk); } if (advise) {#ifdef __linux__ posix_fadvise(fd, 0, (size + chunk) & ~(page_size - 1), POSIX_FADV_DONTNEED);#endif } if (size % (1024 * 1024) == 0) { printf("."); fflush(stdout); } } printf("\n");}voidusage(){}ulongparse_size(const char *s){ ulong value; char *suffix; value = strtoul(s, &suffix, 10); if (*suffix) { int c = toupper(*suffix); if (c == 'K') { value <<= 10; } else if (c == 'M') { value <<= 20; } else { usage(); } } return value;}intmain(int ac, char *av[]){ int c; int prepare, use_mmap, use_write, sync, range, advise; ulong chunk; int fd; void *mm; prepare = use_mmap = use_write = sync = range = advise = 0; chunk = 0; while ((c = getopt(ac, av, "pmwfras:c:")) != -1) { switch (c) { case 'p': prepare = 1; break; case 'm': use_mmap = 1; break; case 'w': use_write = 1; break; case 'f': sync = 1; break; case 'r': range = 1; break; case 'a': advise = 1; break; case 's': file_size = parse_size(optarg); break; case 'c': chunk = parse_size(optarg); break; default: usage(); exit(EXIT_FAILURE); } } ac -= optind; av += optind; if ((prepare + use_mmap + use_write) != 1) { usage(); exit(EXIT_FAILURE); } if ((sync + range) > 1) { usage(); exit(EXIT_FAILURE); } if (chunk == 0) { chunk = prepare ? LARGE_CHUNK : SMALL_CHUNK; } if (range == 1) { sync = 2; } printf("file size: %ld\n", file_size); printf("chunk size: %ld\n", chunk); switch (sync) { case 0: printf("sync: no\n"); break; case 1: printf("sync: file\n"); break; case 2: printf("sync: range\n"); break; } page_size = getpagesize(); mm = NULL; if (prepare) { printf("prepare the file\n"); fd = open_file(O_CREAT | O_RDWR | O_TRUNC); } else if (use_write) { printf("write to the file\n"); fd = open_file(O_RDWR); } else { printf("copy to the file mmap\n"); fd = open_file(O_RDWR); mm = mmap_file(fd); } test(fd, mm, chunk, sync, advise); if (mm) { munmap(mm, file_size); } fsync(fd); close(fd); return 0;}