xref: /haiku/src/tests/system/kernel/set_area_protection_test1.cpp (revision e5c9c9e371e0c96d0a50bdde17fc88b9735d0690)
168f20814SIngo Weinhold #include <errno.h>
268f20814SIngo Weinhold #include <stdio.h>
368f20814SIngo Weinhold #include <stdlib.h>
468f20814SIngo Weinhold #include <string.h>
568f20814SIngo Weinhold #include <unistd.h>
668f20814SIngo Weinhold 
768f20814SIngo Weinhold #include <OS.h>
868f20814SIngo Weinhold 
9538abf58SIngo Weinhold 
10538abf58SIngo Weinhold int
test_function()11538abf58SIngo Weinhold test_function()
12538abf58SIngo Weinhold {
13538abf58SIngo Weinhold 	return 0;
14538abf58SIngo Weinhold }
15538abf58SIngo Weinhold 
16538abf58SIngo Weinhold 
1768f20814SIngo Weinhold static area_id
create_test_area(const char * name,int ** address,uint32 protection)1868f20814SIngo Weinhold create_test_area(const char* name, int** address, uint32 protection)
1968f20814SIngo Weinhold {
2068f20814SIngo Weinhold 	area_id area = create_area(name, (void**)address, B_ANY_ADDRESS,
2168f20814SIngo Weinhold 		B_PAGE_SIZE, B_NO_LOCK, protection);
2268f20814SIngo Weinhold 	if (area < 0) {
2368f20814SIngo Weinhold 		fprintf(stderr, "Error: Failed to create area %s: %s\n", name,
2468f20814SIngo Weinhold 			strerror(area));
2568f20814SIngo Weinhold 		exit(1);
2668f20814SIngo Weinhold 	}
2768f20814SIngo Weinhold 
2868f20814SIngo Weinhold 	return area;
2968f20814SIngo Weinhold }
3068f20814SIngo Weinhold 
3168f20814SIngo Weinhold 
3268f20814SIngo Weinhold static area_id
clone_test_area(const char * name,int ** address,uint32 protection,area_id source)3368f20814SIngo Weinhold clone_test_area(const char* name, int** address, uint32 protection,
3468f20814SIngo Weinhold 	area_id source)
3568f20814SIngo Weinhold {
3668f20814SIngo Weinhold 	area_id area = clone_area(name, (void**)address, B_ANY_ADDRESS,
3768f20814SIngo Weinhold 		protection, source);
3868f20814SIngo Weinhold 	if (area < 0) {
3968f20814SIngo Weinhold 		fprintf(stderr, "Error: Failed to clone area %s: %s\n", name,
4068f20814SIngo Weinhold 			strerror(area));
4168f20814SIngo Weinhold 		exit(1);
4268f20814SIngo Weinhold 	}
4368f20814SIngo Weinhold 
4468f20814SIngo Weinhold 	return area;
4568f20814SIngo Weinhold }
4668f20814SIngo Weinhold 
4768f20814SIngo Weinhold 
4868f20814SIngo Weinhold int
main()4968f20814SIngo Weinhold main()
5068f20814SIngo Weinhold {
5168f20814SIngo Weinhold 	// allocate read-only areas
52538abf58SIngo Weinhold 	const int kAreaCount = 4;
5368f20814SIngo Weinhold 	area_id areas[kAreaCount];
5468f20814SIngo Weinhold 	int* areaAddresses[kAreaCount];
55*e5c9c9e3SIngo Weinhold 
5668f20814SIngo Weinhold 	areas[0] = create_test_area("area0", &areaAddresses[0], B_READ_AREA);
5768f20814SIngo Weinhold 	areas[1] = create_test_area("area1", &areaAddresses[1], B_READ_AREA);
5868f20814SIngo Weinhold 	areas[2] = create_test_area("area2", &areaAddresses[2], B_READ_AREA);
59538abf58SIngo Weinhold 	areaAddresses[3] = (int*)test_function;
60538abf58SIngo Weinhold 	areas[3] = area_for(areaAddresses[3]);
6168f20814SIngo Weinhold 
6268f20814SIngo Weinhold 	int* area2CloneAddress;
6368f20814SIngo Weinhold 	/*area_id area2Clone =*/ clone_test_area("area2clone", &area2CloneAddress,
6468f20814SIngo Weinhold 		B_READ_AREA | B_WRITE_AREA, areas[2]);
6568f20814SIngo Weinhold 
66*e5c9c9e3SIngo Weinhold 	int area3Value = *areaAddresses[3];
67*e5c9c9e3SIngo Weinhold 
68538abf58SIngo Weinhold 	for (int i = 0; i < kAreaCount; i++) {
69*e5c9c9e3SIngo Weinhold 		printf("parent: areas[%d]: %ld, %p (0x%08x)\n", i, areas[i],
70538abf58SIngo Weinhold 			areaAddresses[i], *areaAddresses[i]);
71538abf58SIngo Weinhold 	}
7268f20814SIngo Weinhold 
7368f20814SIngo Weinhold 	// fork()
7468f20814SIngo Weinhold 	pid_t pid = fork();
7568f20814SIngo Weinhold 	if (pid < 0) {
7668f20814SIngo Weinhold 		fprintf(stderr, "Error: Failed to fork(): %s\n", strerror(errno));
7768f20814SIngo Weinhold 		exit(1);
7868f20814SIngo Weinhold 	}
7968f20814SIngo Weinhold 
8068f20814SIngo Weinhold 	if (pid == 0) {
8168f20814SIngo Weinhold 		// child
82*e5c9c9e3SIngo Weinhold 		pid = find_thread(NULL);
83*e5c9c9e3SIngo Weinhold 
84*e5c9c9e3SIngo Weinhold 		int expectedValues[kAreaCount] = {
85*e5c9c9e3SIngo Weinhold 			0,				// CoW -- the child should see the original value
86*e5c9c9e3SIngo Weinhold 			pid,			// clone -- the child should see the change
87*e5c9c9e3SIngo Weinhold 			pid,			// clone -- the child should see the change
88*e5c9c9e3SIngo Weinhold 			area3Value		// CoW -- the child should see the original value
89*e5c9c9e3SIngo Weinhold 							// Note: It looks alright in BeOS in the first run,
90*e5c9c9e3SIngo Weinhold 							// but the parent actually seems to modify some
91*e5c9c9e3SIngo Weinhold 							// cached page, and in the next run, we'll see
92*e5c9c9e3SIngo Weinhold 							// the changed value.
93*e5c9c9e3SIngo Weinhold 		};
9468f20814SIngo Weinhold 
9568f20814SIngo Weinhold 		// get the IDs of the copied areas
9668f20814SIngo Weinhold 		area_id parentAreas[kAreaCount];
9768f20814SIngo Weinhold 		for (int i = 0; i < kAreaCount; i++) {
9868f20814SIngo Weinhold 			parentAreas[i] = areas[i];
9968f20814SIngo Weinhold 			areas[i] = area_for(areaAddresses[i]);
10068f20814SIngo Weinhold 		}
10168f20814SIngo Weinhold 
10268f20814SIngo Weinhold 		for (int i = 0; i < kAreaCount; i++) {
10368f20814SIngo Weinhold 			printf("child: areas[%d]: %ld, %p\n", i, areas[i],
10468f20814SIngo Weinhold 				areaAddresses[i]);
10568f20814SIngo Weinhold 		}
10668f20814SIngo Weinhold 
10768f20814SIngo Weinhold 		// clone area 1
10868f20814SIngo Weinhold 		delete_area(areas[1]);
10968f20814SIngo Weinhold 		areas[1] = clone_test_area("child:area1", &areaAddresses[1],
11068f20814SIngo Weinhold 			B_READ_AREA, parentAreas[1]);
11168f20814SIngo Weinhold 
11268f20814SIngo Weinhold 		// clone area 2
11368f20814SIngo Weinhold 		delete_area(areas[2]);
11468f20814SIngo Weinhold 		areas[2] = clone_test_area("child:area2", &areaAddresses[2],
11568f20814SIngo Weinhold 			B_READ_AREA, parentAreas[2]);
11668f20814SIngo Weinhold 
11768f20814SIngo Weinhold 		snooze(400000);
11868f20814SIngo Weinhold 
119*e5c9c9e3SIngo Weinhold 		for (int i = 0; i < kAreaCount; i++) {
120*e5c9c9e3SIngo Weinhold 			printf("child: area[%d] contains: 0x%08x (expected: 0x%08x)\n", i,
121*e5c9c9e3SIngo Weinhold 				*areaAddresses[i], expectedValues[i]);
122*e5c9c9e3SIngo Weinhold 		}
12368f20814SIngo Weinhold 
12468f20814SIngo Weinhold 	} else {
12568f20814SIngo Weinhold 		// parent
12668f20814SIngo Weinhold 
12768f20814SIngo Weinhold 		snooze(200000);
12868f20814SIngo Weinhold 
12968f20814SIngo Weinhold 		for (int i = 0; i < kAreaCount; i++) {
13068f20814SIngo Weinhold 			status_t error = set_area_protection(areas[i],
13168f20814SIngo Weinhold 				B_READ_AREA | B_WRITE_AREA);
13268f20814SIngo Weinhold 			if (error == B_OK) {
13368f20814SIngo Weinhold 				*areaAddresses[i] = pid;
13468f20814SIngo Weinhold 			} else {
13568f20814SIngo Weinhold 				fprintf(stderr, "parent: Error: set_area_protection(areas[%d]) "
13668f20814SIngo Weinhold 					"failed: %s\n", i, strerror(error));
13768f20814SIngo Weinhold 			}
13868f20814SIngo Weinhold 		}
13968f20814SIngo Weinhold 
14068f20814SIngo Weinhold 		status_t result;
14168f20814SIngo Weinhold 		wait_for_thread(pid, &result);
14268f20814SIngo Weinhold 	}
14368f20814SIngo Weinhold 
14468f20814SIngo Weinhold 	return 0;
14568f20814SIngo Weinhold }
146