more stuff

This commit is contained in:
2026-09-19 21:57:06 +02:00
parent 1e9a1ebf4d
commit 831308b2ad
61 changed files with 777 additions and 837 deletions
+6 -6
View File
@@ -1,24 +1,24 @@
#include <zinnia/atomic.h>
#include <zinnia/clock.h>
#include <zinnia/compiler.h>
#include <zinnia/print.h>
#include <zinnia/spin.h>
#include <stdatomic.h>
#include <stdint.h>
static struct clock* active_clock = nullptr;
static uint64_t counter_base = 0;
static spinlock_t lock = {};
static struct spinlock lock = {};
bool clock_available() {
return active_clock != nullptr;
}
uint64_t clock_get_elapsed_ns() {
struct clock* active = atomic_load(&active_clock);
struct clock* active = atomic_load(&active_clock, ATOMIC_RELAXED);
if (__unlikely(!active))
return 0;
return atomic_load(&counter_base) + active->get_elapsed_ns(active);
return atomic_load(&counter_base, ATOMIC_RELAXED) + active->get_elapsed_ns(active);
}
bool clock_switch(struct clock* clock) {
@@ -31,7 +31,7 @@ bool clock_switch(struct clock* clock) {
}
}
log("clock", "Switching to clock source \"%s\"\n", clock->name);
log("clock: Switching to clock source \"%s\"\n", clock->name);
uint64_t elapsed = clock_get_elapsed_ns();
counter_base += elapsed;
@@ -43,7 +43,7 @@ bool clock_switch(struct clock* clock) {
void clock_spin_ns(uint64_t ns) {
if (active_clock == nullptr) {
log("clock", "Unable to sleep for %lu ns, no clock available!\n", ns);
log("clock: Unable to sleep for %lu ns, no clock available!\n", ns);
return;
}
+2 -2
View File
@@ -27,7 +27,7 @@ static void console_setup(const char* value) {
}
}
CMDLINE_OPTION("console", console_setup);
CMDLINE_OPTION("console", "Set a default console", console_setup);
void console_init() {
// If we have no console set and at least one set, use that as a default.
@@ -38,6 +38,6 @@ void console_init() {
if (active->init(active) == false)
active = nullptr;
log("console", "Logging on console \"%s\"\n", active->name);
log("console: Logging on console \"%s\"\n", active->name);
}
}
-120
View File
@@ -1,120 +0,0 @@
#include <zinnia/errno.h>
#include <zinnia/futex.h>
#include <zinnia/percpu.h>
#include <zinnia/print.h>
#include <zinnia/sched.h>
#include <zinnia/spin.h>
#include <zinnia/usercopy.h>
struct futex_bucket {
struct wait_queue wq;
uintptr_t key; // Virtual address used as the futex key.
bool in_use;
};
#define FUTEX_BUCKET_COUNT 64
static struct futex_bucket futex_table[FUTEX_BUCKET_COUNT];
static spinlock_t futex_table_lock;
void futex_init(void) {
futex_table_lock = (spinlock_t){0};
for (size_t i = 0; i < FUTEX_BUCKET_COUNT; i++) {
wait_queue_init(&futex_table[i].wq);
futex_table[i].key = 0;
futex_table[i].in_use = false;
}
}
static size_t futex_hash(uintptr_t addr) {
// Simple hash: mix the address bits and mod by bucket count.
addr = (addr >> 2) ^ (addr >> 12);
return addr % FUTEX_BUCKET_COUNT;
}
static struct futex_bucket* futex_bucket_get(uintptr_t addr) {
size_t idx = futex_hash(addr);
// Linear probing to find a matching or free bucket.
for (size_t i = 0; i < FUTEX_BUCKET_COUNT; i++) {
size_t slot = (idx + i) % FUTEX_BUCKET_COUNT;
struct futex_bucket* b = &futex_table[slot];
if (b->in_use && b->key == addr)
return b;
if (!b->in_use) {
b->key = addr;
b->in_use = true;
return b;
}
}
return nullptr;
}
errno_t futex_wait(__user int* addr, int expected) {
uintptr_t key = (uintptr_t)addr;
spin_lock(&futex_table_lock);
// Read the current value at the userspace address.
int current;
if (!usercopy_read(&current, addr, sizeof(*addr))) {
spin_unlock(&futex_table_lock);
return EFAULT;
}
// If the value has already changed, don't block.
if (current != expected) {
spin_unlock(&futex_table_lock);
return 0;
}
struct futex_bucket* bucket = futex_bucket_get(key);
if (!bucket) {
spin_unlock(&futex_table_lock);
return ENOMEM;
}
spin_unlock(&futex_table_lock);
// Block on the bucket's wait queue.
struct sched_percpu* sched = &percpu_get()->sched;
sched_block(sched, &bucket->wq);
return 0;
}
errno_t futex_wake(__user int* addr, int count) {
uintptr_t key = (uintptr_t)addr;
spin_lock(&futex_table_lock);
size_t idx = futex_hash(key);
struct futex_bucket* bucket = nullptr;
for (size_t i = 0; i < FUTEX_BUCKET_COUNT; i++) {
size_t slot = (idx + i) % FUTEX_BUCKET_COUNT;
struct futex_bucket* b = &futex_table[slot];
if (b->in_use && b->key == key) {
bucket = b;
break;
}
if (!b->in_use)
break;
}
if (!bucket) {
spin_unlock(&futex_table_lock);
return 0; // No waiters, nothing to do.
}
spin_unlock(&futex_table_lock);
struct sched_percpu* sched = &percpu_get()->sched;
if (count == INT32_MAX) {
sched_wake_all(sched, &bucket->wq);
} else {
for (int i = 0; i < count; i++) {
sched_wake(sched, &bucket->wq);
}
}
return 0;
}
+6 -6
View File
@@ -1,7 +1,7 @@
#include <zinnia/atomic.h>
#include <zinnia/irq.h>
#include <zinnia/percpu.h>
#include <arch/irq.h>
#include <stdatomic.h>
void irq_set_state(bool state) {
arch_irq_set_state(state);
@@ -17,19 +17,19 @@ void irq_wait() {
void irq_lock() {
struct irq_percpu* cpu = &percpu_get()->irq;
if (atomic_load_explicit(&cpu->in_interrupt, memory_order_acquire))
if (atomic_load(&cpu->in_interrupt, ATOMIC_ACQUIRE))
return;
arch_irq_set_state(false);
atomic_fetch_add_explicit(&percpu_get()->irq.level, 1, memory_order_acq_rel);
atomic_fetch_add(&percpu_get()->irq.level, 1, ATOMIC_ACQ_REL);
}
void irq_unlock() {
struct irq_percpu* cpu = &percpu_get()->irq;
if (atomic_load_explicit(&cpu->in_interrupt, memory_order_acquire))
if (atomic_load(&cpu->in_interrupt, ATOMIC_ACQUIRE))
return;
uint32_t old_level = atomic_fetch_sub_explicit(&cpu->level, 1, memory_order_acq_rel);
uint32_t old_level = atomic_fetch_sub(&cpu->level, 1, ATOMIC_ACQ_REL);
// If it was 1, the new IRQ level is now 0.
if (old_level == 1) {
arch_irq_set_state(true);
@@ -37,5 +37,5 @@ void irq_unlock() {
}
bool irq_set_interrupted(bool is_interrupted) {
return atomic_exchange_explicit(&percpu_get()->irq.in_interrupt, is_interrupted, memory_order_release);
return atomic_exchange(&percpu_get()->irq.in_interrupt, is_interrupted, ATOMIC_RELEASE);
}
+1
View File
@@ -1,5 +1,6 @@
# Freestanding libc functions that are needed in the kernel
kernel_sources += files(
'stdlib.c',
'string.c',
)
+102
View File
@@ -0,0 +1,102 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
static void reverse(char* s) {
int i, j;
char c;
for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
static int char_to_digit(char c) {
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'z')
return c - 'a' + 10;
if (c >= 'A' && c <= 'Z')
return c - 'A' + 10;
return -1;
}
unsigned long atolu(const char* str, int base) {
unsigned long result = 0;
if (base == 16 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
str += 2;
}
while (*str) {
int digit = char_to_digit(*str++);
if (digit < 0 || digit >= base)
break;
result = result * base + digit;
}
return result;
}
long atol(const char* str, int base) {
int neg = 0;
if (*str == '-') {
neg = 1;
str++;
}
unsigned long val = atolu(str, base);
return neg ? -(long)val : (long)val;
}
char* lutoa(uint64_t value, char* str, int base) {
if (base < 2 || base > 36)
return nullptr;
size_t i = 0;
do {
uint64_t digit = value % base;
str[i++] = (digit < 10) ? '0' + digit : 'a' + (digit - 10);
value /= base;
} while (value);
str[i] = '\0';
reverse(str);
return str;
}
char* ltoa(int64_t value, char* str, int base) {
if (base < 2 || base > 36)
return nullptr;
uint64_t magnitude;
int negative = 0;
if (value < 0) {
negative = 1;
magnitude = (uint64_t)(-(value + 1)) + 1;
// avoids INT64_MIN overflow
} else {
magnitude = (uint64_t)value;
}
size_t i = 0;
do {
uint64_t digit = magnitude % base;
str[i++] = (digit < 10) ? '0' + digit : 'a' + (digit - 10);
magnitude /= base;
} while (magnitude);
if (negative)
str[i++] = '-';
str[i] = '\0';
reverse(str);
return str;
}
+7 -8
View File
@@ -23,7 +23,7 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_
const size_t pgsz = arch_mem_page_size();
log("mem", "Memory map:\n");
log("mem: Memory map:\n");
for (size_t i = 0; i < map_len; i++) {
if (map[i].length == 0)
continue;
@@ -44,7 +44,7 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_
break;
}
log("mem", "[%p - %p] %s\n", (void*)map[i].address, (void*)(map[i].address + map[i].length - 1), label);
log("mem: [%p - %p] %s\n", (void*)map[i].address, (void*)(map[i].address + map[i].length - 1), label);
}
// Set up the bootstrap allocator.
@@ -54,8 +54,7 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_
largest = &map[i];
}
mem_phys_bootstrap(largest);
log("mem",
"Using region [%p - %p] for bootstrap allocator\n",
log("mem: Using region [%p - %p] for bootstrap allocator\n",
(void*)largest->address,
(void*)(largest->address + largest->length - 1));
@@ -67,7 +66,7 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_
assert(pmap_new_kernel(&kernel_vma.pmap, 0) == 0, "Unable to allocate the kernel page table\n");
// text
log("mem", "Mapping text segment at %p\n", __ld_text_start);
log("mem: Mapping text segment at %p\n", __ld_text_start);
for (uint8_t* p = __ld_text_start; p <= __ld_text_end; p += pgsz) {
errno_t status = pmap_map(
&kernel_vma.pmap,
@@ -80,7 +79,7 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_
}
// rodata
log("mem", "Mapping rodata segment at %p\n", __ld_rodata_start);
log("mem: Mapping rodata segment at %p\n", __ld_rodata_start);
for (uint8_t* p = __ld_rodata_start; p < __ld_rodata_end; p += pgsz) {
errno_t status = pmap_map(
&kernel_vma.pmap,
@@ -93,7 +92,7 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_
}
// data
log("mem", "Mapping data segment at %p\n", __ld_data_start);
log("mem: Mapping data segment at %p\n", __ld_data_start);
for (uint8_t* p = __ld_data_start; p < __ld_data_end; p += pgsz) {
errno_t status = pmap_map(
&kernel_vma.pmap,
@@ -161,5 +160,5 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_
slab_init();
log("mem", "Memory initialization complete\n");
log("mem: Memory initialization complete\n");
}
+2 -2
View File
@@ -15,7 +15,7 @@ errno_t pmap_new_kernel(struct pmap* pt, enum alloc_flags flags) {
struct pmap result = {
.root = addr,
.lock = (spinlock_t){0},
.lock = (struct spinlock){0},
.is_user = false,
};
@@ -35,7 +35,7 @@ errno_t pmap_new_user(struct pmap* pt, enum alloc_flags flags) {
struct pmap result = {
.root = user_l1,
.lock = (spinlock_t){0},
.lock = (struct spinlock){0},
.is_user = true,
};
+4 -5
View File
@@ -56,7 +56,7 @@ void mem_phys_bootstrap(struct phys_mem* mem) {
}
static struct page* pmm_head = nullptr;
static spinlock_t pmm_lock = {0};
static struct spinlock pmm_lock = {0};
static size_t pmm_total_free = 0;
static errno_t freelist_alloc(size_t num_pages, enum alloc_flags flags, phys_t* out) {
@@ -84,11 +84,10 @@ static errno_t freelist_alloc(size_t num_pages, enum alloc_flags flags, phys_t*
// If the current block has exactly enough pages left, consume it entirely.
if (__unlikely(it->freelist.count == num_pages)) {
if (prev_it) {
if (prev_it)
prev_it->freelist.next = it->freelist.next;
} else {
else
pmm_head = it->freelist.next;
}
it->freelist.next = nullptr;
it->freelist.count = 0;
@@ -150,5 +149,5 @@ void mem_phys_init(struct phys_mem* map, size_t length) {
}
const size_t free_bytes = (pmm_total_free * arch_mem_page_size());
log("pmm", "Total available memory: %zu MiB\n", free_bytes / 1024 / 1024);
log("pmm: Total available memory: %zu MiB\n", free_bytes / 1024 / 1024);
}
+3 -3
View File
@@ -10,8 +10,8 @@ typedef struct {
} slab_info;
struct slab {
spinlock_t lock; // Access lock.
size_t ent_size; // Size of one entry.
struct spinlock lock; // Access lock.
size_t ent_size; // Size of one entry.
void** head;
};
@@ -24,7 +24,7 @@ typedef struct {
static struct slab slabs[8] = {0};
static errno_t slab_new(struct slab* slab, size_t size) {
slab->lock = (spinlock_t){0};
slab->lock = (struct spinlock){0};
// Allocate a new page for the head.
phys_t addr;
+2 -3
View File
@@ -1,7 +1,7 @@
#include <zinnia/alloc.h>
#include <zinnia/atomic.h>
#include <zinnia/utils.h>
#include <zinnia/virt.h>
#include <stdatomic.h>
#include <stddef.h>
struct page* vm_pfndb = nullptr;
@@ -12,8 +12,7 @@ static size_t mapping_offset = 0;
uintptr_t vm_alloc(size_t length) {
uintptr_t base = arch_mem_mapping_addr();
size_t offset =
atomic_fetch_add_explicit(&mapping_offset, ALIGN_UP(length, arch_mem_page_size()), memory_order_acquire);
size_t offset = atomic_fetch_add(&mapping_offset, ALIGN_UP(length, arch_mem_page_size()), ATOMIC_ACQUIRE);
return base + offset;
}
+1 -1
View File
@@ -2,12 +2,12 @@ kernel_sources += files(
'clock.c',
'console.c',
'elf.c',
'futex.c',
'irq.c',
'panic.c',
'percpu.c',
'print.c',
'spin.c',
'wait.c',
)
subdir('lib')
+1 -1
View File
@@ -2,7 +2,7 @@
#include <zinnia/percpu.h>
#include <arch/percpu.h>
[[__used, __section(".percpu")]]
[[__percpu]]
struct percpu percpu_bsp = {
.self = &percpu_bsp,
.id = 0,
+1 -99
View File
@@ -5,107 +5,9 @@
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
static void reverse(char* s) {
int i, j;
char c;
for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
static int char_to_digit(char c) {
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'z')
return c - 'a' + 10;
if (c >= 'A' && c <= 'Z')
return c - 'A' + 10;
return -1;
}
unsigned long atolu(const char* str, int base) {
unsigned long result = 0;
if (base == 16 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
str += 2;
}
while (*str) {
int digit = char_to_digit(*str++);
if (digit < 0 || digit >= base)
break;
result = result * base + digit;
}
return result;
}
long atol(const char* str, int base) {
int neg = 0;
if (*str == '-') {
neg = 1;
str++;
}
unsigned long val = atolu(str, base);
return neg ? -(long)val : (long)val;
}
char* lutoa(uint64_t value, char* str, int base) {
if (base < 2 || base > 36)
return nullptr;
size_t i = 0;
do {
uint64_t digit = value % base;
str[i++] = (digit < 10) ? '0' + digit : 'a' + (digit - 10);
value /= base;
} while (value);
str[i] = '\0';
reverse(str);
return str;
}
char* ltoa(int64_t value, char* str, int base) {
if (base < 2 || base > 36)
return nullptr;
uint64_t magnitude;
int negative = 0;
if (value < 0) {
negative = 1;
magnitude = (uint64_t)(-(value + 1)) + 1;
// avoids INT64_MIN overflow
} else {
magnitude = (uint64_t)value;
}
size_t i = 0;
do {
uint64_t digit = magnitude % base;
str[i++] = (digit < 10) ? '0' + digit : 'a' + (digit - 10);
magnitude /= base;
} while (magnitude);
if (negative)
str[i++] = '-';
str[i] = '\0';
reverse(str);
return str;
}
typedef void (*log_fn_t)(void* ctx, const char* buf, size_t len);
static void do_print(log_fn_t callback, void* ctx, const char* restrict fmt, va_list args) {
+1
View File
@@ -0,0 +1 @@
#include <zinnia/sched.h>
+1
View File
@@ -1,3 +1,4 @@
kernel_sources += files(
'core.c',
'sched_dumb.c',
)
+15 -56
View File
@@ -1,5 +1,6 @@
#include <zinnia/alloc.h>
#include <zinnia/assert.h>
#include <zinnia/atomic.h>
#include <zinnia/errno.h>
#include <zinnia/irq.h>
#include <zinnia/list.h>
@@ -10,7 +11,7 @@
#include <zinnia/spin.h>
#include <zinnia/tailq.h>
#include <zinnia/vma.h>
#include <stdatomic.h>
#include <arch/sched.h>
#include <stdint.h>
#include <string.h>
@@ -34,7 +35,7 @@ void sched_to_user_context(uintptr_t ctx) {
arch_sched_jump_to_context((struct arch_context*)ctx);
}
void sched_init(struct sched_percpu* sched) {
void sched_init(struct scheduler* sched) {
struct task* idle_task;
assert(task_create("idle", &kernel_vma, idle_func, 0, &idle_task) == 0, "Unable to create idle task!\n");
sched->idle_task = idle_task;
@@ -42,15 +43,15 @@ void sched_init(struct sched_percpu* sched) {
tailq_init(&sched->run_queue);
log("sched", "Scheduler initialized\n");
log("sched: Scheduler initialized\n");
}
void sched_add_task(struct sched_percpu* sched, struct task* task) {
void sched_add_task(struct scheduler* sched, struct task* task) {
assert(task != nullptr, "Tried to add NULL to the run queue\n");
tailq_insert_tail(&sched->run_queue, task, next);
}
static struct task* next_task(struct sched_percpu* sched) {
static struct task* next_task(struct scheduler* sched) {
struct task* t = tailq_first(&sched->run_queue);
if (t == nullptr)
@@ -61,17 +62,17 @@ static struct task* next_task(struct sched_percpu* sched) {
return t;
}
static void do_reschedule(struct sched_percpu* sched) {
struct task* from = atomic_load_explicit(&sched->current, memory_order_acquire);
static void do_reschedule(struct scheduler* sched) {
struct task* from = sched->current;
struct task* to = next_task(sched);
// We'd end up on the same task, skip switching altogether.
if (from == to) {
irq_unlock();
return;
}
atomic_store_explicit(&sched->current, to, memory_order_relaxed);
sched->current = to;
pmap_set(&to->space->pmap);
struct percpu* cpu = percpu_get();
@@ -80,17 +81,17 @@ static void do_reschedule(struct sched_percpu* sched) {
cpu->kernel_stack = to->kernel_stack;
cpu->user_stack = to->user_stack;
arch_sched_switch(from, to);
struct task* old = arch_sched_switch(from, to);
}
void sched_reschedule(struct sched_percpu* sched) {
void sched_reschedule(struct scheduler* sched) {
irq_lock();
if (sched->current->state != TASK_STATE_DEAD)
sched_add_task(sched, sched->current);
do_reschedule(sched);
}
void sched_yield(struct sched_percpu* sched) {
void sched_yield(struct scheduler* sched) {
irq_lock();
do_reschedule(sched);
}
@@ -104,7 +105,7 @@ errno_t task_create(const char* name, struct vma* space, task_fn_t entry, uintpt
return ENOMEM;
static size_t last_tid = 0;
new_task->id = atomic_fetch_add(&last_tid, 1);
new_task->id = atomic_fetch_add(&last_tid, 1, ATOMIC_ACQUIRE);
new_task->space = space;
strncpy(new_task->name, name, sizeof(new_task->name));
@@ -126,50 +127,8 @@ errno_t task_create(const char* name, struct vma* space, task_fn_t entry, uintpt
void task_entry(task_fn_t entry, uintptr_t arg0) {
entry(arg0);
struct sched_percpu* sched = &percpu_get()->sched;
struct scheduler* sched = &percpu_get()->sched;
sched->current->state = TASK_STATE_DEAD;
sched_yield(sched);
panic("unreachable");
}
void wait_queue_init(struct wait_queue* wq) {
tailq_init(&wq->waiters);
wq->lock = (spinlock_t){0};
}
void sched_block(struct sched_percpu* sched, struct wait_queue* wq) {
irq_lock();
spin_lock(&wq->lock);
sched->current->state = TASK_STATE_BLOCKED;
tailq_insert_tail(&wq->waiters, sched->current, next);
spin_unlock(&wq->lock);
do_reschedule(sched);
}
void sched_wake(struct sched_percpu* sched, struct wait_queue* wq) {
spin_lock(&wq->lock);
struct task* t = tailq_first(&wq->waiters);
if (t != nullptr) {
tailq_remove(&wq->waiters, t, next);
t->state = TASK_STATE_READY;
sched_add_task(sched, t);
}
spin_unlock(&wq->lock);
}
void sched_wake_all(struct sched_percpu* sched, struct wait_queue* wq) {
spin_lock(&wq->lock);
struct task* t;
while ((t = tailq_first(&wq->waiters)) != nullptr) {
tailq_remove(&wq->waiters, t, next);
t->state = TASK_STATE_READY;
sched_add_task(sched, t);
}
spin_unlock(&wq->lock);
}
+7 -7
View File
@@ -1,15 +1,15 @@
#include <zinnia/atomic.h>
#include <zinnia/spin.h>
#include <stdatomic.h>
void spin_lock(spinlock_t* spin) {
uint32_t my = atomic_fetch_add_explicit(&spin->next, 1, memory_order_relaxed);
void spin_lock(struct spinlock* spin) {
uint32_t my = atomic_fetch_add(&spin->next, 1, ATOMIC_RELAXED);
while (atomic_load_explicit(&spin->owner, memory_order_acquire) != my) {
while (atomic_load(&spin->owner, ATOMIC_ACQUIRE) != my) {
asm volatile("pause");
}
}
void spin_unlock(spinlock_t* spin) {
uint32_t val = atomic_load_explicit(&spin->owner, memory_order_relaxed);
atomic_store_explicit(&spin->owner, val + 1, memory_order_release);
void spin_unlock(struct spinlock* spin) {
uint32_t val = atomic_load(&spin->owner, ATOMIC_RELAXED);
atomic_store(&spin->owner, val + 1, ATOMIC_RELEASE);
}
+7 -146
View File
@@ -3,157 +3,18 @@
#include <zinnia/print.h>
#include <zinnia/sched.h>
#include <zinnia/syscall.h>
#include <zinnia/syscall_list.h>
#include <zinnia/types.h>
#include <zinnia/utils.h>
#include <bits/sched.h>
// Declare all syscalls.
#include <zinnia/syscall_list.inc>
#undef SYSCALL_DECLARE
// Define them.
const struct syscall syscall_table[256] = {
// [0] = {sys_exit, 0},
// [1] = {sys_syslog, 0},
[2] = {sys_getuname, 0},
// [3] = {sys_setuname, 0},
[4] = {sys_archctl, 0},
// [5] = {sys_reboot, 0},
// [6] = {sys_mmap, 0},
// [7] = {sys_munmap, 0},
// [8] = {sys_mprotect, 0},
// [9] = {sys_madvise, 0},
// [10] = {sys_sigprocmask, 0},
// [11] = {sys_sigsuspend, 0},
// [12] = {sys_sigpending, 0},
// [13] = {sys_sigaction, 0},
// [14] = {sys_sigtimedwait, 0},
// [15] = {sys_sigaltstack, 0},
// [16] = {sys_sigreturn, 0},
// [17] = {sys_sigqueue, 0},
// [18] = {sys_execve, 0},
// [19] = {sys_fexecve, 0},
// [20] = {sys_fork, 0},
// [21] = {sys_kill, 0},
// [22] = {sys_gettid, 0},
// [23] = {sys_getpid, 0},
// [24] = {sys_getppid, 0},
// [25] = {sys_waitid, 0},
// [26] = {sys_waitpid, 0},
// [27] = {sys_pread, 0},
// [28] = {sys_readv, 0},
// [29] = {sys_pwrite, 0},
// [30] = {sys_writev, 0},
// [31] = {sys_seek, 0},
// [32] = {sys_ioctl, 0},
// [33] = {sys_openat, 0},
// [34] = {sys_close, 0},
// [35] = {sys_fstat, 0},
// [36] = {sys_fstatat, 0},
// [37] = {sys_statvfs, 0},
// [38] = {sys_fstatvfs, 0},
// [39] = {sys_faccessat, 0},
// [40] = {sys_fcntl, 0},
// [41] = {sys_ftruncate, 0},
// [42] = {sys_truncate, 0},
// [43] = {sys_fallocate, 0},
// [44] = {sys_fadvise, 0},
// [45] = {sys_utimensat, 0},
// [46] = {sys_mknodat, 0},
// [47] = {sys_getcwd, 0},
// [48] = {sys_chdir, 0},
// [49] = {sys_fchdir, 0},
// [50] = {sys_mkdirat, 0},
// [51] = {sys_rmdirat, 0},
// [52] = {sys_getdents, 0},
// [53] = {sys_renameat, 0},
// [54] = {sys_fchmod, 0},
// [55] = {sys_fchmodat, 0},
// [56] = {sys_fchownat, 0},
// [57] = {sys_linkat, 0},
// [58] = {sys_symlinkat, 0},
// [59] = {sys_unlinkat, 0},
// [60] = {sys_readlinkat, 0},
// [61] = {sys_flock, 0},
// [62] = {sys_ppoll, 0},
// [63] = {sys_dup, 0},
// [64] = {sys_dup3, 0},
// [65] = {sys_sync, 0},
// [66] = {sys_fsync, 0},
// [67] = {sys_fdatasync, 0},
// [68] = {sys_getgroups, 0},
// [69] = {sys_setgroups, 0},
// [70] = {sys_getsid, 0},
// [71] = {sys_setsid, 0},
// [72] = {sys_setuid, 0},
// [73] = {sys_getuid, 0},
// [74] = {sys_setgid, 0},
// [75] = {sys_getgid, 0},
// [76] = {sys_geteuid, 0},
// [77] = {sys_seteuid, 0},
// [78] = {sys_getegid, 0},
// [79] = {sys_setegid, 0},
// [80] = {sys_getpgid, 0},
// [81] = {sys_setpgid, 0},
// [82] = {sys_getresuid, 0},
// [83] = {sys_setresuid, 0},
// [84] = {sys_getresgid, 0},
// [85] = {sys_setresgid, 0},
// [86] = {sys_setreuid, 0},
// [87] = {sys_setregid, 0},
// [88] = {sys_umask, 0},
// [89] = {sys_pipe, 0},
// [90] = {sys_futex_wait, 0},
// [91] = {sys_futex_wake, 0},
// [92] = {sys_thread_create, 0},
// [93] = {sys_thread_kill, 0},
// [94] = {sys_thread_exit, 0},
// [95] = {sys_thread_setname, 0},
// [96] = {sys_thread_getname, 0},
// [97] = {sys_timer_create, 0},
// [98] = {sys_timer_set, 0},
// [99] = {sys_timer_get, 0},
// [100] = {sys_timer_getoverrun, 0},
// [101] = {sys_timer_delete, 0},
// [102] = {sys_itimer_get, 0},
// [103] = {sys_itimer_set, 0},
// [104] = {sys_clock_get, 0},
// [105] = {sys_clock_getres, 0},
// [106] = {sys_clock_set, 0},
// [107] = {sys_sleep, 0},
// [108] = {sys_yield, 0},
// [109] = {sys_chroot, 0},
// [110] = {sys_mount, 0},
// [111] = {sys_umount, 0},
// [112] = {sys_socket, 0},
// [113] = {sys_socketpair, 0},
// [114] = {sys_shutdown, 0},
// [115] = {sys_bind, 0},
// [116] = {sys_connect, 0},
// [117] = {sys_accept, 0},
// [118] = {sys_listen, 0},
// [119] = {sys_getpeername, 0},
// [120] = {sys_getsockname, 0},
// [121] = {sys_getsockopt, 0},
// [122] = {sys_setsockopt, 0},
// [123] = {sys_sendmsg, 0},
// [124] = {sys_recvmsg, 0},
// [125] = {sys_getentropy, 0},
// [126] = {sys_getrusage, 0},
// [127] = {sys_getrlimit, 0},
// [128] = {sys_setrlimit, 0},
// [129] = {sys_getpriority, 0},
// [130] = {sys_setpriority, 0},
// [131] = {sys_sched_getparam, 0},
// [132] = {sys_sched_setparam, 0},
// [133] = {sys_module_insert, 0},
// [134] = {sys_module_remove, 0},
// [135] = {sys_epoll_create, 0},
// [136] = {sys_epoll_ctl, 0},
// [137] = {sys_epoll_pwait, 0},
// [138] = {sys_timerfd_create, 0},
// [139] = {sys_timerfd_gettime, 0},
// [140] = {sys_timerfd_settime, 0},
// [141] = {sys_signalfd_create, 0},
// [142] = {sys_eventfd_create, 0},
// [143] = {sys_msync, 0},
// [144] = {sys_sysconf, 0},
#define SYSCALL_DECLARE(number, name, num_args) [number] = {sys_##name, num_args},
#include <zinnia/syscall_list.inc>
};
[[gnu::no_caller_saved_registers]]
-17
View File
@@ -1,17 +0,0 @@
#include <zinnia/errno.h>
#include <zinnia/futex.h>
#include <zinnia/syscall.h>
errno_t syscall_futex_wait(struct arch_context* ctx) {
__user int* addr = (__user int*)ctx->ARCH_CTX_A0;
int expected = (int)ctx->ARCH_CTX_A1;
return futex_wait(addr, expected);
}
errno_t syscall_futex_wake(struct arch_context* ctx) {
__user int* addr = (__user int*)ctx->ARCH_CTX_A0;
int count = (int)ctx->ARCH_CTX_A1;
return futex_wake(addr, count);
}
+1 -1
View File
@@ -4,7 +4,7 @@
#include <config.h>
#include <uapi/utsname.h>
static spinlock_t uname_lock = {};
static struct spinlock uname_lock = {};
static struct utsname uname_buf = {
.sysname = "Zinnia",
-1
View File
@@ -1,6 +1,5 @@
kernel_sources += files(
'archctl.c',
'dispatch.c',
'futex.c',
'getuname.c',
)
+17
View File
@@ -0,0 +1,17 @@
#include <zinnia/waitq.h>
void waitq_init(struct waitq* wq) {
tailq_init(&wq->waiters);
}
void waitq_wait(struct waitq* wq) {
// TODO
}
void waitq_wake_one(struct waitq* wq) {
// TODO
}
void waitq_wake_all(struct waitq* wq) {
// TODO
}