diff --git a/src/hulk/acpi.d b/src/hulk/acpi.d index 0563592..720584b 100644 --- a/src/hulk/acpi.d +++ b/src/hulk/acpi.d @@ -6,14 +6,14 @@ module hulk.acpi; import hulk.hurl; import hulk.klog; import hulk.memory; -import hulk.list; +import hulk.hurl.a1; struct Acpi { /** * List of ACPI tables. */ - private static __gshared List!(Header *) tables; + private static __gshared Header *[] tables; enum uint XSDT_SIGNATURE = signature("XSDT"); @@ -65,6 +65,8 @@ struct Acpi map_table(acpi_xsdt_phys, xsdt.header.length); } 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++) { ulong address = xsdt.tables[i]; @@ -75,7 +77,7 @@ struct Acpi { map_table(address, length); } - tables.add(header); + tables[i] = header; uint signature = header.signature; Klog.writefln("Found ACPI table '%c%c%c%c' at %p", signature & 0xFFu, diff --git a/src/hulk/list.d b/src/hulk/list.d index 88b1bbf..44ee61d 100644 --- a/src/hulk/list.d +++ b/src/hulk/list.d @@ -3,125 +3,97 @@ */ module hulk.list; -import hulk.hurl.a1; - /** - * Linked list structure. + * Linked list mixin. */ -struct List(T) +mixin template List(T) { - struct Node + /** + * Next item in linked list. + */ + T * list_next; + + /** + * Previous item in linked list. + */ + T * list_prev; + + /** + * Initialize linked list fields. + */ + public void list_init() { - /** - * Linked list node. - */ - T item; - alias item this; - - /** - * Next node. - */ - Node * next; - - /** - * Previous node. - */ - Node * prev; + list_next = &this; + list_prev = &this; } /** - * Head node. + * Add this item after another in a list. */ - public Node * head; - - /** - * Tail node. - */ - public Node * tail; - - /** - * Add an item to this linked list. - */ - public void add(T)(auto ref T item) + public void list_insert_after(T * item) { - Node * new_node = A1.allocate!Node(); - new_node.item = item; - new_node.next = null; - new_node.prev = tail; - if (tail != null) - { - tail.next = new_node; - } - tail = new_node; - if (head == null) - { - head = new_node; - } + list_next = item.list_next; + list_prev = item; + item.list_next = &this; + list_next.list_prev = &this; } /** - * 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) - { - node.prev.next = node.next; - } - 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; - } + list_next = item; + list_prev = item.list_prev; + item.list_prev = &this; + list_prev.list_next = &this; } /** - * 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; - const(Node) * node = head; - while (node != null) + size_t count = 1; + const(T) * item = &this; + while (item.list_next != &this) { count++; - node = node.next; + item = item.list_next; } 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; - while (node != null) + T * item = &this; + T * last = item.list_prev; + for (;;) { - Node * current = node; - node = node.next; - int result = dg(*current); + T * next = item.list_next; + int result = dg(item); if (result != 0) { return result; } + if (item == last) + { + break; + } + item = next; } return 0; } diff --git a/src/hulk/pci.d b/src/hulk/pci.d index b4987d5..cfa250c 100644 --- a/src/hulk/pci.d +++ b/src/hulk/pci.d @@ -148,8 +148,11 @@ struct Pci bool multifunction; Range[6] memory_ranges; + mixin List!Device; + void initialize(Address address, Configuration * config) { + list_init(); this.config = config; this.address = address; 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) { @@ -402,7 +405,14 @@ struct Pci if (config.vendor_id != 0xFFFFu) { 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); if (device.multifunction) { diff --git a/src/hulk/test.d b/src/hulk/test.d index 1aecdf5..1251f13 100644 --- a/src/hulk/test.d +++ b/src/hulk/test.d @@ -6,6 +6,7 @@ module hulk.test; import hulk.klog; import hulk.list; import hulk.time; +import hulk.hurl.a1; struct Test { @@ -33,30 +34,45 @@ struct Test private static void test_list() { Klog.writefln("Testing list..."); - List!ulong list; - assert_eq(null, list.head); - assert_eq(null, list.tail); - ulong v = 33; - list.add(42); - assert_neq(null, list.head); - assert_neq(null, list.tail); - list.add(v); - list.add(0xFFFF); - v = 55; + + struct S + { + size_t v; + mixin List!S; + void initialize() + { + list_init(); + } + } + + 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; - assert_eq(3, list.count); - foreach (entry; list) + assert_eq(3, s1.list_count); + assert_eq(3, s2.list_count); + assert_eq(3, s3.list_count); + foreach (entry; *s1) { switch (count) { case 0: - assert_eq(42, entry); + assert_eq(33, entry.v); break; case 1: - assert_eq(33, entry); + assert_eq(42, entry.v); break; case 2: - assert_eq(0xFFFF, entry); + assert_eq(55, entry.v); break; case 3: assert_eq(0, 1); @@ -66,24 +82,24 @@ struct Test } 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; - foreach (entry; list) + foreach (entry; *s3) { switch (count) { case 0: - assert_eq(42, entry); + assert_eq(55, entry.v); break; case 1: - assert_eq(0xFFFF, entry); + assert_eq(42, entry.v); break; case 2: assert_eq(0, 1); @@ -93,51 +109,30 @@ struct Test } 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); - count = 0; - 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); + assert_eq(1, s2.list_count); + assert_eq(1, s3.list_count); } - 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) { - 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) { - Klog.fatal_error("Assertion failed! %x == %x", first, second); + Klog.fatal_error("Assertion failed! %x == %x (line %u)", first, second, line_number); } } } diff --git a/src/hulk/thread.d b/src/hulk/thread.d index 9ab703a..faf82b4 100644 --- a/src/hulk/thread.d +++ b/src/hulk/thread.d @@ -16,19 +16,6 @@ struct Thread /* TODO: currently kernel thread stack size is fixed. */ 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. */ static immutable __gshared ulong[Idt.ISF_COUNT] interrupt_stack_template = [ 0x16161616_16161616u, /* RBP */ @@ -54,11 +41,31 @@ struct Thread 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. */ public void initialize(void function() fn) { + list_init(); + if (threads == null) + { + threads = &this; + } stack_addr = A1.allocate(STACK_SIZE); ulong * stack_top = cast(ulong *)(stack_addr + STACK_SIZE); stack_pointer = stack_top - Idt.ISF_COUNT; @@ -73,6 +80,11 @@ struct Thread */ public void initialize_main_thread() { + list_init(); + if (threads == null) + { + threads = &this; + } stack_addr = cast(void *)(Hurl.HULK_STACK_TOP - STACK_SIZE); } diff --git a/src/hulk/usb/usb.d b/src/hulk/usb/usb.d index 95c9ec4..352772c 100644 --- a/src/hulk/usb/usb.d +++ b/src/hulk/usb/usb.d @@ -13,7 +13,7 @@ struct Usb { Klog.writefln("\a3Initializing USB"); - foreach (pci_device; Pci.devices) + foreach (pci_device; *Pci.devices) { if (pci_device.type == Pci.XHCI_CONTROLLER) {