134ce5866SIngo Weinhold#include <stdio.h>
2f9eba888SStefano Ceccherini#include <string.h>
334ce5866SIngo Weinhold#include <sys/stat.h>
434ce5866SIngo Weinhold#include <unistd.h>
534ce5866SIngo Weinhold
634ce5866SIngo Weinhold#include <OS.h>
734ce5866SIngo Weinhold
834ce5866SIngo Weinholdconst char* kInitialValue = "/dev/null";
934ce5866SIngo Weinholdconst char* kChangedValue = "Argh!";
1034ce5866SIngo Weinhold
1134ce5866SIngo Weinholdint
1234ce5866SIngo Weinholdmain(int argc, const char* const* argv)
1334ce5866SIngo Weinhold{
1434ce5866SIngo Weinhold	thread_id parent = find_thread(NULL);
1534ce5866SIngo Weinhold
1634ce5866SIngo Weinhold	char* globalVar = NULL;
1734ce5866SIngo Weinhold	area_id area = create_area("cow test", (void**)&globalVar,
1834ce5866SIngo Weinhold		B_ANY_ADDRESS, B_PAGE_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
1934ce5866SIngo Weinhold	if (area < 0) {
2034ce5866SIngo Weinhold		printf("failed to create area\n");
2134ce5866SIngo Weinhold		return 1;
2234ce5866SIngo Weinhold	}
2334ce5866SIngo Weinhold
2434ce5866SIngo Weinhold	strcpy(globalVar, kInitialValue);
2534ce5866SIngo Weinhold
2634ce5866SIngo Weinhold	printf("[%ld] parent: before fork(): globalVar(%p): \"%s\"\n", parent,
2734ce5866SIngo Weinhold		globalVar, globalVar);
2834ce5866SIngo Weinhold
2934ce5866SIngo Weinhold	pid_t child = fork();
3034ce5866SIngo Weinhold	if (child == 0) {
3134ce5866SIngo Weinhold		// child
3234ce5866SIngo Weinhold		child = find_thread(NULL);
3334ce5866SIngo Weinhold
3434ce5866SIngo Weinhold		// let the kernel read access the page
3534ce5866SIngo Weinhold		struct stat st;
3634ce5866SIngo Weinhold		stat(globalVar, &st);
3734ce5866SIngo Weinhold
3834ce5866SIngo Weinhold		printf("[%ld] child: after kernel read: globalVar: \"%s\"\n",
3934ce5866SIngo Weinhold			child, globalVar);
4034ce5866SIngo Weinhold
4134ce5866SIngo Weinhold		// write access the page from userland
4234ce5866SIngo Weinhold		strcpy(globalVar, kChangedValue);
4334ce5866SIngo Weinhold
4434ce5866SIngo Weinhold		printf("[%ld] child: after change: globalVar: \"%s\"\n", child,
4534ce5866SIngo Weinhold			globalVar);
4634ce5866SIngo Weinhold
4734ce5866SIngo Weinhold	} else {
4834ce5866SIngo Weinhold		// parent
4934ce5866SIngo Weinhold
5034ce5866SIngo Weinhold		// wait for the child
5134ce5866SIngo Weinhold		status_t exitVal;
5234ce5866SIngo Weinhold		while (wait_for_thread(child, &exitVal) == B_INTERRUPTED);
5334ce5866SIngo Weinhold
5434ce5866SIngo Weinhold		// check the value
5534ce5866SIngo Weinhold		printf("[%ld] parent: after exit child: globalVar: \"%s\"\n",
5634ce5866SIngo Weinhold			parent, globalVar);
5734ce5866SIngo Weinhold
5834ce5866SIngo Weinhold		if (strcmp(globalVar, kInitialValue) == 0)
5934ce5866SIngo Weinhold			printf("test OK\n");
6034ce5866SIngo Weinhold		else
6134ce5866SIngo Weinhold			printf("test FAILED: child process changed parent's memory!\n");
6234ce5866SIngo Weinhold	}
6334ce5866SIngo Weinhold
6434ce5866SIngo Weinhold	return 0;
6534ce5866SIngo Weinhold}
66