]> git.saurik.com Git - apple/xnu.git/blob - tools/tests/xnu_quick_test/memory_tests.c
xnu-1504.15.3.tar.gz
[apple/xnu.git] / tools / tests / xnu_quick_test / memory_tests.c
1 /*
2 * memory_tests.c.c
3 * xnu_quick_test
4 *
5 * Created by Jerry Cottingham on 4/12/05.
6 * Copyright 2005 Apple Computer Inc. All rights reserved.
7 *
8 */
9
10 #include "tests.h"
11 #include <mach/mach.h>
12
13 extern char g_target_path[ PATH_MAX ];
14
15 /* **************************************************************************************************************
16 * Test madvise, mincore, minherit, mlock, mlock, mmap, mprotect, msync, munmap system calls.
17 * todo - see if Francois has better versions of these tests...
18 * **************************************************************************************************************
19 */
20 int memory_tests( void * the_argp )
21 {
22 int my_err;
23 int my_page_size, my_status;
24 int my_fd = -1;
25 char * my_pathp = NULL;
26 char * my_bufp = NULL;
27 char * my_addr = NULL;
28 char * my_test_page_p = NULL;
29 ssize_t my_result;
30 pid_t my_pid, my_wait_pid;
31 kern_return_t my_kr;
32
33 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
34 if(my_kr != KERN_SUCCESS){
35 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
36 goto test_failed_exit;
37 }
38
39 *my_pathp = 0x00;
40 strcat( my_pathp, &g_target_path[0] );
41 strcat( my_pathp, "/" );
42
43 /* create a test file */
44 my_err = create_random_name( my_pathp, 1 );
45 if ( my_err != 0 ) {
46 goto test_failed_exit;
47 }
48
49 my_page_size = getpagesize( );
50 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_test_page_p, my_page_size, VM_FLAGS_ANYWHERE);
51 if(my_kr != KERN_SUCCESS){
52 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
53 goto test_failed_exit;
54 }
55
56 *my_test_page_p = 0x00;
57 strcat( my_test_page_p, "parent data" );
58
59 /* test minherit - share a page with child, add to the string in child then
60 * check for modification after child terminates.
61 */
62 my_err = minherit( my_test_page_p, my_page_size, VM_INHERIT_SHARE );
63 if ( my_err == -1 ) {
64 printf( "minherit failed with error %d - \"%s\" \n", errno, strerror( errno) );
65 goto test_failed_exit;
66 }
67
68 /*
69 * spin off a child process that we will use for testing.
70 */
71 my_pid = fork( );
72 if ( my_pid == -1 ) {
73 printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
74 goto test_failed_exit;
75 }
76 if ( my_pid == 0 ) {
77 /*
78 * child process...
79 */
80 strcat( my_test_page_p, " child data" );
81
82 /* create a test file in page size chunks */
83 my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_bufp, (my_page_size * 10), VM_FLAGS_ANYWHERE);
84 if(my_kr != KERN_SUCCESS){
85 printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
86 my_err = -1;
87 goto exit_child;
88 }
89
90 /* test madvise on anonymous memory */
91 my_err = madvise(my_bufp, (my_page_size * 10), MADV_WILLNEED);
92 if ( my_err == -1 ) {
93 printf("madvise WILLNEED on anon memory failed with error %d - \"%s\" \n", errno, strerror( errno ) );
94 my_err = -1;
95 goto exit_child;
96 }
97
98 memset( my_bufp, 'j', (my_page_size * 10) );
99 my_fd = open( my_pathp, O_RDWR, 0 );
100 if ( my_fd == -1 ) {
101 printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
102 my_err = -1;
103 goto exit_child;
104 }
105
106 /* test madvise on anonymous memory */
107 my_err = madvise(my_bufp, (my_page_size * 10), MADV_DONTNEED);
108 if ( my_err == -1 ) {
109 printf("madvise DONTNEED on anon memory failed with error %d - \"%s\" \n", errno, strerror( errno ) );
110 my_err = -1;
111 goto exit_child;
112 }
113
114 my_result = write( my_fd, my_bufp, (my_page_size * 10) );
115 if ( my_result == -1 ) {
116 printf( "write call failed with error %d - \"%s\" \n", errno, strerror( errno) );
117 my_err = -1;
118 goto exit_child;
119 }
120
121 /* map the file into memory */
122 my_addr = (char *) mmap( NULL, (my_page_size * 2), (PROT_READ | PROT_WRITE), (MAP_FILE | MAP_SHARED), my_fd, 0 );
123 if ( my_addr == (char *) -1 ) {
124 printf( "mmap call failed with error %d - \"%s\" \n", errno, strerror( errno) );
125 my_err = -1;
126 goto exit_child;
127 }
128
129 /* make sure we got the right data mapped */
130 if ( *my_addr != 'j' || *(my_addr + my_page_size) != 'j' ) {
131 printf( "did not map in correct data \n" );
132 my_err = -1;
133 goto exit_child;
134 }
135
136 /* test madvise */
137 my_err = madvise( my_addr, (my_page_size * 2), MADV_WILLNEED );
138 if ( my_err == -1 ) {
139 printf( "madvise WILLNEED call failed with error %d - \"%s\" \n", errno, strerror( errno) );
140 my_err = -1;
141 goto exit_child;
142 }
143
144 my_err = madvise( my_addr, (my_page_size * 2), MADV_DONTNEED );
145 if ( my_err == -1 ) {
146 printf( "madvise DONTNEED call failed with error %d - \"%s\" \n", errno, strerror( errno) );
147 my_err = -1;
148 goto exit_child;
149 }
150
151 /* test mincore, mlock, mlock */
152 my_err = mlock( my_addr, my_page_size );
153 if ( my_err == -1 ) {
154 printf( "mlock call failed with error %d - \"%s\" \n", errno, strerror( errno) );
155 my_err = -1;
156 goto exit_child;
157 }
158
159 /* mybufp is about to be reused, so test madvise on anonymous memory */
160 my_err = madvise(my_bufp, (my_page_size * 10), MADV_FREE);
161 if ( my_err == -1 ) {
162 printf("madvise FREE on anon memory failed with error %d - \"%s\" \n", errno, strerror( errno ) );
163 my_err = -1;
164 goto exit_child;
165 }
166
167 my_err = mincore( my_addr, 1, my_bufp );
168 if ( my_err == -1 ) {
169 printf( "mincore call failed with error %d - \"%s\" \n", errno, strerror( errno) );
170 my_err = -1;
171 goto exit_child;
172 }
173 /* page my_addr is in should be resident after mlock */
174 if ( (*my_bufp & MINCORE_INCORE) == 0 ) {
175 printf( "mincore call failed to find resident page \n" );
176 my_err = -1;
177 goto exit_child;
178 }
179
180 my_err = munlock( my_addr, my_page_size );
181 if ( my_err == -1 ) {
182 printf( "munlock call failed with error %d - \"%s\" \n", errno, strerror( errno) );
183 my_err = -1;
184 goto exit_child;
185 }
186
187 /* modify first page then use msync to push data out */
188 memset( my_addr, 'x', my_page_size );
189 my_err = msync( my_addr, my_page_size, (MS_SYNC | MS_INVALIDATE) );
190 if ( my_err == -1 ) {
191 printf( "msync call failed with error %d - \"%s\" \n", errno, strerror( errno) );
192 my_err = -1;
193 goto exit_child;
194 }
195
196 /* test madvise */
197 my_err = madvise( my_addr, (my_page_size * 2), MADV_DONTNEED );
198 if ( my_err == -1 ) {
199 printf( "madvise DONTNEED call failed with error %d - \"%s\" \n", errno, strerror( errno) );
200 my_err = -1;
201 goto exit_child;
202 }
203
204 /* test madvise */
205 my_err = madvise( my_addr, (my_page_size * 2), MADV_FREE );
206 if ( my_err == -1 ) {
207 printf( "madvise FREE call failed with error %d - \"%s\" \n", errno, strerror( errno) );
208 my_err = -1;
209 goto exit_child;
210 }
211
212 /* verify that the file was updated */
213 lseek( my_fd, 0, SEEK_SET );
214 bzero( (void *)my_bufp, my_page_size );
215 my_result = read( my_fd, my_bufp, my_page_size );
216 if ( my_result == -1 ) {
217 printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
218 my_err = -1;
219 goto exit_child;
220 }
221 if ( *my_bufp != 'x' ) {
222 printf( "msync did not flush correct data \n" );
223 my_err = -1;
224 goto exit_child;
225 }
226
227 /* unmap our test page */
228 my_err = munmap( my_addr, (my_page_size * 2) );
229 if ( my_err == -1 ) {
230 printf( "munmap call failed with error %d - \"%s\" \n", errno, strerror( errno) );
231 my_err = -1;
232 goto exit_child;
233 }
234 my_addr = NULL;
235
236 /* map the file into memory again for mprotect test */
237 my_addr = (char *) mmap( NULL, (my_page_size * 2), (PROT_READ | PROT_WRITE), (MAP_FILE | MAP_SHARED), my_fd, 0 );
238 if ( my_addr == (char *) -1 ) {
239 printf( "mmap call failed with error %d - \"%s\" \n", errno, strerror( errno) );
240 my_err = -1;
241 goto exit_child;
242 }
243 *my_addr = 'a';
244
245
246
247 /* test mprotect - change protection to only PROT_READ */
248 my_err = mprotect( my_addr, my_page_size, PROT_READ );
249 if ( my_err == -1 ) {
250 printf( "mprotect call failed with error %d - \"%s\" \n", errno, strerror( errno) );
251 my_err = -1;
252 goto exit_child;
253 }
254
255 *my_addr = 'z'; /* should cause SIGBUS signal (we look for this at child termination within the parent) */
256
257
258
259 my_err = 0;
260 exit_child:
261 exit( my_err );
262 }
263
264
265 /* parent process -
266 * we should get SIGBUS exit when child tries to write to read only memory
267 */
268 my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
269 if ( my_wait_pid == -1 ) {
270 printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
271 goto test_failed_exit;
272 }
273
274 /* wait4 should return our child's pid when it exits */
275 if ( my_wait_pid != my_pid ) {
276 printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid, my_pid );
277 goto test_failed_exit;
278 }
279
280 if ( WIFSIGNALED( my_status ) && WTERMSIG( my_status ) != SIGBUS ) {
281 printf( "wait4 returned wrong signal status - 0x%02X \n", my_status );
282 goto test_failed_exit;
283 }
284
285 /* make sure shared page got modified in child */
286 if ( strcmp( my_test_page_p, "parent data child data" ) != 0 ) {
287 printf( "minherit did not work correctly - shared page looks wrong \n" );
288 goto test_failed_exit;
289 }
290 my_err = 0;
291 goto test_passed_exit;
292
293 test_failed_exit:
294 my_err = -1;
295
296 test_passed_exit:
297 if ( my_pathp != NULL ) {
298 remove( my_pathp );
299 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
300 }
301 if ( my_test_page_p != NULL ) {
302 vm_deallocate(mach_task_self(), (vm_address_t)my_test_page_p, my_page_size);
303 }
304 return( my_err );
305 }
306