diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index e7700d9..f61826b 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -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; diff --git a/arch/x86/mm/page_table.c b/arch/x86/mm/page_table.c index ad584f6..74f41ec 100644 --- a/arch/x86/mm/page_table.c +++ b/arch/x86/mm/page_table.c @@ -2,6 +2,7 @@ #include #include +#include #include #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)); diff --git a/docs/agents/code-style.md b/docs/agents/code-style.md index 94d4345..931bc3c 100644 --- a/docs/agents/code-style.md +++ b/docs/agents/code-style.md @@ -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`,只增加当前内核实际使用的值。 diff --git a/include/tianole/errno.h b/include/tianole/errno.h new file mode 100644 index 0000000..7a0e5e8 --- /dev/null +++ b/include/tianole/errno.h @@ -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 diff --git a/include/tianole/irq.h b/include/tianole/irq.h index 57d7b60..063af86 100644 --- a/include/tianole/irq.h +++ b/include/tianole/irq.h @@ -3,6 +3,11 @@ #include +/** + * 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); diff --git a/include/tianole/mm.h b/include/tianole/mm.h index 5094db0..7322543 100644 --- a/include/tianole/mm.h +++ b/include/tianole/mm.h @@ -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); diff --git a/include/tianole/sched.h b/include/tianole/sched.h index ae05f94..6941e68 100644 --- a/include/tianole/sched.h +++ b/include/tianole/sched.h @@ -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, diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index c4f42e0..60bc95d 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c @@ -1,3 +1,4 @@ +#include #include #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; diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c index 7b54512..0bb65db 100644 --- a/kernel/sched/wait.c +++ b/kernel/sched/wait.c @@ -1,3 +1,4 @@ +#include #include #include @@ -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); diff --git a/kernel/selftest/sched.c b/kernel/selftest/sched.c index 5aeeab8..5b1f1d4 100644 --- a/kernel/selftest/sched.c +++ b/kernel/selftest/sched.c @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -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"); diff --git a/mm/heap.c b/mm/heap.c index 26c724d..e06839b 100644 --- a/mm/heap.c +++ b/mm/heap.c @@ -2,6 +2,7 @@ #include #include +#include #include #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;