X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/0c530ab8987f0ae6a1a3d9284f40182b88852816..2d21ac55c334faf3a56e5634905ed6987fc787d4:/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 index 000000000..952be5ab9 --- /dev/null +++ b/tools/tests/xnu_quick_test/memory_tests.c @@ -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 ); +} +