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.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,
|
||||||
|
120
src/hulk/list.d
120
src/hulk/list.d
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user