From 0b3a3bf7a3072efb2632a5b4810affbdd6740401 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 29 Aug 2016 11:54:01 +0100 Subject: [PATCH] pipe: redo reader/writer counting It's almost as cheap to keep counters as go scanning each time in terms of memory usage and much much faster. --- Kernel/filesys.c | 15 --------------- Kernel/include/kernel.h | 20 +++++++++----------- Kernel/inode.c | 19 +++++++++++++------ Kernel/syscall_fs.c | 2 ++ Kernel/syscall_fs3.c | 7 ++++++- Kernel/syscall_net.c | 2 ++ 6 files changed, 32 insertions(+), 33 deletions(-) diff --git a/Kernel/filesys.c b/Kernel/filesys.c index 2dfdde67..57ac39c2 100644 --- a/Kernel/filesys.c +++ b/Kernel/filesys.c @@ -687,21 +687,6 @@ int8_t oft_alloc(void) return -1; } -/* Check if an inode is open for reading or for writing. Needed for pipe - * EOF and will one day be needed for shared code segments (8086 etc) - */ -int8_t oft_inuse(inoptr ino, uint8_t rw) -{ - struct oft *ofptr = of_tab; - while(ofptr <= &of_tab[OFTSIZE - 1]) { - if (ofptr->o_refs && ofptr->o_inode == ino && - O_ACCMODE(ofptr->o_access) != rw) - return 1; - ofptr++; - } - return 0; -} - /* * To minimise storage we don't track exclusive locks explicitly. We know * that if we are dropping an exclusive lock then we must be the owner, diff --git a/Kernel/include/kernel.h b/Kernel/include/kernel.h index 3ecf6eac..d425c33c 100644 --- a/Kernel/include/kernel.h +++ b/Kernel/include/kernel.h @@ -219,12 +219,15 @@ struct hd_geometry { #define major(x) ((x) >> 8) #define minor(x) ((x) & 0xFF) -typedef struct cinode { // note: exists in memory *and* on disk - uint16_t c_magic; /* Used to check for corruption. */ - uint16_t c_dev; /* Inode's device */ - uint16_t c_num; /* Inode # */ - dinode c_node; - uint8_t c_refs; /* In-core reference count */ +/* In memory inode structure */ +typedef struct cinode { + uint16_t c_magic; /* Used to check for corruption. */ + uint16_t c_dev; /* Inode's device */ + uint16_t c_num; /* Inode # */ + dinode c_node; /* On disk inode data */ + uint8_t c_refs; /* In-core reference count */ + uint8_t c_readers; /* Count of readers by oft entry */ + uint8_t c_writers; /* Count of writers by oft entry */ uint8_t c_flags; #define CDIRTY 0x80 /* Modified flag. */ #define CRDONLY 0x40 /* On a read only file system */ @@ -776,11 +779,6 @@ extern void i_free(uint16_t devno, uint16_t ino); extern blkno_t blk_alloc(uint16_t devno); extern void blk_free(uint16_t devno, blkno_t blk); extern int8_t oft_alloc(void); -extern int8_t oft_inuse(inoptr ino, uint8_t rw); -/* Yes these are intentionally backwards - there are 3 modes so the loop looks - for "not this mode" */ -#define INUSE_R O_WRONLY -#define INUSE_W O_RDONLY extern void deflock(struct oft *ofptr); extern void oft_deref(int8_t of); /* returns index of slot, or -1 on failure */ diff --git a/Kernel/inode.c b/Kernel/inode.c index dc0f2ac1..84cf6969 100644 --- a/Kernel/inode.c +++ b/Kernel/inode.c @@ -15,10 +15,8 @@ how we handle the psleep_flags bit */ static uint8_t pipewait(inoptr ino, uint8_t flag) { - int8_t n; while(ino->c_node.i_size == 0) { - n = oft_inuse(ino, INUSE_W); - if (n == 0 || psleep_flags(ino, flag)) { + if (ino->c_writers == 0 || psleep_flags(ino, flag)) { udata.u_count = 0; return 0; } @@ -164,7 +162,7 @@ void writei(inoptr ino, uint8_t flag) in one go - needs merging into the loop */ while ((towrite = udata.u_count) > (16 * BLKSIZE) - ino->c_node.i_size) { - if (!oft_inuse(ino, INUSE_R)) { /* No readers */ + if (ino->c_readers == 0) { /* No readers */ udata.u_count = (usize_t)-1; udata.u_error = EPIPE; ssig(udata.u_ptab, SIGPIPE); @@ -238,18 +236,22 @@ void writei(inoptr ino, uint8_t flag) int16_t doclose(uint8_t uindex) { int8_t oftindex; + struct oft *oftp; inoptr ino; uint16_t flush_dev = NO_DEVICE; + uint8_t m; if (!(ino = getinode(uindex))) return (-1); oftindex = udata.u_files[uindex]; + oftp = of_tab + udata.u_files[uindex]; + m = O_ACCMODE(oftp->o_access); - if (of_tab[oftindex].o_refs == 1) { + if (oftp->o_refs == 1) { if (isdevice(ino)) d_close((int) (ino->c_node.i_addr[0])); - if (getmode(ino) == MODE_R(F_REG) && O_ACCMODE(of_tab[oftindex].o_access)) + if (getmode(ino) == MODE_R(F_REG) && m) flush_dev = ino->c_dev; #ifdef CONFIG_NET if (issocket(ino)) @@ -260,6 +262,11 @@ int16_t doclose(uint8_t uindex) udata.u_cloexec &= ~(1 << uindex); oft_deref(oftindex); + if (m != O_RDONLY) + ino->c_writers--; + if (m != O_WRONLY) + ino->c_readers--; + /* if we closed a file in write mode, flush the device's cache after inode has been deferenced */ if(flush_dev != NO_DEVICE) d_flush(flush_dev); diff --git a/Kernel/syscall_fs.c b/Kernel/syscall_fs.c index 10d7c550..db58a8cc 100644 --- a/Kernel/syscall_fs.c +++ b/Kernel/syscall_fs.c @@ -337,6 +337,8 @@ arg_t _pipe(void) ++ino->c_refs; ino->c_node.i_mode = F_PIPE | 0777; /* No permissions necessary on pipes */ ino->c_node.i_nlink = 0; /* a pipe is not in any directory */ + ino->c_readers++; + ino->c_writers++; // write results to userspace uputw(u1, fildes); diff --git a/Kernel/syscall_fs3.c b/Kernel/syscall_fs3.c index 2f63b4f5..9cdf2f91 100644 --- a/Kernel/syscall_fs3.c +++ b/Kernel/syscall_fs3.c @@ -128,8 +128,13 @@ arg_t _open(void) of_tab[oftindex].o_access = flag; /* Save the low bits only */ if (flag & O_CLOEXEC) udata.u_cloexec |= (1 << oftindex); - /* FIXME: ATIME ? */ + if (O_ACCMODE(flag) != O_RDONLY) + ino->c_writers++; + if (O_ACCMODE(flag) != O_WRONLY) + ino->c_readers++; + + /* FIXME: ATIME ? */ /* * Sleep process if no writer or reader */ diff --git a/Kernel/syscall_net.c b/Kernel/syscall_net.c index 58c7a933..1beab3e0 100644 --- a/Kernel/syscall_net.c +++ b/Kernel/syscall_net.c @@ -324,6 +324,8 @@ arg_t make_socket(struct sockinfo *s, struct socket **np) /* The nlink cheat needs to be taught to fsck! */ ino->c_node.i_mode = F_SOCK | 0777; ino->c_node.i_nlink = n->s_num; /* Cheat !! */ + ino->c_readers = 1; + ino->c_writers = 1; of_tab[oftindex].o_inode = ino; of_tab[oftindex].o_access = O_RDWR; -- 2.34.1