refactor(kernel): use linux-style errno returns

This commit is contained in:
Microindole 2026-05-12 23:00:24 +08:00
parent 78bc6b70cf
commit 9cab2673af
No known key found for this signature in database
GPG Key ID: 22FB34CD2133ACA1
11 changed files with 117 additions and 39 deletions

View File

@ -5,6 +5,7 @@
#include <tianole/arch.h>
#include <tianole/early_log.h>
#include <tianole/errno.h>
#include <tianole/irq.h>
#include <tianole/timer.h>
@ -102,14 +103,14 @@ int irq_register(uint8_t irq, irq_handler_t handler, void *data)
uint64_t flags;
if (irq >= IRQ_COUNT || handler == 0) {
return -1;
return -EINVAL;
}
flags = arch_irq_save();
if (irq_actions[irq].handler != 0) {
arch_irq_restore(flags);
return -1;
return -EBUSY;
}
irq_actions[irq].handler = handler;

View File

@ -2,6 +2,7 @@
#include <tianole/arch.h>
#include <tianole/early_log.h>
#include <tianole/errno.h>
#include <tianole/mm.h>
#include "page_table.h"
@ -172,7 +173,7 @@ static int ensure_next_table(uint64_t *table, uint64_t index, uint64_t **next)
page = alloc_page();
if (page == 0) {
return -1;
return -ENOMEM;
}
clear_page(page);
@ -193,24 +194,34 @@ static int page_entry(virt_addr_t virt, int create, uint64_t **entry)
uint64_t pt_index = table_index(virt, 12);
if (create != 0) {
if (ensure_next_table(pml4, pml4_index, &pdpt) != 0 ||
ensure_next_table(pdpt, pdpt_index, &pd) != 0 ||
ensure_next_table(pd, pd_index, &pt) != 0) {
return -1;
int ret = ensure_next_table(pml4, pml4_index, &pdpt);
if (ret != 0) {
return ret;
}
ret = ensure_next_table(pdpt, pdpt_index, &pd);
if (ret != 0) {
return ret;
}
ret = ensure_next_table(pd, pd_index, &pt);
if (ret != 0) {
return ret;
}
} else {
if ((pml4[pml4_index] & PAGE_PRESENT) == 0) {
return -1;
return -ENOENT;
}
pdpt = entry_table(pml4[pml4_index]);
if ((pdpt[pdpt_index] & PAGE_PRESENT) == 0) {
return -1;
return -ENOENT;
}
pd = entry_table(pdpt[pdpt_index]);
if ((pd[pd_index] & PAGE_PRESENT) == 0) {
return -1;
return -ENOENT;
}
pt = entry_table(pd[pd_index]);
}
@ -222,17 +233,19 @@ static int page_entry(virt_addr_t virt, int create, uint64_t **entry)
int map_page(virt_addr_t virt, phys_addr_t phys, uint64_t flags)
{
uint64_t *entry;
int ret;
if ((virt & (PAGE_SIZE - 1)) != 0 || (phys & (PAGE_SIZE - 1)) != 0) {
return -1;
return -EINVAL;
}
if (page_entry(virt, 1, &entry) != 0) {
return -1;
ret = page_entry(virt, 1, &entry);
if (ret != 0) {
return ret;
}
if ((*entry & PAGE_PRESENT) != 0) {
return -1;
return -EEXIST;
}
*entry = (phys & PAGE_MASK) | flags | PAGE_PRESENT;
@ -243,13 +256,15 @@ int map_page(virt_addr_t virt, phys_addr_t phys, uint64_t flags)
int unmap_page(virt_addr_t virt)
{
uint64_t *entry;
int ret;
if ((virt & (PAGE_SIZE - 1)) != 0) {
return -1;
return -EINVAL;
}
if (page_entry(virt, 0, &entry) != 0 || (*entry & PAGE_PRESENT) == 0) {
return -1;
ret = page_entry(virt, 0, &entry);
if (ret != 0 || (*entry & PAGE_PRESENT) == 0) {
return -ENOENT;
}
*entry = 0;
@ -260,10 +275,15 @@ int unmap_page(virt_addr_t virt)
int virt_to_phys(virt_addr_t virt, phys_addr_t *phys)
{
uint64_t *entry;
int ret;
if (phys == 0 || page_entry(virt, 0, &entry) != 0 ||
(*entry & PAGE_PRESENT) == 0) {
return -1;
if (phys == 0) {
return -EINVAL;
}
ret = page_entry(virt, 0, &entry);
if (ret != 0 || (*entry & PAGE_PRESENT) == 0) {
return -ENOENT;
}
*phys = (*entry & PAGE_MASK) | (virt & (PAGE_SIZE - 1));

View File

@ -83,3 +83,11 @@
- 新增或大改 C/H 文件后运行 `clang-format`
- 提交前至少运行 `scripts/check.sh`
- 如果只是文档修改,至少运行 `git diff --check`
## 错误码
- 可恢复的内核内部错误优先返回 Linux 风格的负 errno例如
`-EINVAL`、`-ENOMEM`、`-ENOENT`、`-EBUSY`、`-EEXIST`、`-ETIMEDOUT`。
- 不要用裸 `-1` 表达多个失败原因;调用者需要能区分输入错误、资源耗尽、
对象已存在和超时。
- errno 常量放在 `include/tianole/errno.h`,只增加当前内核实际使用的值。

34
include/tianole/errno.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef TIANOLE_ERRNO_H
#define TIANOLE_ERRNO_H
/**
* EINVAL - Invalid argument.
*/
#define EINVAL 22
/**
* ENOENT - No such entry or mapping.
*/
#define ENOENT 2
/**
* ENOMEM - Out of memory.
*/
#define ENOMEM 12
/**
* EBUSY - Resource is already busy.
*/
#define EBUSY 16
/**
* EEXIST - Object already exists.
*/
#define EEXIST 17
/**
* ETIMEDOUT - Operation timed out.
*/
#define ETIMEDOUT 110
#endif

View File

@ -3,6 +3,11 @@
#include <stdint.h>
/**
* typedef irq_handler_t - External IRQ dispatch callback.
* @irq: IRQ line that triggered the callback.
* @data: Opaque pointer supplied at registration time.
*/
typedef void (*irq_handler_t)(uint8_t irq, void *data);
/**
@ -11,7 +16,7 @@ typedef void (*irq_handler_t)(uint8_t irq, void *data);
* @handler: Function called when the IRQ is dispatched.
* @data: Opaque handler data passed back during dispatch.
*
* Return: 0 on success, negative value on failure.
* Return: 0 on success, -EINVAL for bad input or -EBUSY if occupied.
*/
int irq_register(uint8_t irq, irq_handler_t handler, void *data);

View File

@ -85,7 +85,7 @@ void kfree(void *ptr);
* @phys: Physical page address.
* @flags: Generic page flags such as PAGE_WRITABLE.
*
* Return: 0 on success, negative value on failure.
* Return: 0 on success, -EINVAL, -ENOMEM or -EEXIST on failure.
*/
int map_page(virt_addr_t virt, phys_addr_t phys, uint64_t flags);
@ -93,7 +93,7 @@ int map_page(virt_addr_t virt, phys_addr_t phys, uint64_t flags);
* unmap_page() - Remove one virtual page mapping.
* @virt: Virtual page address to unmap.
*
* Return: 0 on success, negative value on failure.
* Return: 0 on success, -EINVAL or -ENOENT on failure.
*/
int unmap_page(virt_addr_t virt);
@ -102,7 +102,7 @@ int unmap_page(virt_addr_t virt);
* @virt: Virtual address to query.
* @phys: Output storage for the resolved physical address.
*
* Return: 0 when a mapping exists, negative value otherwise.
* Return: 0 when a mapping exists, -EINVAL or -ENOENT otherwise.
*/
int virt_to_phys(virt_addr_t virt, phys_addr_t *phys);

View File

@ -175,7 +175,7 @@ void wait_queue_sleep(struct wait_queue *queue);
* @condition: Predicate checked before and after sleeping.
* @arg: Opaque predicate argument.
*
* Return: 0 when the condition is true, negative value on invalid input.
* Return: 0 when the condition is true, -EINVAL on invalid input.
*/
int wait_queue_wait(
struct wait_queue *queue, wait_condition_t condition, void *arg);
@ -187,7 +187,7 @@ int wait_queue_wait(
* @arg: Opaque predicate argument.
* @ticks: Maximum number of timer ticks to wait.
*
* Return: 0 when the condition is true, negative value on timeout or error.
* Return: 0 when the condition is true, -EINVAL or -ETIMEDOUT otherwise.
*/
int wait_queue_wait_timeout(struct wait_queue *queue,
wait_condition_t condition,

View File

@ -1,3 +1,4 @@
#include <tianole/errno.h>
#include <tianole/sched.h>
#include "sched.h"
@ -15,7 +16,7 @@ int sched_idle_create(void)
{
idle_thread = kernel_thread_create("idle", idle_thread_entry, 0);
if (idle_thread == 0) {
return -1;
return -ENOMEM;
}
return 0;

View File

@ -1,3 +1,4 @@
#include <tianole/errno.h>
#include <tianole/sched.h>
#include <tianole/timer.h>
@ -96,7 +97,7 @@ int wait_queue_wait(
uint64_t flags;
if (queue == 0 || condition == 0 || current_thread == 0) {
return -1;
return -EINVAL;
}
for (;;) {
@ -127,7 +128,7 @@ int wait_queue_wait_timeout(struct wait_queue *queue,
uint64_t flags;
if (queue == 0 || condition == 0 || current_thread == 0) {
return -1;
return -EINVAL;
}
if (condition(arg) != 0) {
@ -135,7 +136,7 @@ int wait_queue_wait_timeout(struct wait_queue *queue,
}
if (ticks == 0) {
return -1;
return -ETIMEDOUT;
}
deadline = timer_ticks() + ticks;
@ -152,7 +153,7 @@ int wait_queue_wait_timeout(struct wait_queue *queue,
if (now >= deadline) {
current_thread->wake_tick = 0;
spin_unlock_irqrestore(&queue->lock, flags);
return -1;
return -ETIMEDOUT;
}
thread_set_sleeping(current_thread, deadline);

View File

@ -1,6 +1,7 @@
#include <stdint.h>
#include <tianole/early_log.h>
#include <tianole/errno.h>
#include <tianole/sched.h>
#include <tianole/spinlock.h>
@ -128,7 +129,7 @@ static void timeout_wait_demo_waiter(void *arg)
early_log_puts("timeout waiter sleeping\n");
if (wait_queue_wait_timeout(
&timeout_wait_queue, condition_is_ready, &never_ready, 3) !=
-1) {
-ETIMEDOUT) {
panic("timeout wait did not time out");
}
early_log_puts("timeout waiter timed out\n");

View File

@ -2,6 +2,7 @@
#include <stdint.h>
#include <tianole/early_log.h>
#include <tianole/errno.h>
#include <tianole/mm.h>
#define HEAP_BASE 0xffffff2000000000ull
@ -85,12 +86,16 @@ static int map_heap_range(virt_addr_t start, size_t bytes)
for (current = start; current < end; current += PAGE_SIZE) {
phys_addr_t page = alloc_page();
int ret;
if (page == 0 ||
map_page(current,
page,
PAGE_WRITABLE | PAGE_NO_EXECUTE) != 0) {
return -1;
if (page == 0) {
return -ENOMEM;
}
ret = map_page(current, page, PAGE_WRITABLE | PAGE_NO_EXECUTE);
if (ret != 0) {
free_page(page);
return ret;
}
}
@ -102,9 +107,11 @@ static int heap_extend(size_t min_size)
size_t bytes =
align_up_size(min_size + sizeof(struct heap_block), PAGE_SIZE);
struct heap_block *block = (struct heap_block *)(uintptr_t)heap_end;
int ret;
if (map_heap_range(heap_end, bytes) != 0) {
return -1;
ret = map_heap_range(heap_end, bytes);
if (ret != 0) {
return ret;
}
heap_end += bytes;