refactor(kernel): use linux-style errno returns
This commit is contained in:
parent
78bc6b70cf
commit
9cab2673af
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <tianole/arch.h>
|
#include <tianole/arch.h>
|
||||||
#include <tianole/early_log.h>
|
#include <tianole/early_log.h>
|
||||||
|
#include <tianole/errno.h>
|
||||||
#include <tianole/irq.h>
|
#include <tianole/irq.h>
|
||||||
#include <tianole/timer.h>
|
#include <tianole/timer.h>
|
||||||
|
|
||||||
@ -102,14 +103,14 @@ int irq_register(uint8_t irq, irq_handler_t handler, void *data)
|
|||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
|
|
||||||
if (irq >= IRQ_COUNT || handler == 0) {
|
if (irq >= IRQ_COUNT || handler == 0) {
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = arch_irq_save();
|
flags = arch_irq_save();
|
||||||
|
|
||||||
if (irq_actions[irq].handler != 0) {
|
if (irq_actions[irq].handler != 0) {
|
||||||
arch_irq_restore(flags);
|
arch_irq_restore(flags);
|
||||||
return -1;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
irq_actions[irq].handler = handler;
|
irq_actions[irq].handler = handler;
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <tianole/arch.h>
|
#include <tianole/arch.h>
|
||||||
#include <tianole/early_log.h>
|
#include <tianole/early_log.h>
|
||||||
|
#include <tianole/errno.h>
|
||||||
#include <tianole/mm.h>
|
#include <tianole/mm.h>
|
||||||
|
|
||||||
#include "page_table.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();
|
page = alloc_page();
|
||||||
if (page == 0) {
|
if (page == 0) {
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_page(page);
|
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);
|
uint64_t pt_index = table_index(virt, 12);
|
||||||
|
|
||||||
if (create != 0) {
|
if (create != 0) {
|
||||||
if (ensure_next_table(pml4, pml4_index, &pdpt) != 0 ||
|
int ret = ensure_next_table(pml4, pml4_index, &pdpt);
|
||||||
ensure_next_table(pdpt, pdpt_index, &pd) != 0 ||
|
|
||||||
ensure_next_table(pd, pd_index, &pt) != 0) {
|
if (ret != 0) {
|
||||||
return -1;
|
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 {
|
} else {
|
||||||
if ((pml4[pml4_index] & PAGE_PRESENT) == 0) {
|
if ((pml4[pml4_index] & PAGE_PRESENT) == 0) {
|
||||||
return -1;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
pdpt = entry_table(pml4[pml4_index]);
|
pdpt = entry_table(pml4[pml4_index]);
|
||||||
|
|
||||||
if ((pdpt[pdpt_index] & PAGE_PRESENT) == 0) {
|
if ((pdpt[pdpt_index] & PAGE_PRESENT) == 0) {
|
||||||
return -1;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
pd = entry_table(pdpt[pdpt_index]);
|
pd = entry_table(pdpt[pdpt_index]);
|
||||||
|
|
||||||
if ((pd[pd_index] & PAGE_PRESENT) == 0) {
|
if ((pd[pd_index] & PAGE_PRESENT) == 0) {
|
||||||
return -1;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
pt = entry_table(pd[pd_index]);
|
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)
|
int map_page(virt_addr_t virt, phys_addr_t phys, uint64_t flags)
|
||||||
{
|
{
|
||||||
uint64_t *entry;
|
uint64_t *entry;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if ((virt & (PAGE_SIZE - 1)) != 0 || (phys & (PAGE_SIZE - 1)) != 0) {
|
if ((virt & (PAGE_SIZE - 1)) != 0 || (phys & (PAGE_SIZE - 1)) != 0) {
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_entry(virt, 1, &entry) != 0) {
|
ret = page_entry(virt, 1, &entry);
|
||||||
return -1;
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*entry & PAGE_PRESENT) != 0) {
|
if ((*entry & PAGE_PRESENT) != 0) {
|
||||||
return -1;
|
return -EEXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
*entry = (phys & PAGE_MASK) | flags | PAGE_PRESENT;
|
*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)
|
int unmap_page(virt_addr_t virt)
|
||||||
{
|
{
|
||||||
uint64_t *entry;
|
uint64_t *entry;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if ((virt & (PAGE_SIZE - 1)) != 0) {
|
if ((virt & (PAGE_SIZE - 1)) != 0) {
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_entry(virt, 0, &entry) != 0 || (*entry & PAGE_PRESENT) == 0) {
|
ret = page_entry(virt, 0, &entry);
|
||||||
return -1;
|
if (ret != 0 || (*entry & PAGE_PRESENT) == 0) {
|
||||||
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
*entry = 0;
|
*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)
|
int virt_to_phys(virt_addr_t virt, phys_addr_t *phys)
|
||||||
{
|
{
|
||||||
uint64_t *entry;
|
uint64_t *entry;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (phys == 0 || page_entry(virt, 0, &entry) != 0 ||
|
if (phys == 0) {
|
||||||
(*entry & PAGE_PRESENT) == 0) {
|
return -EINVAL;
|
||||||
return -1;
|
}
|
||||||
|
|
||||||
|
ret = page_entry(virt, 0, &entry);
|
||||||
|
if (ret != 0 || (*entry & PAGE_PRESENT) == 0) {
|
||||||
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
*phys = (*entry & PAGE_MASK) | (virt & (PAGE_SIZE - 1));
|
*phys = (*entry & PAGE_MASK) | (virt & (PAGE_SIZE - 1));
|
||||||
|
|||||||
@ -83,3 +83,11 @@
|
|||||||
- 新增或大改 C/H 文件后运行 `clang-format`。
|
- 新增或大改 C/H 文件后运行 `clang-format`。
|
||||||
- 提交前至少运行 `scripts/check.sh`。
|
- 提交前至少运行 `scripts/check.sh`。
|
||||||
- 如果只是文档修改,至少运行 `git diff --check`。
|
- 如果只是文档修改,至少运行 `git diff --check`。
|
||||||
|
|
||||||
|
## 错误码
|
||||||
|
|
||||||
|
- 可恢复的内核内部错误优先返回 Linux 风格的负 errno,例如
|
||||||
|
`-EINVAL`、`-ENOMEM`、`-ENOENT`、`-EBUSY`、`-EEXIST`、`-ETIMEDOUT`。
|
||||||
|
- 不要用裸 `-1` 表达多个失败原因;调用者需要能区分输入错误、资源耗尽、
|
||||||
|
对象已存在和超时。
|
||||||
|
- errno 常量放在 `include/tianole/errno.h`,只增加当前内核实际使用的值。
|
||||||
|
|||||||
34
include/tianole/errno.h
Normal file
34
include/tianole/errno.h
Normal 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
|
||||||
@ -3,6 +3,11 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#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);
|
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.
|
* @handler: Function called when the IRQ is dispatched.
|
||||||
* @data: Opaque handler data passed back during dispatch.
|
* @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);
|
int irq_register(uint8_t irq, irq_handler_t handler, void *data);
|
||||||
|
|
||||||
|
|||||||
@ -85,7 +85,7 @@ void kfree(void *ptr);
|
|||||||
* @phys: Physical page address.
|
* @phys: Physical page address.
|
||||||
* @flags: Generic page flags such as PAGE_WRITABLE.
|
* @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);
|
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.
|
* unmap_page() - Remove one virtual page mapping.
|
||||||
* @virt: Virtual page address to unmap.
|
* @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);
|
int unmap_page(virt_addr_t virt);
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ int unmap_page(virt_addr_t virt);
|
|||||||
* @virt: Virtual address to query.
|
* @virt: Virtual address to query.
|
||||||
* @phys: Output storage for the resolved physical address.
|
* @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);
|
int virt_to_phys(virt_addr_t virt, phys_addr_t *phys);
|
||||||
|
|
||||||
|
|||||||
@ -175,7 +175,7 @@ void wait_queue_sleep(struct wait_queue *queue);
|
|||||||
* @condition: Predicate checked before and after sleeping.
|
* @condition: Predicate checked before and after sleeping.
|
||||||
* @arg: Opaque predicate argument.
|
* @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(
|
int wait_queue_wait(
|
||||||
struct wait_queue *queue, wait_condition_t condition, void *arg);
|
struct wait_queue *queue, wait_condition_t condition, void *arg);
|
||||||
@ -187,7 +187,7 @@ int wait_queue_wait(
|
|||||||
* @arg: Opaque predicate argument.
|
* @arg: Opaque predicate argument.
|
||||||
* @ticks: Maximum number of timer ticks to wait.
|
* @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,
|
int wait_queue_wait_timeout(struct wait_queue *queue,
|
||||||
wait_condition_t condition,
|
wait_condition_t condition,
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#include <tianole/errno.h>
|
||||||
#include <tianole/sched.h>
|
#include <tianole/sched.h>
|
||||||
|
|
||||||
#include "sched.h"
|
#include "sched.h"
|
||||||
@ -15,7 +16,7 @@ int sched_idle_create(void)
|
|||||||
{
|
{
|
||||||
idle_thread = kernel_thread_create("idle", idle_thread_entry, 0);
|
idle_thread = kernel_thread_create("idle", idle_thread_entry, 0);
|
||||||
if (idle_thread == 0) {
|
if (idle_thread == 0) {
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#include <tianole/errno.h>
|
||||||
#include <tianole/sched.h>
|
#include <tianole/sched.h>
|
||||||
#include <tianole/timer.h>
|
#include <tianole/timer.h>
|
||||||
|
|
||||||
@ -96,7 +97,7 @@ int wait_queue_wait(
|
|||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
|
|
||||||
if (queue == 0 || condition == 0 || current_thread == 0) {
|
if (queue == 0 || condition == 0 || current_thread == 0) {
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -127,7 +128,7 @@ int wait_queue_wait_timeout(struct wait_queue *queue,
|
|||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
|
|
||||||
if (queue == 0 || condition == 0 || current_thread == 0) {
|
if (queue == 0 || condition == 0 || current_thread == 0) {
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (condition(arg) != 0) {
|
if (condition(arg) != 0) {
|
||||||
@ -135,7 +136,7 @@ int wait_queue_wait_timeout(struct wait_queue *queue,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ticks == 0) {
|
if (ticks == 0) {
|
||||||
return -1;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
deadline = timer_ticks() + ticks;
|
deadline = timer_ticks() + ticks;
|
||||||
@ -152,7 +153,7 @@ int wait_queue_wait_timeout(struct wait_queue *queue,
|
|||||||
if (now >= deadline) {
|
if (now >= deadline) {
|
||||||
current_thread->wake_tick = 0;
|
current_thread->wake_tick = 0;
|
||||||
spin_unlock_irqrestore(&queue->lock, flags);
|
spin_unlock_irqrestore(&queue->lock, flags);
|
||||||
return -1;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_set_sleeping(current_thread, deadline);
|
thread_set_sleeping(current_thread, deadline);
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <tianole/early_log.h>
|
#include <tianole/early_log.h>
|
||||||
|
#include <tianole/errno.h>
|
||||||
#include <tianole/sched.h>
|
#include <tianole/sched.h>
|
||||||
#include <tianole/spinlock.h>
|
#include <tianole/spinlock.h>
|
||||||
|
|
||||||
@ -128,7 +129,7 @@ static void timeout_wait_demo_waiter(void *arg)
|
|||||||
early_log_puts("timeout waiter sleeping\n");
|
early_log_puts("timeout waiter sleeping\n");
|
||||||
if (wait_queue_wait_timeout(
|
if (wait_queue_wait_timeout(
|
||||||
&timeout_wait_queue, condition_is_ready, &never_ready, 3) !=
|
&timeout_wait_queue, condition_is_ready, &never_ready, 3) !=
|
||||||
-1) {
|
-ETIMEDOUT) {
|
||||||
panic("timeout wait did not time out");
|
panic("timeout wait did not time out");
|
||||||
}
|
}
|
||||||
early_log_puts("timeout waiter timed out\n");
|
early_log_puts("timeout waiter timed out\n");
|
||||||
|
|||||||
21
mm/heap.c
21
mm/heap.c
@ -2,6 +2,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <tianole/early_log.h>
|
#include <tianole/early_log.h>
|
||||||
|
#include <tianole/errno.h>
|
||||||
#include <tianole/mm.h>
|
#include <tianole/mm.h>
|
||||||
|
|
||||||
#define HEAP_BASE 0xffffff2000000000ull
|
#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) {
|
for (current = start; current < end; current += PAGE_SIZE) {
|
||||||
phys_addr_t page = alloc_page();
|
phys_addr_t page = alloc_page();
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (page == 0 ||
|
if (page == 0) {
|
||||||
map_page(current,
|
return -ENOMEM;
|
||||||
page,
|
}
|
||||||
PAGE_WRITABLE | PAGE_NO_EXECUTE) != 0) {
|
|
||||||
return -1;
|
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 =
|
size_t bytes =
|
||||||
align_up_size(min_size + sizeof(struct heap_block), PAGE_SIZE);
|
align_up_size(min_size + sizeof(struct heap_block), PAGE_SIZE);
|
||||||
struct heap_block *block = (struct heap_block *)(uintptr_t)heap_end;
|
struct heap_block *block = (struct heap_block *)(uintptr_t)heap_end;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (map_heap_range(heap_end, bytes) != 0) {
|
ret = map_heap_range(heap_end, bytes);
|
||||||
return -1;
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_end += bytes;
|
heap_end += bytes;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user