From: Alan Cox Date: Tue, 29 Jan 2019 23:02:55 +0000 (+0000) Subject: malloc: lay basis for new buddy allocator that can also pair with flat.c X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=bcc5620417ad683c6b2ed7a8343b6d8e8bbff197;p=FUZIX.git malloc: lay basis for new buddy allocator that can also pair with flat.c --- diff --git a/Kernel/flat.c b/Kernel/flat.c index 7d4feaf1..c6a774a0 100644 --- a/Kernel/flat.c +++ b/Kernel/flat.c @@ -65,7 +65,7 @@ static void mem_free(struct mem *m) m->users--; if (m->users == 0) { for (i = 0; i < MAX_BLOCKS; i++) { - kfree(p->start); + kfree_s(p->start, p->end - p->start); p->start = NULL; p++; } @@ -87,10 +87,9 @@ static struct mem *mem_alloc(void) panic(PANIC_MLEAK); } -static void *kdup(void *p, void *e) +static void *kdup(void *p, void *e, uint8_t owner) { - void *n = kmalloc(e - p); - /* We chunk in 512 byte blocks */ + void *n = kmalloc(e - p, owner); if (n) { // copy_blocks(n, p, (e - p) >> 9); memcpy32(n, p, (e - p)); @@ -98,7 +97,7 @@ static void *kdup(void *p, void *e) return n; } -static struct mem *mem_clone(struct mem *m) +static struct mem *mem_clone(struct mem *m, uint8_t owner) { struct mem *n = mem_alloc(); struct memblk *p = &m->memblk[0]; @@ -107,7 +106,7 @@ static struct mem *mem_clone(struct mem *m) /* FIXME: need a per block 'RO' flag for non-copied blocks */ for (i = 0; i < MAX_BLOCKS; i++) { if (p->start) { - t->start = kdup(p->start, p->end); + t->start = kdup(p->start, p->end, owner); if (t->start == NULL) { mem_free(n); return NULL; @@ -137,6 +136,7 @@ static void mem_exchange(uint8_t * a8, uint8_t * b8, uint32_t count) } } +/* May need to switch owners on objects when we do swap etc */ static void mem_switch(struct mem *a, struct mem *b) { struct memblk *t1 = &a->memblk[0]; @@ -167,35 +167,6 @@ static void mem_copy(struct mem *to, struct mem *from) } } -/* - * We make an assumption here: The user process is not guaranteed that - * two allocations are adjacent, therefore we don't allow a copy across - * what happens to be a join of two banks. We could fix this but it's not - * clear it would be wise! - */ -usize_t valaddr(const char *pp, usize_t l) -{ - const void *p = pp; - const void *e = p + l; - unsigned int proc = udata.u_page; - int n = 0; - struct memblk *m = &mem[proc]->memblk[0]; - - while (n < MAX_BLOCKS) { - /* Found the right block ? */ - if (m->start && p >= m->start && p < m->end) { - /* Check the actual space */ - if (e >= m->end) - e = m->end; - /* Return the size we can copy */ - return e - m->start; - } - m++; - n++; - } - return 0; -} - /* Called on a fork and similar We make a copy of the pages in the memory, but we don't actually create @@ -226,7 +197,7 @@ int pagemap_alloc(ptptr p) mem[nproc]->last = 0; mb = &mem[nproc]->memblk[0]; /* Must be a multiple of 512 */ - mb->start = kmalloc(8192); + mb->start = kmalloc(8192, 0xFD /* Dummy owner */); mb->end = mb->start + 8192; if (mb->start == 0) panic("alloc"); @@ -240,7 +211,7 @@ int pagemap_alloc(ptptr p) #ifdef DEBUG kprintf("%d: Cloning %d as %d\n", proc, proc, nproc); #endif - store[nproc] = mem_clone(mem[proc]); + store[nproc] = mem_clone(mem[proc], nproc); if (store[nproc] == NULL) return ENOMEM; mem[nproc] = mem[proc]; @@ -367,32 +338,42 @@ void pagemap_free(ptptr p) mem[proc] = NULL; } -/* Called on execve */ +/* Called on execve: we should ideally work out whether freeing the + old map would allow us to make the new allocation but in practice we almost + always fork/exec so it's not that important. + + TODO: support multiple blocks and allocate code/data separately allowing + for the alignment. We should probably trim the alignment to 64 bytes as + well + + Supporting re-entrant binaries will need the binaries to have the data + aligned so maybe force it in the link ? */ int pagemap_realloc(usize_t code, usize_t size, usize_t stack) { unsigned int proc = udata.u_page; struct memblk *mb; + struct mem *m; - pagemap_free(udata.u_ptab); - - store[proc] = mem[proc] = mem_alloc(); + m = mem_alloc(); #ifdef DEBUG kprintf("%d:pr:store %p mem %p\n", proc, store[proc], mem[proc]); #endif - mb = &mem[proc]->memblk[0]; + mb = &m->memblk[0]; /* Snap to a block boundary for a fast memcpy/swap */ size = (size + 511) & ~511; - mb->start = kmalloc(size); + mb->start = kmalloc(size, proc); mb->end = mb->start + size; - /* FIXME: on the fail case we should put back the old maps */ if (mb->start == NULL) return ENOMEM; + /* Free the old map */ + pagemap_free(udata.u_ptab); + store[proc] = mem[proc] = m; return 0; } @@ -406,7 +387,7 @@ unsigned long pagemap_mem_used(void) uaddr_t pagemap_base(void) { unsigned int proc = udata.u_page; - return mem[proc]->memblk[0].start; + return (uaddr_t)mem[proc]->memblk[0].start; } /* The extra syscalls for the pool allocator */ @@ -428,7 +409,7 @@ arg_t _memalloc(void) /* Map 0 is the image, the user doesn't get to play with that one */ for (i = 1; i < MAX_BLOCKS; i++) { if (m->start == NULL) { - m->start = kmalloc(size); + m->start = kmalloc(size, proc); if (m->start == NULL) { udata.u_error = ENOMEM; return -1; @@ -460,7 +441,7 @@ arg_t _memfree(void) for (i = 1; i < MAX_BLOCKS; i++) { if (m->start == base) { - kfree(base); + kfree_s(m->start, m->end - m->start); m->start = NULL; return 0; } @@ -472,4 +453,39 @@ arg_t _memfree(void) #undef size +/* + * We make an assumption here: The user process is not guaranteed that + * two allocations are adjacent, therefore we don't allow a copy across + * what happens to be a join of two banks. We could fix this but it's not + * clear it would be wise! + * + * FIXME: need to fix this due to code/data alignment ? + */ +usize_t valaddr(const char *pp, usize_t l) +{ + const void *p = pp; + const void *e = p + l; + unsigned int proc = udata.u_page; + int n = 0; + struct memblk *m = &mem[proc]->memblk[0]; + + while (n < MAX_BLOCKS) { + /* Found the right block ? */ + if (m->start && p >= m->start && p < m->end) { + /* Check the actual space */ + if (e >= m->end) + e = m->end; + /* Fault error ? */ + if (e == p) + break; + /* Return the size we can copy */ + return e - p; + } + m++; + n++; + } + udata.u_error = EFAULT; + return 0; +} + #endif diff --git a/Kernel/include/kernel32.h b/Kernel/include/kernel32.h index 9ac0c19f..f4ef04b4 100644 --- a/Kernel/include/kernel32.h +++ b/Kernel/include/kernel32.h @@ -5,14 +5,19 @@ #ifndef __FUZIX__KERNEL_32_H #define __FUZIX__KERNEL_32_H -/* malloc.c */ -extern void *kmalloc(size_t); -extern void *kzalloc(size_t); -extern void kfree(void *); -extern void kmemaddblk(void *, size_t); +/* flat allocators */ +extern void *kmalloc(size_t, uint8_t owner); +extern void kfree_s(void *, size_t); extern unsigned long kmemavail(void); extern unsigned long kmemused(void); +/* buddymem.c */ +extern void buddy_pin(uint16_t node, uint8_t owner); +extern void buddy_init(uint16_t start, uint16_t end); + +/* malloc.c */ +extern void kmemaddblk(void *, size_t); + /* flat.c */ extern void pagemap_switch(ptptr p, int death); extern uaddr_t pagemap_base(void); diff --git a/Kernel/malloc.c b/Kernel/malloc.c index ea8ac94d..88b36641 100644 --- a/Kernel/malloc.c +++ b/Kernel/malloc.c @@ -111,10 +111,11 @@ static void split_block(struct block *b, size_t size) /* * Allocate a block. */ -void *kmalloc(size_t size) +void *kmalloc(size_t size, uint8_t owner) { struct block *b; + used(owner); /* For now */ size = ALIGNUP(size) + sizeof(struct block); b = find_smallest(size); if (!b) @@ -188,6 +189,12 @@ void kfree(void *p) merge_all_blocks(); } +void kfree_s(void *p, size_t unused) +{ + /* FIXME: we could do length checks ? */ + kfree(p); +} + unsigned long kmemavail(void) { return mfree; diff --git a/Kernel/platform-atarist/main.c b/Kernel/platform-atarist/main.c index 7fe922d9..9c50cc10 100644 --- a/Kernel/platform-atarist/main.c +++ b/Kernel/platform-atarist/main.c @@ -86,7 +86,7 @@ uint8_t platform_udata_set(ptptr p) { u_block **up = &udata_block[p - ptab]; if (*up == NULL) { - *up = kmalloc(sizeof(struct u_block)); + *up = kmalloc(sizeof(struct u_block), 0); if (*up == NULL) return ENOMEM; } diff --git a/Kernel/platform-tiny68k/main.c b/Kernel/platform-tiny68k/main.c index 385d4e02..d7f8778b 100644 --- a/Kernel/platform-tiny68k/main.c +++ b/Kernel/platform-tiny68k/main.c @@ -70,7 +70,7 @@ uint8_t platform_udata_set(ptptr p) { u_block **up = &udata_block[p - ptab]; if (*up == NULL) { - *up = kmalloc(sizeof(struct u_block)); + *up = kmalloc(sizeof(struct u_block), 0); if (*up == NULL) return ENOMEM; }