diff --git a/kernel/mm/mm.c b/kernel/mm/mm.c index 195b9d76..4efc0863 100644 --- a/kernel/mm/mm.c +++ b/kernel/mm/mm.c @@ -680,13 +680,15 @@ void mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_ uint64_t mm_do_brk(uint64_t old_brk_end_addr, int64_t offset) { // 暂不支持缩小堆内存 - if(offset <0) + if (offset < 0) return old_brk_end_addr; uint64_t end_addr = old_brk_end_addr + offset; for (uint64_t i = old_brk_end_addr; i < end_addr; i += PAGE_2M_SIZE) - mm_map_proc_page_table(current_pcb->mm->pgd, true, i, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED), PAGE_2M_SIZE, PAGE_USER_PAGE, true); - + { + kdebug("map [%d]", i); + mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, i, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true); + } current_pcb->mm->brk_end = end_addr; return end_addr; } \ No newline at end of file diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index d12c993d..03e646f3 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -345,30 +345,58 @@ uint64_t sys_vfork(struct pt_regs *regs) } /** - * @brief 堆内存调整 + * @brief 将堆内存调整为arg0 * * @param arg0 新的堆区域的结束地址 - * @return uint64_t 调整后的堆区域的结束地址 + * arg0=-1 ===> 返回堆区域的起始地址 + * arg0=-2 ===> 返回堆区域的结束地址 + * @return uint64_t 错误码 + * */ uint64_t sys_brk(struct pt_regs *regs) { uint64_t new_brk = PAGE_2M_ALIGN(regs->r8); - kdebug("sys_brk input= %#010lx bytes, new_brk= %#010lx bytes current->end_brk=%#018lx", regs->r8, new_brk, current_pcb->mm->brk_end); + kdebug("sys_brk input= %#010lx , new_brk= %#010lx bytes current_pcb->mm->brk_start=%#018lx current->end_brk=%#018lx", regs->r8, new_brk, current_pcb->mm->brk_start, current_pcb->mm->brk_end); - if (new_brk == 0) + if ((int64_t)regs->r8 == -1) + { + kdebug("get brk_start=%#018lx", current_pcb->mm->brk_start); + return 0; return current_pcb->mm->brk_start; - - if(new_brk > current_pcb->addr_limit) // 堆地址空间超过限制 - return -EADDRNOTAVAIL; - + } + if ((int64_t)regs->r8 == -2) + { + kdebug("get brk_end=%#018lx", current_pcb->mm->brk_end); + return current_pcb->mm->brk_end; + } + if (new_brk > current_pcb->addr_limit) // 堆地址空间超过限制 + return -ENOMEM; + if (new_brk < current_pcb->mm->brk_end) // todo: 释放堆内存空间 return 0; new_brk = mm_do_brk(current_pcb->mm->brk_end, new_brk - current_pcb->mm->brk_end); // 扩展堆内存空间 current_pcb->mm->brk_end = new_brk; - return new_brk; + return 0; +} + +/** + * @brief 将堆内存空间加上offset(注意,该系统调用只应在普通进程中调用,而不能是内核线程) + * + * @param arg0 offset偏移量 + * @return uint64_t the previous program break + */ +uint64_t sys_sbrk(struct pt_regs *regs) +{ + uint64_t retval = current_pcb->mm->brk_end; + regs->r8 = (int64_t)current_pcb->mm->brk_end + (int64_t)regs->r8; + + if (sys_brk(regs) == 0) + return retval; + else + return -ENOMEM; } ul sys_ahci_end_req(struct pt_regs *regs) @@ -380,8 +408,15 @@ ul sys_ahci_end_req(struct pt_regs *regs) // 系统调用的内核入口程序 void do_syscall_int(struct pt_regs *regs, unsigned long error_code) { - + if(regs->rax == SYS_BRK) + { + kdebug("is sysbrk"); + regs->rax = 0xc00000UL; + return; + } ul ret = system_call_table[regs->rax](regs); + if(regs->rax == SYS_BRK) + kdebug("brk ret=%#018lx", ret); regs->rax = ret; // 返回码 } @@ -396,5 +431,7 @@ system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] = [6] = sys_lseek, [7] = sys_fork, [8] = sys_vfork, - [9 ... 254] = system_call_not_exists, + [9] = sys_brk, + [10] = sys_sbrk, + [11 ... 254] = system_call_not_exists, [255] = sys_ahci_end_req}; diff --git a/kernel/syscall/syscall.h b/kernel/syscall/syscall.h index 24a5e4d1..fb89227c 100644 --- a/kernel/syscall/syscall.h +++ b/kernel/syscall/syscall.h @@ -55,6 +55,25 @@ ul system_call_not_exists(struct pt_regs *regs) */ ul sys_printf(struct pt_regs *regs); +/** + * @brief 将堆内存调整为arg0 + * + * @param arg0 新的堆区域的结束地址 + * arg0=0 ===> 返回堆区域的起始地址 + * arg0=-1 ===> 返回堆区域的结束地址 + * @return uint64_t 错误码 + * + */ +uint64_t sys_brk(struct pt_regs *regs); + +/** + * @brief 将堆内存空间加上offset(注意,该系统调用只应在普通进程中调用,而不能是内核线程) + * + * @param arg0 offset偏移量 + * @return uint64_t the previous program break + */ +uint64_t sys_sbrk(struct pt_regs *regs); + ul sys_ahci_end_req(struct pt_regs *regs); // 系统调用的内核入口程序 diff --git a/kernel/syscall/syscall_num.h b/kernel/syscall/syscall_num.h index e892e2c5..9e4f7eb1 100644 --- a/kernel/syscall/syscall_num.h +++ b/kernel/syscall/syscall_num.h @@ -18,5 +18,7 @@ #define SYS_LSEEK 6 #define SYS_FORK 7 #define SYS_VFORK 8 +#define SYS_BRK 9 +#define SYS_SBRK 10 #define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用 \ No newline at end of file diff --git a/user/init.c b/user/init.c index 27e6fa16..67efe1e4 100644 --- a/user/init.c +++ b/user/init.c @@ -1,6 +1,7 @@ #include #include #include +#include int main() { @@ -9,7 +10,11 @@ int main() uint8_t buf[128] = {0}; char tips_str[] = "The first application 'init.bin' started successfully!\n"; put_string(tips_str, COLOR_GREEN, COLOR_BLACK); + + printf("test printf: %s size: %d\n", string, sizeof(string)); int fd = open(string, 0); + printf("fd=%d\n", fd); + /* read(fd, buf, 128); put_string(buf, COLOR_ORANGE, COLOR_BLACK); @@ -25,12 +30,16 @@ int main() read(fd, buf, 128); put_string(buf, COLOR_YELLOW, COLOR_BLACK); close(fd); - + */ + char* p = malloc(100); + printf("p=%lld\n", (uint64_t)p); + // *p = 'a'; + /* pid_t p = fork(); if(p == 0) put_string("subproc\n", COLOR_PURPLE, COLOR_BLACK); else put_string("parent proc\n", COLOR_ORANGE, COLOR_BLACK); - +*/ while (1) ; } \ No newline at end of file diff --git a/user/libs/libc/Makefile b/user/libs/libc/Makefile index 82960d60..dc644236 100644 --- a/user/libs/libc/Makefile +++ b/user/libs/libc/Makefile @@ -2,11 +2,34 @@ all: libc CFLAGS += -I . +libc_sub_dirs=math -libc: unistd.o fcntl.o + +libc: unistd.o fcntl.o malloc.o errno.o printf.o stdlib.o ctype.o + @list='$(libc_sub_dirs)'; for subdir in $$list; do \ + echo "make all in $$subdir";\ + cd $$subdir;\ + $(MAKE) all CFLAGS="$(CFLAGS) -I $(shell pwd)";\ + cd ..;\ + done unistd.o: unistd.c gcc $(CFLAGS) -c unistd.c -o unistd.o fcntl.o: fcntl.c gcc $(CFLAGS) -c fcntl.c -o fcntl.o + +malloc.o: malloc.c + gcc $(CFLAGS) -c malloc.c -o malloc.o + +errno.o: errno.c + gcc $(CFLAGS) -c errno.c -o errno.o + +printf.o: printf.c + gcc $(CFLAGS) -c printf.c -o printf.o + +stdlib.o: stdlib.c + gcc $(CFLAGS) -c stdlib.c -o stdlib.o + +ctype.o: ctype.c + gcc $(CFLAGS) -c ctype.c -o ctype.o \ No newline at end of file diff --git a/user/libs/libc/__libc__.h b/user/libs/libc/__libc__.h new file mode 100644 index 00000000..3147bc74 --- /dev/null +++ b/user/libs/libc/__libc__.h @@ -0,0 +1,20 @@ +#pragma once + +#pragma once + +#ifdef __cplusplus + +# define __BEGIN_HEADER \ + extern "C" \ + { + +# define __END_HEADER \ + } + +#else + +# define __BEGIN_HEADER + +# define __END_HEADER + +#endif \ No newline at end of file diff --git a/user/libs/libc/ctype.c b/user/libs/libc/ctype.c new file mode 100644 index 00000000..384b3e27 --- /dev/null +++ b/user/libs/libc/ctype.c @@ -0,0 +1,75 @@ +#include + + +int isprint(int c) +{ + if (c >= 0x20 && c <= 0x7e) + { + return 1; + } + + return 0; +} + +int islower(int c) +{ + if (c >= 'a' && c <= 'z') + { + return 1; + } + + return 0; +} + +int isupper(int c) +{ + if (c >= 'A' && c <= 'Z') + { + return 1; + } + + return 0; +} + +int isalpha(int c) +{ + if (islower(c) || isupper(c)) + { + return 1; + } + + return 0; +} + +int isdigit(int c) +{ + if (c >= '0' && c <= '9') + { + return 1; + } + + return 0; +} + +int toupper(int c) +{ + if (c >= 'a' && c <= 'z') + { + return c - 'a' + 'A'; + } + return c; +} + +int tolower(int c) +{ + if (c >= 'A' && c <= 'Z') + { + return c - 'A' + 'a'; + } + return c; +} + +int isspace(int c) +{ + return (c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == ' '); +} \ No newline at end of file diff --git a/user/libs/libc/ctype.h b/user/libs/libc/ctype.h new file mode 100644 index 00000000..fea26ea2 --- /dev/null +++ b/user/libs/libc/ctype.h @@ -0,0 +1,38 @@ +#pragma once + +#include + +#pragma once + +#include + + +int isalnum(int c); +int isalpha(int c); +int isdigit(int c); +int islower(int c); +int isprint(int c); +int isgraph(int c); +int iscntrl(int c); +int isgraph(int c); +int ispunct(int c); +int isspace(int c); +int isupper(int c); +int isxdigit(int c); + +int isascii(int c); + +int tolower(int c); +int toupper(int c); + +#define _U 01 +#define _L 02 +#define _N 04 +#define _S 010 +#define _P 020 +#define _C 040 +#define _X 0100 +#define _B 0200 + +extern char _ctype_[256]; + diff --git a/user/libs/libc/errno.c b/user/libs/libc/errno.c new file mode 100644 index 00000000..0efabf5d --- /dev/null +++ b/user/libs/libc/errno.c @@ -0,0 +1,2 @@ +#include "errno.h" +int errno = 0; \ No newline at end of file diff --git a/user/libs/libc/errno.h b/user/libs/libc/errno.h index a1ebef05..d2902ddc 100644 --- a/user/libs/libc/errno.h +++ b/user/libs/libc/errno.h @@ -98,4 +98,6 @@ #define ETXTBSY 79 /* 文本文件忙 Text file busy. */ #define EWOULDBLOCK 80 /* 操作将被禁止 Operation would block (may be the same value as [EAGAIN]). */ -#define EXDEV 81 /* 跨设备连接 Cross-device link. */ \ No newline at end of file +#define EXDEV 81 /* 跨设备连接 Cross-device link. */ + +extern int errno; \ No newline at end of file diff --git a/user/libs/libc/malloc.c b/user/libs/libc/malloc.c new file mode 100644 index 00000000..041f5d0d --- /dev/null +++ b/user/libs/libc/malloc.c @@ -0,0 +1,392 @@ +#include +#include +#include +#include +#include +#include + +/** + * @brief 显式链表的结点 + * + */ +typedef struct malloc_mem_chunk_t +{ + uint64_t start_addr; // 整个块所在内存区域的起始地址(包括header) + uint64_t length; // 整个块所占用的内存区域的大小 + struct malloc_mem_chunk_t *prev; // 上一个结点的指针 + struct malloc_mem_chunk_t *next; // 下一个结点的指针 +} malloc_mem_chunk_t; + +static uint64_t brk_base_addr = 0; // 堆区域的内存基地址 +static uint64_t brk_max_addr = 0; // 堆区域的内存最大地址 +static uint64_t brk_managed_addr = 0; // 堆区域已经被管理的地址 + +// 空闲链表 +// 按start_addr升序排序 +static malloc_mem_chunk_t *malloc_free_list = NULL; +// 已分配链表 +// 使用LIFO策略。基于假设:程序运行早期分配的内存会被最晚释放 +static malloc_mem_chunk_t *malloc_allocated_list = NULL; + +/** + * @brief 获取一块堆内存(不尝试扩大堆内存) + * + * @param size + * @return void* 内存的地址指针,获取失败时返回-ENOMEM + */ +static void *malloc_no_enlarge(ssize_t size); + +/** + * @brief 将块插入空闲链表 + * + * @param ck 待插入的块 + */ +static void malloc_insert_free_list(malloc_mem_chunk_t *ck); + +/** + * @brief 在链表中检索符合要求的空闲块(best fit) + * + * @param size 块的大小 + * @return malloc_mem_chunk_t* + */ +static malloc_mem_chunk_t *malloc_query_free_chunk_bf(uint64_t size) +{ + // 在满足best fit的前提下,尽可能的使分配的内存在低地址 + // 使得总的堆内存可以更快被释放 + + if (malloc_free_list == NULL) + { + printf("free list is none.\n"); + return NULL; + } + malloc_mem_chunk_t *ptr = malloc_free_list; + malloc_mem_chunk_t *best = NULL; + printf("query size=%d", size); + while (ptr) + { + printf("ptr->length=%#010lx\n", ptr->length); + if (ptr->length == size) + { + best = ptr; + break; + } + + if (ptr->length > size) + { + if (best == NULL) + best = ptr; + else if (best->length > ptr->length) + best = ptr; + } + ptr = ptr->next; + } + + return best; +} + +/** + * @brief 在链表中检索符合要求的空闲块(first fit) + * + * @param size + * @return malloc_mem_chunk_t* + */ +static malloc_mem_chunk_t *malloc_query_free_chunk_ff(uint64_t size) +{ + if (malloc_free_list == NULL) + return NULL; + malloc_mem_chunk_t *ptr = malloc_free_list; + + while (ptr) + { + if (ptr->length >= size) + { + return ptr; + } + ptr = ptr->next; + } + + return NULL; +} + +/** + * @brief 扩容malloc管理的内存区域 + * + * @param size 扩大的内存大小 + */ +static int malloc_enlarge(int32_t size) +{ + if (brk_base_addr == 0) // 第一次调用,需要初始化 + { + brk_base_addr = brk(-1); + printf("brk_base_addr=%#018lx\n", brk_base_addr); + brk_managed_addr = brk_base_addr; + brk_max_addr = brk(-2); + } + + int64_t tmp = brk_managed_addr + size - brk_max_addr; + if (tmp > 0) // 现有堆空间不足 + { + if (sbrk(tmp) != (-1)) + brk_max_addr = brk((-1)); + else + { + put_string("malloc_enlarge(): no_mem", COLOR_YELLOW, COLOR_BLACK); + return -ENOMEM; + } + } + + // 扩展管理的堆空间 + // 在新分配的内存的底部放置header + malloc_mem_chunk_t *new_ck = (malloc_mem_chunk_t *)brk_managed_addr; + new_ck->start_addr = (uint64_t)new_ck; + new_ck->length = brk_max_addr - brk_managed_addr; + printf("new_ck->start_addr=%#018lx\tbrk_max_addr=%#018lx\tbrk_managed_addr=%#018lx\n", new_ck->start_addr, brk_max_addr, brk_managed_addr); + new_ck->prev = new_ck->next = NULL; + brk_managed_addr = brk_max_addr; + + malloc_insert_free_list(new_ck); + + return 0; +} + +/** + * @brief 合并空闲块 + * + */ +static void malloc_merge_free_chunk() +{ + if (malloc_free_list == NULL) + return; + malloc_mem_chunk_t *ptr = malloc_free_list->next; + while (ptr) + { + // 内存块连续 + if (ptr->prev->start_addr + ptr->prev->length == ptr->start_addr) + { + // 将ptr与前面的空闲块合并 + ptr->prev->length += ptr->length; + ptr->prev->next = ptr->next; + // 由于内存组成结构的原因,不需要free掉header + ptr = ptr->prev; + } + ptr = ptr->next; + } +} + +/** + * @brief 将块插入空闲链表 + * + * @param ck 待插入的块 + */ +static void malloc_insert_free_list(malloc_mem_chunk_t *ck) +{ + if (malloc_free_list == NULL) // 空闲链表为空 + { + malloc_free_list = ck; + ck->prev = ck->next = NULL; + return; + } + else + { + uint64_t ck_end = ck->start_addr + ck->length; + malloc_mem_chunk_t *ptr = malloc_free_list; + while (ptr) + { + if (ptr->start_addr < ck->start_addr) + { + if (ptr->next == NULL) // 当前是最后一个项 + { + ptr->next = ck; + ck->next = NULL; + ck->prev = ptr; + break; + } + else if (ptr->next->start_addr > ck->start_addr) + { + ck->prev = ptr; + ck->next = ptr->next; + ck->prev->next = ck; + ck->next->prev = ck; + break; + } + } + else // 在ptr之前插入 + { + + if (ptr->prev == NULL) // 是第一个项 + { + malloc_free_list = ck; + ck->prev = NULL; + ck->next = ptr; + ptr->prev = ck; + break; + } + else + { + ck->prev = ptr->prev; + ck->next = ptr; + ck->prev->next = ck; + ptr->prev = ck; + break; + } + } + ptr = ptr->next; + } + } +} + +/** + * @brief 获取一块堆内存(不尝试扩大堆内存) + * + * @param size + * @return void* 内存的地址指针,获取失败时返回-ENOMEM + */ +static void *malloc_no_enlarge(ssize_t size) +{ + // 加上header的大小 + size += sizeof(malloc_mem_chunk_t); + + // 采用best fit + malloc_mem_chunk_t *ck = malloc_query_free_chunk_bf(size); + + if (ck == NULL) // 没有空闲块 + { + // 尝试合并空闲块 + + malloc_merge_free_chunk(); + ck = malloc_query_free_chunk_bf(size); + + // 找到了合适的块 + if (ck) + goto found; + else + return -ENOMEM; // 内存不足 + } +found:; + // 分配空闲块 + // 从空闲链表取出 + if (ck->prev == NULL) // 当前是链表的第一个块 + { + malloc_free_list = ck->next; + } + else + ck->prev->next = ck->next; + + if (ck->next != NULL) // 当前不是最后一个块 + ck->next->prev = ck->prev; + + // 当前块剩余的空间还能容纳多一个结点的空间,则分裂当前块 + if (ck->length - size > sizeof(malloc_mem_chunk_t)) + { + malloc_mem_chunk_t *new_ck = ((uint64_t)ck) + ck->length; + new_ck->length = ck->length - size; + new_ck->start_addr = (uint64_t)new_ck; + new_ck->prev = new_ck->next = NULL; + + ck->length = size; + malloc_insert_free_list(new_ck); + } + + // 插入到已分配链表 + // 直接插入到链表头,符合LIFO + ck->prev = NULL; + if (malloc_allocated_list) // 已分配链表不为空 + { + malloc_allocated_list->prev = ck; + ck->next = malloc_allocated_list; + malloc_allocated_list = ck; + } + else // 已分配链表为空 + { + malloc_allocated_list = ck; + ck->next = NULL; + } + return (void *)(ck->start_addr + sizeof(malloc_mem_chunk_t)); +} +/** + * @brief 获取一块堆内存 + * + * @param size 内存大小 + * @return void* 内存空间的指针 + */ +void *malloc(ssize_t size) +{ + // 加上header的大小 + size += sizeof(malloc_mem_chunk_t); + + // 采用best fit + malloc_mem_chunk_t *ck = malloc_query_free_chunk_bf(size); + + if (ck == NULL) // 没有空闲块 + { + + // 尝试合并空闲块 + printf("merge\n"); + malloc_merge_free_chunk(); + ck = malloc_query_free_chunk_bf(size); + + // 找到了合适的块 + if (ck) + goto found; + // 找不到合适的块,扩容堆区域 + printf("enlarge\n"); + if (malloc_enlarge(size) == -ENOMEM) + return -ENOMEM; // 内存不足 + // 扩容后再次尝试获取 + printf("query\n"); + ck = malloc_query_free_chunk_bf(size); + } +found:; + if (ck == NULL) + return -ENOMEM; + // 分配空闲块 + // 从空闲链表取出 + if (ck->prev == NULL) // 当前是链表的第一个块 + { + malloc_free_list = ck->next; + } + else + ck->prev->next = ck->next; + + if (ck->next != NULL) // 当前不是最后一个块 + ck->next->prev = ck->prev; + + // 当前块剩余的空间还能容纳多一个结点的空间,则分裂当前块 + if (ck->length - size > sizeof(malloc_mem_chunk_t)) + { + malloc_mem_chunk_t *new_ck = ((uint64_t)ck) + ck->length; + new_ck->length = ck->length - size; + new_ck->start_addr = (uint64_t)new_ck; + new_ck->prev = new_ck->next = NULL; + + ck->length = size; + malloc_insert_free_list(new_ck); + } + + // 插入到已分配链表 + // 直接插入到链表头,符合LIFO + ck->prev = NULL; + if (malloc_allocated_list) // 已分配链表不为空 + { + malloc_allocated_list->prev = ck; + ck->next = malloc_allocated_list; + malloc_allocated_list = ck; + } + else // 已分配链表为空 + { + malloc_allocated_list = ck; + ck->next = NULL; + } + printf("ck=%lld\n", (uint64_t)ck); + printf("ck->start_addr=%lld\n", ck->start_addr); + return (void *)(ck->start_addr + sizeof(malloc_mem_chunk_t)); +} + +/** + * @brief 释放一块堆内存 + * + * @param ptr 堆内存的指针 + */ +void free(void *ptr) +{ +} diff --git a/user/libs/libc/math.h b/user/libs/libc/math.h new file mode 100644 index 00000000..ef470a48 --- /dev/null +++ b/user/libs/libc/math.h @@ -0,0 +1,10 @@ +#pragma once + + +double fabs(double x); +float fabsf(float x); +long double fabsl(long double x); + +double round(double x); +float roundf(float x); +long double roundl(long double x); \ No newline at end of file diff --git a/user/libs/libc/math/Makefile b/user/libs/libc/math/Makefile new file mode 100644 index 00000000..1e62c359 --- /dev/null +++ b/user/libs/libc/math/Makefile @@ -0,0 +1,11 @@ + +all: fabs.o round.o + +CFLAGS += -I . + + +fabs.o: fabs.c + gcc $(CFLAGS) -c fabs.c -o fabs.o + +round.o: round.c + gcc $(CFLAGS) -c round.c -o round.o \ No newline at end of file diff --git a/user/libs/libc/math/fabs.c b/user/libs/libc/math/fabs.c new file mode 100644 index 00000000..c64b1670 --- /dev/null +++ b/user/libs/libc/math/fabs.c @@ -0,0 +1,29 @@ +#include +#include +#include "libm.h" +double fabs(double x) +{ + union + { + double f; + uint64_t i; + } u = {x}; + u.i &= -1ULL / 2; + return u.f; +} + + +#if __LDBL_MANT_DIG__ == 53 && __LDBL_MAX_EXP__ == 1024 +long double fabsl(long double x) +{ + return fabs(x); +} +#elif (__LDBL_MANT_DIG__ == 64 || __LDBL_MANT_DIG__ == 113) && __LDBL_MAX_EXP__ == 16384 +long double fabsl(long double x) +{ + union ldshape u = {x}; + + u.i.se &= 0x7fff; + return u.f; +} +#endif \ No newline at end of file diff --git a/user/libs/libc/math/libm.h b/user/libs/libc/math/libm.h new file mode 100644 index 00000000..8c76e56b --- /dev/null +++ b/user/libs/libc/math/libm.h @@ -0,0 +1,75 @@ +#pragma once +#include + +// ===== 描述long double 的数据比特结构 +#if __LDBL_MANT_DIG__ == 53 && __LDBL_MAX_EXP__ == 1024 +#elif __LDBL_MANT_DIG__ == 64 && __LDBL_MAX_EXP__ == 16384 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +union ldshape +{ + long double f; + struct + { + uint64_t m; + uint16_t se; + } i; +}; +#elif __LDBL_MANT_DIG__ == 113 && __LDBL_MAX_EXP__ == 16384 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +union ldshape +{ + long double f; + struct + { + uint64_t lo; + uint32_t mid; + uint16_t top; + uint16_t se; + } i; + struct + { + uint64_t lo; + uint64_t hi; + } i2; +}; +#elif __LDBL_MANT_DIG__ == 113 && __LDBL_MAX_EXP__ == 16384 && __BYTE_ORDER__ == __BIG_ENDIAN +union ldshape +{ + long double f; + struct + { + uint16_t se; + uint16_t top; + uint32_t mid; + uint64_t lo; + } i; + struct + { + uint64_t hi; + uint64_t lo; + } i2; +}; +#else +#error Unsupported long double representation +#endif + +#define FORCE_EVAL(x) \ + do \ + { \ + if (sizeof(x) == sizeof(float)) \ + { \ + volatile float __x; \ + __x = (x); \ + (void)__x; \ + } \ + else if (sizeof(x) == sizeof(double)) \ + { \ + volatile double __x; \ + __x = (x); \ + (void)__x; \ + } \ + else \ + { \ + volatile long double __x; \ + __x = (x); \ + (void)__x; \ + } \ + } while (0) diff --git a/user/libs/libc/math/round.c b/user/libs/libc/math/round.c new file mode 100644 index 00000000..120cd90f --- /dev/null +++ b/user/libs/libc/math/round.c @@ -0,0 +1,43 @@ + + +#include "libm.h" + +#if __FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1 +#define EPS __DBL_EPSILON__ +#elif __FLT_EVAL_METHOD__ == 2 +#define EPS __LDBL_EPSILON__ +#endif +static const double toint = 1 / EPS; + +double round(double x) +{ + union + { + double f; + uint64_t i; + } u = {x}; + + int e = u.i >> 52 & 0x7ff; + double y; + + if (e >= 0x3ff + 52) + return x; + if (u.i >> 63) + x = -x; + if (e < 0x3ff - 1) + { + /* raise inexact if x!=0 */ + FORCE_EVAL(x + toint); + return 0 * u.f; + } + y = x + toint - toint - x; + if (y > 0.5) + y = y + x - 1; + else if (y <= -0.5) + y = y + x + 1; + else + y = y + x; + if (u.i >> 63) + y = -y; + return y; +} \ No newline at end of file diff --git a/user/libs/libc/printf.c b/user/libs/libc/printf.c new file mode 100644 index 00000000..4002f16d --- /dev/null +++ b/user/libs/libc/printf.c @@ -0,0 +1,536 @@ +#include "printf.h" + +#include +#include +#include +#include +#include + +static char *write_num(char *str, uint64_t num, int base, int field_width, int precision, int flags); +static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags); + +/** + * @brief 往屏幕上输出字符串 + * + * @param str 字符串指针 + * @param front_color 前景色 + * @param bg_color 背景色 + * @return int64_t + */ +int64_t put_string(char *str, uint64_t front_color, uint64_t bg_color) +{ + return syscall_invoke(SYS_PUT_STRING, (uint64_t)str, front_color, bg_color, 0, 0, 0, 0, 0); +} + +int printf(const char *fmt, ...) +{ + char buf[4096]; + int count = 0; + va_list args; + va_start(args, fmt); + + count = vsprintf(buf, fmt, args); + va_end(args); + put_string(buf, COLOR_WHITE, COLOR_BLACK); + return count; +} + +int sprintf(char *buf, const char *fmt, ...) +{ + int count = 0; + va_list args; + + va_start(args, fmt); + count = vsprintf(buf, fmt, args); + va_end(args); + + return count; +} + +int vsprintf(char *buf, const char *fmt, va_list args) +{ + /** + * 将字符串按照fmt和args中的内容进行格式化,然后保存到buf中 + * @param buf 结果缓冲区 + * @param fmt 格式化字符串 + * @param args 内容 + * @return 最终字符串的长度 + */ + + char *str, *s; + + str = buf; + + int flags; // 用来存储格式信息的bitmap + int field_width; //区域宽度 + int precision; //精度 + int qualifier; //数据显示的类型 + int len; + + //开始解析字符串 + for (; *fmt; ++fmt) + { + //内容不涉及到格式化,直接输出 + if (*fmt != '%') + { + *str = *fmt; + ++str; + continue; + } + + //开始格式化字符串 + + //清空标志位和field宽度 + field_width = flags = 0; + + bool flag_tmp = true; + bool flag_break = false; + + ++fmt; + while (flag_tmp) + { + switch (*fmt) + { + case '\0': + //结束解析 + flag_break = true; + flag_tmp = false; + break; + + case '-': + // 左对齐 + flags |= LEFT; + ++fmt; + break; + case '+': + //在正数前面显示加号 + flags |= PLUS; + ++fmt; + break; + case ' ': + flags |= SPACE; + ++fmt; + break; + case '#': + //在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X' + flags |= SPECIAL; + ++fmt; + break; + case '0': + //显示的数字之前填充‘0’来取代空格 + flags |= PAD_ZERO; + ++fmt; + break; + default: + flag_tmp = false; + break; + } + } + if (flag_break) + break; + + //获取区域宽度 + field_width = -1; + if (*fmt == '*') + { + field_width = va_arg(args, int); + ++fmt; + } + else if (is_digit(*fmt)) + { + field_width = atoi(&fmt); + if (field_width < 0) + { + field_width = -field_width; + flags |= LEFT; + } + } + + //获取小数精度 + precision = -1; + if (*fmt == '.') + { + ++fmt; + if (*fmt == '*') + { + precision = va_arg(args, int); + ++fmt; + } + else if is_digit (*fmt) + { + precision = atoi(&fmt); + } + } + + //获取要显示的数据的类型 + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z') + { + qualifier = *fmt; + ++fmt; + } + //为了支持lld + if (qualifier == 'l' && *fmt == 'l', *(fmt + 1) == 'd') + ++fmt; + + //转化成字符串 + long long *ip; + switch (*fmt) + { + //输出 % + case '%': + *str++ = '%'; + + break; + // 显示一个字符 + case 'c': + //靠右对齐 + if (!(flags & LEFT)) + { + while (--field_width > 0) + { + *str = ' '; + ++str; + } + } + + *str++ = (unsigned char)va_arg(args, int); + + while (--field_width > 0) + { + *str = ' '; + ++str; + } + + break; + + //显示一个字符串 + case 's': + s = va_arg(args, char *); + if (!s) + s = '\0'; + len = strlen(s); + if (precision < 0) + { + //未指定精度 + precision = len; + } + + else if (len > precision) + { + len = precision; + } + + //靠右对齐 + if (!(flags & LEFT)) + while (len < field_width--) + { + *str = ' '; + ++str; + } + + for (int i = 0; i < len; i++) + { + *str = *s; + ++s; + ++str; + } + + while (len < field_width--) + { + *str = ' '; + ++str; + } + + break; + //以八进制显示字符串 + case 'o': + flags |= SMALL; + case 'O': + flags |= SPECIAL; + if (qualifier == 'l') + str = write_num(str, va_arg(args, long long), 8, field_width, precision, flags); + else + str = write_num(str, va_arg(args, int), 8, field_width, precision, flags); + break; + + //打印指针指向的地址 + case 'p': + if (field_width == 0) + { + field_width = 2 * sizeof(void *); + flags |= PAD_ZERO; + } + + str = write_num(str, (unsigned long)va_arg(args, void *), 16, field_width, precision, flags); + + break; + + //打印十六进制 + case 'x': + flags |= SMALL; + case 'X': + // flags |= SPECIAL; + if (qualifier == 'l') + str = write_num(str, va_arg(args, int64_t), 16, field_width, precision, flags); + else + str = write_num(str, va_arg(args, int), 16, field_width, precision, flags); + break; + + //打印十进制有符号整数 + case 'i': + case 'd': + + flags |= SIGN; + if (qualifier == 'l') + str = write_num(str, va_arg(args, long long), 10, field_width, precision, flags); + else + str = write_num(str, va_arg(args, int), 10, field_width, precision, flags); + break; + + //打印十进制无符号整数 + case 'u': + if (qualifier == 'l') + str = write_num(str, va_arg(args, unsigned long long), 10, field_width, precision, flags); + else + str = write_num(str, va_arg(args, unsigned int), 10, field_width, precision, flags); + break; + + //输出有效字符数量到*ip对应的变量 + case 'n': + + if (qualifier == 'l') + ip = va_arg(args, long long *); + else + ip = (int64_t *)va_arg(args, int *); + + *ip = str - buf; + break; + case 'f': + // 默认精度为3 + // printk("1111\n"); + // va_arg(args, double); + // printk("222\n"); + + if (precision < 0) + precision = 3; + + str = write_float_point_num(str, va_arg(args, double), field_width, precision, flags); + + break; + + //对于不识别的控制符,直接输出 + default: + *str++ = '%'; + if (*fmt) + *str++ = *fmt; + else + --fmt; + break; + } + } + *str = '\0'; + + //返回缓冲区已有字符串的长度。 + return str - buf; +} + +static char *write_num(char *str, uint64_t num, int base, int field_width, int precision, int flags) +{ + /** + * @brief 将数字按照指定的要求转换成对应的字符串 + * + * @param str 要返回的字符串 + * @param num 要打印的数值 + * @param base 基数 + * @param field_width 区域宽度 + * @param precision 精度 + * @param flags 标志位 + */ + + // 首先判断是否支持该进制 + if (base < 2 || base > 36) + return 0; + char pad, sign, tmp_num[100]; + + const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + // 显示小写字母 + if (flags & SMALL) + digits = "0123456789abcdefghijklmnopqrstuvwxyz"; + + if (flags & LEFT) + flags &= ~PAD_ZERO; + // 设置填充元素 + pad = (flags & PAD_ZERO) ? '0' : ' '; + + sign = 0; + + if (flags & SIGN) + { + int64_t signed_num = (int64_t)num; + if (signed_num < 0) + { + sign = '-'; + num = -signed_num; + } + else + num = signed_num; + } + else + { + // 设置符号 + sign = (flags & PLUS) ? '+' : ((flags & SPACE) ? ' ' : 0); + } + + // sign占用了一个宽度 + if (sign) + --field_width; + + if (flags & SPECIAL) + if (base == 16) // 0x占用2个位置 + field_width -= 2; + else if (base == 8) // O占用一个位置 + --field_width; + + int js_num = 0; // 临时数字字符串tmp_num的长度 + + if (num == 0) + tmp_num[js_num++] = '0'; + else + { + num = llabs(num); + //进制转换 + while (num > 0) + { + tmp_num[js_num++] = digits[num % base]; // 注意这里,输出的数字,是小端对齐的。低位存低位 + num /= base; + } + } + + if (js_num > precision) + precision = js_num; + + field_width -= precision; + + // 靠右对齐 + if (!(flags & (LEFT + PAD_ZERO))) + while (field_width-- > 0) + *str++ = ' '; + + if (sign) + *str++ = sign; + if (flags & SPECIAL) + if (base == 16) + { + *str++ = '0'; + *str++ = digits[33]; + } + else if (base == 8) + *str++ = digits[24]; //注意这里是英文字母O或者o + if (!(flags & LEFT)) + while (field_width-- > 0) + *str++ = pad; + while (js_num < precision) + { + --precision; + *str++ = '0'; + } + + while (js_num-- > 0) + *str++ = tmp_num[js_num]; + + while (field_width-- > 0) + *str++ = ' '; + + return str; +} + +static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags) +{ + /** + * @brief 将浮点数按照指定的要求转换成对应的字符串 + * + * @param str 要返回的字符串 + * @param num 要打印的数值 + * @param field_width 区域宽度 + * @param precision 精度 + * @param flags 标志位 + */ + + char pad, sign, tmp_num_z[100], tmp_num_d[350]; + + const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + // 显示小写字母 + if (flags & SMALL) + digits = "0123456789abcdefghijklmnopqrstuvwxyz"; + + // 设置填充元素 + pad = (flags & PAD_ZERO) ? '0' : ' '; + sign = 0; + if (flags & SIGN && num < 0) + { + sign = '-'; + num = -num; + } + else + { + // 设置符号 + sign = (flags & PLUS) ? '+' : ((flags & SPACE) ? ' ' : 0); + } + + // sign占用了一个宽度 + if (sign) + --field_width; + + int js_num_z = 0, js_num_d = 0; // 临时数字字符串tmp_num_z tmp_num_d的长度 + uint64_t num_z = (uint64_t)(num); // 获取整数部分 + uint64_t num_decimal = (uint64_t)(round((num - num_z) * precision)); // 获取小数部分 + + if (num == 0) + tmp_num_z[js_num_z++] = '0'; + else + { + //存储整数部分 + while (num_z > 0) + { + tmp_num_z[js_num_z++] = digits[num_z % 10]; // 注意这里,输出的数字,是小端对齐的。低位存低位 + num_z /= 10; + } + } + + while (num_decimal > 0) + { + tmp_num_d[js_num_d++] = digits[num_decimal % 10]; + num_decimal /= 10; + } + + field_width -= (precision + 1 + js_num_z); + + // 靠右对齐 + if (!(flags & LEFT)) + while (field_width-- > 0) + *str++ = pad; + + if (sign) + *str++ = sign; + + // 输出整数部分 + while (js_num_z-- > 0) + *str++ = tmp_num_z[js_num_z]; + + *str++ = '.'; + + // 输出小数部分 + while (js_num_d-- > 0) + *str++ = tmp_num_d[js_num_d]; + + while (js_num_d < precision) + { + --precision; + *str++ = '0'; + } + + while (field_width-- > 0) + *str++ = ' '; + + return str; +} \ No newline at end of file diff --git a/user/libs/libc/printf.h b/user/libs/libc/printf.h new file mode 100644 index 00000000..5bd17646 --- /dev/null +++ b/user/libs/libc/printf.h @@ -0,0 +1,13 @@ +#pragma once + + +#define PAD_ZERO 1 // 0填充 +#define LEFT 2 // 靠左对齐 +#define RIGHT 4 // 靠右对齐 +#define PLUS 8 // 在正数前面显示加号 +#define SPACE 16 +#define SPECIAL 32 // 在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X' +#define SMALL 64 // 十进制以上数字显示小写字母 +#define SIGN 128 // 显示符号位 + +#define is_digit(c) ((c) >= '0' && (c) <= '9') // 用来判断是否是数字的宏 \ No newline at end of file diff --git a/user/libs/libc/stddef.h b/user/libs/libc/stddef.h new file mode 100644 index 00000000..038dee40 --- /dev/null +++ b/user/libs/libc/stddef.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#ifdef __cplusplus + #define NULL 0 +#else + #define NULL ((void *)0) +#endif + + +typedef __PTRDIFF_TYPE__ ptrdiff_t; // Signed integer type of the result of subtracting two pointers. + diff --git a/user/libs/libc/stdio.h b/user/libs/libc/stdio.h index c232081b..db165803 100644 --- a/user/libs/libc/stdio.h +++ b/user/libs/libc/stdio.h @@ -1,7 +1,35 @@ #pragma once -#define SEEK_SET 0 /* Seek relative to start-of-file */ -#define SEEK_CUR 1 /* Seek relative to current position */ -#define SEEK_END 2 /* Seek relative to end-of-file */ +#include +#include -#define SEEK_MAX 3 +// 字体颜色的宏定义 +#define COLOR_WHITE 0x00ffffff //白 +#define COLOR_BLACK 0x00000000 //黑 +#define COLOR_RED 0x00ff0000 //红 +#define COLOR_ORANGE 0x00ff8000 //橙 +#define COLOR_YELLOW 0x00ffff00 //黄 +#define COLOR_GREEN 0x0000ff00 //绿 +#define COLOR_BLUE 0x000000ff //蓝 +#define COLOR_INDIGO 0x0000ffff //靛 +#define COLOR_PURPLE 0x008000ff //紫 + +#define SEEK_SET 0 /* Seek relative to start-of-file */ +#define SEEK_CUR 1 /* Seek relative to current position */ +#define SEEK_END 2 /* Seek relative to end-of-file */ + +#define SEEK_MAX 3 + +/** + * @brief 往屏幕上输出字符串 + * + * @param str 字符串指针 + * @param front_color 前景色 + * @param bg_color 背景色 + * @return int64_t + */ +int64_t put_string(char *str, uint64_t front_color, uint64_t bg_color); + +int printf(const char *fmt, ...); +int sprintf(char *buf, const char *fmt, ...); +int vsprintf(char *buf, const char *fmt, va_list args); \ No newline at end of file diff --git a/user/libs/libc/stdlib.c b/user/libs/libc/stdlib.c new file mode 100644 index 00000000..94cd5e55 --- /dev/null +++ b/user/libs/libc/stdlib.c @@ -0,0 +1,45 @@ +#include +#include + +int abs(int i) +{ + return i < 0 ? -i : i; +} + +long labs(long i) +{ + return i < 0 ? -i : i; +} + +long long llabs(long long i) +{ + return i < 0 ? -i : i; +} + +int atoi(const char *str) +{ + int n = 0, neg = 0; + + while (isspace(*str)) + { + str++; + } + + switch (*str) + { + case '-': + neg = 1; + break; + case '+': + str++; + break; + } + + /* Compute n as a negative number to avoid overflow on INT_MIN */ + while (isdigit(*str)) + { + n = 10 * n - (*str++ - '0'); + } + + return neg ? n : -n; +} \ No newline at end of file diff --git a/user/libs/libc/stdlib.h b/user/libs/libc/stdlib.h new file mode 100644 index 00000000..66f49d7e --- /dev/null +++ b/user/libs/libc/stdlib.h @@ -0,0 +1,35 @@ +#pragma once +#include + +/** + * @brief 获取一块堆内存 + * + * @param size 内存大小 + * @return void* 内存空间的指针 + */ +void *malloc(ssize_t size); + +/** + * @brief 释放一块堆内存 + * + * @param ptr 堆内存的指针 + */ +void free(void* ptr); + +/** + * @brief 返回int的绝对值 + * + * @param i + * @return int + */ +int abs(int i); +long labs(long i); +long long llabs(long long i); + +/** + * @brief 字符串转int + * + * @param str + * @return int + */ +int atoi(const char * str); \ No newline at end of file diff --git a/user/libs/libc/string.h b/user/libs/libc/string.h new file mode 100644 index 00000000..c11a74f0 --- /dev/null +++ b/user/libs/libc/string.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +void *memset(void *dst, unsigned char C, uint64_t size) +{ + + int d0, d1; + unsigned long tmp = C * 0x0101010101010101UL; + __asm__ __volatile__("cld \n\t" + "rep \n\t" + "stosq \n\t" + "testb $4, %b3 \n\t" + "je 1f \n\t" + "stosl \n\t" + "1:\ttestb $2, %b3 \n\t" + "je 2f\n\t" + "stosw \n\t" + "2:\ttestb $1, %b3 \n\t" + "je 3f \n\t" + "stosb \n\t" + "3: \n\t" + : "=&c"(d0), "=&D"(d1) + : "a"(tmp), "q"(size), "0"(size / 8), "1"(dst) + : "memory"); + return dst; +} + +size_t strlen(const char *s) +{ + register size_t __res = 0; + while (s[__res] != '\0') + { + ++__res; + } + return __res; +} \ No newline at end of file diff --git a/user/libs/libc/sys/types.h b/user/libs/libc/sys/types.h index 8ece224d..5efae368 100644 --- a/user/libs/libc/sys/types.h +++ b/user/libs/libc/sys/types.h @@ -1,6 +1,7 @@ #pragma once #include +#include typedef unsigned char u_char; typedef unsigned short u_short; diff --git a/user/libs/libc/unistd.c b/user/libs/libc/unistd.c index 9ac9fcee..11f1ffea 100644 --- a/user/libs/libc/unistd.c +++ b/user/libs/libc/unistd.c @@ -1,18 +1,8 @@ #include #include +#include +#include -/** - * @brief 往屏幕上输出字符串 - * - * @param str 字符串指针 - * @param front_color 前景色 - * @param bg_color 背景色 - * @return int64_t - */ -int64_t put_string(char *str, uint64_t front_color, uint64_t bg_color) -{ - return syscall_invoke(SYS_PUT_STRING, (uint64_t)str, front_color, bg_color, 0, 0, 0, 0, 0); -} /** * @brief 关闭文件接口 * @@ -81,4 +71,38 @@ pid_t fork(void) pid_t vfork(void) { return (pid_t)syscall_invoke(SYS_VFORK, 0, 0, 0, 0, 0, 0, 0, 0); +} + +/** + * @brief 将堆内存调整为end_brk + * + * @param end_brk 新的堆区域的结束地址 + * end_brk=-1 ===> 返回堆区域的起始地址 + * end_brk=-2 ===> 返回堆区域的结束地址 + * @return uint64_t 错误码 + * + */ +uint64_t brk(uint64_t end_brk) +{ + uint64_t x = (uint64_t)syscall_invoke(SYS_BRK, (uint64_t)end_brk, 0, 0, 0, 0, 0, 0, 0); + printf("brk(): end_brk=%#018lx x=%#018lx", (uint64_t)end_brk, x); + return x; +} + +/** + * @brief 将堆内存空间加上offset(注意,该系统调用只应在普通进程中调用,而不能是内核线程) + * + * @param increment offset偏移量 + * @return uint64_t the previous program break + */ +void *sbrk(int64_t increment) +{ + void *retval = (void *)syscall_invoke(SYS_SBRK, (uint64_t)increment, 0, 0, 0, 0, 0, 0, 0); + if (retval == (void *)-ENOMEM) + return (void *)(-1); + else + { + errno = 0; + return (void *)retval; + } } \ No newline at end of file diff --git a/user/libs/libc/unistd.h b/user/libs/libc/unistd.h index d6102881..7d15cd22 100644 --- a/user/libs/libc/unistd.h +++ b/user/libs/libc/unistd.h @@ -2,27 +2,9 @@ #include #include -// 字体颜色的宏定义 -#define COLOR_WHITE 0x00ffffff //白 -#define COLOR_BLACK 0x00000000 //黑 -#define COLOR_RED 0x00ff0000 //红 -#define COLOR_ORANGE 0x00ff8000 //橙 -#define COLOR_YELLOW 0x00ffff00 //黄 -#define COLOR_GREEN 0x0000ff00 //绿 -#define COLOR_BLUE 0x000000ff //蓝 -#define COLOR_INDIGO 0x0000ffff //靛 -#define COLOR_PURPLE 0x008000ff //紫 -/** - * @brief 往屏幕上输出字符串 - * - * @param str 字符串指针 - * @param front_color 前景色 - * @param bg_color 背景色 - * @return int64_t - */ -int64_t put_string(char* str, uint64_t front_color, uint64_t bg_color); + /** @@ -77,3 +59,21 @@ pid_t fork(void); */ pid_t vfork(void); +/** + * @brief 将堆内存调整为end_brk + * + * @param end_brk 新的堆区域的结束地址 + * end_brk=0 ===> 返回堆区域的起始地址 + * end_brk=-1 ===> 返回堆区域的结束地址 + * @return uint64_t 错误码 + * + */ +uint64_t brk(uint64_t end_brk); + +/** + * @brief 将堆内存空间加上offset(注意,该系统调用只应在普通进程中调用,而不能是内核线程) + * + * @param increment offset偏移量 + * @return uint64_t the previous program break + */ +void * sbrk(int64_t increment); diff --git a/user/libs/libsystem/syscall.c b/user/libs/libsystem/syscall.c index 3090ffa1..9276c9f4 100644 --- a/user/libs/libsystem/syscall.c +++ b/user/libs/libsystem/syscall.c @@ -1,8 +1,9 @@ #include "syscall.h" - +#include +#include long syscall_invoke(uint64_t syscall_id, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7) { - long err_code; + uint64_t err_code; __asm__ __volatile__( "movq %2, %%r8 \n\t" "movq %3, %%r9 \n\t" @@ -13,8 +14,15 @@ long syscall_invoke(uint64_t syscall_id, uint64_t arg0, uint64_t arg1, uint64_t "movq %8, %%r14 \n\t" "movq %9, %%r15 \n\t" "int $0x80 \n\t" - : "=a"(err_code) + "movq %%rax, %0 \n\t" + : "=m"(err_code) : "a"(syscall_id), "m"(arg0), "m"(arg1), "m"(arg2), "m"(arg3), "m"(arg4), "m"(arg5), "m"(arg6), "m"(arg7) : "memory", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "rcx", "rdx"); + errno = err_code; + if (syscall_id == SYS_BRK || syscall_id == SYS_OPEN) + { + printf("retval = %#018lx\n", (uint64_t)err_code); + printf("errcode = %d\n", err_code); + } return err_code; } diff --git a/user/libs/libsystem/syscall.h b/user/libs/libsystem/syscall.h index 75d65ff5..51ffed68 100644 --- a/user/libs/libsystem/syscall.h +++ b/user/libs/libsystem/syscall.h @@ -12,6 +12,8 @@ #define SYS_LSEEK 6 #define SYS_FORK 7 #define SYS_VFORK 8 +#define SYS_BRK 9 +#define SYS_SBRK 10 /** * @brief 用户态系统调用函数