9os

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 9469372d1915f951022b6e83a77cfa02cd5d0419
parent a71b8e7bb7ede0884ff47116bdefc00a1700762d
Author: Roberto E. Vargas Caballero <roberto.vargas@midokura.com>
Date:   Sat, 19 Nov 2022 08:07:04 +0100

os9: Implement page pool

A page pool is needed if we want to be able to allocate and free
pages. A buffer pool is not enough because we need a container
to keep track of all the pages in a map.

Diffstat:
Minclude/os9/os9.h | 13++++++++++++-
Msrc/os9/alloc.c | 100++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/os9/proc.c | 33++++++++++++++++++++++-----------
3 files changed, 128 insertions(+), 18 deletions(-)

diff --git a/include/os9/os9.h b/include/os9/os9.h @@ -42,12 +42,12 @@ typedef struct ptable Ptable; typedef struct context Context; typedef struct task Task; -typedef struct win Win; typedef struct chan Chan; typedef struct qid Qid; typedef struct dir Dir; typedef struct mach Mach; typedef struct map Map; +typedef struct page Page; typedef struct nspace Nspace; typedef struct fdset Fdset; typedef struct ref Ref; @@ -104,6 +104,12 @@ struct ref { int cnt; }; +struct page { + int allocated; + phyaddr_t pa; + struct page *next; +}; + struct map { Ref ref; char *name; @@ -112,6 +118,9 @@ struct map { phyaddr_t pa; uintptr_t va; size_t siz; + + Page *pages; + Map *next; }; @@ -256,7 +265,9 @@ extern void unlocktask(Task *); /* alloc.c */ extern void *alloc(size_t); extern void *allocb(void); +extern Page *allocp(phyaddr_t); extern void freeb(void *); +extern void freep(Page *); extern void ialloc(void); /* sys.c */ diff --git a/src/os9/alloc.c b/src/os9/alloc.c @@ -1,5 +1,7 @@ #include <os9/os9.h> +#include <libk.h> + #include <errno.h> #include <string.h> @@ -9,23 +11,29 @@ union bucket { union bucket *next; }; -struct { +struct bufpool { union bucket *list; mutex_t m; -} bufpool; +}; + +struct pagepool { + Page *list; + mutex_t m; +}; static union bucket *heap; +static struct bufpool bufpool; +static struct pagepool pagepool; void freeb(void *bp) { - union bucket *p; + union bucket *p = bp; - if (!bp) + if (!p) return; lock(&bufpool.m); - p = bp; p->next = bufpool.list; bufpool.list = p; unlock(&bufpool.m); @@ -77,13 +85,90 @@ alloc(size_t size) return bp; } +/* + * This functions is always called with the page pool locked + */ +static int +morepages(void) +{ + int i; + void *bp; + Page *p, *ptable; + + if (pagepool.list) + return 1; + + if ((bp = allocb()) == NULL) + return 0; + + ptable = bp; + for (i = 0; i < PAGESIZE/sizeof(Page); i++) { + p = &ptable[i]; + p->next = p+1; + } + p->next = NULL; + + pagepool.list = bp; + + return 1; +} + +Page * +allocp(phyaddr_t pa) +{ + int alloc = 0; + void *bp = NULL; + Page *p; + + if (pa == -1) { + if ((bp = allocb()) == NULL) + return NULL; + pa = (phyaddr_t) PMEM(bp); + alloc = 1; + } + + lock(&pagepool.m); + + if (!morepages()) { + freeb(bp); + unlock(&pagepool.m); + return NULL; + } + + p = pagepool.list; + pagepool.list = p->next; + + unlock(&pagepool.m); + + p->pa = pa; + p->allocated = alloc; + p->next = NULL; + + return p; +} + +void +freep(Page *p) +{ + if (!p) + return; + + if (p->allocated) + freeb(VMEM(p->pa)); + + lock(&pagepool.m); + p->next = pagepool.list; + pagepool.list = p; + unlock(&pagepool.m); +} + void ialloc(void) { int i; union bucket *bp, *prev; - heap = buffertab; + heap = (union bucket *) buffertab; prev = NULL; for (i = HEAPSIZ; i < NR_BUFFERS; i++) { @@ -92,4 +177,7 @@ ialloc(void) prev = bp; } bufpool.list = bp; + + kprint("%d available buffers: %d heap, %d buffer pool\n", + NR_BUFFERS, HEAPSIZ, NR_BUFFERS - HEAPSIZ); } diff --git a/src/os9/proc.c b/src/os9/proc.c @@ -108,12 +108,18 @@ gettask(int pid) } int +unmapseg(Map *mp) +{ + return 0; +} + +int mapseg(Map *mp) { phyaddr_t pa; uintptr_t va; - void *bp; unsigned long i, n; + Page *p; assert(mp->perm & MR); @@ -126,26 +132,31 @@ mapseg(Map *mp) (mp->perm & MX) ? 'x' : '-', mp->siz); - bp = NULL; n = (mp->siz + PAGESIZE-1)/PAGESIZE; va = mp->va; pa = mp->pa; + for (i = 0; i < n; i++) { - if (mp->pa == -1) { - if ((bp = allocb()) == NULL) - return -1; - pa = (phyaddr_t) PMEM(bp); - } + if (mp->pa == -1) + pa = -1; + + if ((p = allocp(pa)) == NULL) + goto err; + p->next = mp->pages; + mp->pages = p; + + if (vmap(p->pa, va, mp->perm) < 0) + goto err; - if (vmap(pa, va, mp->perm) < 0) { - freeb(bp); - return -1; - } pa += PAGESIZE; va += PAGESIZE; } return 0; + +err: + unmapseg(mp); + return -1; } Map *