Redesign List as a mixin template

This commit is contained in:
Josh Holtrop 2023-11-27 15:30:09 -05:00
parent db2814596b
commit 3c8587acf5
6 changed files with 144 additions and 153 deletions

View File

@ -6,14 +6,14 @@ module hulk.acpi;
import hulk.hurl; import hulk.hurl;
import hulk.klog; import hulk.klog;
import hulk.memory; import hulk.memory;
import hulk.list; import hulk.hurl.a1;
struct Acpi struct Acpi
{ {
/** /**
* List of ACPI tables. * List of ACPI tables.
*/ */
private static __gshared List!(Header *) tables; private static __gshared Header *[] tables;
enum uint XSDT_SIGNATURE = signature("XSDT"); enum uint XSDT_SIGNATURE = signature("XSDT");
@ -65,6 +65,8 @@ struct Acpi
map_table(acpi_xsdt_phys, xsdt.header.length); map_table(acpi_xsdt_phys, xsdt.header.length);
} }
size_t n_entries = (xsdt.header.length - xsdt.header.sizeof) / xsdt.tables[0].sizeof; size_t n_entries = (xsdt.header.length - xsdt.header.sizeof) / xsdt.tables[0].sizeof;
Header ** table_pointers = cast(Header **)A1.allocate(n_entries * (Header *).sizeof);
tables = table_pointers[0..n_entries];
for (size_t i = 0u; i < n_entries; i++) for (size_t i = 0u; i < n_entries; i++)
{ {
ulong address = xsdt.tables[i]; ulong address = xsdt.tables[i];
@ -75,7 +77,7 @@ struct Acpi
{ {
map_table(address, length); map_table(address, length);
} }
tables.add(header); tables[i] = header;
uint signature = header.signature; uint signature = header.signature;
Klog.writefln("Found ACPI table '%c%c%c%c' at %p", Klog.writefln("Found ACPI table '%c%c%c%c' at %p",
signature & 0xFFu, signature & 0xFFu,

View File

@ -3,125 +3,97 @@
*/ */
module hulk.list; module hulk.list;
import hulk.hurl.a1;
/** /**
* Linked list structure. * Linked list mixin.
*/ */
struct List(T) mixin template List(T)
{
struct Node
{ {
/** /**
* Linked list node. * Next item in linked list.
*/ */
T item; T * list_next;
alias item this;
/** /**
* Next node. * Previous item in linked list.
*/ */
Node * next; T * list_prev;
/** /**
* Previous node. * Initialize linked list fields.
*/ */
Node * prev; public void list_init()
{
list_next = &this;
list_prev = &this;
} }
/** /**
* Head node. * Add this item after another in a list.
*/ */
public Node * head; public void list_insert_after(T * item)
/**
* Tail node.
*/
public Node * tail;
/**
* Add an item to this linked list.
*/
public void add(T)(auto ref T item)
{ {
Node * new_node = A1.allocate!Node(); list_next = item.list_next;
new_node.item = item; list_prev = item;
new_node.next = null; item.list_next = &this;
new_node.prev = tail; list_next.list_prev = &this;
if (tail != null)
{
tail.next = new_node;
}
tail = new_node;
if (head == null)
{
head = new_node;
}
} }
/** /**
* Remove an item from this linked list. * Add this item before another in a list.
*/ */
public void remove(ref Node node) public void list_insert_before(T * item)
{ {
if (node.prev != null) list_next = item;
{ list_prev = item.list_prev;
node.prev.next = node.next; item.list_prev = &this;
} list_prev.list_next = &this;
else
{
/* Removing the first list node. */
head = node.next;
}
if (node.next != null)
{
node.next.prev = node.prev;
}
else
{
/* Removing the last list node. */
tail = node.prev;
}
} }
/** /**
* Remove an item from this linked list. * Remove this item from the list.
*/ */
public void remove(Node * node) public void list_remove()
{ {
remove(*node); list_next.list_prev = list_prev;
list_prev.list_next = list_next;
list_init();
} }
/** /**
* Get the number of nodes in this list. * Get the number of items in this list.
*/ */
public @property size_t count() const public @property size_t list_count() const
{ {
size_t count; size_t count = 1;
const(Node) * node = head; const(T) * item = &this;
while (node != null) while (item.list_next != &this)
{ {
count++; count++;
node = node.next; item = item.list_next;
} }
return count; return count;
} }
/** /**
* Allow foreach iteration across a List. * Allow foreach iteration through this linked list.
*/ */
public int opApply(scope int delegate(ref Node) dg) public int opApply(scope int delegate(T *) dg)
{ {
Node * node = head; T * item = &this;
while (node != null) T * last = item.list_prev;
for (;;)
{ {
Node * current = node; T * next = item.list_next;
node = node.next; int result = dg(item);
int result = dg(*current);
if (result != 0) if (result != 0)
{ {
return result; return result;
} }
if (item == last)
{
break;
}
item = next;
} }
return 0; return 0;
} }

View File

@ -148,8 +148,11 @@ struct Pci
bool multifunction; bool multifunction;
Range[6] memory_ranges; Range[6] memory_ranges;
mixin List!Device;
void initialize(Address address, Configuration * config) void initialize(Address address, Configuration * config)
{ {
list_init();
this.config = config; this.config = config;
this.address = address; this.address = address;
type = Type(config.class_id, config.subclass_id, config.interface_id); type = Type(config.class_id, config.subclass_id, config.interface_id);
@ -233,9 +236,9 @@ struct Pci
} }
/** /**
* Store a list of discovered PCI devices. * Device list.
*/ */
public static __gshared List!(Device *) devices; public static __gshared Device * devices;
private static uint read_config_register(Address address, uint register_id) private static uint read_config_register(Address address, uint register_id)
{ {
@ -402,7 +405,14 @@ struct Pci
if (config.vendor_id != 0xFFFFu) if (config.vendor_id != 0xFFFFu)
{ {
Device * device = A1.allocate!Device(); Device * device = A1.allocate!Device();
devices.add(device); if (devices == null)
{
devices = devices;
}
else
{
device.list_insert_before(devices);
}
device.initialize(Address(bus_nr, device_nr, function_nr), config); device.initialize(Address(bus_nr, device_nr, function_nr), config);
if (device.multifunction) if (device.multifunction)
{ {

View File

@ -6,6 +6,7 @@ module hulk.test;
import hulk.klog; import hulk.klog;
import hulk.list; import hulk.list;
import hulk.time; import hulk.time;
import hulk.hurl.a1;
struct Test struct Test
{ {
@ -33,30 +34,45 @@ struct Test
private static void test_list() private static void test_list()
{ {
Klog.writefln("Testing list..."); Klog.writefln("Testing list...");
List!ulong list;
assert_eq(null, list.head); struct S
assert_eq(null, list.tail); {
ulong v = 33; size_t v;
list.add(42); mixin List!S;
assert_neq(null, list.head); void initialize()
assert_neq(null, list.tail); {
list.add(v); list_init();
list.add(0xFFFF); }
v = 55; }
S * s1 = A1.allocate!S();
s1.initialize();
s1.v = 33;
assert_eq(1, s1.list_count);
S * s2 = A1.allocate!S();
s2.initialize();
s2.v = 42;
s2.list_insert_after(s1);
S * s3 = A1.allocate!S();
s3.initialize();
s3.v = 55;
s3.list_insert_before(s1);
size_t count; size_t count;
assert_eq(3, list.count); assert_eq(3, s1.list_count);
foreach (entry; list) assert_eq(3, s2.list_count);
assert_eq(3, s3.list_count);
foreach (entry; *s1)
{ {
switch (count) switch (count)
{ {
case 0: case 0:
assert_eq(42, entry); assert_eq(33, entry.v);
break; break;
case 1: case 1:
assert_eq(33, entry); assert_eq(42, entry.v);
break; break;
case 2: case 2:
assert_eq(0xFFFF, entry); assert_eq(55, entry.v);
break; break;
case 3: case 3:
assert_eq(0, 1); assert_eq(0, 1);
@ -66,24 +82,24 @@ struct Test
} }
count++; count++;
} }
foreach (entry; list) foreach (entry; *s3)
{ {
if (entry == 33) if (entry.v == 33)
{ {
list.remove(entry); entry.list_remove();
} }
} }
assert_eq(2, list.count); assert_eq(2, s3.list_count);
count = 0; count = 0;
foreach (entry; list) foreach (entry; *s3)
{ {
switch (count) switch (count)
{ {
case 0: case 0:
assert_eq(42, entry); assert_eq(55, entry.v);
break; break;
case 1: case 1:
assert_eq(0xFFFF, entry); assert_eq(42, entry.v);
break; break;
case 2: case 2:
assert_eq(0, 1); assert_eq(0, 1);
@ -93,51 +109,30 @@ struct Test
} }
count++; count++;
} }
foreach (entry; list) foreach (entry; *s2)
{ {
if (entry == 42) if (entry.v == 42)
{ {
list.remove(entry); entry.list_remove();
} }
} }
assert_eq(1, list.count); assert_eq(1, s2.list_count);
count = 0; assert_eq(1, s3.list_count);
foreach (entry; list)
{
switch (count)
{
case 0:
assert_eq(0xFFFF, entry);
break;
case 1:
assert_eq(0, 1);
break;
default:
break;
}
count++;
}
assert_neq(null, list.head);
assert_neq(null, list.tail);
list.remove(list.head);
assert_eq(0, list.count);
assert_eq(null, list.head);
assert_eq(null, list.tail);
} }
private static void assert_eq(T)(T first, T second) private static void assert_eq(T)(T first, T second, size_t line_number = __LINE__)
{ {
if (first != second) if (first != second)
{ {
Klog.fatal_error("Assertion failed! %x != %x", first, second); Klog.fatal_error("Assertion failed! %x != %x (line %u)", first, second, line_number);
} }
} }
private static void assert_neq(T)(T first, T second) private static void assert_neq(T)(T first, T second, size_t line_number = __LINE__)
{ {
if (first == second) if (first == second)
{ {
Klog.fatal_error("Assertion failed! %x == %x", first, second); Klog.fatal_error("Assertion failed! %x == %x (line %u)", first, second, line_number);
} }
} }
} }

View File

@ -16,19 +16,6 @@ struct Thread
/* TODO: currently kernel thread stack size is fixed. */ /* TODO: currently kernel thread stack size is fixed. */
enum STACK_SIZE = 16 * 1024; enum STACK_SIZE = 16 * 1024;
/** List of all kernel threads. */
private static __gshared List!Thread threads;
/** Currently executing kernel thread. */
static __gshared Thread * current_thread;
/** Current kernel thread stack pointer. */
ulong * stack_pointer;
static assert(stack_pointer.offsetof == 0);
/** Base address of kernel thread stack. */
void * stack_addr;
/** Interrupt stack template. */ /** Interrupt stack template. */
static immutable __gshared ulong[Idt.ISF_COUNT] interrupt_stack_template = [ static immutable __gshared ulong[Idt.ISF_COUNT] interrupt_stack_template = [
0x16161616_16161616u, /* RBP */ 0x16161616_16161616u, /* RBP */
@ -54,11 +41,31 @@ struct Thread
Gdt.SELECTOR_KERNEL_DATA, /* SS */ Gdt.SELECTOR_KERNEL_DATA, /* SS */
]; ];
/** List of all kernel threads. */
private static __gshared Thread * threads;
/** Currently executing kernel thread. */
static __gshared Thread * current_thread;
/** Current kernel thread stack pointer. */
ulong * stack_pointer;
static assert(stack_pointer.offsetof == 0);
/** Base address of kernel thread stack. */
void * stack_addr;
mixin List!Thread;
/** /**
* Initialize a kernel thread. * Initialize a kernel thread.
*/ */
public void initialize(void function() fn) public void initialize(void function() fn)
{ {
list_init();
if (threads == null)
{
threads = &this;
}
stack_addr = A1.allocate(STACK_SIZE); stack_addr = A1.allocate(STACK_SIZE);
ulong * stack_top = cast(ulong *)(stack_addr + STACK_SIZE); ulong * stack_top = cast(ulong *)(stack_addr + STACK_SIZE);
stack_pointer = stack_top - Idt.ISF_COUNT; stack_pointer = stack_top - Idt.ISF_COUNT;
@ -73,6 +80,11 @@ struct Thread
*/ */
public void initialize_main_thread() public void initialize_main_thread()
{ {
list_init();
if (threads == null)
{
threads = &this;
}
stack_addr = cast(void *)(Hurl.HULK_STACK_TOP - STACK_SIZE); stack_addr = cast(void *)(Hurl.HULK_STACK_TOP - STACK_SIZE);
} }

View File

@ -13,7 +13,7 @@ struct Usb
{ {
Klog.writefln("\a3Initializing USB"); Klog.writefln("\a3Initializing USB");
foreach (pci_device; Pci.devices) foreach (pci_device; *Pci.devices)
{ {
if (pci_device.type == Pci.XHCI_CONTROLLER) if (pci_device.type == Pci.XHCI_CONTROLLER)
{ {