From: Alan Cox Date: Fri, 9 Feb 2018 23:49:50 +0000 (+0000) Subject: kernel: restructure readi/writei to save memory X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=dbb192b76544dfc00d38c047033b668eb43a65cd;p=FUZIX.git kernel: restructure readi/writei to save memory This saves us 256 bytes on Z80 mostly by removing the amount of 32bit maths SDCC has the opportunity to **** up. We introduce a helper (umove) which adjusts all the pointers and offsets for a given file and use that where we can. We also restructure a bit so we can use the udata.u_done value in readi/writei This has some minor consequences: Callers need to check u_done for completion not u_count Char and Socket handlers don't affect the offset unless they choose to (which is saner). Devsys has been modified accordingly. Handle with care. --- diff --git a/Kernel/devsys.c b/Kernel/devsys.c index 7eb24632..e5283862 100644 --- a/Kernel/devsys.c +++ b/Kernel/devsys.c @@ -35,7 +35,7 @@ int sys_read(uint8_t minor, uint8_t rawflag, uint8_t flag) if (uput((unsigned char *) udata.u_offset, udata.u_base, udata.u_count)) return -1; - return udata.u_count; + return umove(udata.u_count); case 2: if (udata.u_sysio) memset(udata.u_base, 0, udata.u_count); @@ -49,7 +49,7 @@ int sys_read(uint8_t minor, uint8_t rawflag, uint8_t flag) return 0; if (uput(addr + udata.u_offset, udata.u_base, udata.u_count)) return -1; - return udata.u_count; + return umove(udata.u_count); #ifdef CONFIG_DEV_MEM case 4: return devmem_read(); @@ -81,7 +81,7 @@ int sys_write(uint8_t minor, uint8_t rawflag, uint8_t flag) if(uget((unsigned char *) udata.u_offset, udata.u_base, udata.u_count)) return -1; - return udata.u_count; + return umove(udata.u_count); case 3: udata.u_error = EINVAL; return -1; diff --git a/Kernel/filesys.c b/Kernel/filesys.c index 74dcba52..d8b4dfc8 100644 --- a/Kernel/filesys.c +++ b/Kernel/filesys.c @@ -321,11 +321,11 @@ bool ch_link(inoptr wd, char *oldname, char *newname, inoptr nindex) readi(wd, 0); /* Read until EOF or name is found. readi() advances udata.u_offset */ - if(udata.u_count == 0 || namecomp(oldname, curentry.d_name)) + if(udata.u_done == 0 || namecomp(oldname, curentry.d_name)) break; } - if(udata.u_count == 0 && *oldname) { + if(udata.u_done == 0 && *oldname) { udata.u_error = ENOENT; return false; /* Entry not found */ } @@ -344,7 +344,7 @@ bool ch_link(inoptr wd, char *oldname, char *newname, inoptr nindex) curentry.d_ino = 0; /* If an existing slot is being used, we must back up the file offset */ - if(udata.u_count){ + if(udata.u_done){ udata.u_offset -= DIR_LEN; } diff --git a/Kernel/include/kernel.h b/Kernel/include/kernel.h index 54985c9e..e21aaebd 100644 --- a/Kernel/include/kernel.h +++ b/Kernel/include/kernel.h @@ -883,6 +883,7 @@ extern arg_t unlinki(inoptr ino, inoptr pino, char *fname); /* inode.c */ extern void readi(inoptr ino, uint8_t flag); +extern uint16_t umove(uint16_t n); /* Probably wants to move ? */ extern void writei(inoptr ino, uint8_t flag); extern int16_t doclose (uint8_t uindex); extern inoptr rwsetup (bool is_read, uint8_t *flag); diff --git a/Kernel/inode.c b/Kernel/inode.c index 920fb817..340c5db0 100644 --- a/Kernel/inode.c +++ b/Kernel/inode.c @@ -32,11 +32,25 @@ static uint16_t uoff(void) return BLKOFF((uint16_t)udata.u_offset); } +uint16_t umove(uint16_t n) +{ + udata.u_offset += n; + udata.u_count -= n; + udata.u_done += n; + udata.u_base += n; + return udata.u_done; +} + +static uint16_t mapcalc(inoptr ino, uint16_t *size, uint8_t m) +{ + *size = min(udata.u_count, BLKSIZE - uoff()); + return bmap(ino, udata.u_offset >> BLKSHIFT, m); +} + /* Writei (and readi) need more i/o error handling */ void readi(regptr inoptr ino, uint8_t flag) { usize_t amount; - usize_t toread; blkno_t pblk; bufptr bp; uint16_t dev; @@ -44,6 +58,8 @@ void readi(regptr inoptr ino, uint8_t flag) dev = ino->c_dev; ispipe = false; + udata.u_done = 0; + switch (getmode(ino)) { case MODE_R(F_DIR): case MODE_R(F_REG): @@ -59,7 +75,7 @@ void readi(regptr inoptr ino, uint8_t flag) case MODE_R(F_SOCK): #ifdef CONFIG_NET - udata.u_count = sock_read(ino, flag); + udata.u_done = sock_read(ino, flag); break; #endif case MODE_R(F_PIPE): @@ -73,10 +89,8 @@ void readi(regptr inoptr ino, uint8_t flag) dev = *(ino->c_node.i_addr); loop: - toread = udata.u_count; - while (toread) { - amount = min(toread, BLKSIZE - uoff()); - pblk = bmap(ino, udata.u_offset >> BLKSHIFT, 1); + while (udata.u_count) { + pblk = mapcalc(ino, &amount, 1); #if defined(read_direct) if (!ispipe && pblk != NULLBLK && amount == BLKSIZE && read_direct(flag) && bfind(dev, pblk) == 0) { @@ -111,28 +125,22 @@ void readi(regptr inoptr ino, uint8_t flag) /* Bletch */ #if defined(__M6809__) gcc_miscompile_workaround(); -#endif - udata.u_base += amount; - udata.u_offset += amount; +#endif + umove(amount); if (ispipe && (uint16_t)udata.u_offset >= 18 * BLKSIZE) udata.u_offset = 0; - toread -= amount; if (ispipe) { ino->c_node.i_size -= amount; wakeup(ino); } } /* Compute return value */ - udata.u_count -= toread; - if (udata.u_count == 0 && udata.u_error) - udata.u_count = (usize_t) -1; + if (udata.u_done == 0 && udata.u_error) + udata.u_done = (usize_t) -1; break; case MODE_R(F_CDEV): - udata.u_count = cdread(ino->c_node.i_addr[0], flag); - - if (udata.u_count != (usize_t)-1) - udata.u_offset += udata.u_count; + udata.u_done = cdread(ino->c_node.i_addr[0], flag); break; default: @@ -145,22 +153,18 @@ void readi(regptr inoptr ino, uint8_t flag) void writei(regptr inoptr ino, uint8_t flag) { usize_t amount; - usize_t towrite; bufptr bp; - bool ispipe; + bool ispipe = false; blkno_t pblk; uint16_t dev; dev = ino->c_dev; + udata.u_done = 0; switch (getmode(ino)) { case MODE_R(F_BDEV): dev = *(ino->c_node.i_addr); - case MODE_R(F_DIR): - case MODE_R(F_REG): - ispipe = false; - towrite = udata.u_count; goto loop; #ifdef CONFIG_NET @@ -172,10 +176,10 @@ void writei(regptr inoptr ino, uint8_t flag) ispipe = true; /* FIXME: this will hang if you ever write > 16 * BLKSIZE in one go - needs merging into the loop */ - while ((towrite = udata.u_count) > (16 * BLKSIZE) - + while (udata.u_count > (16 * BLKSIZE) - (uint16_t)ino->c_node.i_size) { if (ino->c_readers == 0) { /* No readers */ - udata.u_count = (usize_t)-1; + udata.u_done = (usize_t)-1; udata.u_error = EPIPE; ssig(udata.u_ptab, SIGPIPE); return; @@ -186,11 +190,13 @@ void writei(regptr inoptr ino, uint8_t flag) } /* Sleep if empty pipe */ + case MODE_R(F_DIR): + case MODE_R(F_REG): loop: flag = flag & O_SYNC ? 2 : 1; - while (towrite) { - amount = min(towrite, BLKSIZE - uoff()); + while (udata.u_count) { + pblk = mapcalc(ino, &amount, 0); if (udata.u_offset >> BLKOVERSIZE) { udata.u_error = EFBIG; @@ -198,9 +204,7 @@ void writei(regptr inoptr ino, uint8_t flag) break; } - if ((pblk = - bmap(ino, udata.u_offset >> BLKSHIFT, - 0)) == NULLBLK) + if (pblk == NULLBLK) break; /* No space to make more blocks */ /* If we are writing an entire block, we don't care @@ -216,8 +220,7 @@ void writei(regptr inoptr ino, uint8_t flag) if (bfree(bp, flag)) break; - udata.u_base += amount; - udata.u_offset += amount; + umove(amount); if (ispipe) { if ((uint16_t)udata.u_offset >= 18 * 512) udata.u_offset = 0; @@ -225,7 +228,6 @@ void writei(regptr inoptr ino, uint8_t flag) /* Wake up any readers */ wakeup(ino); } - towrite -= amount; } /* Update size if file grew */ @@ -236,16 +238,12 @@ void writei(regptr inoptr ino, uint8_t flag) } } /* Compute return value */ - udata.u_count -= towrite; - if (udata.u_count == 0 && udata.u_error) - udata.u_count = (usize_t) -1; + if (udata.u_done == 0 && udata.u_error) + udata.u_done = (usize_t) -1; break; case MODE_R(F_CDEV): - udata.u_count = cdwrite(ino->c_node.i_addr[0], flag); - - if (udata.u_count != -1) - udata.u_offset += udata.u_count; + udata.u_done = cdwrite(ino->c_node.i_addr[0], flag); break; default: udata.u_error = ENODEV; @@ -300,7 +298,6 @@ inoptr rwsetup(bool is_read, uint8_t * flag) udata.u_sysio = false; /* I/O to user data space */ udata.u_base = (unsigned char *) udata.u_argn1; /* buf */ udata.u_count = (susize_t) udata.u_argn2; /* nbytes */ - udata.u_done = 0; /* bytes done so far */ if ((ino = getinode(udata.u_argn)) == NULLINODE) { /* kprintf("[WRS: rwsetup(): getinode(%x) fails]", udata.u_argn); */ diff --git a/Kernel/syscall_exec16.c b/Kernel/syscall_exec16.c index 78f4945c..c9d1913a 100644 --- a/Kernel/syscall_exec16.c +++ b/Kernel/syscall_exec16.c @@ -79,7 +79,7 @@ arg_t _execve(void) udata.u_sysio = true; readi(ino, 0); - if (udata.u_count != 16) { + if (udata.u_done != 16) { udata.u_error = ENOEXEC; goto nogood; } @@ -174,7 +174,7 @@ arg_t _execve(void) udata.u_count = bin_size; udata.u_sysio = false; readi(ino, 0); - if (udata.u_count != bin_size) + if (udata.u_done != bin_size) goto nogood4; progptr += bin_size; } diff --git a/Kernel/syscall_exec32.c b/Kernel/syscall_exec32.c index 0fd9cecd..e1380d5a 100644 --- a/Kernel/syscall_exec32.c +++ b/Kernel/syscall_exec32.c @@ -146,7 +146,7 @@ arg_t _execve(void) udata.u_sysio = true; readi(ino, 0); - if (udata.u_count != sizeof(struct binfmt_flat)) { + if (udata.u_done != sizeof(struct binfmt_flat)) { udata.u_error = ENOEXEC; goto nogood; } @@ -232,7 +232,7 @@ arg_t _execve(void) udata.u_count = bin_size; udata.u_sysio = false; readi(ino, 0); - if (udata.u_count != bin_size) + if (udata.u_done != bin_size) goto nogood4; } diff --git a/Kernel/syscall_fs.c b/Kernel/syscall_fs.c index 8e1de08f..2d0e62b4 100644 --- a/Kernel/syscall_fs.c +++ b/Kernel/syscall_fs.c @@ -409,7 +409,7 @@ uint16_t nbytes; #define buf (char *)udata.u_argn1 #define nbytes (susize_t)udata.u_argn2 -arg_t _read(void) +arg_t readwrite(uint8_t reading) { inoptr ino; uint8_t flag; @@ -425,13 +425,18 @@ arg_t _read(void) if (!valaddr(buf, nbytes)) return -1; /* Set up u_base, u_offset, ino; check permissions, file num. */ - if ((ino = rwsetup(true, &flag)) == NULLINODE) + if ((ino = rwsetup(reading, &flag)) == NULLINODE) return -1; /* bomb out if error */ - readi(ino, flag); + (reading ? readi : writei)(ino, flag); updoff(); - return (udata.u_count); + return udata.u_done; +} + +arg_t _read(void) +{ + return readwrite(1); } #undef d @@ -479,27 +484,7 @@ uint16_t nbytes; arg_t _write(void) { - inoptr ino; - uint8_t flag; - - if (!nbytes) - return 0; - - if ((ssize_t)nbytes < 0) { - udata.u_error = EINVAL; - return -1; - } - - if (!valaddr(buf, nbytes)) - return -1; - /* Set up u_base, u_offset, ino; check permissions, file num. */ - if ((ino = rwsetup(false, &flag)) == NULLINODE) - return (-1); /* bomb out if error */ - - writei(ino, flag); - updoff(); - - return (udata.u_count); + return readwrite(0); } #undef d