9os

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

commit 2feb45fcfff34bb9499d4d56cfeb0ebab12dc295
parent 6b7bff0facdbf85b0cd9bf672b53a838e40984f4
Author: Ambroise Vincent <ambroise.vincent@arm.com>
Date:   Tue, 14 May 2019 16:40:23 +0100

[dev] Improve shared resources management

Add locks to channels and mount points.

Change-Id: Ief2b7f6a0e8016ede7b52d94d8922948b414124a
Signed-off-by: Ambroise Vincent <ambroise.vincent@arm.com>

Diffstat:
Mdrivers/dev.c | 139++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Mdrivers/dev.h | 1+
Minclude/rcode/rcode.h | 1+
Mtarget/native/arch.s | 5++++-
4 files changed, 98 insertions(+), 48 deletions(-)

diff --git a/drivers/dev.c b/drivers/dev.c @@ -10,14 +10,25 @@ #define NR_MPOINTS 4 +/* + * 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. + * When a channel is done being used, it needs to be unlocked. This is either + * done when the channel is closed by delchan(), or directly with a call to + * unlock() when inside of dev.c. + * The use of mutexes is then transparent for the drivers. + */ + struct mpoint { Chan *new; Chan *old; + mutex_t mutex; }; static Chan fdset[NR_CHANS]; static Chan slash; -static mutex_t chanlock; static struct mpoint mpoints[NR_MPOINTS]; Chan * @@ -26,29 +37,51 @@ newchan(unsigned char type) Chan *c = NULL; int i; - lock(&chanlock); for (i = 0; i < NR_CHANS; i++) { - if (fdset[i].type == NODEV) { - c = &fdset[i]; + c = &fdset[i]; + if (trylock(&c->mutex) < 0) + continue; + if (c->type == NODEV) { c->type = type; break; } + unlock(&c->mutex); } - unlock(&chanlock); if (!c) errno = ENOMEM; return c; } +void +delchan(Chan *c) +{ + c->qid = 0; + c->dev = 0; + c->offset = 0; + c->type = NODEV; + unlock(&c->mutex); +} + static Chan * fd2chan(int fd) { - if (fd < 0 || fd >= NR_CHANS || fdset[fd].type == NODEV) { - errno = EBADF; - return NULL; - } - return &fdset[fd]; + Chan *c; + + if (fd < 0 || fd >= NR_CHANS) + goto badfd; + + c = &fdset[fd]; + lock(&c->mutex); + if (fdset[fd].type == NODEV) + goto ubadfd; + return c; + +ubadfd: + unlock(&c->mutex); +badfd: + errno = EBADF; + return NULL; } static int @@ -111,15 +144,6 @@ devtype(int c) return i; } -void -delchan(Chan *c) -{ - c->qid = 0; - c->dev = 0; - c->offset = 0; - c->type = NODEV; -} - int buf2chan(Chan *c, void *dst, void *src, int nbytes, long len) { @@ -145,10 +169,16 @@ mntpoint(int type, Qid qid) struct mpoint *mp; for (mp = mpoints; mp < &mpoints[NR_MPOINTS]; mp++) { - if ((cn = mp->new) == NULL) + lock(&mp->mutex); + if ((cn = mp->new) == NULL) { + unlock(&mp->mutex); continue; - if (cn->type == type && cn->qid == qid) + } + if (cn->type == type && cn->qid == qid) { + unlock(&mp->mutex); return mp->old; + } + unlock(&mp->mutex); } return NULL; @@ -340,12 +370,16 @@ int open(const char *fname, int mode) { Chan *c; + int r; if (!validmode(mode)) return -1; + c = namec(fname, mode); - return chan2fd(c); + r = chan2fd(c); + unlock(&c->mutex); + return r; } int @@ -441,73 +475,81 @@ int read(int fd, void *buf, int n) { Chan *c; + int r = -1; if ((c = fd2chan(fd)) == NULL) return -1; - if ((c->qid & CHDIR) && (n < DIRLEN)) { + if ((c->qid & CHDIR) && (n < DIRLEN)) errno = EINVAL; - return -1; - } + else + r = devtab[c->type]->read(c, buf, n); - return devtab[c->type]->read(c, buf, n); + unlock(&c->mutex); + return r; } int write(int fd, void *buf, int n) { Chan *c; + int r = -1; if ((c = fd2chan(fd)) == NULL) return -1; - if (c->qid & CHDIR) { + if (c->qid & CHDIR) errno = EISDIR; - return -1; - } + else + r = devtab[c->type]->write(c, buf, n); - return devtab[c->type]->write(c, buf, n); + unlock(&c->mutex); + return r; } int seek(int fd, long off, int whence) { Chan *c; + int r = -1; if ((c = fd2chan(fd)) == NULL) return -1; - if (c->qid & CHDIR) { + if (c->qid & CHDIR) errno = EISDIR; - return -1; - } + else + r = devtab[c->type]->seek(c, off, whence); - return devtab[c->type]->seek(c, off, whence); + unlock(&c->mutex); + return r; } int fsync(int fd) { Chan *c; + int r = -1; if ((c = fd2chan(fd)) == NULL) return -1; - if (c->qid & CHDIR) { - errno = EISDIR; - return -1; - } + if (c->qid & CHDIR) + errno = EISDIR; + else + r = devtab[c->type]->sync(c, SYNCDEV); - return devtab[c->type]->sync(c, SYNCDEV); + unlock(&c->mutex); + return r; } void sync(void) { Chan *c; - Dev * const *dp; + Dev * const *dp; - for (dp = devtab; *dp; ++dp) { + for (dp = devtab; *dp; ++dp) { c = attach((*dp)->id, 0); devtab[c->type]->sync(c, SYNCALL); delchan(c); @@ -575,8 +617,10 @@ addmntpoint(Chan *c, char *new) for (i = NR_MPOINTS-1; i >= 0; i--) { mp = &mpoints[i]; + lock(&mp->mutex); if (!mp->new) break; + unlock(&mp->mutex); } if (i < 0) { @@ -586,6 +630,7 @@ addmntpoint(Chan *c, char *new) mp->new = cn; mp->old = c; + unlock(&mp->mutex); return 0; @@ -607,6 +652,7 @@ bind(char *old, char *new) delchan(c); return -1; } + unlock(&c->mutex); return 0; } @@ -620,19 +666,18 @@ mount(char *srv, char *where, char *spec) goto err0; c = devtab[cs->type]->mount(cs, spec); + delchan(cs); if (!c) - goto err1; + goto err0; if (addmntpoint(c, where) < 0) - goto err2; - delchan(cs); + goto err1; + unlock(&c->mutex); return 0; -err2: - delchan(c); err1: - delchan(cs); + delchan(c); err0: return -1; } diff --git a/drivers/dev.h b/drivers/dev.h @@ -43,6 +43,7 @@ struct chan { unsigned char type; unsigned char dev; unsigned char mode; + mutex_t mutex; }; struct attr { diff --git a/include/rcode/rcode.h b/include/rcode/rcode.h @@ -104,6 +104,7 @@ extern uint16_t outm16(uint16_t, void *addr); extern uint32_t outm32(uint32_t, void *addr); extern void lock(mutex_t *m); extern void unlock(mutex_t *m); +extern int trylock(mutex_t *m); /* dlang.c */ extern unsigned in_debug; diff --git a/target/native/arch.s b/target/native/arch.s @@ -6,7 +6,7 @@ .globl outm8,outm16,outm32 .globl invdcachesetway,invicache,vectbl,doswtch .globl inm8,inm16,inm32,outm8,outm16,outm32 - .globl lock,unlock + .globl lock,unlock,trylock intr: cmp x0,#0 @@ -86,6 +86,9 @@ unlock: sev ret +trylock: + ret // TODO + dohalt: msr daifset,#15 wfe