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
|
//! 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 memory = @import("memory.zig");
const types = @import("types.zig");
const waker = @import("sensei/waker.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 = .Alive;
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 {
for (&pool, 0..) |*kata, i| {
if (used[i] and kata.id == kata_id) {
// Mark as dying
kata.state = .Dying;
// Clean up attachments
for (&kata.attachments) |*slot| {
if (slot.*) |ptr| {
attachment.free(ptr);
slot.* = null;
}
}
// Clean up letter data
if (kata.letter_data) |data| {
heap.free(@ptrCast(data), kata.letter_capacity);
kata.letter_data = null;
kata.letter_capacity = 0;
}
// Try to clean up memory
memory.cleanup(kata);
// Check if page table was destroyed or needs Shinigami
if (kata.page_table != 0) {
// Page table still exists - become zombie for Shinigami to reap
kata.state = .Zombie;
// Keep used[i] = true so slot isn't reused yet
} else {
// Fully cleaned up
kata.state = .Dissolved;
used[i] = false;
}
waker.wake_waiting(kata_id);
return;
}
}
}
fn create_empty() types.Kata {
return types.Kata{
.id = 0,
.state = .Dissolved,
.mode = .Persona,
.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,
};
}
|