Kernel, libc and userspace: Add basic errno support.
Kernel: Add an errno.h header with definitions for each header, and return those, negated, from syscalls when there is an error. mmap() returns an invalid address with errno encoded, instead of returning a negated errno; this address is encoded as ffffffffffffffEE where EE is errno in hex. libc: make syscall() return -1 and set errno on error, instead of returning the raw return value of the system call. Also, add mmap() and munmap() wrappers in sys/mman.h :). userspace: make the memeater program show the value of errno when allocating memory fails. Things to improve: add perror() and strerror() to make the errno experience even better! >.<
This commit is contained in:
parent
ad115e9bab
commit
71e15e94af
@ -1,3 +1,4 @@
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@ -13,5 +14,6 @@ int main()
|
||||
printf("Allocating 4 MB of memory... %lx\n", (unsigned long)allocated);
|
||||
sleep(1);
|
||||
} while ((allocated = malloc(CHUNK)));
|
||||
printf("Out of memory.\n");
|
||||
printf("Out of memory. (errno=%d)\n", errno);
|
||||
printf("Press any key to restart.\n");
|
||||
}
|
5
kernel/include/errno.h
Normal file
5
kernel/include/errno.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#define EPERM 1
|
||||
#define ENOMEM 12
|
||||
#define EINVAL 22
|
@ -1,17 +1,20 @@
|
||||
#define MODULE "mem"
|
||||
|
||||
#include "errno.h"
|
||||
#include "interrupts/Context.h"
|
||||
#include "log/Log.h"
|
||||
#include "memory/MemoryManager.h"
|
||||
#include "memory/VMM.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#define MAP_FAIL(errno) 0xffffffffffffff00 | (unsigned char)(errno)
|
||||
|
||||
void sys_mmap(Context* context, void* address, size_t size, int flags)
|
||||
{
|
||||
if (size < 4096)
|
||||
{
|
||||
kdbgln("sys_mmap: size too small");
|
||||
context->rax = 0;
|
||||
context->rax = MAP_FAIL(EINVAL);
|
||||
return;
|
||||
}
|
||||
int real_flags = MAP_USER;
|
||||
@ -23,7 +26,7 @@ void sys_mmap(Context* context, void* address, size_t size, int flags)
|
||||
if (kernelVMM.getPhysical((uint64_t)address) != (uint64_t)-1) // Address is already used.
|
||||
{
|
||||
kdbgln("attempt to mmap an already mapped address");
|
||||
context->rax = 0;
|
||||
context->rax = MAP_FAIL(ENOMEM);
|
||||
return;
|
||||
}
|
||||
uint64_t offset = (uint64_t)address % 4096;
|
||||
@ -37,7 +40,7 @@ void sys_mmap(Context* context, void* address, size_t size, int flags)
|
||||
else
|
||||
{
|
||||
kdbgln("mmap failed");
|
||||
context->rax = 0;
|
||||
context->rax = MAP_FAIL(ENOMEM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -52,7 +55,7 @@ void sys_mmap(Context* context, void* address, size_t size, int flags)
|
||||
else
|
||||
{
|
||||
kdbgln("mmap failed");
|
||||
context->rax = 0;
|
||||
context->rax = MAP_FAIL(ENOMEM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -60,17 +63,23 @@ void sys_mmap(Context* context, void* address, size_t size, int flags)
|
||||
void sys_munmap(Context* context, void* address, size_t size)
|
||||
{
|
||||
kdbgln("sys_munmap: attempting to unmap %lx", (uint64_t)address);
|
||||
if (size < 4096)
|
||||
{
|
||||
kdbgln("munmap failed: size is too small");
|
||||
context->rax = -EINVAL;
|
||||
return;
|
||||
}
|
||||
if (!address)
|
||||
{
|
||||
kdbgln("munmap failed: attempted to unmap page 0");
|
||||
context->rax = -1;
|
||||
context->rax = -EINVAL;
|
||||
return;
|
||||
}
|
||||
uint64_t flags = kernelVMM.getFlags((uint64_t)address);
|
||||
if (!(flags & MAP_USER))
|
||||
{
|
||||
kdbgln("munmap failed: attempted to unmap a kernel page");
|
||||
context->rax = -1;
|
||||
context->rax = -EINVAL;
|
||||
return;
|
||||
}
|
||||
uint64_t offset = (uint64_t)address % 4096;
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "bootboot.h"
|
||||
#include "errno.h"
|
||||
#include "interrupts/Context.h"
|
||||
#include "render/Framebuffer.h"
|
||||
#include <stdint.h>
|
||||
@ -9,12 +10,12 @@ void sys_paint(Context* context, uint64_t x, uint64_t y, uint64_t w, uint64_t h,
|
||||
{
|
||||
if ((x + w) > bootboot.fb_width)
|
||||
{
|
||||
context->rax = -1;
|
||||
context->rax = -EINVAL;
|
||||
return;
|
||||
}
|
||||
if ((y + h) > bootboot.fb_height)
|
||||
{
|
||||
context->rax = -1;
|
||||
context->rax = -EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,19 @@
|
||||
#include "config.h"
|
||||
#include "errno.h"
|
||||
#include "interrupts/Context.h"
|
||||
#include "std/stdio.h"
|
||||
|
||||
void sys_getversion(Context* context, char* buffer, size_t max)
|
||||
{
|
||||
if (!max)
|
||||
{
|
||||
context->rax = -EINVAL;
|
||||
return;
|
||||
}
|
||||
if (!buffer)
|
||||
{
|
||||
context->rax = -EINVAL;
|
||||
return;
|
||||
}
|
||||
context->rax = snprintf(buffer, max, "moon %s", moon_version());
|
||||
}
|
26
libs/libc/include/bits/error.h
Normal file
26
libs/libc/include/bits/error.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef _BITS_ERROR_H
|
||||
#define _BITS_ERROR_H
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define _RETURN_WITH_ERRNO(rc, type) \
|
||||
do { \
|
||||
if (rc < 0) \
|
||||
{ \
|
||||
errno = (int)rc; \
|
||||
return -1; \
|
||||
} \
|
||||
return (type)rc; \
|
||||
} while (0)
|
||||
|
||||
#define _RETURN_WITH_MEMORY_ERRNO(rc, type) \
|
||||
do { \
|
||||
if ((unsigned long int)rc > 0xffffffffffffff00) \
|
||||
{ \
|
||||
errno = (int)((rc)&0xff); \
|
||||
return (type)-1; \
|
||||
} \
|
||||
return (type)rc; \
|
||||
} while (0)
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
#ifndef __BITS_MACROS_H
|
||||
#define __BITS_MACROS_H
|
||||
#ifndef _BITS_MACROS_H
|
||||
#define _BITS_MACROS_H
|
||||
|
||||
#define noreturn __attribute__((noreturn))
|
||||
#define align(n) __attribute__((aligned(n)))
|
||||
|
@ -0,0 +1,10 @@
|
||||
#ifndef _ERRNO_H
|
||||
#define _ERRNO_H
|
||||
|
||||
extern int errno;
|
||||
|
||||
#define EPERM 1
|
||||
#define ENOMEM 12
|
||||
#define EINVAL 22
|
||||
|
||||
#endif
|
22
libs/libc/include/sys/mman.h
Normal file
22
libs/libc/include/sys/mman.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef _SYS_MMAN_H
|
||||
#define _SYS_MMAN_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef unsigned long off_t;
|
||||
|
||||
#define MAP_FAILED (void*)-1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void* mmap(void*, size_t, int, int, int, off_t);
|
||||
int munmap(void* addr, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,6 +1,5 @@
|
||||
#include <stddef.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
int liballoc_lock()
|
||||
{
|
||||
@ -14,14 +13,12 @@ int liballoc_unlock()
|
||||
|
||||
void* liballoc_alloc(size_t size)
|
||||
{
|
||||
unsigned long int result = (unsigned long int)syscall(SYS_mmap, NULL, size * 4096, 1);
|
||||
void* result = mmap(NULL, size * 4096, 0, 1, 0, 0);
|
||||
if (result == MAP_FAILED) return 0;
|
||||
return (void*)result;
|
||||
}
|
||||
|
||||
int liballoc_free(void* address, size_t size)
|
||||
{
|
||||
int result = (int)syscall(SYS_munmap, address, size * 4096);
|
||||
if (result < 0) return 1;
|
||||
else
|
||||
return 0;
|
||||
return munmap(address, size * 4096);
|
||||
}
|
3
libs/libc/src/errno.cpp
Normal file
3
libs/libc/src/errno.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include <errno.h>
|
||||
|
||||
int errno;
|
@ -1,4 +1,5 @@
|
||||
#include <luna.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
@ -20,7 +21,6 @@ extern "C"
|
||||
noreturn void __luna_abort(const char* message)
|
||||
{
|
||||
syscall(SYS_write, message, strlen(message));
|
||||
syscall(SYS_exit);
|
||||
__builtin_unreachable();
|
||||
abort();
|
||||
}
|
||||
}
|
@ -50,6 +50,7 @@ extern "C"
|
||||
int puts(const char* s)
|
||||
{
|
||||
long nwritten = syscall(SYS_write, s, strlen(s));
|
||||
if (nwritten < 0) return -1;
|
||||
nwritten += syscall(SYS_write, "\n", 1);
|
||||
return (int)nwritten;
|
||||
}
|
||||
|
17
libs/libc/src/sys/mman.cpp
Normal file
17
libs/libc/src/sys/mman.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
// FIXME: Implement a POSIX-compliant mmap.
|
||||
void* mmap(void* addr, size_t len, int, int flags, int, off_t)
|
||||
{
|
||||
return (void*)syscall(SYS_mmap, addr, len, flags);
|
||||
}
|
||||
|
||||
int munmap(void* addr, size_t len)
|
||||
{
|
||||
return (int)syscall(SYS_munmap, addr, len);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
#include <bits/error.h>
|
||||
#include <luna.h>
|
||||
#include <luna/syscall.h>
|
||||
#include <stdarg.h>
|
||||
@ -62,7 +63,8 @@ extern "C"
|
||||
default: result = -1; break;
|
||||
}
|
||||
va_end(ap);
|
||||
return result;
|
||||
if (number == SYS_mmap) { _RETURN_WITH_MEMORY_ERRNO(result, long int); }
|
||||
else { _RETURN_WITH_ERRNO(result, long); }
|
||||
}
|
||||
|
||||
unsigned int sleep(unsigned int seconds)
|
||||
|
Loading…
Reference in New Issue
Block a user