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:
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 *