File: c_api.c

package info (click to toggle)
thunderbird 1%3A78.14.0-1~deb10u1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 2,922,628 kB
  • sloc: cpp: 5,990,120; javascript: 4,418,692; ansic: 3,063,889; python: 915,509; asm: 304,197; xml: 206,623; sh: 109,253; java: 108,679; makefile: 22,985; perl: 15,867; yacc: 4,565; objc: 3,026; pascal: 1,787; lex: 1,720; ada: 1,681; cs: 879; exp: 505; awk: 485; sql: 452; php: 436; lisp: 432; ruby: 99; sed: 69; csh: 45
file content (180 lines) | stat: -rw-r--r-- 5,241 bytes parent folder | download | duplicates (10)
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#include <stdbool.h>
#include <stdio.h>

#include "lucet.h"

bool lucet_runtime_test_expand_heap(struct lucet_dl_module *mod)
{
    struct lucet_region *     region;
    struct lucet_alloc_limits limits = {
        .heap_memory_size        = 4 * 1024 * 1024,
        .heap_address_space_size = 8 * 1024 * 1024,
        .stack_size              = 64 * 1024,
        .globals_size            = 4096,
        .signal_stack_size       = 12 * 1024,
    };

    enum lucet_error err;

    err = lucet_mmap_region_create(1, &limits, &region);
    if (err != lucet_error_ok) {
        fprintf(stderr, "failed to create region\n");
        goto fail1;
    }

    struct lucet_instance *inst;
    err = lucet_region_new_instance(region, mod, &inst);
    if (err != lucet_error_ok) {
        fprintf(stderr, "failed to create instance\n");
        goto fail2;
    }

    uint32_t newpage_start;
    err = lucet_instance_grow_heap(inst, 1, &newpage_start);
    if (err != lucet_error_ok) {
        fprintf(stderr, "failed to grow memory\n");
        goto fail3;
    }

    lucet_instance_release(inst);
    lucet_region_release(region);
    lucet_dl_module_release(mod);

    return true;

fail3:
    lucet_instance_release(inst);
fail2:
    lucet_region_release(region);
fail1:
    lucet_dl_module_release(mod);
    return false;
}

enum yield_resume_tag {
    yield_resume_tag_mult,
    yield_resume_tag_result,
};

struct yield_resume_mult {
    uint64_t x;
    uint64_t y;
};

union yield_resume_val_inner {
    struct yield_resume_mult mult;
    uint64_t                 result;
};

struct yield_resume_val {
    enum yield_resume_tag        tag;
    union yield_resume_val_inner val;
};

uint64_t lucet_runtime_test_hostcall_yield_resume(struct lucet_vmctx *vmctx, uint64_t n)
{
    if (n <= 1) {
        struct yield_resume_val result_val = { .tag = yield_resume_tag_result,
                                               .val = { .result = 1 } };
        lucet_vmctx_yield(vmctx, &result_val);
        return 1;
    } else {
        uint64_t                n_rec      = lucet_runtime_test_hostcall_yield_resume(vmctx, n - 1);
        struct yield_resume_val mult_val   = { .tag = yield_resume_tag_mult,
                                             .val = { .mult = { .x = n, .y = n_rec } } };
        uint64_t                n          = *(uint64_t *) lucet_vmctx_yield(vmctx, &mult_val);
        struct yield_resume_val result_val = { .tag = yield_resume_tag_result,
                                               .val = { .result = n } };
        lucet_vmctx_yield(vmctx, &result_val);
        return n;
    }
}

bool lucet_runtime_test_yield_resume(struct lucet_dl_module *mod)
{
    struct lucet_region *     region;
    struct lucet_alloc_limits limits = {
        .heap_memory_size        = 4 * 1024 * 1024,
        .heap_address_space_size = 8 * 1024 * 1024,
        .stack_size              = 64 * 1024,
        .globals_size            = 4096,
        .signal_stack_size       = 12 * 1024,
    };

    enum lucet_error err;

    err = lucet_mmap_region_create(1, &limits, &region);
    if (err != lucet_error_ok) {
        fprintf(stderr, "failed to create region\n");
        goto fail1;
    }

    struct lucet_instance *inst;
    err = lucet_region_new_instance(region, mod, &inst);
    if (err != lucet_error_ok) {
        fprintf(stderr, "failed to create instance\n");
        goto fail2;
    }

    uint64_t results[5] = { 0 };
    size_t   i          = 0;

    struct lucet_result res;
    lucet_instance_run(inst, "f", 0, (const struct lucet_val[]){}, &res);
    while (res.tag == lucet_result_tag_yielded) {
        if (i >= 5) {
            fprintf(stderr, "hostcall yielded too many results\n");
            goto fail3;
        }

        struct yield_resume_val val = *(struct yield_resume_val *) res.val.yielded.val;

        switch (val.tag) {
        case yield_resume_tag_mult: {
            uint64_t mult_result = val.val.mult.x * val.val.mult.y;
            lucet_instance_resume(inst, &mult_result, &res);
            continue;
        }
        case yield_resume_tag_result: {
            results[i++] = val.val.result;
            lucet_instance_resume(inst, NULL, &res);
            continue;
        }
        default: {
            fprintf(stderr, "unexpected yield_resume_tag\n");
            goto fail3;
        }
        }
    }
    if (err != lucet_error_ok) {
        fprintf(stderr, "instance finished with non-ok error: %s\n", lucet_error_name(err));
        goto fail3;
    }

    if (res.tag != lucet_result_tag_returned) {
        fprintf(stderr, "final instance result wasn't returned\n");
        goto fail3;
    }

    uint64_t final_result = LUCET_UNTYPED_RETVAL_TO_U64(res.val.returned);

    lucet_instance_release(inst);
    lucet_region_release(region);
    lucet_dl_module_release(mod);

    uint64_t expected_results[5] = { 1, 2, 6, 24, 120 };
    bool     results_correct     = final_result == 120;
    for (i = 0; i < 5; i++) {
        results_correct = results_correct && (results[i] == expected_results[i]);
    }

    return results_correct;

fail3:
    lucet_instance_release(inst);
fail2:
    lucet_region_release(region);
fail1:
    lucet_dl_module_release(mod);
    return false;
}