implement munmap
Also add basic errno.h
This commit is contained in:
parent
3339f8b059
commit
27c2f503cc
@ -70,8 +70,12 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
|||||||
char path[256];
|
char path[256];
|
||||||
|
|
||||||
as = processGetAddrSpace(getCurrentThread()->process);
|
as = processGetAddrSpace(getCurrentThread()->process);
|
||||||
ret = syscallGet5args(userCtx, (unsigned int *)&uaddr_ptr, (unsigned int *)&size, (unsigned int *)&rights,
|
ret = syscallGet5args(userCtx, (unsigned int *)&uaddr_ptr, (unsigned int *)&size,
|
||||||
(unsigned int *)&flags, (unsigned int *)&userPath);
|
(unsigned int *)&rights, (unsigned int *)&flags,
|
||||||
|
(unsigned int *)&userPath);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
|
||||||
if (memcpyFromUser((vaddr_t)&uaddr, uaddr_ptr, sizeof(uaddr)) != sizeof(uaddr)) {
|
if (memcpyFromUser((vaddr_t)&uaddr, uaddr_ptr, sizeof(uaddr)) != sizeof(uaddr)) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
@ -81,17 +85,31 @@ int syscallExecute(int syscallId, const struct cpu_state *userCtx)
|
|||||||
strzcpyFromUser((vaddr_t *)path, (uaddr_t *)userPath, sizeof(path));
|
strzcpyFromUser((vaddr_t *)path, (uaddr_t *)userPath, sizeof(path));
|
||||||
|
|
||||||
printf("Trying mmap for device %s at %lu\n", path, (vaddr_t)uaddr);
|
printf("Trying mmap for device %s at %lu\n", path, (vaddr_t)uaddr);
|
||||||
if(strcmp(path, "/dev/zero") == 0){
|
if (strcmp(path, "/dev/zero") == 0) {
|
||||||
ret = zeroMmap(as, &uaddr, size, rights,flags);
|
ret = zeroMmap(as, &uaddr, size, rights, flags);
|
||||||
}
|
}
|
||||||
if(!ret){
|
if (!ret) {
|
||||||
if(memcpyToUser(uaddr_ptr, (vaddr_t)&uaddr, sizeof(uaddr)) != sizeof(uaddr)){
|
if (memcpyToUser(uaddr_ptr, (vaddr_t)&uaddr, sizeof(uaddr)) != sizeof(uaddr)) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SYSCALL_ID_MUNMAP: {
|
||||||
|
struct uAddrSpace *as;
|
||||||
|
uaddr_t uaddr;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
ret = syscallGet2args(userCtx, (unsigned int *)&uaddr, (unsigned int *)&size);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
|
||||||
|
as = processGetAddrSpace(getCurrentThread()->process);
|
||||||
|
ret = uAddrSpaceUnmap(as, uaddr, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
printf("Unknon syscall id %d\n", syscallId);
|
printf("Unknon syscall id %d\n", syscallId);
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#define SYSCALL_ID_TEST 5
|
#define SYSCALL_ID_TEST 5
|
||||||
#define SYSCALL_ID_BRK 6
|
#define SYSCALL_ID_BRK 6
|
||||||
#define SYSCALL_ID_MMAP 7
|
#define SYSCALL_ID_MMAP 7
|
||||||
|
#define SYSCALL_ID_MUNMAP 8
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);
|
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "uaddrspace.h"
|
#include "uaddrspace.h"
|
||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
|
#include "errno.h"
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "klibc.h"
|
#include "klibc.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
@ -153,7 +154,9 @@ int uAddrSpaceUnmap(struct uAddrSpace *as, uaddr_t uaddr, size_t size)
|
|||||||
{
|
{
|
||||||
if (uaddr < PAGING_BASE_USER_ADDRESS || uaddr > PAGING_TOP_USER_ADDRESS - size)
|
if (uaddr < PAGING_BASE_USER_ADDRESS || uaddr > PAGING_TOP_USER_ADDRESS - size)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!ALIGN(uaddr, PAGE_SIZE) || size <= 0)
|
if (!IS_ALIGNED(uaddr, PAGE_SIZE) || size <= 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if(!as)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
size = ALIGN(size, PAGE_SIZE);
|
size = ALIGN(size, PAGE_SIZE);
|
||||||
@ -168,13 +171,20 @@ int uAddrSpaceUnmap(struct uAddrSpace *as, uaddr_t uaddr, size_t size)
|
|||||||
if (reg->addr >= uaddr && (reg->addr + reg->size <= uaddr + size)) {
|
if (reg->addr >= uaddr && (reg->addr + reg->size <= uaddr + size)) {
|
||||||
list_delete_named(as->listVirtualReg, reg, prevInAddrSpace, nextInAddrSpace);
|
list_delete_named(as->listVirtualReg, reg, prevInAddrSpace, nextInAddrSpace);
|
||||||
list_delete_named(reg->res->listVirtualReg, reg, prevInMappedRes, nextInMappedRes);
|
list_delete_named(reg->res->listVirtualReg, reg, prevInMappedRes, nextInMappedRes);
|
||||||
|
|
||||||
|
if (reg->res->ops && reg->res->ops->unmap)
|
||||||
|
reg->res->ops->unmap(reg, uaddr, size);
|
||||||
|
|
||||||
if (reg->res->ops && reg->res->ops->close)
|
if (reg->res->ops && reg->res->ops->close)
|
||||||
reg->res->ops->close(reg);
|
reg->res->ops->close(reg);
|
||||||
|
|
||||||
|
if (reg == next)//singleton
|
||||||
|
next = NULL;
|
||||||
|
|
||||||
free(reg);
|
free(reg);
|
||||||
// Unmaped space is inside and smaller than the VR
|
// Unmaped space is inside and smaller than the VR
|
||||||
// VR should be splitted
|
// VR should be splitted
|
||||||
} else if (reg->addr > uaddr && (reg->addr + reg->size <= uaddr + size)) {
|
} else if (reg->addr > uaddr && (reg->addr + reg->size < uaddr + size)) {
|
||||||
struct uAddrVirtualReg *new =
|
struct uAddrVirtualReg *new =
|
||||||
(struct uAddrVirtualReg *)zalloc(sizeof(struct uAddrSpace));
|
(struct uAddrVirtualReg *)zalloc(sizeof(struct uAddrSpace));
|
||||||
if (!new)
|
if (!new)
|
||||||
@ -193,7 +203,7 @@ int uAddrSpaceUnmap(struct uAddrSpace *as, uaddr_t uaddr, size_t size)
|
|||||||
nextInMappedRes);
|
nextInMappedRes);
|
||||||
if (reg->res->ops && reg->res->ops->unmap)
|
if (reg->res->ops && reg->res->ops->unmap)
|
||||||
reg->res->ops->unmap(reg, uaddr, size);
|
reg->res->ops->unmap(reg, uaddr, size);
|
||||||
if (new->res->ops &&new->res->ops->open)
|
if (new->res->ops && new->res->ops->open)
|
||||||
new->res->ops->open(new);
|
new->res->ops->open(new);
|
||||||
break;
|
break;
|
||||||
// Only affect the beginning
|
// Only affect the beginning
|
||||||
|
@ -21,6 +21,7 @@ static int zeroClose(struct uAddrVirtualReg *vreg)
|
|||||||
ent->refCnt--;
|
ent->refCnt--;
|
||||||
if (ent->refCnt == 0) {
|
if (ent->refCnt == 0) {
|
||||||
free(vreg->res->customData);
|
free(vreg->res->customData);
|
||||||
|
free(vreg->res);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,9 @@
|
|||||||
#define SYSCALL_ID_PUTC 3
|
#define SYSCALL_ID_PUTC 3
|
||||||
#define SYSCALL_ID_READ 4
|
#define SYSCALL_ID_READ 4
|
||||||
#define SYSCALL_ID_TEST 5
|
#define SYSCALL_ID_TEST 5
|
||||||
#define SYSCALL_ID_BRK 6
|
#define SYSCALL_ID_BRK 6
|
||||||
#define SYSCALL_ID_MMAP 7
|
#define SYSCALL_ID_MMAP 7
|
||||||
|
#define SYSCALL_ID_MUNMAP 8
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);
|
int syscallExecute(int syscallId, const struct cpu_state *user_ctx);
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#include "libc.h"
|
#include "libc.h"
|
||||||
|
#include "errno.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "minmax.h"
|
#include "minmax.h"
|
||||||
#include "swintr.h"
|
#include "swintr.h"
|
||||||
|
#include "sys/mman.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
|
|
||||||
int errno = 0;
|
int errno = 0;
|
||||||
@ -732,5 +734,14 @@ void *mmap(void *addr, size_t len, int prot, int flags, char *path) {
|
|||||||
if(!ret)
|
if(!ret)
|
||||||
return addr;
|
return addr;
|
||||||
errno = ret;
|
errno = ret;
|
||||||
return (void *)-1;
|
|
||||||
|
return MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int munmap(void *addr, size_t len)
|
||||||
|
{
|
||||||
|
if (len == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return syscall2(SYSCALL_ID_MUNMAP, (unsigned int)&addr, len);
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap) __attribut
|
|||||||
int vprintf(const char *format, va_list ap) __attribute__ ((__format__ (printf, 1, 0)));
|
int vprintf(const char *format, va_list ap) __attribute__ ((__format__ (printf, 1, 0)));
|
||||||
int printf(const char *format, ...) __attribute__ ((__format__ (printf, 1, 2)));
|
int printf(const char *format, ...) __attribute__ ((__format__ (printf, 1, 2)));
|
||||||
void *mmap(void *addr, size_t len, int prot, int flags, char *path);
|
void *mmap(void *addr, size_t len, int prot, int flags, char *path);
|
||||||
|
int munmap(void *addr, size_t len);
|
||||||
|
|
||||||
int asprintf(char **strp, const char *fmt, ...) __attribute__ ((__format__ (printf, 2, 3)));
|
int asprintf(char **strp, const char *fmt, ...) __attribute__ ((__format__ (printf, 2, 3)));
|
||||||
int vasprintf(char **strp, const char *fmt, va_list ap) __attribute__ ((__format__ (printf, 2, 0)));
|
int vasprintf(char **strp, const char *fmt, va_list ap) __attribute__ ((__format__ (printf, 2, 0)));
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
#include "errno.h"
|
||||||
#include "libc.h"
|
#include "libc.h"
|
||||||
#include "stdarg.h"
|
#include "stdarg.h"
|
||||||
|
#include "stddef.h"
|
||||||
#include "sys/mman.h"
|
#include "sys/mman.h"
|
||||||
#include "tiny.h"
|
#include "tiny.h"
|
||||||
|
|
||||||
@ -12,6 +14,7 @@ int func_help()
|
|||||||
printf(" alloc: test allocation\n");
|
printf(" alloc: test allocation\n");
|
||||||
printf(" tiny: a tiny C-like interpreter\n");
|
printf(" tiny: a tiny C-like interpreter\n");
|
||||||
printf(" mmap: test mmap \n");
|
printf(" mmap: test mmap \n");
|
||||||
|
printf(" munmap: test munmap \n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,29 +30,29 @@ char *initialHeap = 0;
|
|||||||
int func_alloc()
|
int func_alloc()
|
||||||
{
|
{
|
||||||
if (initialHeap == 0) {
|
if (initialHeap == 0) {
|
||||||
initialHeap = sbrk(0);
|
initialHeap = sbrk(0);
|
||||||
}
|
}
|
||||||
printf("Testing allocation\n");
|
printf("Testing allocation\n");
|
||||||
int allocSize = 4096 * 2;
|
int allocSize = 4096 * 2;
|
||||||
char *currentHeap = sbrk(0);
|
char *currentHeap = sbrk(0);
|
||||||
if (currentHeap - initialHeap < allocSize) {
|
if (currentHeap - initialHeap < allocSize) {
|
||||||
brk(initialHeap + allocSize);
|
brk(initialHeap + allocSize);
|
||||||
}
|
}
|
||||||
int *allocatedData = (int *)initialHeap;
|
int *allocatedData = (int *)initialHeap;
|
||||||
for (unsigned int i = 0; i < allocSize / sizeof(int); i++) {
|
for (unsigned int i = 0; i < allocSize / sizeof(int); i++) {
|
||||||
allocatedData[i] = i;
|
allocatedData[i] = i;
|
||||||
}
|
}
|
||||||
printf("Success\nTesting malloc\n");
|
printf("Success\nTesting malloc\n");
|
||||||
uintptr_t heap = (uintptr_t)sbrk(0);
|
uintptr_t heap = (uintptr_t)sbrk(0);
|
||||||
|
|
||||||
for (int i = 0; i < 12; i++) {
|
for (int i = 0; i < 12; i++) {
|
||||||
void *ptr = malloc(1 << i);
|
void *ptr = malloc(1 << i);
|
||||||
printf("malloc size %d: 0x%p\n", (1 << i), ptr);
|
printf("malloc size %d: 0x%p\n", (1 << i), ptr);
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
printf("Malloc failed\n");
|
printf("Malloc failed\n");
|
||||||
}
|
}
|
||||||
memset(ptr, 0, 1 << i);
|
memset(ptr, 0, 1 << i);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
uintptr_t newHeap = (uintptr_t)sbrk(0);
|
uintptr_t newHeap = (uintptr_t)sbrk(0);
|
||||||
printf("Malloc used %dB\n", newHeap - heap);
|
printf("Malloc used %dB\n", newHeap - heap);
|
||||||
@ -57,17 +60,63 @@ int func_alloc()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int func_mmap() {
|
struct mmapedArea {
|
||||||
|
void *addr;
|
||||||
|
size_t size;
|
||||||
|
struct mmapedArea *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct mmapedArea *listMmap = NULL;
|
||||||
|
|
||||||
|
int func_mmap()
|
||||||
|
{
|
||||||
|
struct mmapedArea *area = (struct mmapedArea *)malloc(sizeof(struct mmapedArea));
|
||||||
|
|
||||||
|
if (area == NULL) {
|
||||||
|
printf("Fail to allocate area\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
char *path = "/dev/zero";
|
char *path = "/dev/zero";
|
||||||
void *mapAddr = mmap((void *)4096, 4096, PROT_READ | PROT_WRITE, 0, path);
|
void *mapAddr = mmap((void *)0, 4096, PROT_READ | PROT_WRITE, 0, path);
|
||||||
|
|
||||||
|
if (mapAddr == MAP_FAILED) {
|
||||||
|
printf("mmap failed errno %d\n", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
printf("Zero mmaped at %p\n", mapAddr);
|
printf("Zero mmaped at %p\n", mapAddr);
|
||||||
int data = *(int *)mapAddr;
|
int data = *(int *)mapAddr;
|
||||||
*(int *)mapAddr = data;
|
*(int *)mapAddr = data;
|
||||||
|
|
||||||
|
area->addr = mapAddr;
|
||||||
|
area->size = 4096;
|
||||||
|
area->next = listMmap;
|
||||||
|
listMmap = area;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int func_munmap()
|
||||||
|
{
|
||||||
|
if (!listMmap) {
|
||||||
|
printf("Nothing to unmap... mmap first! \n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mmapedArea *area = listMmap;
|
||||||
|
int ret = munmap(area->addr, area->size);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
printf("Fail to unmap area at 0x%p (size %d) error %d\n", area->addr, area->size, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
listMmap = listMmap->next;
|
||||||
|
free(area);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
(void)argc;
|
(void)argc;
|
||||||
@ -102,6 +151,10 @@ int main(int argc, char *argv[])
|
|||||||
func_mmap();
|
func_mmap();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (strcmp(buf, "munmap") == 0) {
|
||||||
|
func_munmap();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -9,3 +9,5 @@
|
|||||||
#define MAP_PRIVATE (1 << 1)
|
#define MAP_PRIVATE (1 << 1)
|
||||||
#define MAP_FIXED (1 << 2)
|
#define MAP_FIXED (1 << 2)
|
||||||
|
|
||||||
|
|
||||||
|
#define MAP_FAILED (void *)-1
|
||||||
|
Loading…
Reference in New Issue
Block a user