aboutsummaryrefslogtreecommitdiff
path: root/mirai/kata/pool.zig
blob: 3fff3e0d546c390b9afd89ae467d358b6fcad613 (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
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
//! Kata pool management

const attachment = @import("attachment.zig");
const attachment_const = @import("../common/constants/attachment.zig");
const heap = @import("../memory/heap.zig");
const kata_const = @import("../common/constants/kata.zig");
const kata_limits = @import("../common/limits/kata.zig");
const types = @import("types.zig");

pub var pool: [kata_limits.MAX_KATAS]types.Kata = undefined;
pub var used: [kata_limits.MAX_KATAS]bool = [_]bool{false} ** kata_limits.MAX_KATAS;
var next_id: u32 = 1;

pub fn init() void {
    for (&pool, 0..) |*kata, i| {
        kata.* = create_empty();
        used[i] = false;
    }
}

pub fn create() !*types.Kata {
    for (&pool, 0..) |*kata, i| {
        if (!used[i]) {
            used[i] = true;

            const kata_id = next_id;
            next_id += 1;

            kata.* = create_empty();
            kata.id = kata_id;
            kata.state = .Ready;

            kata.current_location[0] = '/';

            const stdin = attachment.alloc() orelse return error.OutOfMemory;
            stdin.* = .{
                .attachment_type = .Device,
                .device_type = .Source,
                .flags = attachment_const.VIEW_ONLY,
            };
            kata.attachments[0] = stdin;

            const stdout = attachment.alloc() orelse return error.OutOfMemory;
            stdout.* = .{
                .attachment_type = .Device,
                .device_type = .Stream,
                .flags = attachment_const.MARK_ONLY,
            };
            kata.attachments[1] = stdout;

            const stderr = attachment.alloc() orelse return error.OutOfMemory;
            stderr.* = .{
                .attachment_type = .Device,
                .device_type = .Trace,
                .flags = attachment_const.MARK_ONLY,
            };
            kata.attachments[2] = stderr;

            return kata;
        }
    }

    return error.TooManyKata;
}

pub fn get(id: u32) ?*types.Kata {
    for (&pool, 0..) |*kata, i| {
        if (used[i] and kata.id == id) {
            return kata;
        }
    }
    return null;
}

pub fn dissolve(kata_id: u32) void {
    const waker = @import("sensei/waker.zig");
    const memory = @import("memory.zig");

    for (&pool, 0..) |*kata, i| {
        if (used[i] and kata.id == kata_id) {
            for (&kata.attachments) |*slot| {
                if (slot.*) |ptr| {
                    attachment.free(ptr);
                    slot.* = null;
                }
            }
            if (kata.letter_data) |data| {
                heap.free(@ptrCast(data), kata.letter_capacity);
                kata.letter_data = null;
                kata.letter_capacity = 0;
            }
            memory.cleanup(kata);
            kata.state = .Dissolved;
            used[i] = false;
            waker.wake_waiting(kata_id);
            return;
        }
    }
}

fn create_empty() types.Kata {
    return types.Kata{
        .id = 0,
        .state = .Dissolved,
        .context = types.Context.init(),
        .page_table = 0,
        .stack_top = 0,
        .user_stack_top = 0,
        .user_stack_bottom = 0,
        .user_stack_committed = 0,
        .attachments = [_]?*attachment.Attachment{null} ** kata_limits.MAX_ATTACHMENTS,
        .current_location = undefined,
        .current_location_len = 1,
        .current_cluster = 0,
        .parent_id = 0,
        .letter_type = 0,
        .letter_data = null,
        .letter_len = 0,
        .letter_capacity = 0,
        .vruntime = 0,
        .weight = kata_const.DEFAULT_WEIGHT,
        .last_run = 0,
        .next = null,
        .waiting_for = 0,
        .exit_code = 0,
    };
}