Redesign List as a mixin template
This commit is contained in:
parent
db2814596b
commit
3c8587acf5
@ -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,
|
||||
|
120
src/hulk/list.d
120
src/hulk/list.d
@ -3,125 +3,97 @@
|
||||
*/
|
||||
module hulk.list;
|
||||
|
||||
import hulk.hurl.a1;
|
||||
|
||||
/**
|
||||
* Linked list structure.
|
||||
* Linked list mixin.
|
||||
*/
|
||||
struct List(T)
|
||||
{
|
||||
struct Node
|
||||
mixin template List(T)
|
||||
{
|
||||
/**
|
||||
* Linked list node.
|
||||
* Next item in linked list.
|
||||
*/
|
||||
T item;
|
||||
alias item this;
|
||||
T * list_next;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user