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