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