memory.c revision d2324417d8a06b0d0b7c331a0d004155f3a7bd48
1/* 2 * Memory helpers 3 */ 4#include <unistd.h> 5#include <sys/shm.h> 6#include <sys/mman.h> 7 8#include "fio.h" 9#include "os.h" 10 11static void *pinned_mem; 12 13void fio_unpin_memory(void) 14{ 15 if (pinned_mem) { 16 if (munlock(pinned_mem, mlock_size) < 0) 17 perror("munlock"); 18 munmap(pinned_mem, mlock_size); 19 pinned_mem = NULL; 20 } 21} 22 23int fio_pin_memory(void) 24{ 25 unsigned long long phys_mem; 26 27 if (!mlock_size) 28 return 0; 29 30 /* 31 * Don't allow mlock of more than real_mem-128MB 32 */ 33 phys_mem = os_phys_mem(); 34 if (phys_mem) { 35 if ((mlock_size + 128 * 1024 * 1024) > phys_mem) { 36 mlock_size = phys_mem - 128 * 1024 * 1024; 37 fprintf(f_out, "fio: limiting mlocked memory to %lluMiB\n", mlock_size >> 20); 38 } 39 } 40 41 pinned_mem = mmap(NULL, mlock_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | OS_MAP_ANON, 0, 0); 42 if (pinned_mem == MAP_FAILED) { 43 perror("malloc locked mem"); 44 pinned_mem = NULL; 45 return 1; 46 } 47 if (mlock(pinned_mem, mlock_size) < 0) { 48 perror("mlock"); 49 munmap(pinned_mem, mlock_size); 50 pinned_mem = NULL; 51 return 1; 52 } 53 54 return 0; 55} 56 57/* 58 * Setup the buffer area we need for io. 59 */ 60int allocate_io_mem(struct thread_data *td) 61{ 62 if (td->mem_type == MEM_MALLOC) 63 td->orig_buffer = malloc(td->orig_buffer_size); 64 else if (td->mem_type == MEM_SHM || td->mem_type == MEM_SHMHUGE) { 65 int flags = IPC_CREAT | SHM_R | SHM_W; 66 67 if (td->mem_type == MEM_SHMHUGE) 68 flags |= SHM_HUGETLB; 69 70 td->shm_id = shmget(IPC_PRIVATE, td->orig_buffer_size, flags); 71 if (td->shm_id < 0) { 72 td_verror(td, errno); 73 perror("shmget"); 74 return 1; 75 } 76 77 td->orig_buffer = shmat(td->shm_id, NULL, 0); 78 if (td->orig_buffer == (void *) -1) { 79 td_verror(td, errno); 80 perror("shmat"); 81 td->orig_buffer = NULL; 82 return 1; 83 } 84 } else if (td->mem_type == MEM_MMAP || td->mem_type == MEM_MMAPHUGE) { 85 int flags = MAP_PRIVATE; 86 87 td->hugefd = 0; 88 89 if (td->mem_type == MEM_MMAPHUGE) { 90 td->hugefd = open(td->hugefile, O_RDWR|O_CREAT, 0644); 91 92 if (td->hugefd < 0) { 93 td_verror(td, errno); 94 perror("open huge file"); 95 td->orig_buffer = NULL; 96 return 1; 97 } 98 } else 99 flags |= OS_MAP_ANON; 100 101 td->orig_buffer = mmap(NULL, td->orig_buffer_size, PROT_READ | PROT_WRITE, flags, td->hugefd, 0); 102 if (td->orig_buffer == MAP_FAILED) { 103 td_verror(td, errno); 104 perror("mmap"); 105 td->orig_buffer = NULL; 106 if (td->hugefd) 107 close(td->hugefd); 108 109 return 1; 110 } 111 } 112 113 return 0; 114} 115 116void free_io_mem(struct thread_data *td) 117{ 118 if (td->mem_type == MEM_MALLOC) 119 free(td->orig_buffer); 120 else if (td->mem_type == MEM_SHM || td->mem_type == MEM_SHMHUGE) { 121 struct shmid_ds sbuf; 122 123 shmdt(td->orig_buffer); 124 shmctl(td->shm_id, IPC_RMID, &sbuf); 125 } else if (td->mem_type == MEM_MMAP || td->mem_type == MEM_MMAPHUGE) { 126 munmap(td->orig_buffer, td->orig_buffer_size); 127 if (td->mem_type == MEM_MMAPHUGE) { 128 close(td->hugefd); 129 unlink(td->hugefile); 130 free(td->hugefile); 131 } 132 } else 133 log_err("Bad memory type %u\n", td->mem_type); 134 135 td->orig_buffer = NULL; 136} 137