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