commit 79331ba68b0e49e606df1109b4b077cee0157ba4
parent 32c1c85ecd4b289f5f464b22deb113c89e81836f
Author: Roberto E. Vargas Caballero <roberto.vargas@midokura.com>
Date: Tue, 22 Nov 2022 17:31:33 +0100
os9: Don't duplicate channels in RFFDG
RFFDG must duplicate the pointer table and not the channel
table itself.
Diffstat:
3 files changed, 98 insertions(+), 45 deletions(-)
diff --git a/include/os9/os9.h b/include/os9/os9.h
@@ -160,6 +160,7 @@ struct chan {
unsigned char dev;
unsigned char mode;
mutex_t mutex;
+ Chan *next;
};
struct mpoint {
@@ -179,7 +180,7 @@ struct nspace {
struct fdset {
Ref ref;
mutex_t m;
- Chan fdset[NR_CHANS];
+ Chan *fdset[NR_CHANS];
Fdset *next;
};
@@ -270,11 +271,13 @@ extern Page *allocp(phyaddr_t);
extern Nspace *allocspace(void);
extern Map *allocmap(void);
extern Fdset *allocfds(void);
+extern Chan *allocchan(void);
extern void freeb(void *);
extern void freep(Page *);
extern void freespace(Nspace *);
extern void freemap(Map *);
extern void freefds(Fdset *);
+extern void freechan(Chan *);
extern void ialloc(void);
/* map.c */
diff --git a/src/os9/alloc.c b/src/os9/alloc.c
@@ -36,12 +36,18 @@ struct mappool {
mutex_t m;
};
+struct chanpool {
+ Chan *list;
+ mutex_t m;
+};
+
static union bucket *heap;
static struct bufpool bufpool;
static struct pagepool pagepool;
static struct nspool nspool;
static struct mappool mappool;
static struct fdspool fdspool;
+static struct chanpool chanpool;
void
freeb(void *bp)
@@ -255,6 +261,36 @@ freep(Page *p)
unlock(&pagepool.m);
}
+Chan *
+allocchan(void)
+{
+ Chan *c;
+
+ lock(&chanpool.m);
+ if (chanpool.list) {
+ c = chanpool.list;
+ chanpool.list = c->next;
+ } else {
+ if ((c = alloc(sizeof(*c))) == NULL)
+ return NULL;
+ }
+ unlock(&chanpool.m);
+
+ return c;
+}
+
+void
+freechan(Chan *c)
+{
+ if (!c)
+ return;
+
+ lock(&chanpool.m);
+ c->next = chanpool.list;
+ chanpool.list = c;
+ unlock(&chanpool.m);
+}
+
void
ialloc(void)
{
diff --git a/src/os9/dev/dev.c b/src/os9/dev/dev.c
@@ -9,7 +9,7 @@
#include "dev.h"
/*
- * Lock policy: TODO: Change the lock policy because it generates problems
+ * Lock policy:
* The channels are locked when accessed from the raw fdset array, which is
* currently done by newchan() and fd2chan().
* The channels are propagated through the functions in a locked state.
@@ -29,24 +29,33 @@ sameqid(Qid q1, Qid q2)
Chan *
newchan(unsigned char type)
{
- int i;
- Chan *c = NULL;
- Chan *fdset = proc->fds->fdset;
+ Chan *c, **bp;
+ Fdset *fds = proc->fds;
- for (i = 0; i < NR_CHANS; i++) {
- c = &fdset[i];
- if (!trylock(&c->mutex))
- continue;
- if (c->type == NODEV) {
- c->type = type;
+ lock(&fds->m);
+ for (bp = fds->fdset; bp < &fds->fdset[NR_CHANS]; ++bp) {
+ if (*bp == NULL)
break;
- }
- unlock(&c->mutex);
}
- if (!c)
- errno = ENOMEM;
+ if (bp == &fds->fdset[NR_CHANS])
+ goto err1;
+ if ((c = allocchan()) == NULL)
+ goto err2;
+ memset(c, 0, sizeof(*c));
+ c->type = type;
+
+ lock(&c->mutex);
+ *bp = c;
+ unlock(&fds->m);
+
return c;
+
+err1:
+ errno = ENOMEM;
+err2:
+ unlock(&fds->m);
+ return NULL;
}
Nspace *
@@ -96,45 +105,45 @@ delfds(Fdset *fds)
void
delchan(Chan *c)
{
- c->qid = QID(0, 0, 0);
- c->dev = 0;
- c->offset = 0;
- c->index = 0;
- c->type = NODEV;
+ Chan **bp;
+ Fdset *fds = proc->fds;
+
+ lock(&fds->m);
+ for (bp = fds->fdset; bp < &fds->fdset[NR_CHANS]; ++bp) {
+ if (*bp == c)
+ break;
+ }
+ if (bp == &fds->fdset[NR_CHANS])
+ panic("corrupted channel");
+
+ *bp = NULL;
+ unlock(&fds->m);
unlock(&c->mutex);
+
+ freechan(c);
}
static Chan *
fd2chan(int fd)
{
Chan *c;
- Chan *fdset = proc->fds->fdset;
if (fd < 0 || fd >= NR_CHANS)
- goto badfd;
+ goto err;
- c = &fdset[fd];
+ c = proc->fds->fdset[fd];
+ if (!c)
+ goto err;
lock(&c->mutex);
- if (c->type == NODEV)
- goto ubadfd;
+
return c;
-ubadfd:
- unlock(&c->mutex);
-badfd:
+err:
errno = EBADF;
return NULL;
}
static int
-chan2fd(Chan *c)
-{
- Chan *fdset = proc->fds->fdset;
-
- return (c == NULL) ? -1 : (c - fdset);
-}
-
-static int
validmode(int mode)
{
if ((mode & O_READ) && (mode & (O_WRITE | O_RDWR)))
@@ -429,15 +438,24 @@ devopen(char *fname, int mode)
int
open(char *fname, int mode)
{
- int r;
- Chan *c;
+ int fd;
+ Chan *c, **bp;
+ Fdset *fds = proc->fds;
if ((c = devopen(fname, mode)) == NULL)
return -1;
- r = chan2fd(c);
- unlock(&c->mutex);
- return r;
+ lock(&fds->m);
+ for (bp = fds->fdset; bp < &fds->fdset[NR_CHANS]; ++bp) {
+ if (*bp == c)
+ break;
+ }
+ fd = (bp == &fds->fdset[NR_CHANS]) ? -1 : (bp - fds->fdset);
+ unlock(&fds->m);
+
+ if (fd == -1)
+ panic("corrupted channel");
+ return fd;
}
int
@@ -773,10 +791,6 @@ void
idev(void)
{
Chan *c;
- Chan *fdset = proc->fds->fdset;
-
- for (c = fdset; c < &fdset[NR_CHANS]; c++)
- c->type = NODEV;
if ((c = attach('/', 0)) == NULL)
panic("idev:attach");