]> git.saurik.com Git - apple/xnu.git/blobdiff - tools/tests/xnu_quick_test/memory_tests.c
xnu-1228.tar.gz
[apple/xnu.git] / tools / tests / xnu_quick_test / memory_tests.c
diff --git a/tools/tests/xnu_quick_test/memory_tests.c b/tools/tests/xnu_quick_test/memory_tests.c
new file mode 100644 (file)
index 0000000..952be5a
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ *  memory_tests.c.c
+ *  xnu_quick_test
+ *
+ *  Created by Jerry Cottingham on 4/12/05.
+ *  Copyright 2005 Apple Computer Inc. All rights reserved.
+ *
+ */
+
+#include "tests.h"
+
+extern char  g_target_path[ PATH_MAX ];
+
+/*  **************************************************************************************************************
+ *     Test madvise, mincore, minherit, mlock, mlock, mmap, mprotect, msync, munmap system calls.
+ *     todo - see if Francois has better versions of these tests...
+ *  **************************************************************************************************************
+ */
+int memory_tests( void * the_argp )
+{
+       int                     my_err;
+       int                     my_page_size, my_status;
+       int                     my_fd = -1;
+       char *          my_pathp = NULL;
+       char *          my_bufp = NULL;
+       char *          my_addr = NULL;
+       char *          my_test_page_p = NULL;
+       ssize_t         my_result;
+       pid_t           my_pid, my_wait_pid;
+
+       my_pathp = (char *) malloc( PATH_MAX );
+       if ( my_pathp == NULL ) {
+               printf( "malloc failed with error %d - \"%s\" \n", errno, strerror( errno) );
+               goto test_failed_exit;
+       }
+       *my_pathp = 0x00;
+       strcat( my_pathp, &g_target_path[0] );
+       strcat( my_pathp, "/" );
+
+       /* create a test file */
+       my_err = create_random_name( my_pathp, 1 );
+       if ( my_err != 0 ) {
+               goto test_failed_exit;
+       }
+
+       my_page_size = getpagesize( );
+       my_test_page_p = (char *) malloc( my_page_size );
+       if ( my_test_page_p == NULL ) {
+               printf( "malloc failed with error %d - \"%s\" \n", errno, strerror( errno) );
+               goto test_failed_exit;
+       }
+       *my_test_page_p = 0x00;
+       strcat( my_test_page_p, "parent data" );
+       /* test minherit - share a page with child, add to the string in child then 
+        * check for modification after child terminates.
+        */ 
+       my_err = minherit( my_test_page_p, my_page_size, VM_INHERIT_SHARE );
+       if ( my_err == -1 ) {
+               printf( "minherit failed with error %d - \"%s\" \n", errno, strerror( errno) );
+               goto test_failed_exit;
+       }
+
+       /*
+        * spin off a child process that we will use for testing.   
+        */
+       my_pid = fork( );
+       if ( my_pid == -1 ) {
+               printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
+               goto test_failed_exit;
+       }
+       if ( my_pid == 0 ) {
+               /* 
+                * child process...
+                */             
+               strcat( my_test_page_p, " child data" );
+
+               /* create a test file in page size chunks */
+               my_bufp = (char *) malloc( (my_page_size * 10) );
+               if ( my_bufp == NULL ) {
+                       printf( "malloc failed with error %d - \"%s\" \n", errno, strerror( errno) );
+                       my_err = -1;
+                       goto exit_child;
+               }
+
+               memset( my_bufp, 'j', (my_page_size * 10) );
+               my_fd = open( my_pathp, O_RDWR, 0 );
+               if ( my_fd == -1 ) {
+                       printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+                       my_err = -1;
+                       goto exit_child;
+               }
+               
+               my_result = write( my_fd, my_bufp, (my_page_size * 10) );
+               if ( my_result == -1 ) {
+                       printf( "write call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+                       my_err = -1;
+                       goto exit_child;
+               }
+               
+               /* map the file into memory */
+               my_addr = (char *) mmap( NULL, (my_page_size * 2), (PROT_READ | PROT_WRITE), (MAP_FILE | MAP_SHARED), my_fd, 0 );
+               if ( my_addr == (char *) -1 ) {
+                       printf( "mmap call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+                       my_err = -1;
+                       goto exit_child;
+               }
+               
+               /* make sure we got the right data mapped */
+               if ( *my_addr != 'j' || *(my_addr + my_page_size) != 'j' ) {
+                       printf( "did not map in correct data \n" );
+                       my_err = -1;
+                       goto exit_child;
+               }
+
+               /* test madvise */
+               my_err = madvise( my_addr, (my_page_size * 2), MADV_WILLNEED );
+               if ( my_err == -1 ) {
+                       printf( "madvise call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+                       my_err = -1;
+                       goto exit_child;
+               }
+
+               /* test mincore, mlock, mlock */
+               my_err = mlock( my_addr, my_page_size );
+               if ( my_err == -1 ) {
+                       printf( "mlock call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+                       my_err = -1;
+                       goto exit_child;
+               }
+
+               my_err = mincore( my_addr, 1, my_bufp );        
+               if ( my_err == -1 ) {
+                       printf( "mincore call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+                       my_err = -1;
+                       goto exit_child;
+               }
+               /* page my_addr is in should be resident after mlock */
+               if ( (*my_bufp & MINCORE_INCORE) == 0 ) {
+                       printf( "mincore call failed to find resident page \n" );
+                       my_err = -1;
+                       goto exit_child;
+               }
+               
+               my_err = munlock( my_addr, my_page_size );
+               if ( my_err == -1 ) {
+                       printf( "munlock call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+                       my_err = -1;
+                       goto exit_child;
+               }
+                
+               /* modify first page then use msync to push data out */
+               memset( my_addr, 'x', my_page_size );
+               my_err = msync( my_addr, my_page_size, (MS_SYNC | MS_INVALIDATE) );     
+               if ( my_err == -1 ) {
+                       printf( "msync call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+                       my_err = -1;
+                       goto exit_child;
+               }
+                                       
+               /* verify that the file was updated */
+               lseek( my_fd, 0, SEEK_SET );    
+               bzero( (void *)my_bufp, my_page_size );
+               my_result = read( my_fd, my_bufp, my_page_size );
+               if ( my_result == -1 ) {
+                       printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+                       my_err = -1;
+                       goto exit_child;
+               }
+               if ( *my_bufp != 'x' ) {
+                       printf( "msync did not flush correct data \n" );
+                       my_err = -1;
+                       goto exit_child;
+               }
+                
+               /* unmap our test page */
+               my_err = munmap( my_addr, (my_page_size * 2) );
+               if ( my_err == -1 ) {
+                       printf( "munmap call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+                       my_err = -1;
+                       goto exit_child;
+               }
+               my_addr = NULL;
+
+               /* map the file into memory again for mprotect test  */
+               my_addr = (char *) mmap( NULL, (my_page_size * 2), (PROT_READ | PROT_WRITE), (MAP_FILE | MAP_SHARED), my_fd, 0 );
+               if ( my_addr == (char *) -1 ) {
+                       printf( "mmap call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+                       my_err = -1;
+                       goto exit_child;
+               }
+               *my_addr = 'a';
+        
+
+
+               /* test mprotect - change protection to only PROT_READ */
+               my_err = mprotect( my_addr, my_page_size, PROT_READ );
+               if ( my_err == -1 ) {
+                       printf( "mprotect call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+                       my_err = -1;
+                       goto exit_child;
+               }
+
+               *my_addr = 'z'; /* should cause SIGBUS signal (we look for this at child termination within the parent) */
+       
+
+                
+               my_err = 0;
+exit_child:
+               exit( my_err );
+       }
+
+       
+       /* parent process -
+        * we should get SIGBUS exit when child tries to write to read only memory 
+        */
+       my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
+       if ( my_wait_pid == -1 ) {
+               printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
+               goto test_failed_exit;
+       }
+
+       /* wait4 should return our child's pid when it exits */
+       if ( my_wait_pid != my_pid ) {
+               printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid, my_pid );
+               goto test_failed_exit;
+       }
+
+       if ( WIFSIGNALED( my_status ) && WTERMSIG( my_status ) != SIGBUS ) {
+               printf( "wait4 returned wrong signal status - 0x%02X \n", my_status );
+               goto test_failed_exit;
+       }
+
+       /* make sure shared page got modified in child */
+       if ( strcmp( my_test_page_p, "parent data child data" ) != 0 ) {
+               printf( "minherit did not work correctly - shared page looks wrong \n" );
+               goto test_failed_exit;
+       }
+       my_err = 0;
+       goto test_passed_exit;
+
+test_failed_exit:
+       my_err = -1;
+       
+test_passed_exit:
+       if ( my_pathp != NULL ) {
+               remove( my_pathp );     
+               free( my_pathp );
+        }
+        if ( my_test_page_p != NULL ) {
+               free( my_test_page_p );
+        }
+       return( my_err );
+}
+