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., 59
15* Temple Place - Suite 330, Boston MA 02111-1307, USA.
16
17
18* This sample test aims to check the following assertion:
19*
20* Memory mappings created in the parent are retained in the child process.
21* If the mapping is MAP_PRIVATE, any modification done after the fork()
22* is visible only to the process doing the modification.
23
24* The steps are:
25* -> create two shared memory segments.
26* -> mmap both segment, one is MAP_SHARED and the other MAP_PRIVATE.
27* -> Write some data into the segment.
28* -> fork
29* -> The child checks that the data is visible in the segments, then modifies it.
30* -> child terminates
31* -> The parent checks that the modifications are visible only in the MAP_SHARED segment.
32
33* The test fails if one of the check is not verified.
34
35*/
36
37
38/* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
39#define _POSIX_C_SOURCE 200112L
40
41/********************************************************************************************/
42/****************************** standard includes *****************************************/
43/********************************************************************************************/
44#include <pthread.h>
45 #include <stdarg.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <unistd.h>
50
51#include <sys/wait.h>
52 #include <errno.h>
53
54#include <sys/mman.h>
55#include <fcntl.h>
56#include <sys/stat.h>
57#include <sys/types.h>
58/********************************************************************************************/
59/******************************   Test framework   *****************************************/
60/********************************************************************************************/
61#include "testfrmw.h"
62 #include "testfrmw.c"
63/* This header is responsible for defining the following macros:
64 * UNRESOLVED(ret, descr);
65 *    where descr is a description of the error and ret is an int (error code for example)
66 * FAILED(descr);
67 *    where descr is a short text saying why the test has failed.
68 * PASSED();
69 *    No parameter.
70 *
71 * Both three macros shall terminate the calling process.
72 * The testcase shall not terminate in any other maneer.
73 *
74 * The other file defines the functions
75 * void output_init()
76 * void output(char * string, ...)
77 *
78 * Those may be used to output information.
79 */
80
81/********************************************************************************************/
82/********************************** Configuration ******************************************/
83/********************************************************************************************/
84#ifndef VERBOSE
85#define VERBOSE 1
86#endif
87
88/********************************************************************************************/
89/***********************************    Test case   *****************************************/
90/********************************************************************************************/
91/* The main test function. */
92int main( int argc, char * argv[] )
93{
94	int ret, status;
95	pid_t child, ctl;
96	int fd_s, fd_ns;
97	void *buf_s, *buf_ns;
98
99	/* Initialize output */
100	output_init();
101
102	/* Create the shared memory segment */
103	fd_s = shm_open( "/fork_16_1s", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR );
104
105	if ( fd_s == -1 )
106	{
107		UNRESOLVED( errno, "Failed to open shared memory segment" );
108	}
109
110	fd_ns = shm_open( "/fork_16_1ns", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR );
111
112	if ( fd_ns == -1 )
113	{
114		UNRESOLVED( errno, "Failed to open shared memory segment" );
115	}
116
117	/* Size the memory segment to 1 page size. */
118	ret = ftruncate( fd_s, sysconf( _SC_PAGESIZE ) );
119
120	if ( ret != 0 )
121	{
122		UNRESOLVED( errno, "Failed to size the shared memory segment" );
123	}
124
125	ret = ftruncate( fd_ns, sysconf( _SC_PAGESIZE ) );
126
127	if ( ret != 0 )
128	{
129		UNRESOLVED( errno, "Failed to size the shared memory segment" );
130	}
131
132	/* Map these sengments in the process memory space */
133	buf_s = mmap( NULL, sysconf( _SC_PAGESIZE ), PROT_READ | PROT_WRITE, MAP_SHARED, fd_s, 0 );
134
135	if ( buf_s == MAP_FAILED )
136	{
137		UNRESOLVED( errno, "Failed to mmap the shared memory segment" );
138	}
139
140	buf_ns = mmap( NULL, sysconf( _SC_PAGESIZE ), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd_ns, 0 );
141
142	if ( buf_ns == MAP_FAILED )
143	{
144		UNRESOLVED( errno, "Failed to mmap the shared memory segment in MAP_PRIVATE mode" );
145	}
146
147	/* Write some data into the buffers */
148	*( long * ) buf_ns = 123456L;
149
150	*( long * ) buf_s = 654321L;
151
152
153	/* Create the child */
154	child = fork();
155
156	if ( child == ( pid_t ) - 1 )
157	{
158		UNRESOLVED( errno, "Failed to fork" );
159	}
160
161	/* child */
162	if ( child == ( pid_t ) 0 )
163	{
164		/* Check the values are read -- so that the mappings were inherited */
165
166		if ( ( *( long * ) buf_ns != 123456L ) || ( *( long * ) buf_s != 654321L ) )
167		{
168			output( "Read values: %ld, %ld\n", *( long * ) buf_ns, *( long * ) buf_s );
169			FAILED( "The memory mappings were not inherited by the child process" );
170		}
171
172		/* Now modify the values */
173		*( long * ) buf_ns = 100000L;
174
175		*( long * ) buf_s = 200000L;
176
177		/* We're done */
178		exit( PTS_PASS );
179	}
180
181	/* Parent joins the child */
182	ctl = waitpid( child, &status, 0 );
183
184	if ( ctl != child )
185	{
186		UNRESOLVED( errno, "Waitpid returned the wrong PID" );
187	}
188
189	if ( ( !WIFEXITED( status ) ) || ( WEXITSTATUS( status ) != PTS_PASS ) )
190	{
191		FAILED( "Child exited abnormally" );
192	}
193
194	/* Check that only the MAP_SHARED segment modification is visible */
195	if ( ( *( long * ) buf_ns != 123456L ) || ( *( long * ) buf_s != 200000L ) )
196	{
197		output( "Read values: %ld, %ld\n", *( long * ) buf_ns, *( long * ) buf_s );
198		FAILED( "The memory mappings were not inherited by the child process" );
199	}
200
201	/* Free resources (everything will be removed at destruction time) */
202	ret = shm_unlink( "/fork_16_1ns" );
203
204	if ( ret != 0 )
205	{
206		UNRESOLVED( errno, "Failed to unlink the shared memory segment" );
207	}
208
209	ret = shm_unlink( "/fork_16_1s" );
210
211	if ( ret != 0 )
212	{
213		UNRESOLVED( errno, "Failed to unlink the shared memory segment" );
214	}
215
216	/* Test passed */
217#if VERBOSE > 0
218	output( "Test passed\n" );
219
220#endif
221	PASSED;
222}
223
224