summaryrefslogtreecommitdiff
path: root/imc/checker.c
blob: d3f09cc28b2d0f0143816dc79e6c334ae944d121 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <unistd.h>
#include <sys/fcntl.h>
#include "libimc.h"
#include "magic_buddy.h"

// #define verbose(...) printf(__VA_ARGS__)
#define verbose(...)

void get_random(uint8_t *dst, size_t count) {
    int fd = open("/dev/urandom", O_RDONLY);
    assert(count == read(fd, dst, count));
    close(fd);
}
struct ll {
    size_t data_size;
    struct ll *next;
    uint8_t data[];
};

// basically the simulation described by Knuth on pg 445
void check_main() {
    size_t n_timesteps = 10;
    size_t pool_size = 1024 * 1024 * 1024;

    static void *raw_pool = 0;
    static struct ll **time_to_dielist = 0;
    if (!raw_pool)
        raw_pool = malloc(pool_size + 55);
    if (!time_to_dielist)
        time_to_dielist = calloc(n_timesteps + 1, sizeof(struct ll *));
    else
        memset(time_to_dielist, 0, (n_timesteps + 1) * sizeof(struct ll *));

    void *pool = raw_pool;
    if (choose(2, 0)) pool_size += 11;
    if (choose(2, 0)) pool = (void*)((uint8_t*)pool + 11);

    struct buddy buddy;
    uint8_t magic[MAGIC_COOKIE_BYTES];
    get_random(magic, MAGIC_COOKIE_BYTES);
    init_buddy(pool, pool_size, magic, &buddy);

    size_t size_options[] = {1, 128, 1024, 5, 167, 10500};
    const size_t n_size_options = sizeof(size_options) / sizeof(size_options[0]);

    for (int t = 0; t < n_timesteps; t++) {
        // free the regions at this timestep, and ensure its contents are good
        for (struct ll *p = time_to_dielist[t]; p;) {
            for (size_t i = 0; i < p->data_size; i++) {
                verbose("Checking %p->data[%d] = %u versus %u\n",
                        p, i, (unsigned)p->data[i],
                        (unsigned)(uint8_t)p->data_size);
                assert(p->data[i] == (uint8_t)p->data_size);
            }
            struct ll *next = p->next;
            liberate(p, p->data_size + sizeof(struct ll), &buddy);
            p = next;
        }

        // try allocating a region
        size_t size = size_options[choose(n_size_options, 0)];
        struct ll *ll = allocate(size + sizeof(struct ll), &buddy);
        if (!ll) continue;
        assert((void*)ll >= pool);
        assert((uint8_t*)ll + size + sizeof(struct ll)
                < (uint8_t*)pool + pool_size);

        ll->data_size = size;
        for (size_t i = 0; i < ll->data_size; i++) {
            verbose("Writing %p->data[%d] = %u\n",
                    ll, i, (unsigned)(uint8_t)size);
            ll->data[i] = (uint8_t)size;
        }
        // pick a death time
        int lifetime = choose(n_timesteps - t, 0) + 1;
        ll->next = time_to_dielist[t + lifetime];
        time_to_dielist[t + lifetime] = ll;
        verbose("Allocated %p, which should die at time %lu\n",
                ll, t + lifetime);
    }
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback