sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 1 | #define _GNU_SOURCE |
| 2 | |
| 3 | #include <stdio.h> |
sewardj | 4bdd505 | 2006-10-17 01:28:48 +0000 | [diff] [blame] | 4 | |
| 5 | #if defined(_AIX) |
| 6 | |
| 7 | int main ( void ) |
| 8 | { |
| 9 | printf("This test is Linux-specific.\n"); |
| 10 | return 0; |
| 11 | } |
| 12 | |
| 13 | #else |
| 14 | |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 15 | #include <sys/mman.h> |
| 16 | #include <assert.h> |
| 17 | #include <stdlib.h> |
| 18 | #include <sys/types.h> |
| 19 | #include <unistd.h> |
| 20 | #include <errno.h> |
| 21 | #include <syscall.h> |
| 22 | |
| 23 | |
| 24 | #ifndef REMAP_FIXED |
| 25 | #define MREMAP_FIXED 2 |
| 26 | #endif |
| 27 | |
| 28 | |
| 29 | static int PAGE; |
| 30 | |
| 31 | void mapanon_fixed ( void* start, size_t length ) |
| 32 | { |
| 33 | void* r = mmap(start, length, PROT_NONE, |
| 34 | MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0,0); |
| 35 | assert(r != MAP_FAILED); |
| 36 | assert(r == start); |
| 37 | } |
| 38 | |
| 39 | void unmap_and_check ( void* start, size_t length ) |
| 40 | { |
| 41 | int r = munmap( start, length ); |
| 42 | assert(r == 0); |
| 43 | } |
| 44 | |
| 45 | char* workingarea = NULL; |
| 46 | char* try_dst = NULL; |
| 47 | |
| 48 | // set up working area so expansion limit is 20*PAGE |
| 49 | // |
| 50 | // | 10 | 20 | 10 | 60 | |
| 51 | // | pre | src | FREE | post | |
| 52 | // |
| 53 | // A suitable attempted fixed dst is workingarea + 150*PAGE. |
| 54 | |
| 55 | char* setup ( void* other_stuff, int other_len ) |
| 56 | { |
| 57 | if (!workingarea) { |
| 58 | workingarea = mmap(0, 200*PAGE, PROT_NONE, |
| 59 | MAP_ANONYMOUS|MAP_PRIVATE, 0,0); |
| 60 | assert(workingarea); |
| 61 | try_dst = workingarea + 150*PAGE; |
| 62 | unmap_and_check(workingarea, 200*PAGE); |
| 63 | } |
| 64 | |
| 65 | if (other_stuff) { |
| 66 | unmap_and_check(other_stuff, other_len); |
| 67 | } |
| 68 | |
| 69 | // get rid of the old working area |
| 70 | unmap_and_check( workingarea, 200*PAGE); |
| 71 | |
| 72 | // pre block |
| 73 | mapanon_fixed( workingarea + 0*PAGE, 9*PAGE); |
| 74 | |
| 75 | // the area |
| 76 | mapanon_fixed( workingarea + 10*PAGE, 20*PAGE ); |
| 77 | |
| 78 | // upper half |
| 79 | mapanon_fixed( workingarea + 40*PAGE, 60*PAGE ); |
| 80 | |
| 81 | return workingarea + 10*PAGE; |
| 82 | } |
| 83 | |
| 84 | /* show the working area */ |
| 85 | void show ( void ) |
| 86 | { |
| 87 | int i,r; |
| 88 | for (i = 0; i < 200; i++) { |
| 89 | r = mprotect( workingarea + i * PAGE, PAGE, PROT_NONE ); |
| 90 | printf("%c", r == 0 ? 'X' : '.'); |
| 91 | if (i == 49 || i == 99 || i == 149) printf("\n"); |
| 92 | } |
| 93 | printf("\n"); |
| 94 | } |
| 95 | |
| 96 | |
| 97 | char* dst = NULL; |
| 98 | char* src = NULL; |
| 99 | char* dst_impossible = NULL; |
| 100 | |
| 101 | |
| 102 | char* identify ( char* p ) |
| 103 | { |
| 104 | if (p == dst) return "dst"; |
| 105 | if (p == src) return "src"; |
| 106 | if (p == dst_impossible) return "dst_imp!"; |
| 107 | if (p == try_dst) return "dst_poss"; |
| 108 | return "other"; |
| 109 | } |
| 110 | |
| 111 | int main ( void ) |
| 112 | { |
| 113 | int alocal, maymove, fixed, nsi, dstpossible; |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 114 | int newsizes[6] = { 19, 20, 21, 29, 30, 31 }; |
| 115 | |
| 116 | char* tidythis = NULL; |
| 117 | int tidylen = 0; |
| 118 | int firsttime = 1; |
| 119 | char buf[100]; |
| 120 | |
sewardj | ae986ca | 2005-10-12 12:53:20 +0000 | [diff] [blame] | 121 | dst_impossible = (char*)(&alocal) + 500 * 1000 * 1000; |
| 122 | |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 123 | PAGE = sysconf(_SC_PAGESIZE); |
| 124 | |
| 125 | for (maymove = 0; maymove <= 1 ; maymove++) { |
| 126 | for (fixed = 0; fixed <= 1; fixed++) { |
| 127 | printf("\n"); |
| 128 | for (nsi = 0; nsi < 6; nsi++) { |
| 129 | for (dstpossible = 0; dstpossible <= 1; dstpossible++) { |
| 130 | |
sewardj | ae986ca | 2005-10-12 12:53:20 +0000 | [diff] [blame] | 131 | char* r; |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 132 | int newsize = newsizes[nsi] * PAGE; |
| 133 | int flags = (maymove ? MREMAP_MAYMOVE : 0) | |
| 134 | (fixed ? MREMAP_FIXED : 0); |
| 135 | dst = dstpossible ? try_dst : dst_impossible; |
| 136 | src = setup( tidythis, tidylen ); |
| 137 | |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 138 | if (firsttime) { |
| 139 | printf("dst_possible = %p\n", try_dst ); |
| 140 | printf("dst_impossible = %p\n", dst_impossible ); |
| 141 | printf(" src = %p\n", src); |
| 142 | printf("\n"); |
| 143 | sprintf(buf, "cat /proc/%d/maps", getpid()); |
| 144 | if (0) system(buf); |
| 145 | firsttime = 0; |
| 146 | } |
| 147 | |
| 148 | printf("maymv %d fixed %d newsz %2d dstpo %d dst %p -> ", |
| 149 | maymove, fixed, newsizes[nsi], dstpossible, dst ); |
| 150 | r = (char*) |
| 151 | syscall(__NR_mremap, src, 20*PAGE, newsize, flags, dst, 0 ); |
| 152 | if (r == MAP_FAILED) |
| 153 | printf("error %d\n", errno); |
| 154 | else |
| 155 | printf("%p (== %s)\n", r, identify(r)); |
| 156 | |
| 157 | if (1) { |
| 158 | show(); |
| 159 | printf("\n"); |
| 160 | } |
| 161 | |
| 162 | if (r != MAP_FAILED) { |
| 163 | if (r != src && r != try_dst && r != dst_impossible) { |
| 164 | tidythis = r; |
| 165 | tidylen = newsize; |
| 166 | } |
| 167 | } |
| 168 | |
| 169 | } |
| 170 | } |
| 171 | } |
| 172 | } |
| 173 | return 0; |
| 174 | } |
sewardj | 4bdd505 | 2006-10-17 01:28:48 +0000 | [diff] [blame] | 175 | |
| 176 | #endif /* defined(_AIX5) */ |