The Pedigree Project 0.1
mmap.c
1/*
2 * Copyright (c) 2026, Pedigree Developers
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted.
6 */
7
8#include <errno.h>
9#include <stdint.h>
10#include <stdio.h>
11#include <unistd.h>
12
13#include <sys/mman.h>
14
15extern void fail();
16
17void test_mmap() {
18 const long configured_page_size = sysconf(_SC_PAGESIZE);
19 if (configured_page_size <= 0)
20 fail();
21 const size_t page_size = (size_t)configured_page_size;
22
23 printf("Testing mmap(2) placement semantics...\n");
24 unsigned char* original =
25 mmap(0, page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
26 if (original == MAP_FAILED)
27 fail();
28 *original = 0x5A;
29
30 errno = 0;
31 void* no_replace = mmap(original, page_size, PROT_READ | PROT_WRITE,
32 MAP_PRIVATE | MAP_ANON | MAP_FIXED_NOREPLACE, -1, 0);
33 if (no_replace != MAP_FAILED || errno != EEXIST || *original != 0x5A)
34 fail();
35
36 errno = 0;
37 if (munmap(original, SIZE_MAX) != -1 || errno != EINVAL || *original != 0x5A)
38 fail();
39
40 const size_t replacement_size = page_size * 3;
41 void* replacement = mmap(original, replacement_size, PROT_READ | PROT_WRITE,
42 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
43 if (replacement != original || *original != 0)
44 fail();
45 *original = 0x7C;
46
47 void* follower = mmap(0, page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
48 if (follower == MAP_FAILED || ((uintptr_t)follower >= (uintptr_t)original &&
49 (uintptr_t)follower < (uintptr_t)original + replacement_size))
50 fail();
51
52 void* hinted =
53 mmap(original + 17, page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
54 if (hinted == MAP_FAILED || hinted == original || ((uintptr_t)hinted & (page_size - 1)) ||
55 *original != 0x7C)
56 fail();
57
58 if (munmap(hinted, page_size) || munmap(follower, page_size) ||
59 munmap(replacement, replacement_size))
60 fail();
61
62 void* reclaimed = mmap(replacement, replacement_size, PROT_READ | PROT_WRITE,
63 MAP_PRIVATE | MAP_ANON | MAP_FIXED_NOREPLACE, -1, 0);
64 if (reclaimed != replacement || munmap(reclaimed, replacement_size))
65 fail();
66
67 unsigned char* split =
68 mmap(0, replacement_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
69 if (split == MAP_FAILED || munmap(split + page_size, page_size))
70 fail();
71
72 void* middle = mmap(split + page_size, page_size, PROT_READ | PROT_WRITE,
73 MAP_PRIVATE | MAP_ANON | MAP_FIXED_NOREPLACE, -1, 0);
74 if (middle != split + page_size)
75 fail();
76
77 errno = 0;
78 void* prefix = mmap(split, page_size, PROT_READ | PROT_WRITE,
79 MAP_PRIVATE | MAP_ANON | MAP_FIXED_NOREPLACE, -1, 0);
80 if (prefix != MAP_FAILED || errno != EEXIST || munmap(split, replacement_size))
81 fail();
82
83 void* split_reclaimed = mmap(split, replacement_size, PROT_READ | PROT_WRITE,
84 MAP_PRIVATE | MAP_ANON | MAP_FIXED_NOREPLACE, -1, 0);
85 if (split_reclaimed != split || munmap(split_reclaimed, replacement_size))
86 fail();
87 printf("mmap(2) placement semantics were successful!\n");
88}