]> git.saurik.com Git - apple/xnu.git/blob - tools/tests/xnu_quick_test/memory_tests.c
c14564a32ebd27590395713e71268a20d7b51e4a
[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 * static to localize to this compilation unit; volatile to avoid register
17 * optimization which would prevent modification by a signal handler.
18 */
19 static volatile int my_err;
20
21 void
22 bus_handler(int sig, siginfo_t *si, void *mcontext)
23 {
24 /* Reset global error value when we see a SIGBUS */
25 if (sig == SIGBUS) {
26 _exit(0);
27 }
28 }
29
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 */
35 int memory_tests( void * the_argp )
36 {
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;
45 kern_return_t my_kr;
46 struct sigaction my_sa;
47
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
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( );
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
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 */
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 ) );
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
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
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 ) {
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) );
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
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
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
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
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
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
280 *my_addr = 'z'; /* should cause SIGBUS signal (we look for this at child termination within the parent) */
281
282 /* NOTREACHED */
283
284 printf("Expected SIGBUS signal, got nothing!\n");
285 my_err = -1;
286 exit_child:
287 exit( my_err );
288 }
289
290 /* parent process -
291 * we should get no error if the child has completed all tests successfully
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
305 /* If we did not exit cleanly, report it
306 */
307 if ( !WIFEXITED( my_status ) || (WEXITSTATUS( my_status ) != 0)) {
308 printf( "wait4 returned child died of status - 0x%08X \n", my_status );
309 goto test_failed_exit;
310 }
311
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
320 test_failed_exit:
321 my_err = -1;
322
323 test_passed_exit:
324 if ( my_pathp != NULL ) {
325 remove( my_pathp );
326 vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
327 }
328 if ( my_test_page_p != NULL ) {
329 vm_deallocate(mach_task_self(), (vm_address_t)my_test_page_p, my_page_size);
330 }
331 return( my_err );
332 }
333