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