1 #include <errno.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6
7 #include <OS.h>
8
9
10 int
test_function()11 test_function()
12 {
13 return 0;
14 }
15
16
17 static area_id
create_test_area(const char * name,int ** address,uint32 protection)18 create_test_area(const char* name, int** address, uint32 protection)
19 {
20 area_id area = create_area(name, (void**)address, B_ANY_ADDRESS,
21 B_PAGE_SIZE, B_NO_LOCK, protection);
22 if (area < 0) {
23 fprintf(stderr, "Error: Failed to create area %s: %s\n", name,
24 strerror(area));
25 exit(1);
26 }
27
28 return area;
29 }
30
31
32 static area_id
clone_test_area(const char * name,int ** address,uint32 protection,area_id source)33 clone_test_area(const char* name, int** address, uint32 protection,
34 area_id source)
35 {
36 area_id area = clone_area(name, (void**)address, B_ANY_ADDRESS,
37 protection, source);
38 if (area < 0) {
39 fprintf(stderr, "Error: Failed to clone area %s: %s\n", name,
40 strerror(area));
41 exit(1);
42 }
43
44 return area;
45 }
46
47
48 int
main()49 main()
50 {
51 // allocate read-only areas
52 const int kAreaCount = 4;
53 area_id areas[kAreaCount];
54 int* areaAddresses[kAreaCount];
55
56 areas[0] = create_test_area("area0", &areaAddresses[0], B_READ_AREA);
57 areas[1] = create_test_area("area1", &areaAddresses[1], B_READ_AREA);
58 areas[2] = create_test_area("area2", &areaAddresses[2], B_READ_AREA);
59 areaAddresses[3] = (int*)test_function;
60 areas[3] = area_for(areaAddresses[3]);
61
62 int* area2CloneAddress;
63 /*area_id area2Clone =*/ clone_test_area("area2clone", &area2CloneAddress,
64 B_READ_AREA | B_WRITE_AREA, areas[2]);
65
66 int area3Value = *areaAddresses[3];
67
68 for (int i = 0; i < kAreaCount; i++) {
69 printf("parent: areas[%d]: %ld, %p (0x%08x)\n", i, areas[i],
70 areaAddresses[i], *areaAddresses[i]);
71 }
72
73 // fork()
74 pid_t pid = fork();
75 if (pid < 0) {
76 fprintf(stderr, "Error: Failed to fork(): %s\n", strerror(errno));
77 exit(1);
78 }
79
80 if (pid == 0) {
81 // child
82 pid = find_thread(NULL);
83
84 int expectedValues[kAreaCount] = {
85 0, // CoW -- the child should see the original value
86 pid, // clone -- the child should see the change
87 pid, // clone -- the child should see the change
88 area3Value // CoW -- the child should see the original value
89 // Note: It looks alright in BeOS in the first run,
90 // but the parent actually seems to modify some
91 // cached page, and in the next run, we'll see
92 // the changed value.
93 };
94
95 // get the IDs of the copied areas
96 area_id parentAreas[kAreaCount];
97 for (int i = 0; i < kAreaCount; i++) {
98 parentAreas[i] = areas[i];
99 areas[i] = area_for(areaAddresses[i]);
100 }
101
102 for (int i = 0; i < kAreaCount; i++) {
103 printf("child: areas[%d]: %ld, %p\n", i, areas[i],
104 areaAddresses[i]);
105 }
106
107 // clone area 1
108 delete_area(areas[1]);
109 areas[1] = clone_test_area("child:area1", &areaAddresses[1],
110 B_READ_AREA, parentAreas[1]);
111
112 // clone area 2
113 delete_area(areas[2]);
114 areas[2] = clone_test_area("child:area2", &areaAddresses[2],
115 B_READ_AREA, parentAreas[2]);
116
117 snooze(400000);
118
119 for (int i = 0; i < kAreaCount; i++) {
120 printf("child: area[%d] contains: 0x%08x (expected: 0x%08x)\n", i,
121 *areaAddresses[i], expectedValues[i]);
122 }
123
124 } else {
125 // parent
126
127 snooze(200000);
128
129 for (int i = 0; i < kAreaCount; i++) {
130 status_t error = set_area_protection(areas[i],
131 B_READ_AREA | B_WRITE_AREA);
132 if (error == B_OK) {
133 *areaAddresses[i] = pid;
134 } else {
135 fprintf(stderr, "parent: Error: set_area_protection(areas[%d]) "
136 "failed: %s\n", i, strerror(error));
137 }
138 }
139
140 status_t result;
141 wait_for_thread(pid, &result);
142 }
143
144 return 0;
145 }
146