Skip to content

Commit 3098225

Browse files
committed
Doubly linked list. Preliminary thread and process structures.
1 parent 0c15277 commit 3098225

File tree

10 files changed

+288
-18
lines changed

10 files changed

+288
-18
lines changed

kernel/interrupt.zig

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const isr = @import("isr.zig");
2+
const tty = @import("tty.zig");
23
const x86 = @import("x86.zig");
34

45
// PIC ports.
@@ -16,15 +17,15 @@ const ICW4_8086 = 0x01;
1617
// Default interrupt handler.
1718
//
1819
fn unhandled() {
19-
@panic("unhandled interrupt");
20+
const n = isr.context.interrupt_n;
21+
tty.panic("unhandled interrupt number {d}", n);
2022
}
2123

2224
// Registered interrupt handlers.
2325
export var interrupt_handlers = []fn() { unhandled } ** 48;
2426

2527
////
26-
// Register an interrupt handler.
27-
//
28+
// Register an interrupt handler. //
2829
// Arguments:
2930
// n: Index of the interrupt.
3031
// handler: Interrupt handler.

kernel/isr.s

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111
push $\n // Push the interrupt number.
1212
pusha // Save the registers state.
1313

14-
// Keep a pointer to the saved context.
15-
mov %esp, context
14+
mov %esp, context // Save context pointer.
1615

1716
// Call the designed interrupt handler.
1817
call *(interrupt_handlers + (\n * 4))
1918

19+
mov context, %esp // Restore context pointer (potentially different).
20+
2021
// Only for IRQs: send "End Of Interrupt" signal.
2122
.if (\n >= 32 && \n < 48)
2223
mov $0x20, %al

kernel/isr.zig

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,6 @@ pub const Context = packed struct {
3232
// Pointer to the current saved context.
3333
export var context: &volatile Context = undefined;
3434

35-
////
36-
// Return a pointer to the current saved context.
37-
//
38-
pub inline fn getContext() -> &volatile Context { context }
39-
4035
////
4136
// Install the Interrupt Service Routines in the IDT.
4237
//

kernel/kmain.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use @import("multiboot.zig");
2-
const allocator = @import("allocator.zig");
32
const gdt = @import("gdt.zig");
43
const idt = @import("idt.zig");
54
const scheduler = @import("scheduler.zig");
5+
const mem = @import("mem.zig");
66
const pmem = @import("pmem.zig");
77
const vmem = @import("vmem.zig");
88
const timer = @import("timer.zig");
@@ -47,7 +47,7 @@ export fn kmain(magic: u32, info: &const MultibootInfo) -> noreturn {
4747
idt.initialize();
4848
pmem.initialize(info);
4949
vmem.initialize();
50-
allocator.initialize(pmem.stack_end, 0x100000);
50+
mem.initialize(pmem.stack_end, 0x100000);
5151
timer.initialize(50);
5252
scheduler.initialize();
5353

kernel/list.zig

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
const mem = @import("std").mem;
2+
3+
// Node inside the linked list wrapping the actual data.
4+
fn Node(comptime T: type) -> type {
5+
struct {
6+
const Self = this;
7+
8+
prev: ?&Self,
9+
next: ?&Self,
10+
data: T,
11+
}
12+
}
13+
14+
// Generic doubly linked list.
15+
pub fn List(comptime T: type) -> type {
16+
struct {
17+
const Self = this;
18+
19+
first: ?&Node(T),
20+
last: ?&Node(T),
21+
len: usize,
22+
allocator: &mem.Allocator,
23+
24+
////
25+
// Initialize a linked list.
26+
//
27+
// Arguments:
28+
// allocator: Dynamic memory allocator.
29+
//
30+
// Returns:
31+
// An empty linked list.
32+
//
33+
pub fn init(allocator: &mem.Allocator) -> Self {
34+
Self {
35+
.first = null,
36+
.last = null,
37+
.len = 0,
38+
.allocator = allocator,
39+
}
40+
}
41+
42+
////
43+
// Insert a new node after an existing one.
44+
//
45+
// Arguments:
46+
// node: Pointer to a node in the list.
47+
// new_node: Pointer to the new node to insert.
48+
//
49+
pub fn insert(self: &Self, node: &Node(T), new_node: &Node(T)) {
50+
new_node.prev = node;
51+
if (node.next == null) {
52+
// Last element of the list.
53+
new_node.next = null;
54+
self.last = new_node;
55+
} else {
56+
// Intermediate node.
57+
new_node.next = node.next;
58+
(??node.next).prev = new_node;
59+
}
60+
node.next = new_node;
61+
62+
self.len += 1;
63+
}
64+
65+
////
66+
// Insert a new node before an existing one.
67+
//
68+
// Arguments:
69+
// node: Pointer to a node in the list.
70+
// new_node: Pointer to the new node to insert.
71+
//
72+
pub fn insertBefore(self: &Self, node: &Node(T), new_node: &Node(T)) {
73+
new_node.next = node;
74+
if (node.prev == null) {
75+
// First element of the list.
76+
new_node.prev = null;
77+
self.first = new_node;
78+
} else {
79+
// Intermediate node.
80+
new_node.prev = node.prev;
81+
(??node.prev).next = new_node;
82+
}
83+
node.prev = new_node;
84+
85+
self.len += 1;
86+
}
87+
88+
////
89+
// Insert a new node at the end of the list.
90+
//
91+
// Arguments:
92+
// new_node: Pointer to the new node to insert.
93+
//
94+
pub fn append(self: &Self, new_node: &Node(T)) {
95+
if (self.last == null) {
96+
// Empty list.
97+
self.prepend(new_node);
98+
} else {
99+
// Insert after last.
100+
self.insert(??self.last, new_node);
101+
}
102+
}
103+
104+
////
105+
// Insert a new node at the beginning of the list.
106+
//
107+
// Arguments:
108+
// new_node: Pointer to the new node to insert.
109+
//
110+
pub fn prepend(self: &Self, new_node: &Node(T)) {
111+
if (self.first != null) {
112+
// Insert before first.
113+
self.insert(??self.first, new_node);
114+
} else {
115+
// Empty list.
116+
self.first = new_node;
117+
self.last = new_node;
118+
new_node.prev = null;
119+
new_node.next = null;
120+
121+
self.len = 1;
122+
}
123+
}
124+
125+
////
126+
// Remove a node from the list.
127+
//
128+
// Arguments:
129+
// node: Pointer to the node to be removed.
130+
//
131+
pub fn remove(self: &Self, node: &Node(T)) {
132+
if (node.prev == null) {
133+
// First element of the list.
134+
self.first = node.next;
135+
} else {
136+
(??node.prev).next = node.next;
137+
}
138+
139+
if (node.next == null) {
140+
// Last element of the list.
141+
self.last = node.prev;
142+
} else {
143+
(??node.next).prev = node.prev;
144+
}
145+
146+
self.len -= 1;
147+
}
148+
149+
////
150+
// Remove and return the last node in the list.
151+
//
152+
// Returns:
153+
// A pointer to the last node in the list.
154+
//
155+
pub fn pop(self: &Self) -> ?&Node(T) {
156+
const last = self.last ?? return null;
157+
self.remove(last);
158+
return last;
159+
}
160+
161+
////
162+
// Remove and return the first node in the list.
163+
//
164+
// Returns:
165+
// A pointer to the first node in the list.
166+
//
167+
pub fn popFirst(self: &Self) -> ?&Node(T) {
168+
const first = self.first ?? return null;
169+
self.remove(first);
170+
return first;
171+
}
172+
173+
////
174+
// Allocate a new node.
175+
//
176+
// Returns:
177+
// A pointer to the new node.
178+
//
179+
pub fn createNode(self: &Self) -> ?&Node(T) {
180+
self.allocator.create(Node(T))
181+
}
182+
183+
////
184+
// Deallocate a node.
185+
//
186+
// Arguments:
187+
// node: Pointer to the node to deallocate.
188+
//
189+
pub fn destroyNode(self: &Self, node: &Node(T)) {
190+
self.allocator.destroy(node);
191+
}
192+
193+
////
194+
// Allocate and initialize a node and its data.
195+
//
196+
// Arguments:
197+
// data: The data to put inside the node.
198+
//
199+
// Returns:
200+
// A pointer to the new node.
201+
//
202+
pub fn initNode(self: &Self, data: T) -> %&Node(T) {
203+
var node = %return self.createNode();
204+
node.data = data;
205+
return node;
206+
}
207+
208+
////
209+
// Iterate through the elements of the list.
210+
//
211+
// Returns:
212+
// A list iterator with a next() method.
213+
//
214+
pub fn iterate(self: &Self) -> ListIterator(T, false) {
215+
ListIterator(T, false) {
216+
.node = self.first,
217+
}
218+
}
219+
220+
////
221+
// Iterate through the elements of the list backwards.
222+
//
223+
// Returns:
224+
// A list iterator with a next() method.
225+
//
226+
pub fn iterateBackwards(self: &Self) -> ListIterator(T, true) {
227+
ListIterator(T, true) {
228+
.node = self.last,
229+
}
230+
}
231+
}
232+
}
233+
234+
// Abstract iteration over a linked list.
235+
fn ListIterator(comptime T: type, comptime backwards: bool) -> type {
236+
struct {
237+
const Self = this;
238+
239+
node: ?&Node(T),
240+
241+
////
242+
// Return the next element of the list, until the end.
243+
// When no more elements are available, return null.
244+
//
245+
pub fn next(self: &Self) -> ?&Node(T) {
246+
const current = self.node ?? return null;
247+
self.node = if (backwards) current.prev else current.next;
248+
return current;
249+
}
250+
}
251+
}

kernel/allocator.zig renamed to kernel/mem.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fn realloc(self: &mem.Allocator, old_mem: []u8, new_size: usize) -> %[]u8 {
3030
fn free(self: &mem.Allocator, old_mem: []u8) {}
3131

3232
pub fn initialize(address: usize, capacity: usize) {
33-
tty.step("Initializing the Kernel Allocator");
33+
tty.step("Initializing Dynamic Memory Allocation");
3434

3535
bytes = @intToPtr(&u8, address)[0...capacity];
3636

kernel/process.zig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const Thread = @import("thread.zig").Thread;
2+
const List = @import("std").list.List;
3+
4+
pub const Process = struct {
5+
pid: u16,
6+
threads: List(Thread),
7+
};

kernel/scheduler.zig

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1+
const mem = @import("mem.zig");
12
const timer = @import("timer.zig");
23
const tty = @import("tty.zig");
3-
const x86 = @import("x86.zig");
4+
const Thread = @import("thread.zig").Thread;
5+
const List = @import("list.zig").List;
46

5-
fn schedule() {
6-
tty.printf("\nScheduler running.");
7+
var ready_queue: List(Thread) = undefined;
78

8-
x86.hang();
9+
fn schedule() {
10+
tty.printf("\nSchedule!");
911
}
1012

1113
pub fn initialize() {
1214
tty.step("Initializing the Scheduler");
1315

16+
ready_queue = List(Thread).init(&mem.allocator);
1417
timer.registerHandler(schedule);
1518

1619
tty.stepOK();

kernel/thread.zig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const Context = @import("isr.zig").Context;
2+
3+
pub const Thread = struct {
4+
context: Context,
5+
6+
tid: u16,
7+
local_tid: u8,
8+
};
9+
10+
pub fn create(entry_point: usize) {
11+
12+
}

kernel/vmem.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ fn pageFault() {
8585
// Get the faulting address from the CR2 register.
8686
const address = x86.readCR2();
8787
// Get the error code from the interrupt stack.
88-
const code = isr.getContext().error_code;
88+
const code = isr.context.error_code;
8989

9090
const err = if (code & PAGE_PRESENT != 0) "protection" else "non-present";
9191
const operation = if (code & PAGE_WRITE != 0) "write" else "read";

0 commit comments

Comments
 (0)