Support smp. TODO: delete all inner kernel locks.

This commit is contained in:
TXuian 2024-03-15 16:01:30 +08:00
parent 892613a0d5
commit d987bf0357
34 changed files with 531 additions and 150 deletions

View File

@ -74,7 +74,7 @@ Modification:
#include "cortex_a9.h"
#define NR_CPU 1
#define NR_CPU 4
__attribute__((always_inline)) static inline uint32_t user_mode()
{

View File

@ -232,15 +232,15 @@ static struct DCacheDone dcache_done = {
struct ICacheDone* hardkernel_icache_init(struct TraceTag* hardkernel_tag)
{
/* init icache */
icache_done.enable();
// icache_done.disable();
// icache_done.enable();
icache_done.disable();
return &icache_done;
}
struct DCacheDone* hardkernel_dcache_init(struct TraceTag* hardkernel_tag)
{
/* init dcache */
dcache_done.enable();
// dcache_done.disable();
// dcache_done.enable();
dcache_done.disable();
return &dcache_done;
}

View File

@ -447,11 +447,9 @@ bool tracer_delete_trace(struct TraceTag* target, struct TraceTag* owner)
return true;
}
static struct spinlock ac_tracer_lock;
void tracer_init(void)
{
/* init sys_tracer, the manager */
spinlock_init(&ac_tracer_lock, "tracerlock");
spinlock_init(&sys_tracer.mem_chunk_bitmap_lock, "tracer_mem_chunk_bitmap");
spinlock_init(&sys_tracer.trace_meta_bitmap_lock, "tracer_meta_bitmap");
memset(sys_tracer.mem_chunks_bit_map, 0, sizeof(sys_tracer.mem_chunk_bitmap_lock));

View File

@ -32,31 +32,31 @@ all: init test_fs simple_client simple_server shell fs_server test_priority read
bin:
@mkdir -p bin
shell: shell_port.o libserial.o shell_cmd_list.o shell.o shell_ext.o libfs_to_client.o libipc.o session.o usyscall.o
shell: shell_port.o libserial.o shell_cmd_list.o shell.o shell_ext.o libfs_to_client.o libipc.o session.o usyscall.o libmem.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
init: init.o libfs_to_client.o libipc.o session.o libserial.o usyscall.o
init: init.o libfs_to_client.o libipc.o session.o libserial.o usyscall.o libmem.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
test_fs: test_fs.o libfs_to_client.o libipc.o session.o libserial.o usyscall.o
test_fs: test_fs.o libfs_to_client.o libipc.o session.o libserial.o usyscall.o libmem.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
simple_client: simple_client.o libserial.o libipc.o session.o simple_service.o libfs_to_client.o usyscall.o
simple_client: simple_client.o libserial.o libipc.o session.o simple_service.o libfs_to_client.o usyscall.o libmem.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
simple_server: simple_server.o libserial.o libipc.o session.o simple_service.o usyscall.o
simple_server: simple_server.o libserial.o libipc.o session.o simple_service.o usyscall.o libmem.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
fs_server: fs_server.o libfs_to_client.o fs.o libserial.o libipc.o session.o block_io.o usyscall.o
fs_server: fs_server.o libfs_to_client.o fs.o libserial.o libipc.o session.o block_io.o usyscall.o libmem.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
test_priority: test_priority.o libserial.o usyscall.o
test_priority: test_priority.o libserial.o usyscall.o libmem.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm

View File

@ -32,7 +32,7 @@ int main(int argc, char* argv[])
exit();
}
if (spawn(&session, fd, read, shell_task_param[0], shell_task_param) < 0) {
if (spawn(&session, fd, read, fsize, shell_task_param[0], shell_task_param) < 0) {
printf("Syscall Spawn shell failed\n");
}

View File

@ -113,10 +113,10 @@ int main(int argc, char** argv)
itoa(id - 1, id_buf, 10);
char* shell_task_param[3] = { "/simple_client", id_buf, 0 };
if ((fd = open(&session, shell_task_param[0])) >= 0) {
if (spawn(&session, fd, read, shell_task_param[0], shell_task_param) < 0) {
if (spawn(&session, fd, read, fsize, shell_task_param[0], shell_task_param) < 0) {
printf("Syscall Spawn simple_client failed\n");
}
if (spawn(&session, fd, read, shell_task_param[0], shell_task_param) < 0) {
if (spawn(&session, fd, read, fsize, shell_task_param[0], shell_task_param) < 0) {
printf("Syscall Spawn simple_client failed\n");
}
close(&session, fd);

View File

@ -13,8 +13,8 @@ cflags = -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=so
c_useropts = -O0
INC_DIR = -I$(KERNEL_ROOT)/services/fs/libfs \
-I$(KERNEL_ROOT)/services/fs/fs_server/include \
-I$(KERNEL_ROOT)/services/lib/ipc \
-I$(KERNEL_ROOT)/services/lib/memory \
-I$(KERNEL_ROOT)/services/boards/$(BOARD) \
-I$(KERNEL_ROOT)/services/app

View File

@ -10,6 +10,7 @@
* See the Mulan PSL v2 for more details.
*/
#include "usyscall.h"
#include "libmem.h"
static int
syscall(int sys_num, intptr_t a1, intptr_t a2, intptr_t a3, intptr_t a4)
@ -33,14 +34,18 @@ syscall(int sys_num, intptr_t a1, intptr_t a2, intptr_t a3, intptr_t a4)
return ret;
}
int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, char* name, char** argv)
int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, ipc_fsize_fn ipc_fsize, char* name, char** argv)
{
struct KernReadTool read_tool = {
.session = session,
.fd = fd,
.ipc_read = ipc_read,
};
return syscall(SYSCALL_SPAWN, (intptr_t)&read_tool, (intptr_t)name, (intptr_t)argv, 0);
int file_size = ipc_fsize(session, fd);
void* img = malloc(file_size);
int read_len = 0, cur_read_len = 0;
while (read_len < file_size) {
cur_read_len = file_size - read_len < 4096 ? file_size - read_len : 4096;
read_len += ipc_read(session, fd, img + read_len, read_len, cur_read_len);
}
int ret = syscall(SYSCALL_SPAWN, (intptr_t)img, (intptr_t)name, (intptr_t)argv, 0);
free(img);
return ret;
}
int exit()

View File

@ -51,15 +51,10 @@ typedef union {
} sys_state_info;
typedef int (*ipc_read_fn)(struct Session* session, int fd, char* dst, int offset, int len);
typedef int (*ipc_fsize_fn)(struct Session* session, int fd);
typedef int (*ipc_write_fn)(struct Session* session, int fd, char* src, int offset, int len);
struct KernReadTool {
struct Session* session;
int fd;
ipc_read_fn ipc_read;
};
int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, char* name, char** argv);
int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, ipc_fsize_fn ipc_fsize, char* name, char** argv);
int exit();
int yield();
int register_server(char* name);

View File

@ -18,6 +18,7 @@ c_useropts = -O0
INC_DIR = -I$(KERNEL_ROOT)/services/fs/libfs \
-I$(KERNEL_ROOT)/services/fs/fs_server/include \
-I$(KERNEL_ROOT)/services/lib/ipc \
-I$(KERNEL_ROOT)/services/lib/memory \
-I$(KERNEL_ROOT)/services/boards/$(BOARD) \
-I$(KERNEL_ROOT)/services/app

View File

@ -10,6 +10,7 @@
* See the Mulan PSL v2 for more details.
*/
#include "usyscall.h"
#include "libmem.h"
static int
syscall(int sys_num, intptr_t a1, intptr_t a2, intptr_t a3, intptr_t a4)
@ -33,14 +34,18 @@ syscall(int sys_num, intptr_t a1, intptr_t a2, intptr_t a3, intptr_t a4)
return ret;
}
int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, char* name, char** argv)
int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, ipc_fsize_fn ipc_fsize, char* name, char** argv)
{
struct KernReadTool read_tool = {
.session = session,
.fd = fd,
.ipc_read = ipc_read,
};
return syscall(SYSCALL_SPAWN, (intptr_t)&read_tool, (intptr_t)name, (intptr_t)argv, 0);
int file_size = ipc_fsize(session, fd);
void* img = malloc(file_size);
int read_len = 0, cur_read_len = 0;
while (read_len < file_size) {
cur_read_len = file_size - read_len < 4096 ? file_size - read_len : 4096;
read_len += ipc_read(session, fd, img + read_len, read_len, cur_read_len);
}
int ret = syscall(SYSCALL_SPAWN, (intptr_t)img, (intptr_t)name, (intptr_t)argv, 0);
free(img);
return ret;
}
int exit()

View File

@ -51,15 +51,10 @@ typedef union {
} sys_state_info;
typedef int (*ipc_read_fn)(struct Session* session, int fd, char* dst, int offset, int len);
typedef int (*ipc_fsize_fn)(struct Session* session, int fd);
typedef int (*ipc_write_fn)(struct Session* session, int fd, char* src, int offset, int len);
struct KernReadTool {
struct Session* session;
int fd;
ipc_read_fn ipc_read;
};
int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, char* name, char** argv);
int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, ipc_fsize_fn ipc_fsize, char* name, char** argv);
int exit();
int yield();
int register_server(char* name);

View File

@ -18,6 +18,7 @@ c_useropts = -O0
INC_DIR = -I$(KERNEL_ROOT)/services/fs/libfs \
-I$(KERNEL_ROOT)/services/fs/fs_server/include \
-I$(KERNEL_ROOT)/services/lib/ipc \
-I$(KERNEL_ROOT)/services/lib/memory \
-I$(KERNEL_ROOT)/services/boards/$(BOARD) \
-I$(KERNEL_ROOT)/services/app

View File

@ -282,7 +282,7 @@ int IPC_DO_SERVE_FUNC(Ipc_read)(int* fd, char* dst, int* offset, int* len)
int cur_read_len = InodeRead(ip, dst, *offset, *len);
return *len;
return cur_read_len;
}
int IPC_DO_SERVE_FUNC(Ipc_write)(int* fd, char* src, int* offset, int* len)
@ -305,18 +305,36 @@ int IPC_DO_SERVE_FUNC(Ipc_write)(int* fd, char* src, int* offset, int* len)
return cur_write_len;
}
int IPC_DO_SERVE_FUNC(Ipc_fsize)(int* fd)
{
struct FileDescriptor* fdp = GetFileDescriptor(*fd);
if (!fdp) {
printf("read: fd invalid\n");
return -1;
}
struct Inode* ip = fdp->data;
if (ip->type != FS_FILE) {
printf("read: %s Is not a file\n", fdp->path);
return -1;
}
return ip->size;
}
IPC_SERVER_INTERFACE(Ipc_ls, 1);
IPC_SERVER_INTERFACE(Ipc_cd, 1);
IPC_SERVER_INTERFACE(Ipc_mkdir, 1);
IPC_SERVER_INTERFACE(Ipc_delete, 1);
IPC_SERVER_INTERFACE(Ipc_cat, 1);
IPC_SERVER_INTERFACE(Ipc_fsize, 1);
IPC_SERVER_INTERFACE(Ipc_open, 1);
IPC_SERVER_INTERFACE(Ipc_close, 1);
IPC_SERVER_INTERFACE(Ipc_read, 4);
IPC_SERVER_INTERFACE(Ipc_write, 4);
IPC_SERVER_REGISTER_INTERFACES(IpcFsServer, 9,
IPC_SERVER_REGISTER_INTERFACES(IpcFsServer, 10,
Ipc_ls,
Ipc_cd,
Ipc_mkdir,
@ -325,7 +343,8 @@ IPC_SERVER_REGISTER_INTERFACES(IpcFsServer, 9,
Ipc_open,
Ipc_close,
Ipc_read,
Ipc_write);
Ipc_write,
Ipc_fsize);
int main(int argc, char* argv[])
{

View File

@ -17,6 +17,7 @@ c_useropts = -O0
INC_DIR = -I$(KERNEL_ROOT)/services/fs/libfs \
-I$(KERNEL_ROOT)/services/lib/ipc \
-I$(KERNEL_ROOT)/services/lib/memory \
-I$(KERNEL_ROOT)/services/boards/$(BOARD) \
-I$(KERNEL_ROOT)/services/app

View File

@ -63,4 +63,10 @@ IPC_INTERFACE(Ipc_write, 4, fd, src, offset, len, sizeof(int), *(int*)len, sizeo
int write(struct Session* session, int fd, char* src, int offset, int len)
{
return IPC_CALL(Ipc_write)(session, &fd, src, &offset, &len);
}
IPC_INTERFACE(Ipc_fsize, 1, fd, sizeof(int));
int fsize(struct Session* session, int fd)
{
return IPC_CALL(Ipc_fsize)(session, &fd);
}

View File

@ -15,13 +15,14 @@
#include "libipc.h"
IPC_SERVICES(IpcFsServer, Ipc_ls, Ipc_cd, Ipc_mkdir, Ipc_delete, Ipc_cat,
Ipc_open, Ipc_close, Ipc_read, Ipc_write);
Ipc_open, Ipc_close, Ipc_read, Ipc_write, Ipc_fsize);
int ls(struct Session* session, char* path);
int cd(struct Session* session, char* path);
int mkdir(struct Session* session, char* path);
int rm(struct Session* session, char* path);
int cat(struct Session* session, char* path);
int fsize(struct Session* session, int fd);
int open(struct Session* session, char* path);
int close(struct Session* session, int fd);

View File

@ -1,4 +1,4 @@
SRC_DIR := ipc
SRC_DIR := ipc memory
include $(KERNEL_ROOT)/compiler.mk

View File

@ -15,8 +15,8 @@ objdump = ${toolchain}objdump
c_useropts = -O0
INC_DIR = -I$(KERNEL_ROOT)/services/shell/letter-shell \
-I$(KERNEL_ROOT)/services/lib/ipc \
INC_DIR = -I$(KERNEL_ROOT)/services/lib/ipc \
-I$(KERNEL_ROOT)/services/lib/memory \
-I$(KERNEL_ROOT)/services/boards/$(BOARD) \
-I$(KERNEL_ROOT)/services/app

View File

@ -12,11 +12,14 @@ user_ldflags = -N -Ttext 0
cflags = -std=c11 -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
c_useropts = -O0
INC_DIR = -I$(KERNEL_ROOT)/services/app \
-I$(KERNEL_ROOT)/services/boards/$(BOARD) \
-I$(KERNEL_ROOT)/services/lib/ipc
INC_DIR = -I$(KERNEL_ROOT)/services/app \
-I$(KERNEL_ROOT)/services/fs/libfs \
-I$(KERNEL_ROOT)/services/boards/$(BOARD) \
-I$(KERNEL_ROOT)/services/lib/memory \
-I$(KERNEL_ROOT)/services/lib/ipc
all:
all: libmem.o
@mv $^ ../../app
%.o: %.c
@echo "cc $^"

View File

@ -0,0 +1,369 @@
/*
* mm.c - malloc using segregated list
* KAIST
* Tony Kim
*
* In this approach,
* Every block has a header and a footer
* in which header contains reallocation information, size, and allocation info
* and footer contains size and allocation info.
* Free list are tagged to the segregated list.
* Therefore all free block contains pointer to the predecessor and successor.
* The segregated list headers are organized by 2^k size.
*
*/
#include "libmem.h"
#include "usyscall.h"
/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8
/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~0x7)
// My additional Macros
#define WSIZE 4 // word and header/footer size (bytes)
#define DSIZE 8 // double word size (bytes)
#define INITCHUNKSIZE (1 << 6)
#define CHUNKSIZE (1 << 12) //+(1<<7)
#define LISTLIMIT 20
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#define MIN(x, y) ((x) < (y) ? (x) : (y))
// Pack a size and allocated bit into a word
#define PACK(size, alloc) ((size) | (alloc))
// Read and write a word at address p
#define GET(p) (*(unsigned int*)(p))
#define PUT(p, val) (*(unsigned int*)(p) = (val) | GET_TAG(p))
#define PUT_NOTAG(p, val) (*(unsigned int*)(p) = (val))
// Store predecessor or successor pointer for free blocks
#define SET_PTR(p, ptr) (*(unsigned int*)(p) = (unsigned int)(ptr))
// Read the size and allocation bit from address p
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)
#define GET_TAG(p) (GET(p) & 0x2)
#define SET_RATAG(p) (GET(p) |= 0x2)
#define REMOVE_RATAG(p) (GET(p) &= ~0x2)
// Address of block's header and footer
#define HDRP(ptr) ((char*)(ptr)-WSIZE)
#define FTRP(ptr) ((char*)(ptr) + GET_SIZE(HDRP(ptr)) - DSIZE)
// Address of (physically) next and previous blocks
#define NEXT_BLKP(ptr) ((char*)(ptr) + GET_SIZE((char*)(ptr)-WSIZE))
#define PREV_BLKP(ptr) ((char*)(ptr)-GET_SIZE((char*)(ptr)-DSIZE))
// Address of free block's predecessor and successor entries
#define PRED_PTR(ptr) ((char*)(ptr))
#define SUCC_PTR(ptr) ((char*)(ptr) + WSIZE)
// Address of free block's predecessor and successor on the segregated list
#define PRED(ptr) (*(char**)(ptr))
#define SUCC(ptr) (*(char**)(SUCC_PTR(ptr)))
// End of my additional macros
// Global var
void* segregated_free_lists[LISTLIMIT];
// Functions
static void* extend_heap(size_t size);
static void* coalesce(void* ptr);
static void* place(void* ptr, size_t asize);
static void insert_node(void* ptr, size_t size);
static void delete_node(void* ptr);
static uintptr_t userland_heap_base;
static uintptr_t userland_heap_top;
static uintptr_t requested_heap_size;
static void* mem_sbrk(size_t size)
{
uintptr_t userland_heap_size = userland_heap_top - userland_heap_base;
if (userland_heap_size - requested_heap_size >= size) {
void* ret_ptr = (void*)(userland_heap_base + requested_heap_size);
requested_heap_size += size;
return ret_ptr;
}
uintptr_t size_needed = size - (userland_heap_size - requested_heap_size);
userland_heap_top = mmap(userland_heap_top, (uintptr_t)NULL, size_needed, false);
return mem_sbrk(size);
}
static void* extend_heap(size_t size)
{
void* ptr;
size_t asize; // Adjusted size
asize = ALIGN(size);
if ((ptr = mem_sbrk(asize)) == (void*)-1)
return NULL;
// Set headers and footer
PUT_NOTAG(HDRP(ptr), PACK(asize, 0));
PUT_NOTAG(FTRP(ptr), PACK(asize, 0));
PUT_NOTAG(HDRP(NEXT_BLKP(ptr)), PACK(0, 1));
insert_node(ptr, asize);
return coalesce(ptr);
}
static void insert_node(void* ptr, size_t size)
{
int list = 0;
void* search_ptr = ptr;
void* insert_ptr = NULL;
// Select segregated list
while ((list < LISTLIMIT - 1) && (size > 1)) {
size >>= 1;
list++;
}
// Keep size ascending order and search
search_ptr = segregated_free_lists[list];
while ((search_ptr != NULL) && (size > GET_SIZE(HDRP(search_ptr)))) {
insert_ptr = search_ptr;
search_ptr = PRED(search_ptr);
}
// Set predecessor and successor
if (search_ptr != NULL) {
if (insert_ptr != NULL) {
SET_PTR(PRED_PTR(ptr), search_ptr);
SET_PTR(SUCC_PTR(search_ptr), ptr);
SET_PTR(SUCC_PTR(ptr), insert_ptr);
SET_PTR(PRED_PTR(insert_ptr), ptr);
} else {
SET_PTR(PRED_PTR(ptr), search_ptr);
SET_PTR(SUCC_PTR(search_ptr), ptr);
SET_PTR(SUCC_PTR(ptr), NULL);
segregated_free_lists[list] = ptr;
}
} else {
if (insert_ptr != NULL) {
SET_PTR(PRED_PTR(ptr), NULL);
SET_PTR(SUCC_PTR(ptr), insert_ptr);
SET_PTR(PRED_PTR(insert_ptr), ptr);
} else {
SET_PTR(PRED_PTR(ptr), NULL);
SET_PTR(SUCC_PTR(ptr), NULL);
segregated_free_lists[list] = ptr;
}
}
return;
}
static void delete_node(void* ptr)
{
int list = 0;
size_t size = GET_SIZE(HDRP(ptr));
// Select segregated list
while ((list < LISTLIMIT - 1) && (size > 1)) {
size >>= 1;
list++;
}
if (PRED(ptr) != NULL) {
if (SUCC(ptr) != NULL) {
SET_PTR(SUCC_PTR(PRED(ptr)), SUCC(ptr));
SET_PTR(PRED_PTR(SUCC(ptr)), PRED(ptr));
} else {
SET_PTR(SUCC_PTR(PRED(ptr)), NULL);
segregated_free_lists[list] = PRED(ptr);
}
} else {
if (SUCC(ptr) != NULL) {
SET_PTR(PRED_PTR(SUCC(ptr)), NULL);
} else {
segregated_free_lists[list] = NULL;
}
}
return;
}
static void* coalesce(void* ptr)
{
size_t prev_alloc = GET_ALLOC(HDRP(PREV_BLKP(ptr)));
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(ptr)));
size_t size = GET_SIZE(HDRP(ptr));
// Do not coalesce with previous block if the previous block is tagged with Reallocation tag
if (GET_TAG(HDRP(PREV_BLKP(ptr))))
prev_alloc = 1;
if (prev_alloc && next_alloc) { // Case 1
return ptr;
} else if (prev_alloc && !next_alloc) { // Case 2
delete_node(ptr);
delete_node(NEXT_BLKP(ptr));
size += GET_SIZE(HDRP(NEXT_BLKP(ptr)));
PUT(HDRP(ptr), PACK(size, 0));
PUT(FTRP(ptr), PACK(size, 0));
} else if (!prev_alloc && next_alloc) { // Case 3
delete_node(ptr);
delete_node(PREV_BLKP(ptr));
size += GET_SIZE(HDRP(PREV_BLKP(ptr)));
PUT(FTRP(ptr), PACK(size, 0));
PUT(HDRP(PREV_BLKP(ptr)), PACK(size, 0));
ptr = PREV_BLKP(ptr);
} else { // Case 4
delete_node(ptr);
delete_node(PREV_BLKP(ptr));
delete_node(NEXT_BLKP(ptr));
size += GET_SIZE(HDRP(PREV_BLKP(ptr))) + GET_SIZE(HDRP(NEXT_BLKP(ptr)));
PUT(HDRP(PREV_BLKP(ptr)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(ptr)), PACK(size, 0));
ptr = PREV_BLKP(ptr);
}
insert_node(ptr, size);
return ptr;
}
static void* place(void* ptr, size_t asize)
{
size_t ptr_size = GET_SIZE(HDRP(ptr));
size_t remainder = ptr_size - asize;
delete_node(ptr);
if (remainder <= DSIZE * 2) {
// Do not split block
PUT(HDRP(ptr), PACK(ptr_size, 1));
PUT(FTRP(ptr), PACK(ptr_size, 1));
}
else if (asize >= 100) {
// Split block
PUT(HDRP(ptr), PACK(remainder, 0));
PUT(FTRP(ptr), PACK(remainder, 0));
PUT_NOTAG(HDRP(NEXT_BLKP(ptr)), PACK(asize, 1));
PUT_NOTAG(FTRP(NEXT_BLKP(ptr)), PACK(asize, 1));
insert_node(ptr, remainder);
return NEXT_BLKP(ptr);
}
else {
// Split block
PUT(HDRP(ptr), PACK(asize, 1));
PUT(FTRP(ptr), PACK(asize, 1));
PUT_NOTAG(HDRP(NEXT_BLKP(ptr)), PACK(remainder, 0));
PUT_NOTAG(FTRP(NEXT_BLKP(ptr)), PACK(remainder, 0));
insert_node(NEXT_BLKP(ptr), remainder);
}
return ptr;
}
static bool malloc_inited = false;
int mm_init(void)
{
// init heap
userland_heap_base = task_heap_base();
userland_heap_top = userland_heap_base;
requested_heap_size = 0;
int list;
char* heap_start; // Pointer to beginning of heap
// Initialize segregated free lists
for (list = 0; list < LISTLIMIT; list++) {
segregated_free_lists[list] = NULL;
}
// Allocate memory for the initial empty heap
if ((long)(heap_start = mem_sbrk(4 * WSIZE)) == -1)
return -1;
PUT_NOTAG(heap_start, 0); /* Alignment padding */
PUT_NOTAG(heap_start + (1 * WSIZE), PACK(DSIZE, 1)); /* Prologue header */
PUT_NOTAG(heap_start + (2 * WSIZE), PACK(DSIZE, 1)); /* Prologue footer */
PUT_NOTAG(heap_start + (3 * WSIZE), PACK(0, 1)); /* Epilogue header */
if (extend_heap(INITCHUNKSIZE) == NULL)
return -1;
malloc_inited = true;
return 0;
}
void* malloc(size_t size)
{
while (!malloc_inited) {
mm_init();
}
size_t asize; /* Adjusted block size */
size_t extendsize; /* Amount to extend heap if no fit */
void* ptr = NULL; /* Pointer */
// Ignore size 0 cases
if (size == 0)
return NULL;
// Align block size
if (size <= DSIZE) {
asize = 2 * DSIZE;
} else {
asize = ALIGN(size + DSIZE);
}
int list = 0;
size_t searchsize = asize;
// Search for free block in segregated list
while (list < LISTLIMIT) {
if ((list == LISTLIMIT - 1) || ((searchsize <= 1) && (segregated_free_lists[list] != NULL))) {
ptr = segregated_free_lists[list];
// Ignore blocks that are too small or marked with the reallocation bit
while ((ptr != NULL) && ((asize > GET_SIZE(HDRP(ptr))) || (GET_TAG(HDRP(ptr))))) {
ptr = PRED(ptr);
}
if (ptr != NULL)
break;
}
searchsize >>= 1;
list++;
}
// if free block is not found, extend the heap
if (ptr == NULL) {
extendsize = MAX(asize, CHUNKSIZE);
if ((ptr = extend_heap(extendsize)) == NULL)
return NULL;
}
// Place and divide block
ptr = place(ptr, asize);
// Return pointer to newly allocated block
return ptr;
}
void free(void* ptr)
{
size_t size = GET_SIZE(HDRP(ptr));
REMOVE_RATAG(HDRP(NEXT_BLKP(ptr)));
PUT(HDRP(ptr), PACK(size, 0));
PUT(FTRP(ptr), PACK(size, 0));
insert_node(ptr, size);
coalesce(ptr);
return;
}

View File

@ -10,7 +10,7 @@
* See the Mulan PSL v2 for more details.
*/
/**
* @file libmalloc.h
* @file libmem.h
* @brief support malloc and free in userland
* @version 3.0
* @author AIIT XUOS Lab
@ -18,7 +18,7 @@
*/
/*************************************************
File name: libmalloc.h
File name: libmem.h
Description: support malloc and free in userland
Others:
History:

View File

@ -16,9 +16,10 @@ objdump = ${toolchain}objdump
c_useropts = -O0
INC_DIR = -I$(KERNEL_ROOT)/services/app \
-I$(KERNEL_ROOT)/services/fs/libfs \
-I$(KERNEL_ROOT)/services/lib/memory \
-I$(KERNEL_ROOT)/services/lib/ipc \
-I$(KERNEL_ROOT)/services/boards/$(BOARD) \
-I$(KERNEL_ROOT)/services/fs/libfs
-I$(KERNEL_ROOT)/services/boards/$(BOARD)
all: shell_cmd_list.o shell_ext.o shell.o
@mv $^ ../../app

View File

@ -1282,7 +1282,7 @@ void shellExec(Shell* shell)
if (fd < 0) {
shellWriteString(shell, shellText[SHELL_TEXT_CMD_NOT_FOUND]);
} else {
if (spawn(&session_fs, fd, read, shell->parser.param[0], shell->parser.param) < 0) {
if (spawn(&session_fs, fd, read, fsize, shell->parser.param[0], shell->parser.param) < 0) {
shellWriteString(shell, shellText[SHELL_TEXT_CMD_NOT_FOUND]);
}
close(&session_fs, fd);

View File

@ -74,15 +74,9 @@ typedef union {
typedef int (*ipc_read_fn)(struct Session* session, int fd, char* dst, int offset, int len);
typedef int (*ipc_write_fn)(struct Session* session, int fd, char* src, int offset, int len);
struct KernReadTool {
struct Session* session;
int fd;
ipc_read_fn ipc_read;
};
int syscall(int sys_num, uintptr_t param1, uintptr_t param2, uintptr_t param3, uintptr_t param4);
int sys_spawn(struct KernReadTool* read_tool, char* name, char** argv);
int sys_spawn(char* img_start, char* name, char** argv);
int sys_exit();
int sys_yield();
@ -91,7 +85,7 @@ int sys_connect_session(char* path, int capacity, struct Session* user_session);
int sys_poll_session(struct Session* userland_session_arr, int arr_capacity);
int sys_close_session(struct Session* session);
int sys_exec(struct KernReadTool* read_tool, char* name, char** argv);
int sys_exec(char* img_start, char* name, char** argv);
int sys_state(sys_state_option option, sys_state_info* info);
int sys_mmap(uintptr_t vaddr, uintptr_t paddr, int len, int is_dev);

View File

@ -35,7 +35,7 @@ user_apps:
.section .rawdata_init
.globl initapp
initapp:
.incbin "../services/app/bin/shell"
.incbin "../services/app/bin/init"
.section .rawdata_memfs
.globl memfs

View File

@ -58,17 +58,17 @@ void configure_cpu(uint32_t cpu)
// arm_icache_enable();
// arm_icache_invalidate();
struct TraceTag main_icache_tag, main_dcache_tag;
AchieveResourceTag(&main_icache_tag, &hardkernel_tag, "icache-ac-resource");
AchieveResourceTag(&main_dcache_tag, &hardkernel_tag, "dcache-ac-resource");
struct ICacheDone* p_icache_driver = AchieveResource(&main_icache_tag);
struct DCacheDone* p_dcache_driver = AchieveResource(&main_dcache_tag);
// p_dcache_driver->enable();
// p_dcache_driver->invalidateall();
// p_icache_driver->enable();
// p_icache_driver->invalidateall();
p_dcache_driver->disable();
p_icache_driver->disable();
// struct TraceTag main_icache_tag, main_dcache_tag;
// AchieveResourceTag(&main_icache_tag, &hardkernel_tag, "icache-ac-resource");
// AchieveResourceTag(&main_dcache_tag, &hardkernel_tag, "dcache-ac-resource");
// struct ICacheDone* p_icache_driver = AchieveResource(&main_icache_tag);
// struct DCacheDone* p_dcache_driver = AchieveResource(&main_dcache_tag);
// // p_dcache_driver->enable();
// // p_dcache_driver->invalidateall();
// // p_icache_driver->enable();
// // p_icache_driver->invalidateall();
// p_dcache_driver->disable();
// p_icache_driver->disable();
// Invalidate SCU copy of TAG RAMs
scu_secure_invalidate(cpu, all_ways);
@ -122,15 +122,14 @@ int main(void)
return -1;
}
// scu_enable();
// configure_cpu(cpu_id);
scu_enable();
configure_cpu(cpu_id);
spinlock_init(&whole_kernel_lock, "wklock");
} else {
configure_cpu(cpu_id);
spinlock_lock(&whole_kernel_lock);
configure_cpu(cpu_id);
secondary_cpu_hardkernel_init(cpu_id, &hardkernel_tag);
DEBUG_PRINTF("CPU %d init done.\n", cur_cpuid());
spinlock_unlock(&whole_kernel_lock);
}
@ -162,7 +161,7 @@ int main(void)
assert(AchieveResourceTag(&scheduler_rights.intr_driver_tag, &hardkernel_tag, "intr-ac-resource"));
core_init_done |= (1 << cpu_id);
DEBUG("core_init_done: %x\n", core_init_done);
LOG_PRINTF("CPU %d init done\n", cpu_id);
spinlock_unlock(&whole_kernel_lock);
while (core_init_done != (1 << NR_CPU) - 1)

View File

@ -66,18 +66,15 @@ Modification:
/// @param path path to elf file
/// @param argv arguments giving to main
/// @return
int task_exec(struct TaskMicroDescriptor* task, struct Session* session, int fd, ipc_read_fn ipc_read, char* name, char** argv)
int task_exec(struct TaskMicroDescriptor* task, char* img_start, char* name, char** argv)
{
/* load img to task */
/* 1. load elf header */
struct elfhdr elf;
memcpy((void*)&elf, img_start, sizeof(elf));
// pgdir for new task
struct TopLevelPageDirectory pgdir;
pgdir.pd_addr = NULL;
if (ipc_read(session, fd, (char*)&elf, 0, sizeof(elf)) < sizeof(elf) || elf.magic != ELF_MAGIC) {
ERROR("invalide elf file.\n");
goto error_exec;
}
// pgdir for new task
if (UNLIKELY(!xizi_pager.new_pgdir(&pgdir))) {
ERROR("create new pgdir failed.\n");
goto error_exec;
@ -88,10 +85,8 @@ int task_exec(struct TaskMicroDescriptor* task, struct Session* session, int fd,
uintptr_t load_size = 0;
struct proghdr ph;
for (int sec_idx = 0, off = elf.phoff; sec_idx < elf.phnum; sec_idx++, off += sizeof(ph)) {
if (ipc_read(session, fd, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) {
ERROR("Read elf header failed\n");
goto error_exec;
}
// load proghdr
memcpy((char*)&ph, img_start + off, sizeof(ph));
if (ph.type != ELF_PROG_LOAD)
continue;
@ -114,10 +109,7 @@ int task_exec(struct TaskMicroDescriptor* task, struct Session* session, int fd,
panic("copy elf file to unmapped addr");
}
uintptr_t read_size = (ph.filesz - addr_offset < PAGE_SIZE ? ph.filesz - addr_offset : PAGE_SIZE);
if (read_size != ipc_read(session, fd, P2V(page_paddr), ph.off + addr_offset, read_size)) {
ERROR("read size error, off: %d, read len: %d\n", ph.off + addr_offset, read_size);
goto error_exec;
}
memcpy(P2V(page_paddr), img_start + (ph.off + addr_offset), read_size);
}
}
@ -193,7 +185,7 @@ error_exec:
return -1;
}
int sys_exec(struct KernReadTool* read_tool, char* name, char** argv)
int sys_exec(char* img_start, char* name, char** argv)
{
/// @todo find a source of mmu_driver_tag instead of requiring from root
static struct TraceTag mmu_driver_tag;
@ -204,12 +196,8 @@ int sys_exec(struct KernReadTool* read_tool, char* name, char** argv)
}
struct MmuCommonDone* p_mmu_driver = AchieveResource(&mmu_driver_tag);
struct TaskMicroDescriptor* current_task = cur_cpu()->task;
struct Session* session = read_tool->session;
int fd = read_tool->fd;
ipc_read_fn ipc_read = read_tool->ipc_read;
int ret = task_exec(current_task, session, fd, ipc_read, name, argv);
int ret = task_exec(current_task, img_start, name, argv);
if (ret >= 0) {
spinlock_init(&current_task->lock, current_task->name);
p_mmu_driver->LoadPgdir((uintptr_t)V2P(current_task->pgdir.pd_addr));

View File

@ -33,8 +33,8 @@ Modification:
#include "syscall.h"
#include "task.h"
extern int task_exec(struct TaskMicroDescriptor* task, struct Session* session, int fd, ipc_read_fn ipc_read, char* name, char** argv);
int sys_spawn(struct KernReadTool* read_tool, char* name, char** argv)
extern int task_exec(struct TaskMicroDescriptor* task, char* img_start, char* name, char** argv);
int sys_spawn(char* img_start, char* name, char** argv)
{
// alloc a new pcb
struct TaskMicroDescriptor* new_task_cb = xizi_task_manager.new_task_cb();
@ -44,11 +44,7 @@ int sys_spawn(struct KernReadTool* read_tool, char* name, char** argv)
}
// init trapframe
arch_init_trapframe(new_task_cb->main_thread.trapframe, 0, 0);
struct Session* session = read_tool->session;
int fd = read_tool->fd;
ipc_read_fn ipc_read = read_tool->ipc_read;
if (UNLIKELY(task_exec(new_task_cb, session, fd, ipc_read, name, argv)) < 0) {
if (UNLIKELY(task_exec(new_task_cb, img_start, name, argv)) < 0) {
xizi_task_manager.free_pcb(new_task_cb);
return -1;
}

View File

@ -55,8 +55,17 @@ static inline void _padding(char* name)
void show_tasks(void)
{
struct TaskMicroDescriptor* task = NULL;
DEBUG_PRINTF("******************************************************\n");
DEBUG_PRINTF("STAT ID TASK PRI LEFT_TICKS\n");
LOG_PRINTF("******************************************************\n");
for (int i = 0; i < NR_CPU; i++) {
LOG_PRINTF("CPU %d: ", i);
if (global_cpus[i].task != NULL) {
LOG_PRINTF("%s\n", global_cpus[i].task->name);
} else {
LOG_PRINTF("NULL\n");
}
}
LOG_PRINTF("******************************************************\n");
LOG_PRINTF("STAT ID TASK PRI LEFT_TICKS\n");
for (int i = 0; i < TASK_MAX_PRIORITY; i++) {
if (IS_DOUBLE_LIST_EMPTY(&xizi_task_manager.task_list_head[i])) {
continue;
@ -64,19 +73,19 @@ void show_tasks(void)
DOUBLE_LIST_FOR_EACH_ENTRY(task, &xizi_task_manager.task_list_head[i], node)
{
if (task->state == INIT)
DEBUG_PRINTF(" INIT ");
LOG_PRINTF(" INIT ");
else if (task->state == READY)
DEBUG_PRINTF(" READY ");
LOG_PRINTF(" READY ");
else if (task->state == RUNNING)
DEBUG_PRINTF("RUNNING ");
LOG_PRINTF("RUNNING ");
else if (task->state == DEAD)
DEBUG_PRINTF(" DEAD ");
LOG_PRINTF(" DEAD ");
_padding(task->name);
DEBUG_PRINTF(" %d %s %d %d\n", task->pid, task->name, task->priority, task->remain_tick);
LOG_PRINTF(" %d %s %d %d\n", task->pid, task->name, task->priority, task->remain_tick);
}
}
DEBUG_PRINTF("******************************************************\n");
LOG_PRINTF("******************************************************\n");
return;
}
@ -85,8 +94,8 @@ extern struct KBuddy kern_virtmem_buddy;
extern uint32_t kernel_data_end[];
void show_mem(void)
{
DEBUG_PRINTF("*********************************************************\n");
DEBUG_PRINTF(" TOTAL(KB) USED(KB) FREE(KB) \n");
LOG_PRINTF("*********************************************************\n");
LOG_PRINTF(" TOTAL(KB) USED(KB) FREE(KB) \n");
uint32_t total = (PHY_MEM_STOP - V2P(kernel_data_end)) >> 10;
uint32_t used = 0;
@ -96,14 +105,14 @@ void show_mem(void)
}
used = used >> 10;
DEBUG_PRINTF(" %d %d %d\n", total, total - used, used);
DEBUG_PRINTF("*********************************************************\n");
LOG_PRINTF(" %d %d %d\n", total, total - used, used);
LOG_PRINTF("*********************************************************\n");
return;
}
void show_cpu(void)
{
DEBUG_PRINTF("**********************************************************\n");
LOG_PRINTF("**********************************************************\n");
#ifdef ARCH_SMP
/// @todo support smp
KPrintf(" cpu VALUE \n");
@ -116,10 +125,10 @@ void show_cpu(void)
_padding(current_task->name);
DEBUG_PRINTF(" ID COMMAND USED_TICKS FREE_TICKS \n");
DEBUG_PRINTF(" %d %s %d %d\n", cpu_id, current_task->name, TASK_CLOCK_TICK - current_task->remain_tick, current_task->remain_tick);
LOG_PRINTF(" ID COMMAND USED_TICKS FREE_TICKS \n");
LOG_PRINTF(" %d %s %d %d\n", cpu_id, current_task->name, TASK_CLOCK_TICK - current_task->remain_tick, current_task->remain_tick);
DEBUG_PRINTF("***********************************************************\n");
LOG_PRINTF("***********************************************************\n");
return;
}

View File

@ -41,7 +41,7 @@ int syscall(int sys_num, uintptr_t param1, uintptr_t param2, uintptr_t param3, u
ret = 0;
break;
case SYSCALL_SPAWN:
ret = sys_spawn((struct KernReadTool*)param1, (char*)param2, (char**)param3);
ret = sys_spawn((char*)param1, (char*)param2, (char**)param3);
break;
case SYSCALL_EXIT:
ret = sys_exit();
@ -62,7 +62,7 @@ int syscall(int sys_num, uintptr_t param1, uintptr_t param2, uintptr_t param3, u
ret = sys_close_session((struct Session*)param1);
break;
case SYSCALL_EXEC:
ret = sys_exec((struct KernReadTool*)param1, (char*)param2, (char**)param3);
ret = sys_exec((char*)param1, (char*)param2, (char**)param3);
break;
case SYSCALL_SYS_STATE:
ret = sys_state(param1, (sys_state_info*)param2);

View File

@ -181,34 +181,29 @@ static void _scheduler(struct SchedulerRightGroup right_group)
spinlock_lock(&whole_kernel_lock);
while (1) {
spinlock_unlock(&whole_kernel_lock);
spinlock_lock(&xizi_task_manager.lock);
next_task = NULL;
/* find next runnable task */
assert(cur_cpu()->task == NULL);
if (next_task_emergency != NULL) {
next_task = next_task_emergency;
spinlock_lock(&next_task->lock);
next_task->state = RUNNING;
spinlock_unlock(&next_task->lock);
next_task_emergency = NULL;
} else {
next_task = xizi_task_manager.next_runnable_task();
}
spinlock_unlock(&xizi_task_manager.lock);
spinlock_unlock(&whole_kernel_lock);
/* not a runnable task */
if (UNLIKELY(next_task == NULL)) {
if (UNLIKELY(next_task == NULL) || UNLIKELY(next_task->state != RUNNING)) {
spinlock_lock(&whole_kernel_lock);
continue;
}
/* a runnable task */
spinlock_lock(&whole_kernel_lock);
assert(next_task->state == RUNNING);
// p_mmu_driver->LoadPgdirCrit((uintptr_t)V2P(next_task->pgdir.pd_addr), &right_group.intr_driver_tag);
p_mmu_driver->LoadPgdir((uintptr_t)V2P(next_task->pgdir.pd_addr));
struct CPU* cpu = cur_cpu();
cpu->task = next_task;
// DEBUG_PRINTF("CPU %d switch to task %s\n", cur_cpuid(), next_task->name);
p_mmu_driver->LoadPgdir((uintptr_t)V2P(next_task->pgdir.pd_addr));
context_switch(&cpu->scheduler, next_task->main_thread.context);
}
}

View File

@ -65,7 +65,7 @@ void intr_irq_dispatch(struct trapframe* tf)
if ((int_info = p_intr_driver->hw_before_irq()) == 0) {
return;
}
// spinlock_lock(&whole_kernel_lock);
spinlock_lock(&whole_kernel_lock);
DSB();
// DEBUG("CPU %d in\n", cur_cpuid());
@ -96,6 +96,6 @@ void intr_irq_dispatch(struct trapframe* tf)
assert(current_task == cur_cpu()->task);
// DEBUG("CPU %d out\n", cur_cpuid());
// spinlock_unlock(&whole_kernel_lock);
spinlock_unlock(&whole_kernel_lock);
p_intr_driver->cpu_irq_enable();
}

View File

@ -52,7 +52,7 @@ void software_irq_dispatch(struct trapframe* tf)
assert(p_intr_driver != NULL);
p_intr_driver->cpu_irq_disable();
// spinlock_lock(&whole_kernel_lock);
spinlock_lock(&whole_kernel_lock);
DSB();
// DEBUG("CPU %d in\n", cur_cpuid());
// get current task
@ -78,10 +78,10 @@ void software_irq_dispatch(struct trapframe* tf)
}
assert(cur_task == cur_cpu()->task);
if (syscall_num == SYSCALL_EXIT) {
ERROR("Exit reaches");
panic("Exit reaches");
}
// DEBUG("CPU %d out\n", cur_cpuid());
// spinlock_unlock(&whole_kernel_lock);
spinlock_unlock(&whole_kernel_lock);
p_intr_driver->cpu_irq_enable();
}