#include #include #include #include #include #include int test_function() { return 0; } static area_id create_test_area(const char* name, int** address, uint32 protection) { area_id area = create_area(name, (void**)address, B_ANY_ADDRESS, B_PAGE_SIZE, B_NO_LOCK, protection); if (area < 0) { fprintf(stderr, "Error: Failed to create area %s: %s\n", name, strerror(area)); exit(1); } return area; } static area_id clone_test_area(const char* name, int** address, uint32 protection, area_id source) { area_id area = clone_area(name, (void**)address, B_ANY_ADDRESS, protection, source); if (area < 0) { fprintf(stderr, "Error: Failed to clone area %s: %s\n", name, strerror(area)); exit(1); } return area; } int main() { // allocate read-only areas const int kAreaCount = 4; area_id areas[kAreaCount]; int* areaAddresses[kAreaCount]; areas[0] = create_test_area("area0", &areaAddresses[0], B_READ_AREA); areas[1] = create_test_area("area1", &areaAddresses[1], B_READ_AREA); areas[2] = create_test_area("area2", &areaAddresses[2], B_READ_AREA); areaAddresses[3] = (int*)test_function; areas[3] = area_for(areaAddresses[3]); int* area2CloneAddress; /*area_id area2Clone =*/ clone_test_area("area2clone", &area2CloneAddress, B_READ_AREA | B_WRITE_AREA, areas[2]); int area3Value = *areaAddresses[3]; for (int i = 0; i < kAreaCount; i++) { printf("parent: areas[%d]: %ld, %p (0x%08x)\n", i, areas[i], areaAddresses[i], *areaAddresses[i]); } // fork() pid_t pid = fork(); if (pid < 0) { fprintf(stderr, "Error: Failed to fork(): %s\n", strerror(errno)); exit(1); } if (pid == 0) { // child pid = find_thread(NULL); int expectedValues[kAreaCount] = { 0, // CoW -- the child should see the original value pid, // clone -- the child should see the change pid, // clone -- the child should see the change area3Value // CoW -- the child should see the original value // Note: It looks alright in BeOS in the first run, // but the parent actually seems to modify some // cached page, and in the next run, we'll see // the changed value. }; // get the IDs of the copied areas area_id parentAreas[kAreaCount]; for (int i = 0; i < kAreaCount; i++) { parentAreas[i] = areas[i]; areas[i] = area_for(areaAddresses[i]); } for (int i = 0; i < kAreaCount; i++) { printf("child: areas[%d]: %ld, %p\n", i, areas[i], areaAddresses[i]); } // clone area 1 delete_area(areas[1]); areas[1] = clone_test_area("child:area1", &areaAddresses[1], B_READ_AREA, parentAreas[1]); // clone area 2 delete_area(areas[2]); areas[2] = clone_test_area("child:area2", &areaAddresses[2], B_READ_AREA, parentAreas[2]); snooze(400000); for (int i = 0; i < kAreaCount; i++) { printf("child: area[%d] contains: 0x%08x (expected: 0x%08x)\n", i, *areaAddresses[i], expectedValues[i]); } } else { // parent snooze(200000); for (int i = 0; i < kAreaCount; i++) { status_t error = set_area_protection(areas[i], B_READ_AREA | B_WRITE_AREA); if (error == B_OK) { *areaAddresses[i] = pid; } else { fprintf(stderr, "parent: Error: set_area_protection(areas[%d]) " "failed: %s\n", i, strerror(error)); } } status_t result; wait_for_thread(pid, &result); } return 0; }