Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
87e4f04
Adds support for pointers to align_down and align_up.
remexre Nov 9, 2025
0f036e7
Implements iomem_map and iomem_unmap.
remexre Nov 9, 2025
7b8642c
Makes devicetree_print prints the path to the node.
remexre Nov 9, 2025
2a50ea8
Adds initializers and documentation about them.
remexre Jul 26, 2025
9372ec8
Adds a notion of device objects.
remexre Nov 9, 2025
0287b44
Adds support for enumerating devices in a Devicetree.
remexre Nov 9, 2025
df910ec
Adds the UART device class.
remexre Nov 9, 2025
42c8ab0
Adds the ns16550a driver.
remexre Nov 9, 2025
9e91c26
Adds a script that build-tests each commit since trunk.
remexre Feb 28, 2026
dacbac9
Switches qemu-riscv64 target to RVA23.
remexre Feb 14, 2026
7e5eb72
Gives the qemu-riscv64 target a second hart.
remexre Feb 14, 2026
48b80ad
Bumps the Milk-V Duo S U-Boot to update Devicetree.
remexre Feb 14, 2026
3e5c5e3
Adds busybox to Nix flake devShell.
remexre Feb 14, 2026
c887d76
Adds watchexec to the devcontainer and flake.
remexre Feb 3, 2026
1819a64
Adds documentation for the bytes format directive, adds {bytes:?}.
remexre Feb 13, 2026
5d91e35
Adds the strnlen builtin.
remexre Feb 14, 2026
bc35bb0
Adds a page documenting lists.
remexre Jan 18, 2026
35b6639
Adds a device class for hart devices.
remexre Feb 13, 2026
475db86
Adds a driver for riscv64 harts.
remexre Feb 27, 2026
a68132c
Adds a page documenting guards.
remexre Jan 18, 2026
7cdb80a
Moves "Threads and Harts" docs page to the start of a tasks section.
remexre Jan 18, 2026
5e0a3c9
Adds the refcount_t type.
remexre Jan 18, 2026
2c74d27
ckpt tasks impl
remexre Jan 18, 2026
3fb19c0
mutex ckpt
remexre Jan 19, 2026
2b91acc
checkpoint of tasks; gonna need cpu drivers
remexre Feb 13, 2026
51f9084
ckpt tasks impl
remexre Jan 18, 2026
f3fd82a
feat: spinlocks
auctumnus Jan 30, 2026
fbc1d16
docs: add license for spinlock.c
auctumnus Jan 30, 2026
404ff17
fix: use <stdatomic.h>
auctumnus Jan 31, 2026
bd33691
Update src/kernel/include/arch/riscv64/insns.h
auctumnus Jan 31, 2026
5cb8cec
review comments from 02/18
auctumnus Feb 19, 2026
c924289
feat: hartlocks
auctumnus Mar 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2025 ukoOS Contributors
# SPDX-FileCopyrightText: 2025-2026 ukoOS Contributors
#
# SPDX-License-Identifier: GPL-3.0-or-later

Expand All @@ -23,4 +23,5 @@ RUN apk add --no-interactive \
shellcheck \
tar \
tio \
watchexec \
zstd
9 changes: 8 additions & 1 deletion doc/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,18 @@
- [Using GDB](./getting-started/using-gdb.md)
- [Kernel]()
- [The `print()` and `format()` functions](./kernel/print.md)
- [Threads and Harts](./kernel/threads-and-harts.md)
- [Init Functions](./kernel/init.md)
- [Devices](./kernel/devices.md)
- [Containers]()
- [Lists](./kernel/containers/lists.md)
- [Guards](./kernel/containers/guards.md)
- [Reference counting](./kernel/containers/refcounting.md)
- [Memory management]()
- [Overview](./kernel/mm/overview.md)
- [Memory map](./kernel/mm/memory-map.md)
- [Booting](./kernel/mm/booting.md)
- [Tasks]()
- [Overview](./kernel/task/overview.md)
- [Targets](./targets.md)
- [Tutorials](./tutorials/tutorials.md)
- [First Day](./tutorials/first-day.md)
Expand Down
58 changes: 58 additions & 0 deletions doc/kernel/containers/guards.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Guards

RAII, or "resource acquisition is initialization," is a common pattern in C++, Rust, and similar languages.
With RAII, some object or resource being acquired (i.e., having a value of that type in a valid state) is tied to that object being initialized and deinitialized.

In C++, this is accomplished with constructors and destructors; in Rust, with privacy and the Drop trait.
In C, we can implement this with [the `cleanup` attribute](https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-cleanup-variable-attribute).
This attribute applies to a variable, and registers a function to run when the variable goes out of scope.

This is roughly equivalent to the Drop trait, with one limitation -- we can't easily move the variable to extend its lifetime past the scope it's declared in.
However, this is still useful enough for us to have RAII objects to manage access to resources.

The objects that manage access to the resource are called "guards."
These are usually used to handle locks and refcounts.

## Using a guard

Most types of guards will have a macro for acquiring the guard, typically named something like `FOO_GUARD`.
This macro takes a variable name (for the guarded resource) as the first argument, and some number of arguments afterwards.

Typically, there's another macro for declaring guarded variables, to make it harder to accidentally use them without acquiring the guard.
For example:

```c
#include <mutex.h>
#include <print.h>

struct foo {
// Declare a mutex named bar and some variables protected by it.
MUTEX_GUARDED(bar, {
int baz;
char *asdf;
});

// This variable is not protected by the mutex.
int qwerty;
};

int foo_func(struct foo* foo) {
int x = 3 * foo->qwerty;

// Because of the MUTEX_GUARDED macro, we can't just write e.g.
// x += foo->baz;

{
MUTEX_GUARD(g, foo, bar);

// We can access the variables through g instead, though!
x += g->baz;

print("{cstr}", g->asdf);
}

// Mutex is no longer held here, but g is out of scope, so we can't use
// foo->baz or g->baz.
return x;
}
```
85 changes: 85 additions & 0 deletions doc/kernel/containers/lists.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Lists

Many resources in the ukoOS kernel need to be in some registry.
For example, devices of a certain device class (e.g. UARTs) generally need to be in some list, so that the kernel can iterate through all UARTs.
Lists (`struct list_head`, after the same structure in Linux) allow for this in ukoOS.
See `src/kernel/include/list.h` for the actual list API.

ukoOS lists are doubly-linked circular *intrusive* linked lists; that is, rather than the list containing the element in some way (whether by having a pointer that points to it or by including it in each link's memory allocation), elements contain the link.

For example, let's say we had a list of RGB colors and names.
We might write that data structure as:

```c
struct named_color {
struct list_head list;
const char *name;
u8 r, g, b;
};
```

This might seem strange, but it has one big advantage over a container that owns its data -- elements can belong to multiple lists.
For example, pretend we had both an `all_colors` list and a `favorite_colors` list:

```c
struct named_color {
struct list_head all_colors;
struct list_head favorite_colors;
const char *name;
u8 r, g, b;
};
```

This lets the color be in both lists at once.

Lists are intended to have a single owning node / sentinel node.
This is **not** embedded in the structure like other nodes are, but stands alone, often as a global:

```c
struct named_color {
struct list_head all_colors;
struct list_head favorite_colors;
const char *name;
u8 r, g, b;
};

struct list_head all_colors = LIST_INIT(all_colors);
struct list_head favorite_colors = LIST_INIT(favorite_colors);
```

Since the lists are circular, we can use this sentinel node to know when we've reached the end of the list.

We can also use this to create a tree:

```c
struct tree_node {
/**
* The parent of this node.
*/
struct tree_node *parent;

/**
* This node's link in its parent's children.
*/
struct list_head list;

/**
* This node's children.
*/
struct list_head children;
};
```

The `container_of` macro can be used to go from a `struct list_head *` to a `struct tree_node *`:

```c
struct tree_node node = { /* ... */ };

struct list_head *ptr1 = &node.list;
struct tree_node *node1 = container_of(ptr1, struct tree_node, list);
assert(node1 == &node);

struct list_head *ptr2 = &node.children;
struct tree_node *node2 = container_of(ptr2, struct tree_node, children);
assert(node2 == &node);
```
43 changes: 43 additions & 0 deletions doc/kernel/containers/refcounting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Reference counting

Many resources in the ukoOS kernel have dynamic enough ownership that reference counting is useful to determine if they're still in use and when they should be freed.

We have a helper type, `refcount_t`, to help manage these.
This is similar to the type with the same name in the Linux kernel, but we provide different helpers.

```c
#include <refcount.h>

/**
* This type is some random example resource. It's always
*/
struct foo {
/**
* This field stores the actual reference count. This is an integral type
* that is no wider than usize.
*/
refcount_t refcount;

/**
* A list the value is in.
*/
struct list_head all_foos;

/**
* Another list the value might be in (or the list might be self-linked).
*/
struct list_head bars;
};

struct list_head all_foos;

void add_foos_not_in_a_bars_to_list(struct list_head *bars) {
for (struct list_head *iter = all_foos.next; iter != all_foos;
iter = iter->next) {
struct foo *foo = container_of(iter, struct foo, all_foos);
if (list_is_empty(foo->bars))
continue;
list_push(bars, &foo->bars);
}
}
```
Loading