1 /* 2 * Copyright (c) 2004, Bull S.A.. All rights reserved. 3 * Created by: Sebastien Decugis 4 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program; if not, write the Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 17 * This sample test aims to check the following assertion: 18 * 19 * Memory mappings created in the parent are retained in the child process. 20 * If the mapping is MAP_PRIVATE, any modification done after the fork() 21 * is visible only to the process doing the modification. 22 23 * The steps are: 24 * -> create two shared memory segments. 25 * -> mmap both segment, one is MAP_SHARED and the other MAP_PRIVATE. 26 * -> Write some data into the segment. 27 * -> fork 28 * -> The child checks that the data is visible in the segments, then modifies it. 29 * -> child terminates 30 * -> The parent checks that the modifications are visible only in the MAP_SHARED segment. 31 32 * The test fails if one of the check is not verified. 33 34 */ 35 36 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 37 #define _POSIX_C_SOURCE 200112L 38 39 #include <pthread.h> 40 #include <stdarg.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <unistd.h> 45 46 #include <sys/wait.h> 47 #include <errno.h> 48 49 #include <sys/mman.h> 50 #include <fcntl.h> 51 #include <sys/stat.h> 52 #include <sys/types.h> 53 54 #include "../testfrmw/testfrmw.h" 55 #include "../testfrmw/testfrmw.c" 56 57 #ifndef VERBOSE 58 #define VERBOSE 1 59 #endif 60 61 int main(void) 62 { 63 int ret, status; 64 pid_t child, ctl; 65 int fd_s, fd_ns; 66 void *buf_s, *buf_ns; 67 68 output_init(); 69 70 /* Create the shared memory segment */ 71 fd_s = shm_open("/fork_16_1s", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); 72 73 if (fd_s == -1) { 74 UNRESOLVED(errno, "Failed to open shared memory segment"); 75 } 76 77 fd_ns = shm_open("/fork_16_1ns", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); 78 79 if (fd_ns == -1) { 80 UNRESOLVED(errno, "Failed to open shared memory segment"); 81 } 82 83 /* Size the memory segment to 1 page size. */ 84 ret = ftruncate(fd_s, sysconf(_SC_PAGESIZE)); 85 86 if (ret != 0) { 87 UNRESOLVED(errno, "Failed to size the shared memory segment"); 88 } 89 90 ret = ftruncate(fd_ns, sysconf(_SC_PAGESIZE)); 91 92 if (ret != 0) { 93 UNRESOLVED(errno, "Failed to size the shared memory segment"); 94 } 95 96 /* Map these sengments in the process memory space */ 97 buf_s = 98 mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, 99 MAP_SHARED, fd_s, 0); 100 101 if (buf_s == MAP_FAILED) { 102 UNRESOLVED(errno, "Failed to mmap the shared memory segment"); 103 } 104 105 buf_ns = 106 mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, 107 MAP_PRIVATE, fd_ns, 0); 108 109 if (buf_ns == MAP_FAILED) { 110 UNRESOLVED(errno, 111 "Failed to mmap the shared memory segment in MAP_PRIVATE mode"); 112 } 113 114 /* Write some data into the buffers */ 115 *(long *)buf_ns = 123456L; 116 117 *(long *)buf_s = 654321L; 118 119 /* Create the child */ 120 child = fork(); 121 122 if (child == -1) { 123 UNRESOLVED(errno, "Failed to fork"); 124 } 125 126 if (child == 0) { 127 /* Check the values are read -- so that the mappings were inherited */ 128 129 if ((*(long *)buf_ns != 123456L) || (*(long *)buf_s != 654321L)) { 130 output("Read values: %ld, %ld\n", *(long *)buf_ns, 131 *(long *)buf_s); 132 FAILED 133 ("The memory mappings were not inherited by the child process"); 134 } 135 136 /* Now modify the values */ 137 *(long *)buf_ns = 100000L; 138 139 *(long *)buf_s = 200000L; 140 141 /* We're done */ 142 exit(PTS_PASS); 143 } 144 145 /* Parent joins the child */ 146 ctl = waitpid(child, &status, 0); 147 148 if (ctl != child) { 149 UNRESOLVED(errno, "Waitpid returned the wrong PID"); 150 } 151 152 if (!WIFEXITED(status) || (WEXITSTATUS(status) != PTS_PASS)) { 153 FAILED("Child exited abnormally"); 154 } 155 156 /* Check that only the MAP_SHARED segment modification is visible */ 157 if ((*(long *)buf_ns != 123456L) || (*(long *)buf_s != 200000L)) { 158 output("Read values: %ld, %ld\n", *(long *)buf_ns, 159 *(long *)buf_s); 160 FAILED 161 ("The memory mappings were not inherited by the child process"); 162 } 163 164 /* Free resources (everything will be removed at destruction time) */ 165 ret = shm_unlink("/fork_16_1ns"); 166 167 if (ret != 0) { 168 UNRESOLVED(errno, "Failed to unlink the shared memory segment"); 169 } 170 171 ret = shm_unlink("/fork_16_1s"); 172 173 if (ret != 0) { 174 UNRESOLVED(errno, "Failed to unlink the shared memory segment"); 175 } 176 177 #if VERBOSE > 0 178 output("Test passed\n"); 179 #endif 180 PASSED; 181 } 182