Compare commits

..

21 Commits

Author SHA1 Message Date
9a90662eaa libmango: add userspace syscall call-gates 2026-02-19 19:22:06 +00:00
1d4fd4f586 syscall: add lots of syscalls 2026-02-19 19:21:50 +00:00
dbc7b8fc59 kernel: libc: add headers 2026-02-19 19:21:15 +00:00
aa9439c392 kernel: add channel/port ipc mechanism 2026-02-19 19:21:04 +00:00
8e072945d8 kernel: add functions for moving sets of handles between tasks 2026-02-19 19:20:39 +00:00
821246bc16 kernel: add functions for iterating through an array of iovecs 2026-02-19 19:19:52 +00:00
fc8cdf62d3 bsp: adjust bsp executable mapping 2026-02-19 19:18:31 +00:00
b2dbb88778 thread: move thread awaken functionality to a dedicated function 2026-02-19 19:17:38 +00:00
9424e7bcd6 thread: fix thread object data corruption 2026-02-19 19:17:18 +00:00
4c35723959 sched: add helper functions for opening and resolving handles for a task 2026-02-19 19:16:59 +00:00
2b7e5368c9 vm: implement copying data between different vm-regions 2026-02-19 19:15:15 +00:00
85006411bd kernel: add header files 2026-02-19 19:13:44 +00:00
f2e128c57e handle: re-arrange handle space layout
the lowest 2 bits of handle values are no longer unused, and 0 is
now a valid handle value.

the first 64 handles are now reserved, and will not be automatically
allocated by the kernel. however, they are still valid handles, and
other handles can be moved to this area using an as-yet-unwritten
function. this is to allow support for standard POSIX file descriptors,
which require the values 0, 1, and 2.
2026-02-19 19:11:11 +00:00
c6e1ba21dd vm: implement direct read/write/copy access to vm-object memory 2026-02-19 19:09:38 +00:00
2f413c603d kernel: all string parameters now take a corresponding length parameter 2026-02-19 19:08:17 +00:00
291a5f677e sched: implement passing arguments to user-mode threads 2026-02-19 19:05:53 +00:00
b188573eea x86_64: pmap: change pmap_remove* pointer args to virt_addr_t 2026-02-19 19:02:28 +00:00
c69aed254f x86_64: enable interrupts during syscall execution 2026-02-19 19:00:04 +00:00
44c2904c11 x86_64: re-arrange user and kernel GDT entries for compatibility with syscall instruction 2026-02-19 18:59:37 +00:00
f89e3cb12c kernel: adjust formatting 2026-02-19 18:57:53 +00:00
6019c9307d kernel: separate headers into kernel and user headers
all kernel headers have been moved from include/mango to include/kernel
and include definitions that are only relevant to kernel-space.

any definitions that are relevant to both kernel- and user-space
(i.e. type definitions, syscall IDs) have been moved to
include/mango within libmango.
2026-02-19 18:54:48 +00:00
143 changed files with 5702 additions and 1442 deletions

View File

@@ -40,6 +40,7 @@ add_executable(${kernel_exe_name}
target_include_directories(${kernel_exe_name} PRIVATE
include
libc/include
libmango/include
arch/${kernel_arch}/include)
target_compile_options(${kernel_exe_name} PRIVATE
-nostdlib -ffreestanding

View File

@@ -1,5 +1,5 @@
#include <unistd.h>
#include <mango/machine/cpu.h>
#include <kernel/machine/cpu.h>
int ml_init_bootcpu(void)
{

View File

@@ -1,5 +1,5 @@
#include <mango/machine/hwlock.h>
#include <mango/compiler.h>
#include <kernel/machine/hwlock.h>
#include <kernel/compiler.h>
void ml_hwlock_lock(ml_hwlock_t *lck)
{

View File

@@ -1,11 +1,11 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <mango/init.h>
#include <mango/memblock.h>
#include <mango/vm.h>
#include <mango/object.h>
#include <mango/printk.h>
#include <kernel/init.h>
#include <kernel/memblock.h>
#include <kernel/vm.h>
#include <kernel/object.h>
#include <kernel/printk.h>
#include <arch/stdcon.h>
#include <sys/mman.h>

View File

@@ -1,4 +1,4 @@
#include <mango/init.h>
#include <kernel/init.h>
#ifdef __APPLE__
extern char __start_initcall0[] __asm("section$start$__DATA$__initcall0.init");

View File

@@ -1,10 +1,10 @@
#include <mango/libc/string.h>
#include <mango/libc/ctype.h>
#include <kernel/libc/string.h>
#include <kernel/libc/ctype.h>
#include <stdint.h>
#include <stdio.h>
#include <mango/console.h>
#include <mango/vm.h>
#include <mango/printk.h>
#include <kernel/console.h>
#include <kernel/vm.h>
#include <kernel/printk.h>
static void stdcon_write(struct console *con, const char *s, unsigned int len)
{

View File

@@ -1,5 +1,5 @@
#include <mango/sched.h>
#include <mango/compiler.h>
#include <kernel/sched.h>
#include <kernel/compiler.h>
//size_t THREAD_sp = offsetof(struct thread, tr_sp);

View File

@@ -1,5 +1,5 @@
#include <arch/msr.h>
#include <mango/machine/cpu.h>
#include <kernel/machine/cpu.h>
int ml_cpu_block_init(ml_cpu_block *p)
{

View File

@@ -1,8 +1,8 @@
#include "mango/types.h"
#include <mango/memblock.h>
#include <mango/printk.h>
#include <mango/util.h>
#include <arch/e820.h>
#include <kernel/memblock.h>
#include <kernel/printk.h>
#include <kernel/types.h>
#include <kernel/util.h>
void e820_scan(multiboot_memory_map_t *mmap, size_t len)
{
@@ -36,7 +36,9 @@ void e820_scan(multiboot_memory_map_t *mmap, size_t len)
}
printk("e820: [mem 0x%016llx-0x%016llx] %s",
entry->addr, entry->addr + entry->len - 1, type);
entry->addr,
entry->addr + entry->len - 1,
type);
memblock_add(entry->addr, entry->len);
@@ -53,7 +55,12 @@ void e820_scan(multiboot_memory_map_t *mmap, size_t len)
char str_mem_total[64], str_mem_reserved[64];
data_size_to_string(mem_total, str_mem_total, sizeof str_mem_total);
data_size_to_string(mem_reserved, str_mem_reserved, sizeof str_mem_reserved);
data_size_to_string(
mem_reserved,
str_mem_reserved,
sizeof str_mem_reserved);
printk("e820: total memory: %s, hw reserved: %s", str_mem_total, str_mem_reserved);
printk("e820: total memory: %s, hw reserved: %s",
str_mem_total,
str_mem_reserved);
}

View File

@@ -1,7 +1,7 @@
#include <arch/gdt.h>
#include <arch/tss.h>
#include <mango/libc/string.h>
#include <mango/types.h>
#include <kernel/libc/string.h>
#include <kernel/types.h>
#include <stddef.h>
static void init_entry(struct gdt_entry *entry, int access, int flags)
@@ -28,11 +28,11 @@ int gdt_init(struct gdt *gdt, struct gdt_ptr *gdtp)
GDT_F_64BIT);
init_entry(
&gdt->g_entries[3],
GDT_A_PRESENT | GDT_A_USER | GDT_A_CODEREAD | GDT_A_CODE,
GDT_A_PRESENT | GDT_A_USER | GDT_A_DATAWRITE | GDT_A_DATA,
GDT_F_64BIT);
init_entry(
&gdt->g_entries[4],
GDT_A_PRESENT | GDT_A_USER | GDT_A_DATAWRITE | GDT_A_DATA,
GDT_A_PRESENT | GDT_A_USER | GDT_A_CODEREAD | GDT_A_CODE,
GDT_F_64BIT);
gdtp->g_ptr = (uint64_t)gdt;

View File

@@ -2,7 +2,7 @@
#define ARCH_GDT_H_
#include <arch/tss.h>
#include <mango/compiler.h>
#include <kernel/compiler.h>
#include <stdint.h>
#ifdef __cplusplus

View File

@@ -1,8 +1,8 @@
#ifndef ARCH_IRQ_H_
#define ARCH_IRQ_H_
#include <mango/compiler.h>
#include <mango/queue.h>
#include <kernel/compiler.h>
#include <kernel/queue.h>
#include <stdint.h>
#ifdef __cplusplus

View File

@@ -1,8 +1,8 @@
#ifndef ARCH_PAGING_H_
#define ARCH_PAGING_H_
#include <mango/types.h>
#include <mango/compiler.h>
#include <kernel/types.h>
#include <kernel/compiler.h>
#ifdef __cplusplus
extern "C" {

View File

@@ -1,8 +1,8 @@
#ifndef ARCH_TSS_H_
#define ARCH_TSS_H_
#include <mango/compiler.h>
#include <mango/types.h>
#include <kernel/compiler.h>
#include <kernel/types.h>
#include <stdint.h>
#define TSS_GDT_INDEX 5

View File

@@ -1,10 +1,10 @@
#ifndef MANGO_X86_64_CPU_H_
#define MANGO_X86_64_CPU_H_
#ifndef KERNEL_X86_64_CPU_H_
#define KERNEL_X86_64_CPU_H_
#include <arch/gdt.h>
#include <arch/irq.h>
#include <arch/tss.h>
#include <mango/types.h>
#include <kernel/types.h>
#ifdef __cplusplus
extern "C" {
@@ -38,6 +38,10 @@ typedef struct ml_cpu_block {
struct cpu_data *c_data;
} ml_cpu_block;
struct ml_int_context {
uint64_t rip, cs, rflags, rsp, ss;
};
struct ml_cpu_context {
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
uint64_t rdi, rsi, rbp, unused_rsp, rbx, rdx, rcx, rax;

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_X86_64_HWLOCK_H_
#define MANGO_X86_64_HWLOCK_H_
#ifndef KERNEL_X86_64_HWLOCK_H_
#define KERNEL_X86_64_HWLOCK_H_
#define ML_HWLOCK_INIT (0)

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_X86_64_INIT_H_
#define MANGO_X86_64_INIT_H_
#ifndef KERNEL_X86_64_INIT_H_
#define KERNEL_X86_64_INIT_H_
#include <stddef.h>
#include <stdint.h>

View File

@@ -0,0 +1,5 @@
#ifndef KERNEL_X86_64_IRQ_H_
#define KERNEL_X86_64_IRQ_H_
#endif

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_X86_64_PANIC_H_
#define MANGO_X86_64_PANIC_H_
#ifndef KERNEL_X86_64_PANIC_H_
#define KERNEL_X86_64_PANIC_H_
#include <stdint.h>

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_X86_64_PMAP_H_
#define MANGO_X86_64_PMAP_H_
#ifndef KERNEL_X86_64_PMAP_H_
#define KERNEL_X86_64_PMAP_H_
#include <arch/paging.h>

View File

@@ -1,7 +1,7 @@
#ifndef MANGO_X86_64_THREAD_H_
#define MANGO_X86_64_THREAD_H_
#ifndef KERNEL_X86_64_THREAD_H_
#define KERNEL_X86_64_THREAD_H_
#include <mango/sched.h>
#include <kernel/sched.h>
struct ml_cpu_context;
@@ -21,9 +21,11 @@ extern void ml_thread_switch_user(void);
extern void ml_thread_prepare_kernel_context(uintptr_t ip, uintptr_t *sp);
/* prepare the stack so that ml_thread_switch_user can jump to usermode
* with the specified IP/user SP */
extern void ml_thread_prepare_user_context(
extern kern_status_t ml_thread_prepare_user_context(
virt_addr_t ip,
virt_addr_t user_sp,
virt_addr_t *kernel_sp);
virt_addr_t *kernel_sp,
const uintptr_t *args,
size_t nr_args);
#endif

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_X86_64_VM_H_
#define MANGO_X86_64_VM_H_
#ifndef KERNEL_X86_64_VM_H_
#define KERNEL_X86_64_VM_H_
/* kernel higher-half base virtual address. */
#define VM_KERNEL_VOFFSET 0xFFFFFFFF80000000

View File

@@ -1,5 +0,0 @@
#ifndef MANGO_X86_64_IRQ_H_
#define MANGO_X86_64_IRQ_H_
#endif

View File

@@ -2,21 +2,21 @@
#include <arch/pit.h>
#include <arch/serial.h>
#include <arch/vgacon.h>
#include <mango/arg.h>
#include <mango/bsp.h>
#include <mango/clock.h>
#include <mango/console.h>
#include <mango/cpu.h>
#include <mango/init.h>
#include <mango/libc/stdio.h>
#include <mango/machine/cpu.h>
#include <mango/memblock.h>
#include <mango/object.h>
#include <mango/percpu.h>
#include <mango/pmap.h>
#include <mango/printk.h>
#include <mango/types.h>
#include <mango/vm.h>
#include <kernel/arg.h>
#include <kernel/bsp.h>
#include <kernel/clock.h>
#include <kernel/console.h>
#include <kernel/cpu.h>
#include <kernel/init.h>
#include <kernel/libc/stdio.h>
#include <kernel/machine/cpu.h>
#include <kernel/memblock.h>
#include <kernel/object.h>
#include <kernel/percpu.h>
#include <kernel/pmap.h>
#include <kernel/printk.h>
#include <kernel/types.h>
#include <kernel/vm.h>
#define PTR32(x) ((void *)((uintptr_t)(x)))

View File

@@ -1,4 +1,4 @@
#include <mango/init.h>
#include <kernel/init.h>
extern char __initcall0_start[];
extern char __initcall1_start[];

View File

@@ -1,13 +1,13 @@
#include <arch/irq.h>
#include <arch/msr.h>
#include <arch/ports.h>
#include <mango/cpu.h>
#include <mango/libc/string.h>
#include <mango/machine/cpu.h>
#include <mango/machine/irq.h>
#include <mango/panic.h>
#include <mango/sched.h>
#include <mango/syscall.h>
#include <kernel/cpu.h>
#include <kernel/libc/string.h>
#include <kernel/machine/cpu.h>
#include <kernel/machine/irq.h>
#include <kernel/panic.h>
#include <kernel/sched.h>
#include <kernel/syscall.h>
#include <stddef.h>
#define MAX_ISR_HANDLERS 16
@@ -31,7 +31,7 @@ static uintptr_t int_entry_points[NR_IDT_ENTRIES];
static void set_syscall_gate(uintptr_t rip)
{
uint64_t user_cs = 0x13;
uint64_t kernel_cs = 0x8;
uint64_t kernel_cs = 0x08;
uintptr_t star_reg = 0xC0000081;
uintptr_t lstar_reg = 0xC0000082;
@@ -97,11 +97,7 @@ static void pf_handler(struct ml_cpu_context *regs)
virt_addr_t fault_ptr = pf_faultptr();
kern_status_t status = KERN_FATAL_ERROR;
if (regs->err_no & PF_USER) {
status = pmap_handle_fault(fault_ptr, fault_flags);
}
kern_status_t status = pmap_handle_fault(fault_ptr, fault_flags);
if (status == KERN_OK) {
return;
@@ -226,6 +222,7 @@ void syscall_dispatch(struct ml_cpu_context *regs)
SYSCALL_SIGNATURE(fn) = (SYSCALL_SIGNATURE())syscall_impl;
ml_int_enable();
regs->rax
= fn(regs->rdi,
regs->rsi,
@@ -235,6 +232,7 @@ void syscall_dispatch(struct ml_cpu_context *regs)
regs->r9,
regs->r13,
regs->r14);
ml_int_disable();
}
void hook_irq(enum irq_vector vec, struct irq_hook *hook)

View File

@@ -332,80 +332,80 @@ IRQ 223, 255
isr_common_stub:
PUSH_REGS
mov %rsp, %rdi
call isr_dispatch
POP_REGS
add $16, %rsp
iretq
.global irq_common_stub
.type irq_common_stub, @function
irq_common_stub:
PUSH_REGS
mov %rsp, %rdi
call irq_dispatch
POP_REGS
add $16, %rsp
iretq
.global syscall_gate
.type syscall_gate, @function
.extern syscall_dispatch
.type syscall_dispatch, @function
syscall_gate:
swapgs
movq %rsp, %gs:20 # GS+20 = rsp2 in the current TSS block (user stack storage)
movq %gs:4, %rsp # GS+4 = rsp0 in the current TSS block (per-thread kstack)
# start building a pf_cpu_context
# start building a ml_cpu_context
pushq $0x1b
pushq %gs:20
push %r11
push $0x23
push %rcx
pushq $0
pushq $0x80
PUSH_REGS
mov %rsp, %rdi
# switch back to user gs while in syscall_dispatch. Interrupts are enabled in syscall_dispatch,
# and if the task gets pre-empted, the incoming task will expect %gs to have its usermode value.
swapgs
call syscall_dispatch
POP_REGS
add $16, %rsp
pop %rcx
add $8, %rsp
pop %r11
add $16, %rsp
swapgs
movq %gs:20, %rsp # GS+20 = rsp2 in the current TSS block
swapgs
# back to usermode
sysretq
.global pf_faultptr
.type pf_faultptr, @function
pf_faultptr:
mov %cr2, %rax
ret

View File

@@ -1,9 +1,9 @@
#include <arch/irq.h>
#include <mango/libc/stdio.h>
#include <mango/machine/cpu.h>
#include <mango/machine/panic.h>
#include <mango/printk.h>
#include <mango/vm.h>
#include <kernel/libc/stdio.h>
#include <kernel/machine/cpu.h>
#include <kernel/machine/panic.h>
#include <kernel/printk.h>
#include <kernel/vm.h>
#define R_CF 0
#define R_PF 2

View File

@@ -1,8 +1,8 @@
#include <arch/irq.h>
#include <arch/ports.h>
#include <mango/clock.h>
#include <mango/cpu.h>
#include <mango/printk.h>
#include <kernel/clock.h>
#include <kernel/cpu.h>
#include <kernel/printk.h>
#define PIT_COUNTER0 0x40
#define PIT_CMD 0x43

View File

@@ -1,14 +1,14 @@
#include <mango/compiler.h>
#include <mango/libc/stdio.h>
#include <mango/memblock.h>
#include <mango/pmap.h>
#include <mango/printk.h>
#include <mango/sched.h>
#include <kernel/compiler.h>
#include <kernel/libc/stdio.h>
#include <kernel/memblock.h>
#include <kernel/pmap.h>
#include <kernel/printk.h>
#include <kernel/sched.h>
#include <kernel/types.h>
#include <kernel/vm-object.h>
#include <kernel/vm-region.h>
#include <kernel/vm.h>
#include <mango/status.h>
#include <mango/types.h>
#include <mango/vm-object.h>
#include <mango/vm-region.h>
#include <mango/vm.h>
/* some helpful datasize constants */
#define C_1GiB 0x40000000ULL
@@ -43,7 +43,7 @@ static pmap_t alloc_pmap(void)
return vm_virt_to_phys(p);
}
static pte_t make_pte(pfn_t pfn, enum vm_prot prot, enum page_size size)
static pte_t make_pte(pfn_t pfn, vm_prot_t prot, enum page_size size)
{
pte_t v = pfn;
@@ -139,7 +139,7 @@ static kern_status_t do_pmap_add(
pmap_t pmap,
virt_addr_t pv,
pfn_t pfn,
enum vm_prot prot,
vm_prot_t prot,
enum page_size size)
{
unsigned int pml4t_index = BAD_INDEX, pdpt_index = BAD_INDEX,
@@ -371,7 +371,7 @@ kern_status_t pmap_add(
pmap_t pmap,
virt_addr_t p,
pfn_t pfn,
enum vm_prot prot,
vm_prot_t prot,
enum pmap_flags flags)
{
enum page_size ps = PS_4K;
@@ -387,18 +387,18 @@ kern_status_t pmap_add_block(
virt_addr_t p,
pfn_t pfn,
size_t len,
enum vm_prot prot,
vm_prot_t prot,
enum pmap_flags flags)
{
return KERN_OK;
}
kern_status_t pmap_remove(pmap_t pmap, void *p)
kern_status_t pmap_remove(pmap_t pmap, virt_addr_t p)
{
return KERN_OK;
}
kern_status_t pmap_remove_range(pmap_t pmap, void *p, size_t len)
kern_status_t pmap_remove_range(pmap_t pmap, virt_addr_t p, size_t len)
{
return KERN_OK;
}

View File

@@ -1,8 +1,8 @@
#include <arch/irq.h>
#include <arch/ports.h>
#include <arch/serial.h>
#include <mango/libc/stdio.h>
#include <mango/printk.h>
#include <kernel/libc/stdio.h>
#include <kernel/printk.h>
#define COM1 0x3F8
#define COM2 0x2F8

View File

@@ -1,5 +1,13 @@
#include <mango/machine/cpu.h>
#include <mango/machine/thread.h>
#include <kernel/machine/cpu.h>
#include <kernel/machine/thread.h>
#define MAX_REG_ARGS 6
#define REG_ARG_0 rdi
#define REG_ARG_1 rsi
#define REG_ARG_2 rdx
#define REG_ARG_3 rcx
#define REG_ARG_4 r8
#define REG_ARG_5 r9
/* this is the context information restored by ml_thread_switch.
* since ml_thread_switch only jumps to kernel-mode, IRETQ isn't used,
@@ -23,19 +31,49 @@ void ml_thread_prepare_kernel_context(uintptr_t ip, uintptr_t *sp)
ctx->rfl = 0x202;
}
extern void ml_thread_prepare_user_context(
extern kern_status_t ml_thread_prepare_user_context(
virt_addr_t ip,
virt_addr_t user_sp,
virt_addr_t *kernel_sp)
virt_addr_t *kernel_sp,
const uintptr_t *args,
size_t nr_args)
{
(*kernel_sp) -= sizeof(struct ml_cpu_context);
struct ml_cpu_context *ctx = (struct ml_cpu_context *)(*kernel_sp);
memset(ctx, 0x0, sizeof *ctx);
ctx->rip = ip;
ctx->rsp = user_sp;
ctx->ss = 0x23;
ctx->cs = 0x1B;
ctx->ss = 0x1b;
ctx->cs = 0x23;
ctx->rflags = 0x202;
ctx->rdi = 0; // arg 0
ctx->rsi = 0; // arg 1
for (size_t i = 0; i < nr_args; i++) {
switch (i) {
case 0:
ctx->REG_ARG_0 = args[i];
break;
case 1:
ctx->REG_ARG_1 = args[i];
break;
case 2:
ctx->REG_ARG_2 = args[i];
break;
case 3:
ctx->REG_ARG_3 = args[i];
break;
case 4:
ctx->REG_ARG_4 = args[i];
break;
case 5:
ctx->REG_ARG_5 = args[i];
break;
default:
return KERN_INVALID_ARGUMENT;
}
}
return KERN_OK;
}

View File

@@ -2,7 +2,7 @@
#include <arch/gdt.h>
#include <arch/tss.h>
#include <mango/libc/string.h>
#include <kernel/libc/string.h>
static void tss_flush(int index)
{

View File

@@ -1,9 +1,9 @@
#include <arch/irq.h>
#include <arch/ports.h>
#include <arch/serial.h>
#include <mango/libc/stdio.h>
#include <mango/machine/vm.h>
#include <mango/printk.h>
#include <kernel/libc/stdio.h>
#include <kernel/machine/vm.h>
#include <kernel/printk.h>
struct vga_console {
uint16_t *vga_framebuffer;

View File

@@ -1,5 +1,5 @@
#include <mango/bitmap.h>
#include <mango/libc/string.h>
#include <kernel/bitmap.h>
#include <kernel/libc/string.h>
void bitmap_zero(unsigned long *map, unsigned long nbits)
{

View File

@@ -57,7 +57,7 @@
provide a comparator function.
*/
#include <mango/btree.h>
#include <kernel/btree.h>
#include <stddef.h>
#define MAX(a, b) ((a) > (b) ? (a) : (b))

View File

@@ -1,4 +1,4 @@
#include <mango/queue.h>
#include <kernel/queue.h>
size_t queue_length(struct queue *q)
{

View File

@@ -1,5 +1,5 @@
#include <mango/ringbuffer.h>
#include <mango/sched.h>
#include <kernel/ringbuffer.h>
#include <kernel/sched.h>
size_t ringbuffer_unread(struct ringbuffer *ring_buffer)
{

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_ARG_H_
#define MANGO_ARG_H_
#ifndef KERNEL_ARG_H_
#define KERNEL_ARG_H_
#include <stdbool.h>
#include <mango/status.h>

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_BITMAP_H_
#define MANGO_BITMAP_H_
#ifndef KERNEL_BITMAP_H_
#define KERNEL_BITMAP_H_
#include <stdbool.h>

View File

@@ -1,9 +1,9 @@
#ifndef MANGO_BSP_H_
#define MANGO_BSP_H_
#ifndef KERNEL_BSP_H_
#define KERNEL_BSP_H_
#include <mango/compiler.h>
#include <kernel/compiler.h>
#include <mango/status.h>
#include <mango/types.h>
#include <kernel/types.h>
#include <stddef.h>
#include <stdint.h>

View File

@@ -20,99 +20,130 @@
software without specific prior written permission.
*/
#ifndef MANGO_BTREE_H_
#define MANGO_BTREE_H_
#ifndef KERNEL_BTREE_H_
#define KERNEL_BTREE_H_
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* if your custom structure contains a struct btree_node (i.e. it can be part of a btree),
you can use this macro to convert a struct btree_node* to a your_type*
/* if your custom structure contains a struct btree_node (i.e. it can be part of
a btree), you can use this macro to convert a struct btree_node* to a
your_type*
@param t the name of your custom type (something that can be passed to offsetof)
@param m the name of the struct btree_node member variable within your custom type.
@param v the struct btree_node pointer that you wish to convert. if this is NULL, NULL will be returned.
@param t the name of your custom type (something that can be passed to
offsetof)
@param m the name of the struct btree_node member variable within your custom
type.
@param v the struct btree_node pointer that you wish to convert. if this is
NULL, NULL will be returned.
*/
#define BTREE_CONTAINER(t, m, v) ((void *)((v) ? (uintptr_t)(v) - (offsetof(t, m)) : 0))
#define BTREE_CONTAINER(t, m, v) \
((void *)((v) ? (uintptr_t)(v) - (offsetof(t, m)) : 0))
/* defines a simple node insertion function.
this function assumes that your nodes have simple integer keys that can be compared with the usual operators.
this function assumes that your nodes have simple integer keys that can be
compared with the usual operators.
EXAMPLE:
if you have a tree node type like this:
struct my_tree_node {
int key;
struct btree_node base;
struct btree_node base;
}
You would use the following call to generate an insert function for a tree with this node type:
You would use the following call to generate an insert function for a tree
with this node type:
BTREE_DEFINE_SIMPLE_INSERT(struct my_tree_node, base, key, my_tree_node_insert);
BTREE_DEFINE_SIMPLE_INSERT(struct my_tree_node, base, key,
my_tree_node_insert);
Which would emit a function defined like:
static void my_tree_node_insert(struct btree *tree, struct my_tree_node *node);
static void my_tree_node_insert(struct btree *tree, struct my_tree_node
*node);
@param node_type your custom tree node type. usually a structure that contains a struct btree_node member.
@param container_node_member the name of the struct btree_node member variable within your custom type.
@param container_key_member the name of the key member variable within your custom type.
@param node_type your custom tree node type. usually a structure that
contains a struct btree_node member.
@param container_node_member the name of the struct btree_node member
variable within your custom type.
@param container_key_member the name of the key member variable within your
custom type.
@param function_name the name of the function to generate.
*/
#define BTREE_DEFINE_SIMPLE_INSERT(node_type, container_node_member, container_key_member, function_name) \
void function_name(struct btree *tree, node_type *node) \
{ \
if (!tree->b_root) { \
tree->b_root = &node->container_node_member; \
btree_insert_fixup(tree, &node->container_node_member); \
return; \
} \
\
struct btree_node *cur = tree->b_root; \
while (1) { \
node_type *cur_node = BTREE_CONTAINER(node_type, container_node_member, cur); \
struct btree_node *next = NULL; \
\
if (node->container_key_member > cur_node->container_key_member) { \
next = btree_right(cur); \
\
if (!next) { \
btree_put_right(cur, &node->container_node_member); \
break; \
} \
} else if (node->container_key_member < cur_node->container_key_member) { \
next = btree_left(cur); \
\
if (!next) { \
btree_put_left(cur, &node->container_node_member); \
break; \
} \
} else { \
return; \
} \
\
cur = next; \
} \
\
btree_insert_fixup(tree, &node->container_node_member); \
#define BTREE_DEFINE_SIMPLE_INSERT( \
node_type, \
container_node_member, \
container_key_member, \
function_name) \
void function_name(struct btree *tree, node_type *node) \
{ \
if (!tree->b_root) { \
tree->b_root = &node->container_node_member; \
btree_insert_fixup( \
tree, \
&node->container_node_member); \
return; \
} \
\
struct btree_node *cur = tree->b_root; \
while (1) { \
node_type *cur_node = BTREE_CONTAINER( \
node_type, \
container_node_member, \
cur); \
struct btree_node *next = NULL; \
\
if (node->container_key_member \
> cur_node->container_key_member) { \
next = btree_right(cur); \
\
if (!next) { \
btree_put_right( \
cur, \
&node->container_node_member); \
break; \
} \
} else if ( \
node->container_key_member \
< cur_node->container_key_member) { \
next = btree_left(cur); \
\
if (!next) { \
btree_put_left( \
cur, \
&node->container_node_member); \
break; \
} \
} else { \
return; \
} \
\
cur = next; \
} \
\
btree_insert_fixup(tree, &node->container_node_member); \
}
/* defines a node insertion function.
this function should be used for trees with complex node keys that cannot be directly compared.
a comparator for your keys must be supplied.
this function should be used for trees with complex node keys that cannot be
directly compared. a comparator for your keys must be supplied.
EXAMPLE:
if you have a tree node type like this:
struct my_tree_node {
complex_key_t key;
struct btree_node base;
struct btree_node base;
}
You would need to define a comparator function or macro with the following signature:
You would need to define a comparator function or macro with the following
signature:
int my_comparator(struct my_tree_node *a, struct my_tree_node *b);
@@ -122,102 +153,136 @@ extern "C" {
return 0 if a == b
return 1 if a > b
You would use the following call to generate an insert function for a tree with this node type:
You would use the following call to generate an insert function for a tree
with this node type:
BTREE_DEFINE_INSERT(struct my_tree_node, base, key, my_tree_node_insert, my_comparator);
BTREE_DEFINE_INSERT(struct my_tree_node, base, key, my_tree_node_insert,
my_comparator);
Which would emit a function defined like:
static void my_tree_node_insert(struct btree *tree, struct my_tree_node *node);
static void my_tree_node_insert(struct btree *tree, struct my_tree_node
*node);
@param node_type your custom tree node type. usually a structure that contains a struct btree_node member.
@param container_node_member the name of the struct btree_node member variable within your custom type.
@param container_key_member the name of the key member variable within your custom type.
@param node_type your custom tree node type. usually a structure that
contains a struct btree_node member.
@param container_node_member the name of the struct btree_node member
variable within your custom type.
@param container_key_member the name of the key member variable within your
custom type.
@param function_name the name of the function to generate.
@param comparator the name of a comparator function or functional-macro that conforms to the
requirements listed above.
@param comparator the name of a comparator function or functional-macro that
conforms to the requirements listed above.
*/
#define BTREE_DEFINE_INSERT(node_type, container_node_member, container_key_member, function_name, comparator) \
void function_name(struct btree *tree, node_type *node) \
{ \
if (!tree->b_root) { \
tree->b_root = &node->container_node_member; \
btree_insert_fixup(tree, &node->container_node_member); \
return; \
} \
\
struct btree_node *cur = tree->b_root; \
while (1) { \
node_type *cur_node = BTREE_CONTAINER(node_type, container_node_member, cur); \
struct btree_node *next = NULL; \
int cmp = comparator(node, cur_node); \
\
if (cmp == 1) { \
next = btree_right(cur); \
\
if (!next) { \
btree_put_right(cur, &node->container_node_member); \
break; \
} \
} else if (cmp == -1) { \
next = btree_left(cur); \
\
if (!next) { \
btree_put_left(cur, &node->container_node_member); \
break; \
} \
} else { \
return; \
} \
\
cur = next; \
} \
\
btree_insert_fixup(tree, &node->container_node_member); \
#define BTREE_DEFINE_INSERT( \
node_type, \
container_node_member, \
container_key_member, \
function_name, \
comparator) \
void function_name(struct btree *tree, node_type *node) \
{ \
if (!tree->b_root) { \
tree->b_root = &node->container_node_member; \
btree_insert_fixup( \
tree, \
&node->container_node_member); \
return; \
} \
\
struct btree_node *cur = tree->b_root; \
while (1) { \
node_type *cur_node = BTREE_CONTAINER( \
node_type, \
container_node_member, \
cur); \
struct btree_node *next = NULL; \
int cmp = comparator(node, cur_node); \
\
if (cmp == 1) { \
next = btree_right(cur); \
\
if (!next) { \
btree_put_right( \
cur, \
&node->container_node_member); \
break; \
} \
} else if (cmp == -1) { \
next = btree_left(cur); \
\
if (!next) { \
btree_put_left( \
cur, \
&node->container_node_member); \
break; \
} \
} else { \
return; \
} \
\
cur = next; \
} \
\
btree_insert_fixup(tree, &node->container_node_member); \
}
/* defines a simple tree search function.
this function assumes that your nodes have simple integer keys that can be compared with the usual operators.
this function assumes that your nodes have simple integer keys that can be
compared with the usual operators.
EXAMPLE:
if you have a tree node type like this:
struct my_tree_node {
int key;
struct btree_node base;
struct btree_node base;
}
You would use the following call to generate a search function for a tree with this node type:
You would use the following call to generate a search function for a tree
with this node type:
BTREE_DEFINE_SIMPLE_GET(struct my_tree_node, int, base, key, my_tree_node_get);
BTREE_DEFINE_SIMPLE_GET(struct my_tree_node, int, base, key,
my_tree_node_get);
Which would emit a function defined like:
static struct my_tree_node *my_tree_node_get(struct btree *tree, int key);
@param node_type your custom tree node type. usually a structure that contains a struct btree_node member.
@param key_type the type name of the key embedded in your custom tree node type. this type must be
compatible with the builtin comparison operators.
@param container_node_member the name of the struct btree_node member variable within your custom type.
@param container_key_member the name of the key member variable within your custom type.
@param node_type your custom tree node type. usually a structure that
contains a struct btree_node member.
@param key_type the type name of the key embedded in your custom tree node
type. this type must be compatible with the builtin comparison operators.
@param container_node_member the name of the struct btree_node member
variable within your custom type.
@param container_key_member the name of the key member variable within your
custom type.
@param function_name the name of the function to generate.
*/
#define BTREE_DEFINE_SIMPLE_GET(node_type, key_type, container_node_member, container_key_member, function_name) \
node_type *function_name(struct btree *tree, key_type key) \
{ \
struct btree_node *cur = tree->b_root; \
while (cur) { \
node_type *cur_node = BTREE_CONTAINER(node_type, container_node_member, cur); \
if (key > cur_node->container_key_member) { \
cur = btree_right(cur); \
} else if (key < cur_node->container_key_member) { \
cur = btree_left(cur); \
} else { \
return cur_node; \
} \
} \
\
return NULL; \
#define BTREE_DEFINE_SIMPLE_GET( \
node_type, \
key_type, \
container_node_member, \
container_key_member, \
function_name) \
node_type *function_name(struct btree *tree, key_type key) \
{ \
struct btree_node *cur = tree->b_root; \
while (cur) { \
node_type *cur_node = BTREE_CONTAINER( \
node_type, \
container_node_member, \
cur); \
if (key > cur_node->container_key_member) { \
cur = btree_right(cur); \
} else if (key < cur_node->container_key_member) { \
cur = btree_left(cur); \
} else { \
return cur_node; \
} \
} \
\
return NULL; \
}
/* perform an in-order traversal of a binary tree
@@ -230,7 +295,7 @@ extern "C" {
struct my_tree_node {
int key;
struct btree_node base;
struct btree_node base;
}
and you want to do something like:
@@ -241,15 +306,23 @@ extern "C" {
btree_foreach (struct my_tree_node, node, &my_tree, base) { ... }
@param iter_type the type name of the iterator variable. this should be the tree's node type, and shouldn't be a pointer.
@param iter_type the type name of the iterator variable. this should be the
tree's node type, and shouldn't be a pointer.
@param iter_name the name of the iterator variable.
@param tree_name a pointer to the tree to traverse.
@param node_member the name of the struct btree_node member variable within the tree node type.
@param node_member the name of the struct btree_node member variable within
the tree node type.
*/
#define btree_foreach(iter_type, iter_name, tree_name, node_member) \
for (iter_type *iter_name = BTREE_CONTAINER(iter_type, node_member, btree_first(tree_name)); \
iter_name; \
iter_name = BTREE_CONTAINER(iter_type, node_member, btree_next(&((iter_name)->node_member))))
#define btree_foreach(iter_type, iter_name, tree_name, node_member) \
for (iter_type *iter_name = BTREE_CONTAINER( \
iter_type, \
node_member, \
btree_first(tree_name)); \
iter_name; \
iter_name = BTREE_CONTAINER( \
iter_type, \
node_member, \
btree_next(&((iter_name)->node_member))))
/* perform an reverse in-order traversal of a binary tree
@@ -261,7 +334,7 @@ extern "C" {
struct my_tree_node {
int key;
struct btree_node base;
struct btree_node base;
}
and you want to do something like:
@@ -272,35 +345,43 @@ extern "C" {
btree_foreach_r (struct my_tree_node, node, &my_tree, base) { ... }
@param iter_type the type name of the iterator variable. this should be the tree's node type, and shouldn't be a pointer.
@param iter_type the type name of the iterator variable. this should be the
tree's node type, and shouldn't be a pointer.
@param iter_name the name of the iterator variable.
@param tree_name a pointer to the tree to traverse.
@param node_member the name of the struct btree_node member variable within the tree node type.
@param node_member the name of the struct btree_node member variable within
the tree node type.
*/
#define btree_foreach_r(iter_type, iter_name, tree_name, node_member) \
for (iter_type *iter_name = BTREE_CONTAINER(iter_type, node_member, btree_last(tree_name)); \
iter_name; \
iter_name = BTREE_CONTAINER(iter_type, node_member, btree_prev(&((iter_name)->node_member))))
#define btree_foreach_r(iter_type, iter_name, tree_name, node_member) \
for (iter_type *iter_name \
= BTREE_CONTAINER(iter_type, node_member, btree_last(tree_name)); \
iter_name; \
iter_name = BTREE_CONTAINER( \
iter_type, \
node_member, \
btree_prev(&((iter_name)->node_member))))
/* binary tree nodes. this *cannot* be used directly. you need to define a custom node type
that contains a member variable of type struct btree_node.
/* binary tree nodes. this *cannot* be used directly. you need to define a
custom node type that contains a member variable of type struct btree_node.
you would then use the supplied macros to define functions to manipulate your custom binary tree.
you would then use the supplied macros to define functions to manipulate your
custom binary tree.
*/
struct btree_node {
struct btree_node *b_parent, *b_left, *b_right;
unsigned short b_height;
};
/* binary tree. unlike struct btree_node, you can define variables of type struct btree. */
/* binary tree. unlike struct btree_node, you can define variables of type
* struct btree. */
struct btree {
struct btree_node *b_root;
};
/* re-balance a binary tree after an insertion operation.
NOTE that, if you define an insertion function using BTREE_DEFINE_INSERT or similar,
this function will automatically called for you.
NOTE that, if you define an insertion function using BTREE_DEFINE_INSERT or
similar, this function will automatically called for you.
@param tree the tree to re-balance.
@param node the node that was just inserted into the tree.
@@ -316,29 +397,42 @@ extern void btree_delete(struct btree *tree, struct btree_node *node);
/* get the first node in a binary tree.
this will be the node with the smallest key (i.e. the node that is furthest-left from the root)
this will be the node with the smallest key (i.e. the node that is
furthest-left from the root)
*/
extern struct btree_node *btree_first(struct btree *tree);
/* get the last node in a binary tree.
this will be the node with the largest key (i.e. the node that is furthest-right from the root)
this will be the node with the largest key (i.e. the node that is
furthest-right from the root)
*/
extern struct btree_node *btree_last(struct btree *tree);
/* for any binary tree node, this function returns the node with the next-largest key value */
/* for any binary tree node, this function returns the node with the
* next-largest key value */
extern struct btree_node *btree_next(struct btree_node *node);
/* for any binary tree node, this function returns the node with the next-smallest key value */
/* for any binary tree node, this function returns the node with the
* next-smallest key value */
extern struct btree_node *btree_prev(struct btree_node *node);
static inline bool btree_empty(const struct btree *tree)
{
return tree->b_root == NULL;
}
/* sets `child` as the immediate left-child of `parent` */
static inline void btree_put_left(struct btree_node *parent, struct btree_node *child)
static inline void btree_put_left(
struct btree_node *parent,
struct btree_node *child)
{
parent->b_left = child;
child->b_parent = parent;
}
/* sets `child` as the immediate right-child of `parent` */
static inline void btree_put_right(struct btree_node *parent, struct btree_node *child)
static inline void btree_put_right(
struct btree_node *parent,
struct btree_node *child)
{
parent->b_right = child;
child->b_parent = parent;

53
include/kernel/channel.h Normal file
View File

@@ -0,0 +1,53 @@
#ifndef KERNEL_CHANNEL_H_
#define KERNEL_CHANNEL_H_
#include <kernel/object.h>
#include <kernel/sched.h>
struct kmsg;
struct channel {
struct object c_base;
unsigned int c_id;
struct waitqueue c_wq;
struct btree c_msg;
struct btree_node c_node;
};
extern kern_status_t channel_type_init(void);
extern struct channel *channel_create(void);
extern kern_status_t channel_enqueue_msg(
struct channel *channel,
struct kmsg *msg);
extern kern_status_t channel_recv_msg(
struct channel *channel,
struct msg *out_msg,
msgid_t *out_id,
unsigned long *irq_flags);
extern kern_status_t channel_reply_msg(
struct channel *channel,
msgid_t id,
const struct msg *resp,
unsigned long *irq_flags);
extern kern_status_t channel_read_msg(
struct channel *channel,
msgid_t msg,
size_t offset,
void *buf,
size_t len,
size_t *nr_read);
extern kern_status_t channel_write_msg(
struct channel *channel,
msgid_t msg,
size_t offset,
const void *buf,
size_t len,
size_t *nr_written);
DEFINE_OBJECT_LOCK_FUNCTION(channel, c_base)
#endif

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_CLOCK_H_
#define MANGO_CLOCK_H_
#ifndef KERNEL_CLOCK_H_
#define KERNEL_CLOCK_H_
#include <stdint.h>

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_COMPILER_H_
#define MANGO_COMPILER_H_
#ifndef KERNEL_COMPILER_H_
#define KERNEL_COMPILER_H_
#ifdef __cplusplus
template <typename T>

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_CONSOLE_H_
#define MANGO_CONSOLE_H_
#ifndef KERNEL_CONSOLE_H_
#define KERNEL_CONSOLE_H_
/* The console system
@@ -14,8 +14,8 @@
representing a serial port may allow both sending AND receiving over the
port.
*/
#include <mango/queue.h>
#include <mango/locks.h>
#include <kernel/queue.h>
#include <kernel/locks.h>
#include <mango/status.h>
#ifdef __cplusplus

View File

@@ -1,10 +1,10 @@
#ifndef MANGO_CPU_H_
#define MANGO_CPU_H_
#ifndef KERNEL_CPU_H_
#define KERNEL_CPU_H_
#include <mango/types.h>
#include <mango/machine/cpu.h>
#include <kernel/types.h>
#include <kernel/machine/cpu.h>
#include <stdint.h>
#include <mango/sched.h>
#include <kernel/sched.h>
#ifdef __cplusplus
extern "C" {

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_FB_H_
#define MANGO_FB_H_
#ifndef KERNEL_FB_H_
#define KERNEL_FB_H_
#include <stdint.h>

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_FLAGS_H_
#define MANGO_FLAGS_H_
#ifndef KERNEL_FLAGS_H_
#define KERNEL_FLAGS_H_
#include <stdint.h>

View File

@@ -1,8 +1,9 @@
#ifndef MANGO_HANDLE_H_
#define MANGO_HANDLE_H_
#ifndef KERNEL_HANDLE_H_
#define KERNEL_HANDLE_H_
#include <mango/bitmap.h>
#include <kernel/bitmap.h>
#include <mango/status.h>
#include <stddef.h>
#include <stdint.h>
/* subtract 32 bytes to account for the handle bitmap */
@@ -11,15 +12,15 @@
typedef uint32_t kern_handle_t;
typedef uintptr_t handle_flags_t;
struct task;
struct object;
struct handle_list;
struct handle {
union {
struct object *h_object;
uint64_t __x;
};
uint64_t h_flags;
struct object *h_object;
handle_flags_t h_flags;
};
struct handle_table {
@@ -46,11 +47,19 @@ extern kern_status_t handle_table_alloc_handle(
struct handle_table *tab,
struct handle **out_slot,
kern_handle_t *out_handle);
extern void handle_table_free_handle(
extern kern_status_t handle_table_free_handle(
struct handle_table *tab,
kern_handle_t handle);
extern struct handle *handle_table_get_handle(
struct handle_table *tab,
kern_handle_t handle);
extern kern_status_t handle_list_transfer(
struct handle_table *dest,
struct handle_list *dest_list,
size_t dest_list_count,
struct handle_table *src,
const struct handle_list *src_list,
size_t src_list_count);
#endif

View File

@@ -1,8 +1,8 @@
#ifndef MANGO_INIT_H_
#define MANGO_INIT_H_
#ifndef KERNEL_INIT_H_
#define KERNEL_INIT_H_
#include <mango/compiler.h>
#include <mango/machine/init.h>
#include <kernel/compiler.h>
#include <kernel/machine/init.h>
#ifdef __cplusplus
extern "C" {

View File

@@ -1,8 +1,8 @@
#ifndef MANGO_INPUT_H_
#define MANGO_INPUT_H_
#ifndef KERNEL_INPUT_H_
#define KERNEL_INPUT_H_
#include <stdint.h>
#include <mango/queue.h>
#include <kernel/queue.h>
#include <mango/status.h>
enum input_event_hook_flags {

23
include/kernel/iovec.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef KERNEL_IOVEC_H_
#define KERNEL_IOVEC_H_
#include <mango/types.h>
#include <stddef.h>
struct iovec_iterator {
const struct iovec *it_vecs;
size_t it_nr_vecs;
size_t it_vec_ptr;
virt_addr_t it_base;
size_t it_len;
};
extern void iovec_iterator_begin(
struct iovec_iterator *it,
const struct iovec *vecs,
size_t nr_vecs);
extern void iovec_iterator_seek(struct iovec_iterator *it, size_t nr_bytes);
#endif

View File

@@ -1,8 +1,8 @@
#ifndef MANGO_LOCKS_H_
#define MANGO_LOCKS_H_
#ifndef KERNEL_LOCKS_H_
#define KERNEL_LOCKS_H_
#include <mango/compiler.h>
#include <mango/machine/hwlock.h>
#include <kernel/compiler.h>
#include <kernel/machine/hwlock.h>
#ifdef __cplusplus
extern "C" {

View File

@@ -19,11 +19,11 @@
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
*/
#ifndef MANGO_MEMBLOCK_H_
#define MANGO_MEMBLOCK_H_
#ifndef KERNEL_MEMBLOCK_H_
#define KERNEL_MEMBLOCK_H_
#include <limits.h>
#include <mango/types.h>
#include <kernel/types.h>
#include <stddef.h>
#ifdef __cplusplus

30
include/kernel/msg.h Normal file
View File

@@ -0,0 +1,30 @@
#ifndef KERNEL_MSG_H_
#define KERNEL_MSG_H_
#include <kernel/btree.h>
#include <kernel/locks.h>
#include <mango/status.h>
#include <mango/types.h>
struct port;
struct thread;
enum kmsg_status {
KMSG_WAIT_RECEIVE,
KMSG_WAIT_REPLY,
KMSG_REPLY_SENT,
};
struct kmsg {
spin_lock_t msg_lock;
enum kmsg_status msg_status;
struct btree_node msg_node;
msgid_t msg_id;
kern_status_t msg_result;
struct port *msg_sender_port;
struct thread *msg_sender_thread;
const struct msg *msg_req;
struct msg *msg_resp;
};
#endif

View File

@@ -1,10 +1,10 @@
#ifndef MANGO_OBJECT_H_
#define MANGO_OBJECT_H_
#ifndef KERNEL_OBJECT_H_
#define KERNEL_OBJECT_H_
#include <mango/flags.h>
#include <mango/locks.h>
#include <kernel/flags.h>
#include <kernel/locks.h>
#include <mango/status.h>
#include <mango/vm.h>
#include <kernel/vm.h>
#include <stddef.h>
#ifdef __cplusplus

View File

@@ -1,7 +1,7 @@
#ifndef MANGO_PANIC_H_
#define MANGO_PANIC_H_
#ifndef KERNEL_PANIC_H_
#define KERNEL_PANIC_H_
#include <mango/compiler.h>
#include <kernel/compiler.h>
struct ml_cpu_context;

View File

@@ -1,9 +1,9 @@
#ifndef MANGO_PERCPU_H_
#define MANGO_PERCPU_H_
#ifndef KERNEL_PERCPU_H_
#define KERNEL_PERCPU_H_
#include <mango/status.h>
#include <mango/compiler.h>
#include <mango/sched.h>
#include <kernel/compiler.h>
#include <kernel/sched.h>
#ifdef __cplusplus
extern "C" {

View File

@@ -1,11 +1,11 @@
#ifndef MANGO_PMAP_H_
#define MANGO_PMAP_H_
#ifndef KERNEL_PMAP_H_
#define KERNEL_PMAP_H_
/* all the functions declared in this file are defined in arch/xyz/pmap.c */
#include <mango/machine/pmap.h>
#include <kernel/machine/pmap.h>
#include <kernel/vm.h>
#include <mango/status.h>
#include <mango/vm.h>
#include <stddef.h>
#define PMAP_INVALID ML_PMAP_INVALID
@@ -61,18 +61,18 @@ extern kern_status_t pmap_add(
pmap_t pmap,
virt_addr_t p,
pfn_t pfn,
enum vm_prot prot,
vm_prot_t prot,
enum pmap_flags flags);
extern kern_status_t pmap_add_block(
pmap_t pmap,
virt_addr_t p,
pfn_t pfn,
size_t len,
enum vm_prot prot,
vm_prot_t prot,
enum pmap_flags flags);
extern kern_status_t pmap_remove(pmap_t pmap, void *p);
extern kern_status_t pmap_remove_range(pmap_t pmap, void *p, size_t len);
extern kern_status_t pmap_remove(pmap_t pmap, virt_addr_t p);
extern kern_status_t pmap_remove_range(pmap_t pmap, virt_addr_t p, size_t len);
#ifdef __cplusplus
}

39
include/kernel/port.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef KERNEL_PORT_H_
#define KERNEL_PORT_H_
#include <kernel/object.h>
#include <kernel/sched.h>
enum port_status {
/* port is not connected */
PORT_OFFLINE = 0,
/* port is connected and ready to send messages */
PORT_READY,
/* port has sent a message, and is waiting for the remote to receive it
*/
PORT_SEND_BLOCKED,
/* port has sent a message, and the remote has received it. waiting for
* the remote to reply. */
PORT_REPLY_BLOCKED,
};
struct port {
struct object p_base;
enum port_status p_status;
struct channel *p_remote;
};
extern kern_status_t port_type_init(void);
extern struct port *port_cast(struct object *obj);
extern struct port *port_create(void);
extern kern_status_t port_connect(struct port *port, struct channel *remote);
extern kern_status_t port_send_msg(
struct port *port,
const struct msg *req,
struct msg *resp);
DEFINE_OBJECT_LOCK_FUNCTION(port, p_base)
#endif

View File

@@ -1,7 +1,9 @@
#ifndef MANGO_PRINTK_H_
#define MANGO_PRINTK_H_
#ifndef KERNEL_PRINTK_H_
#define KERNEL_PRINTK_H_
#include <mango/console.h>
#include <kernel/console.h>
#undef TRACE
#ifdef __cplusplus
extern "C" {

View File

@@ -1,7 +1,7 @@
#ifndef MANGO_QUEUE_H_
#define MANGO_QUEUE_H_
#ifndef KERNEL_QUEUE_H_
#define KERNEL_QUEUE_H_
#include <mango/libc/string.h>
#include <kernel/libc/string.h>
#include <stdbool.h>
#ifdef __cplusplus

View File

@@ -1,8 +1,8 @@
#ifndef MANGO_RINGBUFFER_H_
#define MANGO_RINGBUFFER_H_
#ifndef KERNEL_RINGBUFFER_H_
#define KERNEL_RINGBUFFER_H_
#include <mango/locks.h>
#include <mango/sched.h>
#include <kernel/locks.h>
#include <kernel/sched.h>
struct ringbuffer {
unsigned char *r_buffer;

View File

@@ -1,11 +1,13 @@
#ifndef MANGO_SCHED_H_
#define MANGO_SCHED_H_
#ifndef KERNEL_SCHED_H_
#define KERNEL_SCHED_H_
#include <mango/btree.h>
#include <mango/locks.h>
#include <mango/object.h>
#include <mango/pmap.h>
#include <mango/queue.h>
#include <kernel/btree.h>
#include <kernel/handle.h>
#include <kernel/locks.h>
#include <kernel/msg.h>
#include <kernel/object.h>
#include <kernel/pmap.h>
#include <kernel/queue.h>
#include <mango/status.h>
#define TASK_NAME_MAX 64
@@ -33,6 +35,7 @@
extern "C" {
#endif
struct channel;
struct runqueue;
struct work_item;
@@ -83,6 +86,7 @@ struct task {
pmap_t t_pmap;
struct vm_region *t_address_space;
struct handle_table *t_handles;
struct btree b_channels;
struct btree_node t_tasklist;
struct queue_entry t_child_entry;
@@ -110,6 +114,7 @@ struct thread {
virt_addr_t tr_cpu_user_sp, tr_cpu_kernel_sp;
struct runqueue *tr_rq;
struct kmsg tr_msg;
struct queue_entry tr_parent_entry;
struct queue_entry tr_rqentry;
@@ -183,7 +188,8 @@ extern void rq_remove_thread(struct runqueue *rq, struct thread *thr);
extern struct runqueue *cpu_rq(unsigned int cpu);
extern struct task *task_alloc(void);
extern struct task *task_create(struct task *parent, const char *name);
extern struct task *task_cast(struct object *obj);
extern struct task *task_create(const char *name, size_t name_len);
static inline struct task *task_ref(struct task *task)
{
return OBJECT_CAST(struct task, t_base, object_ref(&task->t_base));
@@ -192,7 +198,24 @@ static inline void task_unref(struct task *task)
{
object_unref(&task->t_base);
}
extern struct task *task_from_pid(unsigned int pid);
extern kern_status_t task_add_child(struct task *parent, struct task *child);
extern kern_status_t task_add_channel(
struct task *task,
struct channel *channel,
unsigned int id);
extern struct channel *task_get_channel(struct task *task, unsigned int id);
extern struct task *task_from_tid(tid_t id);
extern kern_status_t task_open_handle(
struct task *task,
struct object *obj,
handle_flags_t flags,
kern_handle_t *out);
extern kern_status_t task_resolve_handle(
struct task *task,
kern_handle_t handle,
struct object **out_obj,
handle_flags_t *out_flags);
extern kern_status_t task_close_handle(struct task *task, kern_handle_t handle);
extern struct thread *task_create_thread(struct task *parent);
extern struct task *kernel_task(void);
extern struct task *idle_task(void);
@@ -211,12 +234,16 @@ extern void end_charge_period(void);
DEFINE_OBJECT_LOCK_FUNCTION(task, t_base)
extern struct thread *thread_alloc(void);
extern struct thread *thread_cast(struct object *obj);
extern kern_status_t thread_init_kernel(struct thread *thr, virt_addr_t ip);
extern kern_status_t thread_init_user(
struct thread *thr,
virt_addr_t ip,
virt_addr_t sp);
virt_addr_t sp,
const uintptr_t *args,
size_t nr_args);
extern int thread_priority(struct thread *thr);
extern void thread_awaken(struct thread *thr);
extern void idle(void);
extern struct thread *create_kernel_thread(void (*fn)(void));
extern struct thread *create_idle_thread(void);

183
include/kernel/syscall.h Normal file
View File

@@ -0,0 +1,183 @@
#ifndef KERNEL_SYSCALL_H_
#define KERNEL_SYSCALL_H_
#include <kernel/handle.h>
#include <kernel/vm.h>
#include <mango/status.h>
#include <mango/syscall.h>
#define validate_access(task, ptr, len, flags) \
vm_region_validate_access( \
task->t_address_space, \
(virt_addr_t)ptr, \
len, \
flags | VM_PROT_USER)
#define validate_access_r(task, ptr, len) \
validate_access(task, ptr, len, VM_PROT_READ | VM_PROT_USER)
#define validate_access_w(task, ptr, len) \
validate_access(task, ptr, len, VM_PROT_WRITE | VM_PROT_USER)
#define validate_access_rw(task, ptr, len) \
validate_access( \
task, \
ptr, \
len, \
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER)
extern kern_status_t sys_task_exit(int status);
extern kern_status_t sys_task_create(
kern_handle_t parent_handle,
const char *name,
size_t name_len,
kern_handle_t *out_task,
kern_handle_t *out_address_space);
extern kern_status_t sys_task_create_thread(
kern_handle_t task,
virt_addr_t ip,
virt_addr_t sp,
uintptr_t *args,
size_t nr_args,
kern_handle_t *out_thread);
extern kern_status_t sys_thread_start(kern_handle_t thread);
extern kern_status_t sys_vm_object_create(
const char *name,
size_t name_len,
size_t data_len,
vm_prot_t prot,
kern_handle_t *out);
extern kern_status_t sys_vm_object_read(
kern_handle_t object,
void *dst,
off_t offset,
size_t count,
size_t *nr_read);
extern kern_status_t sys_vm_object_write(
kern_handle_t object,
const void *src,
off_t offset,
size_t count,
size_t *nr_written);
extern kern_status_t sys_vm_object_copy(
kern_handle_t dst,
off_t dst_offset,
kern_handle_t src,
off_t src_offset,
size_t count,
size_t *nr_copied);
extern kern_status_t sys_vm_region_create(
kern_handle_t parent,
const char *name,
size_t name_len,
off_t offset,
size_t region_len,
vm_prot_t prot,
kern_handle_t *out,
virt_addr_t *out_base_address);
extern kern_status_t sys_vm_region_read(
kern_handle_t region,
void *dst,
off_t offset,
size_t count,
size_t *nr_read);
extern kern_status_t sys_vm_region_write(
kern_handle_t region,
const void *src,
off_t offset,
size_t count,
size_t *nr_read);
extern kern_status_t sys_vm_region_map_absolute(
kern_handle_t region,
virt_addr_t map_address,
kern_handle_t object,
off_t object_offset,
size_t length,
vm_prot_t prot,
virt_addr_t *out_base_address);
extern kern_status_t sys_vm_region_map_relative(
kern_handle_t region,
off_t region_offset,
kern_handle_t object,
off_t object_offset,
size_t length,
vm_prot_t prot,
virt_addr_t *out_base_address);
extern kern_status_t sys_vm_region_unmap_absolute(
kern_handle_t region,
virt_addr_t address,
size_t length);
extern kern_status_t sys_vm_region_unmap_relative(
kern_handle_t region,
off_t offset,
size_t length);
extern kern_status_t sys_kern_log(const char *s);
extern kern_status_t sys_kern_handle_close(kern_handle_t handle);
extern kern_status_t sys_kern_config_get(
kern_config_key_t key,
void *ptr,
size_t len);
extern kern_status_t sys_kern_config_set(
kern_config_key_t key,
const void *ptr,
size_t len);
extern kern_status_t sys_channel_create(
unsigned int id,
channel_flags_t flags,
kern_handle_t *out);
extern kern_status_t sys_port_create(kern_handle_t *out);
extern kern_status_t sys_port_connect(
kern_handle_t port,
tid_t task_id,
unsigned int channel_id);
extern kern_status_t sys_port_disconnect(kern_handle_t port);
extern kern_status_t sys_msg_send(
kern_handle_t port,
msg_flags_t flags,
const struct msg *req,
struct msg *resp);
extern kern_status_t sys_msg_recv(
kern_handle_t channel,
msg_flags_t flags,
msgid_t *out_id,
struct msg *out_msg);
extern kern_status_t sys_msg_reply(
kern_handle_t channel,
msg_flags_t flags,
msgid_t id,
const struct msg *reply);
extern kern_status_t sys_msg_read(
kern_handle_t channel,
msgid_t id,
size_t offset,
struct iovec *out,
size_t nr_out);
extern kern_status_t sys_msg_read_handles(
kern_handle_t channel,
msgid_t id,
size_t offset,
struct handle_list *out,
size_t nr_out);
extern kern_status_t sys_msg_write(
kern_handle_t channel,
msgid_t id,
size_t offset,
const struct iovec *in,
size_t nr_in);
extern kern_status_t sys_msg_write_handles(
kern_handle_t channel,
msgid_t id,
size_t offset,
const struct handle_list *in,
size_t nr_in);
extern virt_addr_t syscall_get_function(unsigned int sysid);
#endif

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_TEST_H_
#define MANGO_TEST_H_
#ifndef KERNEL_TEST_H_
#define KERNEL_TEST_H_
#ifdef __cplusplus
extern "C" {

View File

@@ -1,18 +1,14 @@
#ifndef MANGO_TYPES_H_
#define MANGO_TYPES_H_
#ifndef KERNEL_TYPES_H_
#define KERNEL_TYPES_H_
#include <mango/types.h>
#include <stddef.h>
#include <stdint.h>
#define CYCLES_MAX UINT64_MAX
typedef uintptr_t phys_addr_t;
typedef uintptr_t virt_addr_t;
typedef uint64_t cycles_t;
typedef uint64_t sectors_t;
typedef uint64_t off_t;
typedef unsigned int umode_t;
struct boot_module {
phys_addr_t mod_base;

View File

@@ -1,6 +1,7 @@
#ifndef MANGO_UTIL_H_
#define MANGO_UTIL_H_
#ifndef KERNEL_UTIL_H_
#define KERNEL_UTIL_H_
#include <mango/types.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

View File

@@ -1,8 +1,8 @@
#ifndef MANGO_VM_OBJECT_H_
#define MANGO_VM_OBJECT_H_
#ifndef KERNEL_VM_OBJECT_H_
#define KERNEL_VM_OBJECT_H_
#include <mango/locks.h>
#include <mango/object.h>
#include <kernel/locks.h>
#include <kernel/object.h>
#define VM_OBJECT_NAME_MAX 64
@@ -23,7 +23,7 @@ struct vm_object {
/* memory protection flags. mappings of this vm_object can only use
* a subset of the flags set in this mask. */
enum vm_prot vo_prot;
vm_prot_t vo_prot;
/* btree of vm_pages that have been allocated to this vm_object.
* vm_page->p_vmo_offset and the size of each page is the bst key. */
@@ -33,6 +33,7 @@ struct vm_object {
};
extern kern_status_t vm_object_type_init(void);
extern struct vm_object *vm_object_cast(struct object *obj);
/* create a vm_object with the specified length in bytes and protection flags.
* the length will be automatically rounded up to the nearest vm_object page
@@ -40,8 +41,9 @@ extern kern_status_t vm_object_type_init(void);
* they are mapped and accessed. */
extern struct vm_object *vm_object_create(
const char *name,
size_t len,
enum vm_prot prot);
size_t name_len,
size_t data_len,
vm_prot_t prot);
/* create a vm_object that represents the specified range of physical memory.
* the length will be automatically rounded up to the nearest vm_object page
@@ -50,9 +52,10 @@ extern struct vm_object *vm_object_create(
* reserved, and is not in use by any other kernel component. */
extern struct vm_object *vm_object_create_in_place(
const char *name,
size_t name_len,
phys_addr_t base,
size_t len,
enum vm_prot prot);
size_t data_len,
vm_prot_t prot);
extern struct vm_page *vm_object_get_page(
const struct vm_object *vo,
@@ -63,6 +66,26 @@ extern struct vm_page *vm_object_alloc_page(
off_t offset,
enum vm_page_order size);
extern kern_status_t vm_object_read(
struct vm_object *vo,
void *dst,
off_t offset,
size_t count,
size_t *nr_read);
extern kern_status_t vm_object_write(
struct vm_object *vo,
const void *dst,
off_t offset,
size_t count,
size_t *nr_written);
extern kern_status_t vm_object_copy(
struct vm_object *dst,
off_t dst_offset,
struct vm_object *src,
off_t src_offset,
size_t count,
size_t *nr_copied);
DEFINE_OBJECT_LOCK_FUNCTION(vm_object, vo_base)
#endif

View File

@@ -1,13 +1,12 @@
#ifndef MANGO_VM_REGION_H_
#define MANGO_VM_REGION_H_
#ifndef KERNEL_VM_REGION_H_
#define KERNEL_VM_REGION_H_
#include <mango/object.h>
#include <mango/pmap.h>
#include <mango/vm.h>
#include <kernel/object.h>
#include <kernel/pmap.h>
#include <kernel/vm.h>
#define VM_REGION_NAME_MAX 64
#define VM_REGION_ANY_OFFSET ((off_t) - 1)
#define VM_REGION_NAME_MAX 64
#define VM_REGION_COPY_ALL ((size_t)-1)
struct vm_region;
struct vm_object;
@@ -35,7 +34,7 @@ struct vm_region_mapping {
/* used to link to vm_object->vo_mappings */
struct queue_entry m_object_entry;
enum vm_prot m_prot;
vm_prot_t m_prot;
/* offset in bytes to the start of the object data that was mapped */
off_t m_object_offset;
};
@@ -57,7 +56,7 @@ struct vm_region {
* for example, if VM_PROT_EXEC is /not/ set here, no mapping
* can be created in this region or any child region with VM_PROT_EXEC
* set. */
enum vm_prot vr_prot;
vm_prot_t vr_prot;
/* the physical address space in which mappings in this region (and
* its children) are created */
@@ -65,6 +64,7 @@ struct vm_region {
};
extern kern_status_t vm_region_type_init(void);
extern struct vm_region *vm_region_cast(struct object *obj);
/* create a new vm-region, optionally within a parent region.
* `offset` is the byte offset within the parent region where the new region
@@ -75,9 +75,10 @@ extern kern_status_t vm_region_type_init(void);
extern kern_status_t vm_region_create(
struct vm_region *parent,
const char *name,
size_t name_len,
off_t offset,
size_t len,
enum vm_prot prot,
size_t region_len,
vm_prot_t prot,
struct vm_region **out);
/* map a vm-object into a vm-region.
@@ -93,9 +94,20 @@ extern kern_status_t vm_region_map_object(
struct vm_object *object,
off_t object_offset,
size_t length,
enum vm_prot prot,
vm_prot_t prot,
virt_addr_t *out);
extern kern_status_t vm_region_unmap(
struct vm_region *region,
off_t region_offset,
size_t length);
extern bool vm_region_validate_access(
struct vm_region *region,
off_t offset,
size_t len,
vm_prot_t prot);
/* find the mapping corresponding to the given virtual address, and page-in the
* necessary vm_page to allow the memory access to succeed. if the relevant
* vm-object page hasn't been allocated yet, it will be allocated here. */
@@ -108,7 +120,26 @@ extern kern_status_t vm_region_demand_map(
* parent/ancestors. */
extern virt_addr_t vm_region_get_base_address(const struct vm_region *region);
extern void vm_region_dump(struct vm_region *region, int depth);
extern void vm_region_dump(struct vm_region *region);
extern kern_status_t vm_region_memmove(
struct vm_region *dest_region,
virt_addr_t dest_ptr,
struct vm_region *src_region,
virt_addr_t src_ptr,
size_t count,
size_t *nr_moved);
extern kern_status_t vm_region_memmove_v(
struct vm_region *dest_region,
size_t dest_offset,
struct iovec *dest,
size_t nr_dest,
struct vm_region *src_region,
size_t src_offset,
const struct iovec *src,
size_t nr_src,
size_t bytes_to_move);
DEFINE_OBJECT_LOCK_FUNCTION(vm_region, vr_base)

View File

@@ -1,13 +1,13 @@
#ifndef MANGO_VM_H_
#define MANGO_VM_H_
#ifndef KERNEL_VM_H_
#define KERNEL_VM_H_
#include <mango/bitmap.h>
#include <mango/btree.h>
#include <mango/locks.h>
#include <mango/machine/vm.h>
#include <mango/queue.h>
#include <kernel/bitmap.h>
#include <kernel/btree.h>
#include <kernel/locks.h>
#include <kernel/machine/vm.h>
#include <kernel/queue.h>
#include <kernel/types.h>
#include <mango/status.h>
#include <mango/types.h>
#include <stddef.h>
#ifdef __cplusplus
@@ -47,15 +47,6 @@ enum vm_model {
VM_MODEL_SPARSE,
};
enum vm_prot {
VM_PROT_READ = 0x01u,
VM_PROT_WRITE = 0x02u,
VM_PROT_EXEC = 0x04u,
VM_PROT_USER = 0x08u,
VM_PROT_SVR = 0x10u,
VM_PROT_NOCACHE = 0x20u,
};
enum vm_flags {
VM_NORMAL = 0x00u,
VM_GET_DMA = 0x01u,

View File

@@ -1,20 +0,0 @@
#ifndef MANGO_SYSCALL_H_
#define MANGO_SYSCALL_H_
#include <mango/handle.h>
#include <mango/status.h>
#include <mango/vm.h>
#define SYS_EXIT 1
#define SYS_VM_OBJECT_CREATE 2
extern kern_status_t sys_exit(int status);
extern kern_status_t sys_vm_object_create(
const char *name,
size_t len,
enum vm_prot prot,
kern_handle_t *out_handle);
extern virt_addr_t syscall_get_function(unsigned int sysid);
#endif

View File

@@ -1,5 +1,4 @@
#include <mango/init.h>
#include <kernel/init.h>
int do_initcalls(void)
{

View File

@@ -1,18 +1,20 @@
#include <mango/arg.h>
#include <mango/bsp.h>
#include <mango/clock.h>
#include <mango/cpu.h>
#include <mango/handle.h>
#include <mango/init.h>
#include <mango/input.h>
#include <mango/libc/stdio.h>
#include <mango/machine/init.h>
#include <mango/object.h>
#include <mango/panic.h>
#include <mango/printk.h>
#include <mango/sched.h>
#include <mango/test.h>
#include <mango/vm-object.h>
#include <kernel/arg.h>
#include <kernel/bsp.h>
#include <kernel/channel.h>
#include <kernel/clock.h>
#include <kernel/cpu.h>
#include <kernel/handle.h>
#include <kernel/init.h>
#include <kernel/input.h>
#include <kernel/libc/stdio.h>
#include <kernel/machine/init.h>
#include <kernel/object.h>
#include <kernel/panic.h>
#include <kernel/port.h>
#include <kernel/printk.h>
#include <kernel/sched.h>
#include <kernel/test.h>
#include <kernel/vm-object.h>
#include <stdint.h>
extern unsigned long get_rflags(void);
@@ -31,7 +33,7 @@ static void hang(void)
while (1) {
#if 0
printk("[cpu %u, task %u, thread %u]: tick",
printk("[cpu %u, task %ld, thread %u]: tick",
this_cpu(),
self->t_id,
thread->tr_id);
@@ -72,6 +74,9 @@ void kernel_init(uintptr_t arg)
{
ml_init(arg);
port_type_init();
channel_type_init();
struct boot_module bsp_image = {0};
bsp_get_location(&bsp_image);
@@ -102,7 +107,7 @@ void kernel_init(uintptr_t arg)
bsp.bsp_trailer.bsp_exec_entry,
bsp.bsp_vmo);
struct task *bootstrap_task = task_create(kernel_task(), "bootstrap");
struct task *bootstrap_task = task_create("bootstrap", 9);
tracek("created bootstrap task (pid=%u)", bootstrap_task->t_id);
bsp_launch_async(&bsp, bootstrap_task);

View File

@@ -1,6 +1,6 @@
#include <mango/arg.h>
#include <mango/libc/string.h>
#include <mango/libc/ctype.h>
#include <kernel/arg.h>
#include <kernel/libc/string.h>
#include <kernel/libc/ctype.h>
static char g_cmdline[CMDLINE_MAX + 1] = {0};

View File

@@ -1,9 +1,10 @@
#include <mango/bsp.h>
#include <mango/printk.h>
#include <mango/sched.h>
#include <mango/util.h>
#include <mango/vm-object.h>
#include <mango/vm-region.h>
#include <kernel/bsp.h>
#include <kernel/handle.h>
#include <kernel/printk.h>
#include <kernel/sched.h>
#include <kernel/util.h>
#include <kernel/vm-object.h>
#include <kernel/vm-region.h>
#define BOOTSTRAP_STACK_SIZE 0x10000
@@ -57,6 +58,7 @@ kern_status_t bsp_load(struct bsp *bsp, const struct boot_module *mod)
bsp->bsp_vmo = vm_object_create_in_place(
"bsp",
3,
mod->mod_base,
mod->mod_size,
VM_PROT_READ | VM_PROT_EXEC | VM_PROT_USER);
@@ -86,6 +88,7 @@ static kern_status_t map_executable(
status = vm_region_create(
task->t_address_space,
"exec",
4,
VM_REGION_ANY_OFFSET,
exec_size,
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXEC | VM_PROT_USER,
@@ -96,9 +99,9 @@ static kern_status_t map_executable(
struct vm_object *data = vm_object_create(
".data",
5,
bsp->bsp_trailer.bsp_data_size,
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER);
/* TODO copy .data from executable to memory */
if (!data) {
return KERN_NO_MEMORY;
}
@@ -111,6 +114,19 @@ static kern_status_t map_executable(
off_t text_voffset = bsp->bsp_trailer.bsp_text_vaddr;
off_t data_voffset = bsp->bsp_trailer.bsp_data_vaddr;
#if 0
size_t tmp = 0;
status = vm_object_copy(
data,
0,
bsp->bsp_vmo,
bsp->bsp_trailer.bsp_data_faddr,
bsp->bsp_trailer.bsp_data_size,
&tmp);
tracek("read %zuB of data from executable", tmp);
#endif
tracek("text_foffset=%06llx, data_foffset=%06llx",
text_foffset,
data_foffset);
@@ -150,15 +166,13 @@ static kern_status_t map_executable(
kern_status_t bsp_launch_async(struct bsp *bsp, struct task *task)
{
virt_addr_t stack_buffer;
virt_addr_t stack_buffer, bsp_data_base;
virt_addr_t entry, sp;
kern_status_t status = map_executable(bsp, task, &entry);
if (status != KERN_OK) {
return status;
}
kern_status_t status;
struct vm_object *user_stack = vm_object_create(
"stack",
5,
BOOTSTRAP_STACK_SIZE,
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER);
if (!user_stack) {
@@ -178,15 +192,52 @@ kern_status_t bsp_launch_async(struct bsp *bsp, struct task *task)
return status;
}
status = vm_region_map_object(
task->t_address_space,
VM_REGION_ANY_OFFSET,
bsp->bsp_vmo,
0,
bsp->bsp_trailer.bsp_exec_offset,
VM_PROT_READ | VM_PROT_USER,
&bsp_data_base);
if (status != KERN_OK) {
return status;
}
status = map_executable(bsp, task, &entry);
if (status != KERN_OK) {
return status;
}
#ifdef TRACE
vm_region_dump(task->t_address_space, 0);
vm_region_dump(task->t_address_space);
#endif
sp = stack_buffer + BOOTSTRAP_STACK_SIZE;
tracek("bootstrap: entry=%llx, sp=%llx", entry, sp);
kern_handle_t self, self_address_space;
task_open_handle(task, &task->t_base, 0, &self);
task_open_handle(
task,
&task->t_address_space->vr_base,
0,
&self_address_space);
const uintptr_t args[] = {
0, // int argc
0, // const char ** argv
self, // kern_handle_t task
self_address_space, // kern_handle_t address_space
/* this parameter is specific to the bsp bootstrap program, so
* that it can access the rest of the bsp image. */
bsp_data_base,
};
const size_t nr_args = sizeof args / sizeof args[0];
struct thread *init_thread = task_create_thread(task);
thread_init_user(init_thread, entry, sp);
thread_init_user(init_thread, entry, sp, args, nr_args);
schedule_thread_on_cpu(init_thread);
return KERN_OK;

240
kernel/channel.c Normal file
View File

@@ -0,0 +1,240 @@
#include <kernel/channel.h>
#include <kernel/msg.h>
#include <kernel/util.h>
#include <kernel/vm-region.h>
#define CHANNEL_CAST(p) OBJECT_C_CAST(struct channel, c_base, &channel_type, p)
static struct object_type channel_type = {
.ob_name = "channel",
.ob_size = sizeof(struct channel),
.ob_header_offset = offsetof(struct channel, c_base),
};
BTREE_DEFINE_SIMPLE_GET(struct kmsg, msgid_t, msg_node, msg_id, get_msg_with_id)
kern_status_t channel_type_init(void)
{
return object_type_register(&channel_type);
}
extern struct channel *channel_create(void)
{
struct object *channel_object = object_create(&channel_type);
if (!channel_object) {
return NULL;
}
struct channel *channel = CHANNEL_CAST(channel_object);
return channel;
}
static bool try_enqueue(struct btree *tree, struct kmsg *msg)
{
if (!tree->b_root) {
tree->b_root = &msg->msg_node;
btree_insert_fixup(tree, &msg->msg_node);
return true;
}
struct btree_node *cur = tree->b_root;
while (1) {
struct kmsg *cur_node
= BTREE_CONTAINER(struct kmsg, msg_node, cur);
struct btree_node *next = NULL;
if (msg->msg_id > cur_node->msg_id) {
next = btree_right(cur);
if (!next) {
btree_put_right(cur, &msg->msg_node);
break;
}
} else if (msg->msg_id < cur_node->msg_id) {
next = btree_left(cur);
if (!next) {
btree_put_left(cur, &msg->msg_node);
break;
}
} else {
return false;
}
cur = next;
}
btree_insert_fixup(tree, &msg->msg_node);
return true;
}
static void kmsg_reply_error(struct kmsg *msg, kern_status_t status)
{
msg->msg_status = KMSG_REPLY_SENT;
msg->msg_status = status;
thread_awaken(msg->msg_sender_thread);
}
static struct kmsg *get_next_msg(struct channel *channel)
{
unsigned long flags;
struct btree_node *cur = btree_first(&channel->c_msg);
while (cur) {
struct kmsg *msg = BTREE_CONTAINER(struct kmsg, msg_node, cur);
spin_lock_irqsave(&msg->msg_lock, &flags);
if (msg->msg_status == KMSG_WAIT_RECEIVE) {
msg->msg_status = KMSG_WAIT_REPLY;
return msg;
}
spin_unlock_irqrestore(&msg->msg_lock, flags);
cur = btree_next(cur);
}
return NULL;
}
extern kern_status_t channel_enqueue_msg(
struct channel *channel,
struct kmsg *msg)
{
fill_random(&msg->msg_id, sizeof msg->msg_id);
while (!try_enqueue(&channel->c_msg, msg)) {
msg->msg_id++;
}
wakeup_one(&channel->c_wq);
return KERN_OK;
}
extern kern_status_t channel_recv_msg(
struct channel *channel,
struct msg *out_msg,
msgid_t *out_id,
unsigned long *irq_flags)
{
struct wait_item waiter;
struct thread *self = current_thread();
struct kmsg *msg = NULL;
wait_item_init(&waiter, self);
for (;;) {
thread_wait_begin(&waiter, &channel->c_wq);
msg = get_next_msg(channel);
if (msg) {
break;
}
object_unlock_irqrestore(&channel->c_base, *irq_flags);
schedule(SCHED_NORMAL);
object_lock_irqsave(&channel->c_base, irq_flags);
}
thread_wait_end(&waiter, &channel->c_wq);
/* msg is now set to the next message to process */
struct task *sender = msg->msg_sender_thread->tr_parent;
struct task *receiver = self->tr_parent;
kern_status_t status = vm_region_memmove_v(
receiver->t_address_space,
0,
out_msg->msg_data,
out_msg->msg_data_count,
sender->t_address_space,
0,
msg->msg_req->msg_data,
msg->msg_req->msg_data_count,
VM_REGION_COPY_ALL);
if (status != KERN_OK) {
kmsg_reply_error(msg, status);
return status;
}
status = handle_list_transfer(
receiver->t_handles,
out_msg->msg_handles,
out_msg->msg_handles_count,
sender->t_handles,
msg->msg_req->msg_handles,
msg->msg_req->msg_handles_count);
if (status != KERN_OK) {
kmsg_reply_error(msg, status);
return status;
}
kmsg_reply_error(msg, KERN_OK);
return KERN_OK;
}
extern kern_status_t channel_reply_msg(
struct channel *channel,
msgid_t id,
const struct msg *resp,
unsigned long *irq_flags)
{
struct kmsg *msg = get_msg_with_id(&channel->c_msg, id);
if (!msg || msg->msg_status != KMSG_WAIT_REPLY) {
return KERN_INVALID_ARGUMENT;
}
struct thread *self = current_thread();
struct task *sender = msg->msg_sender_thread->tr_parent;
struct task *receiver = self->tr_parent;
kern_status_t status = vm_region_memmove_v(
receiver->t_address_space,
0,
msg->msg_resp->msg_data,
msg->msg_resp->msg_data_count,
sender->t_address_space,
0,
resp->msg_data,
resp->msg_data_count,
VM_REGION_COPY_ALL);
if (status != KERN_OK) {
kmsg_reply_error(msg, status);
return status;
}
status = handle_list_transfer(
receiver->t_handles,
msg->msg_resp->msg_handles,
msg->msg_resp->msg_handles_count,
sender->t_handles,
resp->msg_handles,
resp->msg_handles_count);
if (status != KERN_OK) {
kmsg_reply_error(msg, status);
return status;
}
msg->msg_status = KERN_OK;
msg->msg_status = KMSG_REPLY_SENT;
return KERN_UNIMPLEMENTED;
}
extern kern_status_t channel_read_msg(
struct channel *channel,
msgid_t msg,
size_t offset,
void *buf,
size_t len,
size_t *nr_read)
{
return KERN_UNIMPLEMENTED;
}
extern kern_status_t channel_write_msg(
struct channel *channel,
msgid_t msg,
size_t offset,
const void *buf,
size_t len,
size_t *nr_written)
{
return KERN_UNIMPLEMENTED;
}

View File

@@ -1,6 +1,6 @@
#include <mango/clock.h>
#include <mango/printk.h>
#include <mango/compiler.h>
#include <kernel/clock.h>
#include <kernel/printk.h>
#include <kernel/compiler.h>
static clock_ticks_t ticks_per_sec = 0;
volatile clock_ticks_t clock_ticks = 0;

View File

@@ -1,7 +1,7 @@
#include <mango/console.h>
#include <mango/queue.h>
#include <mango/locks.h>
#include <mango/libc/string.h>
#include <kernel/console.h>
#include <kernel/queue.h>
#include <kernel/locks.h>
#include <kernel/libc/string.h>
static struct queue consoles;
static spin_lock_t consoles_lock = SPIN_LOCK_INIT;

View File

@@ -1,6 +1,6 @@
#include <mango/cpu.h>
#include <mango/percpu.h>
#include <mango/bitmap.h>
#include <kernel/cpu.h>
#include <kernel/percpu.h>
#include <kernel/bitmap.h>
DECLARE_BITMAP(cpu_available, CPU_MAX);
DECLARE_BITMAP(cpu_online, CPU_MAX);

View File

@@ -1,10 +1,13 @@
#include <mango/handle.h>
#include <mango/libc/string.h>
#include <mango/object.h>
#include <mango/vm.h>
#include <kernel/handle.h>
#include <kernel/libc/string.h>
#include <kernel/object.h>
#include <kernel/sched.h>
#include <kernel/util.h>
#include <kernel/vm.h>
/* depth=3 gives a maximum of ~66.6 million handles */
#define MAX_TABLE_DEPTH 3
#define MAX_TABLE_DEPTH 3
#define RESERVED_HANDLES 64
static struct vm_cache handle_table_cache = {
.c_name = "handle_table",
@@ -36,7 +39,6 @@ static kern_status_t decode_handle_indices(
kern_handle_t handle,
unsigned int indices[MAX_TABLE_DEPTH])
{
handle >>= 2;
for (int i = 0; i < MAX_TABLE_DEPTH; i++) {
unsigned int div = (i > 0 ? REFS_PER_TABLE : HANDLES_PER_TABLE);
@@ -61,8 +63,6 @@ static kern_status_t encode_handle_indices(
mul *= REFS_PER_TABLE;
}
handle <<= 2;
*out_handle = handle;
return KERN_OK;
}
@@ -74,6 +74,7 @@ kern_status_t handle_table_alloc_handle(
{
int i;
unsigned int indices[MAX_TABLE_DEPTH] = {0};
static const unsigned int reserved_indices[MAX_TABLE_DEPTH] = {0};
for (i = 0; i < MAX_TABLE_DEPTH - 1; i++) {
unsigned int next_index = bitmap_lowest_clear(
@@ -99,6 +100,10 @@ kern_status_t handle_table_alloc_handle(
tab = next;
}
if (memcmp(indices, reserved_indices, sizeof indices) == 0) {
bitmap_fill(tab->t_handles.t_handle_map, RESERVED_HANDLES);
}
unsigned int handle_index = bitmap_lowest_clear(
tab->t_handles.t_handle_map,
HANDLES_PER_TABLE);
@@ -117,11 +122,13 @@ kern_status_t handle_table_alloc_handle(
return encode_handle_indices(indices, out_handle);
}
void handle_table_free_handle(struct handle_table *tab, kern_handle_t handle)
kern_status_t handle_table_free_handle(
struct handle_table *tab,
kern_handle_t handle)
{
unsigned int indices[MAX_TABLE_DEPTH];
if (decode_handle_indices(handle, indices) != KERN_OK) {
return;
return KERN_NO_ENTRY;
}
int i;
@@ -129,7 +136,7 @@ void handle_table_free_handle(struct handle_table *tab, kern_handle_t handle)
struct handle_table *next
= tab->t_subtables.t_subtable_list[indices[i]];
if (!next) {
return;
return KERN_NO_ENTRY;
}
bitmap_clear(tab->t_subtables.t_subtable_map, indices[i]);
@@ -137,6 +144,10 @@ void handle_table_free_handle(struct handle_table *tab, kern_handle_t handle)
}
unsigned int handle_index = indices[i];
if (!bitmap_check(tab->t_handles.t_handle_map, handle_index)) {
return KERN_NO_ENTRY;
}
bitmap_clear(tab->t_handles.t_handle_map, handle_index);
struct handle *handle_entry
= &tab->t_handles.t_handle_list[handle_index];
@@ -146,6 +157,7 @@ void handle_table_free_handle(struct handle_table *tab, kern_handle_t handle)
}
memset(handle_entry, 0x0, sizeof *handle_entry);
return KERN_OK;
}
struct handle *handle_table_get_handle(
@@ -173,5 +185,129 @@ struct handle *handle_table_get_handle(
return NULL;
}
if (!tab->t_handles.t_handle_list[handle_index].h_object) {
return NULL;
}
return &tab->t_handles.t_handle_list[handle_index];
}
struct handle_list_iterator {
struct handle_list *it_list;
size_t it_list_count;
size_t it_list_ptr;
kern_handle_t *it_handles;
size_t it_nr_handles;
};
static void handle_list_iterator_begin(
struct handle_list_iterator *it,
struct handle_list *list,
size_t list_count)
{
memset(it, 0x0, sizeof *it);
it->it_list = list;
it->it_list_count = list_count;
while (it->it_list_ptr < list_count) {
if (list[it->it_list_ptr].l_nr_handles > 0) {
break;
}
it->it_list_ptr++;
}
if (it->it_list_ptr >= list_count) {
return;
}
it->it_handles = list[it->it_list_ptr].l_handles;
it->it_nr_handles = list[it->it_list_ptr].l_nr_handles;
}
static void handle_list_iterator_seek(
struct handle_list_iterator *it,
size_t nr_handles)
{
if (nr_handles > it->it_nr_handles) {
nr_handles = it->it_nr_handles;
}
if (nr_handles < it->it_nr_handles) {
it->it_handles += nr_handles;
it->it_nr_handles -= nr_handles;
return;
}
it->it_list_ptr++;
while (it->it_list_ptr < it->it_list_count) {
if (it->it_list[it->it_list_ptr].l_nr_handles > 0) {
break;
}
it->it_list_ptr++;
}
if (it->it_list_ptr >= it->it_list_count) {
return;
}
it->it_handles = it->it_list[it->it_list_ptr].l_handles;
it->it_nr_handles = it->it_list[it->it_list_ptr].l_nr_handles;
}
kern_status_t handle_list_transfer(
struct handle_table *dest_table,
struct handle_list *dest_list,
size_t dest_list_count,
struct handle_table *src_table,
const struct handle_list *src_list,
size_t src_list_count)
{
struct handle_list_iterator src, dest;
handle_list_iterator_begin(
&src,
(struct handle_list *)src_list,
src_list_count);
handle_list_iterator_begin(&dest, dest_list, dest_list_count);
while (src.it_nr_handles && dest.it_nr_handles) {
size_t to_copy = MIN(src.it_nr_handles, dest.it_nr_handles);
for (size_t i = 0; i < to_copy; i++) {
kern_handle_t handle_v = src.it_handles[i];
struct handle *handle
= handle_table_get_handle(src_table, handle_v);
if (!handle) {
return KERN_HANDLE_INVALID;
}
struct object *obj = object_ref(handle->h_object);
handle_flags_t flags = handle->h_flags;
handle_table_free_handle(src_table, handle_v);
struct handle *dest_slot = NULL;
kern_status_t status = handle_table_alloc_handle(
dest_table,
&dest_slot,
&handle_v);
if (status != KERN_OK) {
return status;
}
dest_slot->h_object = obj;
dest_slot->h_flags = flags;
object_add_handle(obj);
object_unref(obj);
dest.it_handles[i] = handle_v;
}
handle_list_iterator_seek(&src, to_copy);
handle_list_iterator_seek(&dest, to_copy);
}
return KERN_OK;
}

59
kernel/iovec.c Normal file
View File

@@ -0,0 +1,59 @@
#include <kernel/iovec.h>
#include <kernel/libc/string.h>
#include <kernel/util.h>
void iovec_iterator_begin(
struct iovec_iterator *it,
const struct iovec *vecs,
size_t nr_vecs)
{
memset(it, 0x0, sizeof *it);
it->it_vecs = vecs;
it->it_nr_vecs = nr_vecs;
while (it->it_vec_ptr < nr_vecs) {
if (vecs[it->it_vec_ptr].io_len > 0) {
break;
}
it->it_vec_ptr++;
}
if (it->it_vec_ptr >= nr_vecs) {
return;
}
it->it_base = vecs[it->it_vec_ptr].io_base;
it->it_len = vecs[it->it_vec_ptr].io_len;
}
void iovec_iterator_seek(struct iovec_iterator *it, size_t nr_bytes)
{
while (nr_bytes > 0) {
size_t to_seek = MIN(nr_bytes, it->it_len);
if (to_seek < it->it_len) {
it->it_len -= to_seek;
it->it_base += to_seek;
break;
}
nr_bytes -= to_seek;
it->it_vec_ptr++;
while (it->it_vec_ptr < it->it_nr_vecs) {
if (it->it_vecs[it->it_vec_ptr].io_len > 0) {
break;
}
it->it_vec_ptr++;
}
if (it->it_vec_ptr >= it->it_nr_vecs) {
return;
}
it->it_base = it->it_vecs[it->it_vec_ptr].io_base;
it->it_len = it->it_vecs[it->it_vec_ptr].io_len;
}
}

View File

@@ -1,6 +1,6 @@
#include <mango/locks.h>
#include <mango/object.h>
#include <mango/queue.h>
#include <kernel/locks.h>
#include <kernel/object.h>
#include <kernel/queue.h>
#define HAS_OP(obj, opname) ((obj)->ob_type->ob_ops.opname)

View File

@@ -1,8 +1,8 @@
#include <mango/cpu.h>
#include <mango/libc/stdio.h>
#include <mango/machine/panic.h>
#include <mango/printk.h>
#include <mango/sched.h>
#include <kernel/cpu.h>
#include <kernel/libc/stdio.h>
#include <kernel/machine/panic.h>
#include <kernel/printk.h>
#include <kernel/sched.h>
#include <stdarg.h>
static int has_panicked = 0;

View File

@@ -1,6 +1,6 @@
#include <mango/percpu.h>
#include <mango/cpu.h>
#include <mango/vm.h>
#include <kernel/percpu.h>
#include <kernel/cpu.h>
#include <kernel/vm.h>
#include <stdint.h>
#include <stddef.h>

78
kernel/port.c Normal file
View File

@@ -0,0 +1,78 @@
#include <kernel/channel.h>
#include <kernel/port.h>
#include <kernel/util.h>
#define PORT_CAST(p) OBJECT_C_CAST(struct port, p_base, &port_type, p)
static struct object_type port_type = {
.ob_name = "port",
.ob_size = sizeof(struct port),
.ob_header_offset = offsetof(struct port, p_base),
};
kern_status_t port_type_init(void)
{
return object_type_register(&port_type);
}
struct port *port_cast(struct object *obj)
{
return PORT_CAST(obj);
}
static void wait_for_reply(struct port *port)
{
}
struct port *port_create(void)
{
struct object *port_object = object_create(&port_type);
if (!port_object) {
return NULL;
}
struct port *port = PORT_CAST(port_object);
port->p_status = PORT_OFFLINE;
return port;
}
kern_status_t port_connect(struct port *port, struct channel *remote)
{
if (port->p_status != PORT_OFFLINE) {
return KERN_BAD_STATE;
}
port->p_remote = remote;
port->p_status = PORT_READY;
return KERN_OK;
}
kern_status_t port_send_msg(
struct port *port,
const struct msg *req,
struct msg *resp)
{
if (port->p_status != PORT_READY) {
return KERN_BAD_STATE;
}
struct thread *self = current_thread();
struct kmsg *msg = &self->tr_msg;
msg->msg_sender_thread = self;
msg->msg_sender_port = port;
msg->msg_req = req;
msg->msg_resp = resp;
unsigned long flags;
channel_lock_irqsave(port->p_remote, &flags);
channel_enqueue_msg(port->p_remote, msg);
channel_unlock_irqrestore(port->p_remote, flags);
port->p_status = PORT_SEND_BLOCKED;
wait_for_reply(port);
return msg->msg_result;
}

View File

@@ -1,7 +1,7 @@
#include <mango/printk.h>
#include <mango/locks.h>
#include <mango/console.h>
#include <mango/libc/stdio.h>
#include <kernel/printk.h>
#include <kernel/locks.h>
#include <kernel/console.h>
#include <kernel/libc/stdio.h>
#include <stdarg.h>
#define LOG_BUFFER_SIZE 0x40000

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_LIBC_TYPES_H_
#define MANGO_LIBC_TYPES_H_
#ifndef KERNEL_LIBC_TYPES_H_
#define KERNEL_LIBC_TYPES_H_
#ifdef __cplusplus
extern "C" {

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_STDIO_H_
#define MANGO_STDIO_H_
#ifndef KERNEL_STDIO_H_
#define KERNEL_STDIO_H_
#include <stdarg.h>
#include <stddef.h>

View File

@@ -1,5 +1,5 @@
#ifndef MANGO_LIBC_STRING_H_
#define MANGO_LIBC_STRING_H_
#ifndef KERNEL_LIBC_STRING_H_
#define KERNEL_LIBC_STRING_H_
#include <stdint.h>
#include <stddef.h>

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
#include <stdint.h>
#include <mango/libc/string.h>
#include <kernel/libc/string.h>
static void *memcpy_r(void *dest, const void *src, size_t sz)
{

View File

@@ -2,12 +2,12 @@
void *memset(void *str, int c, size_t n)
{
unsigned char val = (unsigned char)c;
unsigned char *buf = str;
unsigned char val = (unsigned char)c;
unsigned char *buf = str;
for (size_t i = 0; i < n; i++) {
buf[i] = val;
}
for (size_t i = 0; i < n; i++) {
buf[i] = val;
}
return str;
return str;
}

View File

@@ -1,4 +1,4 @@
#include <mango/libc/string.h>
#include <kernel/libc/string.h>
char *strcat(char *dest, const char *src) {
size_t start = strlen(dest), i = 0;

View File

@@ -1,19 +1,21 @@
int strcmp(const char *s1, const char *s2)
{
int i;
for (i = 0; s1[i] == s2[i]; i++)
if (s1[i] == '\0')
return 0;
int i;
for (i = 0; s1[i] == s2[i]; i++)
if (s1[i] == '\0')
return 0;
return s1[i] - s2[i];
return s1[i] - s2[i];
}
int strncmp(const char *s1, const char *s2, unsigned long n)
{
for (; n > 0; s1++, s2++, --n)
if (*s1 != *s2)
return ((*(unsigned char *)s1 < *(unsigned char *)s2) ? -1 : 1);
else if (*s1 == '\0')
return 0;
return 0;
for (; n > 0; s1++, s2++, --n)
if (*s1 != *s2)
return ((*(unsigned char *)s1 < *(unsigned char *)s2)
? -1
: 1);
else if (*s1 == '\0')
return 0;
return 0;
}

View File

@@ -1,4 +1,4 @@
#include <mango/libc/string.h>
#include <kernel/libc/string.h>
char *strcpy(char *output, const char *input)
{

View File

@@ -1,10 +1,11 @@
#include <mango/libc/string.h>
#include <kernel/libc/string.h>
size_t strlen(const char *str) {
size_t strlen(const char *str)
{
size_t res = 0;
while (str[res]) {
res++;
}
return res;
}

View File

@@ -1,4 +1,4 @@
#include <mango/libc/string.h>
#include <kernel/libc/string.h>
char *strrchr(const char *str, int c) {
size_t len = strlen(str);

View File

@@ -1,5 +1,5 @@
#include <limits.h>
#include <mango/libc/string.h>
#include <kernel/libc/string.h>
#define ALIGN (sizeof(size_t))
#define ONES ((size_t)-1 / UCHAR_MAX)

Some files were not shown because too many files have changed in this diff Show More