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,
};
}
|