Mercurial > hg > CbC > CbC_xv6
changeset 327:6db8be34be04
merged
author | anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 08 Feb 2020 20:45:42 +0900 |
parents | 03be5144b072 (current diff) f0b337cb6024 (diff) |
children | c9daa25b8c3f |
files | .hgtags |
diffstat | 15 files changed, 1117 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Sat Feb 08 20:42:57 2020 +0900 +++ b/.hgtags Sat Feb 08 20:45:42 2020 +0900 @@ -2,3 +2,4 @@ 101b229f182dc04ca38de80af8c4482701f1ddc0 cmake 624fe2ec975c3856ea8e6e501aeedd8a2c120faf cmake-of-the-shelf 9cbd1ecac10dbb7fbace556a763e4ae431a3f68d tobaru-master +98902fad1e2e92b6089bd99e8c1acb7b3b6ba005 menikon_thesis
--- a/src/CMakeLists.txt Sat Feb 08 20:42:57 2020 +0900 +++ b/src/CMakeLists.txt Sat Feb 08 20:45:42 2020 +0900 @@ -128,7 +128,8 @@ SOURCES string.c arm.c asm.S bio.c buddy.c console.cbc exec.c file.cbc fs.c log.c main.c memide.c pipe.cbc proc.cbc spinlock.cbc start.c swtch.S syscall.cbc sysfile.cbc sysproc.c trap_asm.S trap.c vm.c device/picirq.c device/timer.c device/uart.c - SingleLinkedStack.cbc entry.S impl/vm_impl.cbc impl/vm_impl_private.cbc impl/KernelError.cbc + SingleLinkedStack.cbc entry.S impl/vm_impl.cbc impl/vm_impl_private.cbc + impl/fs_impl.cbc impl/fs_impl_private.cbc impl/KernelError.cbc ) # sys_read_impl.cbc
--- a/src/gearsTools/generate_stub.pl Sat Feb 08 20:42:57 2020 +0900 +++ b/src/gearsTools/generate_stub.pl Sat Feb 08 20:45:42 2020 +0900 @@ -134,8 +134,12 @@ if (/^\s*(.*)\s+(\w+);$/ ) { my $ttype = $1; my $tname = $2; - if ($ttype =~ /^(union|struct)?\s*(\w+)/) { - $ttype = $2; + if ($ttype =~ /^(union|struct|const)?\s*(\w+)/) { + if ($1 ne 'const') { + $ttype = $2; + } else { + $ttype = "const $2"; + } } $described_data_gear = 1; $var{$name}->{$tname} = $ttype; @@ -187,12 +191,15 @@ my $next = $2; my @args = split(/,/,$3); push(@{$code{$name}->{$method}},"\_\_code $next"); - } elsif ($args =~ s/^(struct|union)?\s*(\w+)(\**)\s+(\w+)//) { + } elsif ($args =~ s/^(struct|union|const)?\s*(\w+)(\**)\s+(\w+)//) { my $structType = $1; my $typeName = $2; my $ptrType = $3; my $varName = $4; my $typeField = lcfirst($typeName); + if ($structType =~ /const/) { + $typeName = "$structType $typeName"; + } push(@{$code{$name}->{$method}},"$typeName$ptrType $varName"); } elsif ($args =~ s/(.*,)//) { } else { @@ -214,16 +221,24 @@ $inputIncFlag = 0; my @outputs = split(/,/,$3); for my $output (@outputs) { - if ($output =~ /\s*(struct|union)?\s*(\w+)(\*)?+\s(\w+)/) { + if ($output =~ /\s*(struct|union|const)?\s*(\w+)(\*)?+\s(\w+)/) { + my $structType = $1; my $type = $2; my $varName = $4; + if ($structType =~ /const/) { + $type = "$structType $type"; + } $codeGear{$codeGearName}->{"var"}->{$varName} = "$type $outputCount"; $outputCount++; } } - } elsif ($args =~ s/^(struct|union)?\s*(\w+)(\*)?+\s(\w+)// && $inputIncFlag) { + } elsif ($args =~ s/^(struct|union|const)?\s*(\w+)(\*)?+\s(\w+)// && $inputIncFlag) { + my $structType = $1; my $type = $2; my $varName = $4; + if ($structType =~ /const/) { + $type = "$structType $type"; + } $codeGear{$codeGearName}->{"var"}->{$varName} = "$type $inputCount"; $inputCount++; } elsif ($args =~ s/(.*,)//) { @@ -273,7 +288,7 @@ } } } - + # interface continuation for my $cName (keys %{$code{$interface}}) { if ($varName eq $cName) { @@ -282,7 +297,6 @@ return 1; } } - # par goto var for my $var (keys %{$codeGear{$codeGearName}->{"var"}}) { # input data gear field @@ -425,24 +439,30 @@ for my $arg (@args) { $arg =~ s/^\s*//; last if ($arg =~ /\.\.\./); - $arg =~ s/^(struct|union)?\s*(\w+)(\**)\s(\w+)//; + $arg =~ s/^(struct|union|const)?\s*(\w+)(\**)\s(\w+)//; my $structType = $1; my $typeName = $2; my $ptrType = $3; my $varName = $4; + if ($structType =~ /const/) { + $typeName = "$structType $typeName"; + } my $typeField = lcfirst($typeName); push(@{$outputArgs{$codeGearName}->{$next}}, $varName); if (&generateStubArgs($codeGearName, $varName, $typeName, $ptrType, $typeField, $interface,1)) { $newArgs .= ",$structType $typeName **O_$varName"; } } - } elsif ($args =~ s/^(struct|union)?\s*(\w+)(\**)\s(\w+)//) { + } elsif ($args =~ s/^(struct|union|const)?\s*(\w+)(\**)\s(\w+)//) { my $structType = $1; my $typeName = $2; my $ptrType = $3; my $varName = $4; + $newArgs .= $&; # assuming no duplicate + if ($structType =~ /const/) { + $typeName = "$structType $typeName"; + } my $typeField = lcfirst($typeName); - $newArgs .= $&; # assuming no duplicate &generateStubArgs($codeGearName, $varName, $typeName, $ptrType, $typeField, $interface,0); } elsif ($args =~ s/(.*,)//) { $newArgs .= $1;
--- a/src/gearsTools/lib/Gears/Context/Template/XV6.pm Sat Feb 08 20:42:57 2020 +0900 +++ b/src/gearsTools/lib/Gears/Context/Template/XV6.pm Sat Feb 08 20:45:42 2020 +0900 @@ -165,6 +165,11 @@ typedef struct proc proc_struct; typedef uint32 pte_t; typedef uint32 pde_t; +typedef struct stat stat; +typedef struct superblock superblock; +typedef struct buf buf; +typedef struct dinode dinode; +typedef struct dirent dirent; EOFEOF print $out $str; }
--- a/src/gearsTools/lib/Gears/Util.pm Sat Feb 08 20:42:57 2020 +0900 +++ b/src/gearsTools/lib/Gears/Util.pm Sat Feb 08 20:45:42 2020 +0900 @@ -30,6 +30,7 @@ Gears::Util->file_checking($file); open my $fh, '<', $file; my $line = <$fh>; + my $static_data_gear_write_mode = 0; if ($line =~ /typedef struct (\w+)\s?<.*>([\s\w{]+)/) { die "invalied struct name $1" unless $1; @@ -55,6 +56,7 @@ if ($line =~ m|__code (\w+)|) { push(@tmp_args,"enum Code $1;\n"); + next if $static_data_gear_write_mode; my $args = $'; #$args eq (Impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...)); while ($args =~ /\s*(struct|union|const)?\s*([\w*\[\]_]+)\s*(\w+),?/g) { @@ -71,6 +73,7 @@ $line =~ s/^\s+//; push(@tmp_args,$line); + $static_data_gear_write_mode = 1; } push(@{$ir->{content}}, _uniq(@tmp_args)); @@ -229,9 +232,13 @@ } - if ($line =~ /^(\w+)\*\s*create(\w+)\(/) { + if ($line =~ /^(\w+)\*\s*create(\w+)\(([*\w\s]+)\)/) { my $interface = $1; my $implementation = $2; + my $arg = $3; + if ($arg eq "") { + next; + } push(@{$counter{interfaces}->{$interface}->{$cbc_file}},$.); push(@{$counter{impl}->{$implementation}->{$cbc_file}},$.); next;
--- a/src/impl/KernelError.cbc Sat Feb 08 20:42:57 2020 +0900 +++ b/src/impl/KernelError.cbc Sat Feb 08 20:45:42 2020 +0900 @@ -20,7 +20,7 @@ } __code infinity_loopKernelError(struct KernelError* err, __code next(...)) { - + goto next(...); } __code errorKernelError(struct KernelError* err, int err_code, __code next(...)) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/impl/file_impl_inode.cbc Sat Feb 08 20:45:42 2020 +0900 @@ -0,0 +1,48 @@ +#include "../../context.h" +#interface "file.dg" + + +// ---- +// typedef struct inode_impl<Impl, Isa> impl file { +// +// } inode_impl; +// ---- + +file* createinode(struct Context* cbc_context) { + struct file* file = new file(); + struct inode_impl* inode_impl = new inode_impl(); + file->file = (union Data*)inode_impl; + inode_impl->st = NULL; + inode_impl->ip = NULL; + file->stat = C_statinode; + inode_impl->cbc_statinode = C_cbc_statinode_impl; + file->read = C_readinode; + file->write = C_writeinode; + file->close = C_closeinode; + return file; +} +__code statinode(struct inode* ip, struct stat* st, __code next(int ret, ...)) { //:skip + + goto cbc_statinode(ip, st, next(ret, ...)); +} + +__code cbc_statinode_impl(struct inode* ip, struct stat* st, __code next(int ret, ...)){ + + goto next(...); +} + +__code readinode(struct inode* file, char* addr, __code next(...)) { + + goto next(...); +} + +__code writeinode(struct inode* file, char* addr, int n, __code next(...)) { + + goto next(...); +} + +__code closeinode(struct inode* file,int fd, __code next(...)) { + + goto next(...); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/impl/file_impl_none.cbc Sat Feb 08 20:45:42 2020 +0900 @@ -0,0 +1,64 @@ +#include "../context.h" +#interface "file.h" + +// ---- +// typedef struct none<Impl, Isa> impl file { +// +// } none; +// ---- + +file* createnone(struct Context* cbc_context) { + struct file* file = new file(); + struct none* none = new none(); + file->file = (union Data*)none; + file->remoe = 0; + file->off = 0; + file->st = NULL; + file->addr = NULL; + file->pipe = 0; + file->inode = 0; + file->n = 0; + file->fd = 0; + file->stat = C_statnone; + file->read = C_readnone; + file->write = C_writenone; + file->close = C_closenone; + return file; +} +__code statnone(struct none* file, struct stat* st, __code next(...)) { + + goto next(...); +} + +__code readnone(struct none* file, char* addr, __code next(...)) { + + goto next(...); +} + +__code writenone(struct none* file, char* addr, int n, __code next(...)) { + + goto next(...); +} + +__code closenone(struct none* file,int fd, __code next(...)) { + + goto file->noneclose(file->file, next); +} + +__code noneclose(struct none* none, struct file* file, __code next(...){ + struct file ff; + acquire(*ftable.loc) + + if (f->ref < 1) { + goto cbc_context->kernel_error->panic("file close"); + } + goto pipe->cbc_noneclose2(f,ff,next); +} + +__code noneclose2(struct none* none,struct file* file, struct file* ff,__code next(...)){ + if (--f->ref > 0) { + release(&ftable.lock); + goto cbc_context->return(); + } + goto pipe->cbc_pipeclose3(f,ff,next); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/impl/fs_impl.cbc Sat Feb 08 20:45:42 2020 +0900 @@ -0,0 +1,381 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "stat.h" +#include "mmu.h" +#include "proc.h" +#include "spinlock.h" +#include "buf.h" +#include "fs.h" +#include "file.h" +#interface "Err.h" +#interface "fs.dg" + +// ---- +// typedef struct fs_impl<Impl, Isa> impl fs{ +// union Data* fs_impl; +// +// +// +// +// } fs_impl; +// ---- + +fs* createfs_impl(struct Context* cbc_context) { + struct fs* fs = new fs(); + struct fs_impl* fs_impl = new fs_impl(); + fs->fs = (union Data*)fs_impl; + fs_impl->fs_impl = NULL; + fs_impl->sb = NULL; + fs_impl->ret = 0; + fs_impl->dev = 0; + fs_impl->type = 0; + fs_impl->bp = NULL; + fs_impl->dip = NULL; + fs_impl->inum = 0; + fs_impl->dp = NULL; + fs_impl->name = NULL; + fs_impl->off = 0; + fs_impl->poff = NULL; + fs_impl->de = NULL; + fs_impl->tot = 0; + fs_impl->m = 0; + fs_impl->dst = NULL; + fs_impl->n = 0; + fs_impl->src = NULL; + fs_impl->allocinode = C_allocinode; + fs_impl->allocinode_loop = C_allocinode_loop; + fs_impl->allocinode_loopcheck = C_allocinode_loopcheck; + fs_impl->allocinode_noloop = C_allocinode_noloop; + fs_impl->lockinode1 = C_lockinode1; + fs_impl->lockinode2 = C_lockinode2; + fs_impl->lockinode_sleepcheck = C_lockinode_sleepcheck; + fs_impl->iput_check = C_iput_check; + fs_impl->iput_inode_nolink = C_iput_inode_nolink; + fs_impl->readi_check_diskinode = C_readi_check_diskinode; + fs_impl->readi_loopcheck = C_readi_loopcheck; + fs_impl->readi_loop = C_readi_loop; + fs_impl->readi_noloop = C_readi_noloop; + fs_impl->writei_check_diskinode = C_writei_check_diskinode; + fs_impl->writei_loopcheck = C_writei_loopcheck; + fs_impl->writei_loop = C_writei_loop; + fs_impl->writei_noloop = C_writei_noloop; + fs_impl->dirlookup_loopcheck = C_dirlookup_loopcheck; + fs_impl->dirlookup_loop = C_dirlookup_loop; + fs_impl->dirlookup_noloop = C_dirlookup_noloop; + fs_impl->dirlink_namecheck = C_dirlink_namecheck; + fs_impl->dirlink_loopcheck = C_dirlink_loopcheck; + fs_impl->dirlink_loop = C_dirlink_loop; + fs_impl->dirlink_noloop = C_dirlink_noloop; + fs->readsb = C_readsbfs_impl; + fs->iinit = C_iinitfs_impl; + fs->ialloc = C_iallocfs_impl; + fs->iupdate = C_iupdatefs_impl; + fs->idup = C_idupfs_impl; + fs->ilock = C_ilockfs_impl; + fs->iunlock = C_iunlockfs_impl; + fs->iput = C_iputfs_impl; + fs->iunlockput = C_iunlockputfs_impl; + fs->stati = C_statifs_impl; + fs->readi = C_readifs_impl; + fs->writei = C_writeifs_impl; + fs->namecmp = C_namecmpfs_impl; + fs->dirlookup = C_dirlookupfs_impl; + fs->dirlink = C_dirlinkfs_impl; + fs->namei = C_nameifs_impl; + fs->nameiparent = C_nameiparentfs_impl; + return fs; +} + +typedef struct superblock superblock; +__code readsbfs_impl(struct fs_impl* fs, uint dev, struct superblock* sb, __code next(...)) { //:skip + + struct buf* bp; + + bp = bread(dev, 1); + memmove(sb, bp->data, sizeof(*sb)); + brelse(bp); + + goto next(...); +} + +struct { + struct spinlock lock; + struct inode inode[NINODE]; +} icache; + +__code iinitfs_impl(struct fs_impl* fs, __code next(...)) { + + initlock(&icache.lock, "icache"); + + goto next(...); +} + +__code iallocfs_impl(struct fs_impl* fs, uint dev, short type, __code next(...)) { + goto allocinode(fs, dev, sb, next(...)); +} + +__code iupdatefs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) { + + struct buf *bp; + struct dinode *dip; + + bp = bread(ip->dev, IBLOCK(ip->inum)); + + dip = (struct dinode*) bp->data + ip->inum % IPB; + dip->type = ip->type; + dip->major = ip->major; + dip->minor = ip->minor; + dip->nlink = ip->nlink; + dip->size = ip->size; + + memmove(dip->addrs, ip->addrs, sizeof(ip->addrs)); + log_write(bp); + brelse(bp); + + + goto next(...); +} + +__code idupfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) { + + acquire(&icache.lock); + ip->ref++; + release(&icache.lock); + + goto next(ip, ...); + +} + +__code ilockfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) { + + goto lockinode1(fs, ip, bp, dip, next(...)); +} + +__code iunlockfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) { + + if (ip == 0 || !(ip->flags & I_BUSY) || ip->ref < 1) { + char* msg = "iunlock"; + struct Err* err = createKernelError(&proc->cbc_context); + Gearef(cbc_context, Err)->msg = msg; + goto meta(cbc_context, err->panic); + } + + acquire(&icache.lock); + ip->flags &= ~I_BUSY; + wakeup(ip); + release(&icache.lock); + + goto next(...); +} + +__code iputfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) { + if (next == C_iputfs_impl) { + next = fs->next2; + } + goto iput_check(fs, ip, next(...)); + +} + +__code iunlockputfs_impl(struct fs_impl* fs, struct inode* ip, __code next(...)) { + fs->next2 = next; + goto iunlockfs_impl(ip, fs->iput, ...); +} + +typedef struct stat stat; +__code statifs_impl(struct fs_impl* fs , struct inode* ip, struct stat* st, __code next(...)) { //:skip + st->dev = ip->dev; + st->ino = ip->inum; + st->type = ip->type; + st->nlink = ip->nlink; + st->size = ip->size; + goto next(...); +} + +__code readifs_impl(struct fs_impl* fs, struct inode* ip, char* dst, uint off, uint tot, uint n, __code next(int ret, ...)) { + if (ip->type == T_DEV) { + goto readi_check_diskinode(fs, ip, dst, n, next(...)); + } + + if (off > ip->size || off + n < off) { + ret = -1; + goto next(ret, ...); + } + + if (off + n > ip->size) { + n = ip->size - off; + } + Gearef(cbc_context, fs)->tot = 0; + goto readi_loopcheck(fs, tot, m, dst, off, n, next(...)); +} + +__code writeifs_impl(struct fs_impl* fs, struct inode* ip, char* src, uint off, uint tot, uint n, __code next(int ret, ...)) { + if (ip->type == T_DEV) { + goto writei_check_diskinode(fs, ip, src, n, next(...)); + } + + if (off > ip->size || off + n < off) { + ret = -1; + goto next(ret, ...); + } + + if (off + n > MAXFILE * BSIZE) { + ret = -1; + goto next(ret, ...); + } + Gearef(cbc_context, fs)->tot = 0; + goto writei_loopcheck(fs, tot, m, src, off, n, next(...)); +} + + +__code namecmpfs_impl(struct fs_impl* fs, const char* s, const char* t, __code next(int strncmp_val, ...)) { + strncmp_val = strncmp(s, t, DIRSIZ); + goto next(strncmp_val, ...); +} + +__code dirlookupfs_impl(struct fs_impl* fs, struct inode* dp, char* name, uint off, uint* poff, dirent* de, __code next(...)) { //:skip + if (dp->type != T_DIR) { + char* msg = "dirlookup not DIR"; + struct Err* err = createKernelError(&proc->cbc_context); + Gearef(cbc_context, Err)->msg = msg; + goto meta(cbc_context, err->panic); + } + Gearef(cbc_context, fs)->off = 0; + goto dirlookup_loopcheck(fs, dp, name, off, poff, de, next(...)); +} + +__code dirlinkfs_impl(struct fs_impl* fs, struct inode* ip, struct dirent* de, struct inode* dp, char* name, uint off, uint inum, __code next(...)) { //:skip + // Check that name is not present. + if ((ip = dirlookup(dp, name, 0)) != 0) { + goto dirlink_namecheck(fs, ip, next(...)); + } + Gearef(cbc_context, fs)->off = 0; + goto dirlink_loopcheck(fs, de, dp, off, next(...)); +} + +static struct inode* iget (uint dev, uint inum) +{ + struct inode *ip, *empty; + + acquire(&icache.lock); + + // Is the inode already cached? + empty = 0; + + for (ip = &icache.inode[0]; ip < &icache.inode[NINODE]; ip++) { + if (ip->ref > 0 && ip->dev == dev && ip->inum == inum) { + ip->ref++; + release(&icache.lock); + return ip; + } + + if (empty == 0 && ip->ref == 0) { // Remember empty slot. + empty = ip; + } + } + + // Recycle an inode cache entry. + if (empty == 0) { + panic("iget: no inodes"); + } + + ip = empty; + ip->dev = dev; + ip->inum = inum; + ip->ref = 1; + ip->flags = 0; + release(&icache.lock); + + return ip; +} + +static char* skipelem (char *path, char *name) +{ + char *s; + int len; + + while (*path == '/') { + path++; + } + + if (*path == 0) { + return 0; + } + + s = path; + + while (*path != '/' && *path != 0) { + path++; + } + + len = path - s; + + if (len >= DIRSIZ) { + memmove(name, s, DIRSIZ); + } else { + memmove(name, s, len); + name[len] = 0; + } + + while (*path == '/') { + path++; + } + + return path; +} + + +static struct inode* namex (char *path, int nameiparent, char *name) +{ + struct inode *ip, *next; + + if (*path == '/') { + ip = iget(ROOTDEV, ROOTINO); + } else { + ip = idup(proc->cwd); + } + + while ((path = skipelem(path, name)) != 0) { + ilock(ip); + + if (ip->type != T_DIR) { + iunlockput(ip); + return 0; + } + + if (nameiparent && *path == '\0') { + // Stop one level early. + iunlock(ip); + return ip; + } + + if ((next = dirlookup(ip, name, 0)) == 0) { + iunlockput(ip); + return 0; + } + + iunlockput(ip); + ip = next; + } + + if (nameiparent) { + iput(ip); + return 0; + } + + return ip; +} + +__code nameifs_impl(struct fs_impl* fs, char* path, __code next(int namex_val, ...)) { + char name[DIRSIZ]; + namex_val = namex(path, 0, name); + goto next(namex_val, ...); +} + +__code nameiparentfs_impl(struct fs_impl* fs, char* path, char* name, __code next(int namex_val, ...)) { + + namex_val = namex(path, 1, name); + goto next(namex_val, ...); + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/impl/fs_impl.h Sat Feb 08 20:45:42 2020 +0900 @@ -0,0 +1,47 @@ +typedef struct fs_impl<Type, Isa> impl fs{ + union Data* fs_impl; + struct superblock* sb; + int ret; + uint dev; + short type; + struct buf* bp; + struct dinode* dip; + uint inum; + struct inode* dp; + char* name; + uint off; + uint* poff; + dirent* de; + uint tot; + uint m; + char* dst; + uint n; + char* src; + + __code allocinode(Type* fs_impl, uint dev, struct superblock* sb, __code next(...)); + __code allocinode_loop(Type* fs_impl, uint inum, uint dev, short type, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(...)); + __code allocinode_loopcheck(Type* fs_impl, uint inum, uint dev, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(...)); + __code allocinode_noloop(Type* fs_impl, uint inum, uint dev, short type, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(int ret, ...)); + __code lockinode1(Type* fs_impl, struct inode *ip, struct buf *bp, struct dinode *dip, __code next(...)); + __code lockinode2(Type* fs_impl, struct inode* ip, struct buf* bp, struct dinode* dip, __code next(...)); + __code lockinode_sleepcheck(Type* fs_impl, struct inode* ip, __code next(...)); + __code iput_check(Type* fs_impl, struct inode* ip, __code next(...)); + __code iput_inode_nolink(Type* fs_impl, struct inode* ip, __code next(...)); + __code readi_check_diskinode(Type* fs_impl,struct inode* ip, char* dst, uint n, next(int ret, ...)); + __code readi_loopcheck(Type* fs_impl, uint tot, uint m, char* dst, uint off, uint n, __code next(...)); + __code readi_loop(Type* fs_impl, struct inode *ip, struct buf* bp, uint tot, uint m, char* dst, uint off, uint n, __code next(...)); + __code readi_noloop(Type* fs_impl, uint n, __code next(int ret, ...)); + __code writei_check_diskinode(Type* fs_impl,struct inode* ip, char* src, uint n, __code next(int ret, ...)); + __code writei_loopcheck(Type* fs_impl, uint tot, uint m, char* src, uint off, uint n, __code next(...)); + __code writei_loop(Type* fs_impl, struct inode* ip, struct buf* bp, uint tot, uint m, char* src, uint off, uint n, __code next(...)); + __code writei_noloop(Type* fs_impl, struct inode* ip, uint n, uint off, __code next(int ret, ...)); + __code dirlookup_loopcheck(Type* fs_impl, struct inode* dp, char* name, uint off, uint* poff, dirent* de, next(...)); + __code dirlookup_loop(Type* fs_impl, struct inode* dp, char* name, uint off, uint inum, uint* poff, dirent* de, __code next(int ret, ...)); + __code dirlookup_noloop(Type* fs_impl, __code next(int ret, ...)); + __code dirlink_namecheck(Type* fs_impl, struct inode* ip, __code next(int ret, ...)); + __code dirlink_loopcheck(Type* fs_impl, struct dirent* de, struct inode* dp, uint off, __code next(...)); + __code dirlink_loop(Type* fs_impl, struct dirent* de, struct inode* dp, uint off, uint inum, __code next(...)); + __code dirlink_noloop(Type* fs_impl, struct dirent* de, struct inode* dp, uint off, uint inum, char* name, __code next(int ret, ...)); + __code next(...); + __code next2(...); +} fs_impl;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/impl/fs_impl_private.cbc Sat Feb 08 20:45:42 2020 +0900 @@ -0,0 +1,471 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "stat.h" +#include "mmu.h" +#include "proc.h" +#include "spinlock.h" +#include "buf.h" +#include "fs.h" +#include "file.h" +#interface "fs_impl.h" +#interface "Err.h" +#define min(a, b) ((a) < (b) ? (a) : (b)) + +/* +fs_impl* createfs_impl2(); +*/ + +__code allocinode(struct fs_impl* fs_impl, uint dev, struct superblock* sb, __code next(...)){ //:skip + + readsb(dev, sb); + Gearef(cbc_context, fs_impl)->inum = 1; + goto allocinode_loopcheck(fs_impl, inum, dev, sb, bp, dip, next(...)); + +} + +typedef struct buf buf; +typedef struct dinode dinode; + +__code allocinode_loopcheck(struct fs_impl* fs_impl, uint inum, uint dev, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(...)){ //:skip + if( inum < sb->ninodes){ + goto allocinode_loop(fs_impl, inum, dev, type, sb, bp, dip, next(...)); + } + char* msg = "failed allocinode..."; + struct Err* err = createKernelError(&proc->cbc_context); + Gearef(cbc_context, Err)->msg = msg; + goto meta(cbc_context, err->panic); + +} + +__code allocinode_loop(struct fs_impl* fs_impl, uint inum, uint dev, short type, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(...)){ //:skip + bp = bread(dev, IBLOCK(inum)); + dip = (struct dinode*) bp->data + inum % IPB; + if(dip->type = 0){ + goto allocinode_noloop(fs_impl, inum, dev, sb, bp, dip, next(...)); + } + + brelse(bp); + inum++; + goto allocinode_loopcheck(fs_impl, inum, dev, type, sb, bp, dip, next(...)); +} + +struct { + struct spinlock lock; + struct inode inode[NINODE]; +} icache; + +static struct inode* iget (uint dev, uint inum) +{ + struct inode *ip, *empty; + + acquire(&icache.lock); + + // Is the inode already cached? + empty = 0; + + for (ip = &icache.inode[0]; ip < &icache.inode[NINODE]; ip++) { + if (ip->ref > 0 && ip->dev == dev && ip->inum == inum) { + ip->ref++; + release(&icache.lock); + return ip; + } + + if (empty == 0 && ip->ref == 0) { // Remember empty slot. + empty = ip; + } + } + + // Recycle an inode cache entry. + if (empty == 0) { + panic("iget: no inodes"); + } + + ip = empty; + ip->dev = dev; + ip->inum = inum; + ip->ref = 1; + ip->flags = 0; + release(&icache.lock); + + return ip; +} + +__code allocinode_noloop(struct fs_impl* fs_impl, uint inum, uint dev, short type, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(int ret, ...)){ //:skip + + memset(dip, 0, sizeof(*dip)); + dip->type = type; + log_write(bp); + brelse(bp); + + ret = iget(dev, inum); + goto next(ret, ...); + +} + +__code lockinode1(struct fs_impl* fs_impl, struct inode* ip, struct buf* bp, struct dinode* dip, __code next(...)){ //:skip + + if (ip == 0 || ip->ref < 1) { + char* msg = "ilock"; + struct Err* err = createKernelError(&proc->cbc_context); + Gearef(cbc_context, Err)->msg = msg; + goto meta(cbc_context, err->panic); + } + acquire(&icache.lock); + + goto lockinode_sleepcheck(fs_impl, ip, next(...)); + +} + + +__code lockinode2(struct fs_impl* fs_impl, struct inode* ip, struct buf* bp, struct dinode* dip, __code next(...)){ //:skip + + ip->flags |= I_BUSY; + release(&icache.lock); + + if (!(ip->flags & I_VALID)) { + bp = bread(ip->dev, IBLOCK(ip->inum)); + + dip = (struct dinode*) bp->data + ip->inum % IPB; + ip->type = dip->type; + ip->major = dip->major; + ip->minor = dip->minor; + ip->nlink = dip->nlink; + ip->size = dip->size; + + memmove(ip->addrs, dip->addrs, sizeof(ip->addrs)); + brelse(bp); + ip->flags |= I_VALID; + + if (ip->type == 0) { + char* msg = "ilock: no type"; + struct Err* err = createKernelError(&proc->cbc_context); + Gearef(cbc_context, Err)->msg = msg; + goto meta(cbc_context, err->panic); + } + } + goto next(...); +} +__code lockinode_sleepcheck(struct fs_impl* fs_impl, struct inode* ip, __code next(...)){ + if(ip->flags & I_BUSY){ + sleep(ip, &icache.lock); + goto lockinode_sleepcheck(fs_impl, ip, next(...)); + } + goto lockinode2(fs_impl, ip, bp, dip, next(...)); +} + +__code iput_check(struct fs_impl* fs_impl, struct inode* ip, __code next(...)){ + acquire(&icache.lock); + if (ip->ref == 1 && (ip->flags & I_VALID) && ip->nlink == 0) { + goto iput_inode_nolink(fs_impl, ip, next(...)); + } + ip->ref--; + release(&icache.lock); + goto next(...); + +} + +static void bfree (int dev, uint b) +{ + struct buf *bp; + struct superblock sb; + int bi, m; + + readsb(dev, &sb); + bp = bread(dev, BBLOCK(b, sb.ninodes)); + bi = b % BPB; + m = 1 << (bi % 8); + + if ((bp->data[bi / 8] & m) == 0) { + panic("freeing free block"); + } + + bp->data[bi / 8] &= ~m; + log_write(bp); + brelse(bp); +} + + +static void itrunc (struct inode *ip) +{ + int i, j; + struct buf *bp; + uint *a; + + for (i = 0; i < NDIRECT; i++) { + if (ip->addrs[i]) { + bfree(ip->dev, ip->addrs[i]); + ip->addrs[i] = 0; + } + } + + if (ip->addrs[NDIRECT]) { + bp = bread(ip->dev, ip->addrs[NDIRECT]); + a = (uint*) bp->data; + + for (j = 0; j < NINDIRECT; j++) { + if (a[j]) { + bfree(ip->dev, a[j]); + } + } + + brelse(bp); + bfree(ip->dev, ip->addrs[NDIRECT]); + ip->addrs[NDIRECT] = 0; + } + + ip->size = 0; + iupdate(ip); +} + +__code iput_inode_nolink(struct fs_impl* fs_impl, struct inode* ip, __code next(...)){ + + if (ip->flags & I_BUSY) { + char* msg = "iput busy"; + struct Err* err = createKernelError(&proc->cbc_context); + Gearef(cbc_context, Err)->msg = msg; + goto meta(cbc_context, err->panic); + } + + ip->flags |= I_BUSY; + release(&icache.lock); + itrunc(ip); + ip->type = 0; + iupdate(ip); + + acquire(&icache.lock); + ip->flags = 0; + wakeup(ip); + goto next(...); +} + +__code readi_check_diskinode(struct fs_impl* fs_impl,struct inode* ip, char* dst, uint n, __code next(int ret, ...)){ + if (ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].read) { + ret = -1; + goto next(ret, ...); + } + + ret = devsw[ip->major].read(ip, dst, n); + goto next(ret, ...); +} + +__code readi_loopcheck(struct fs_impl* fs_impl, uint tot, uint m, char* dst, uint off, uint n, __code next(...)){ + if(tot < n){ + goto readi_loop(fs_impl, ip, bp, tot, m, dst, off, n, next(...)); + } + goto readi_noloop(fs_impl, next(...)); +} + +static void bzero (int dev, int bno) +{ + struct buf *bp; + + bp = bread(dev, bno); + memset(bp->data, 0, BSIZE); + log_write(bp); + brelse(bp); +} + +static uint balloc (uint dev) +{ + int b, bi, m; + struct buf *bp; + struct superblock sb; + + bp = 0; + readsb(dev, &sb); + + for (b = 0; b < sb.size; b += BPB) { + bp = bread(dev, BBLOCK(b, sb.ninodes)); + + for (bi = 0; bi < BPB && b + bi < sb.size; bi++) { + m = 1 << (bi % 8); + + if ((bp->data[bi / 8] & m) == 0) { // Is block free? + bp->data[bi / 8] |= m; // Mark block in use. + log_write(bp); + brelse(bp); + bzero(dev, b + bi); + return b + bi; + } + } + + brelse(bp); + } + + panic("balloc: out of blocks"); +} + + +static uint bmap (struct inode *ip, uint bn) +{ + uint addr, *a; + struct buf *bp; + + if (bn < NDIRECT) { + if ((addr = ip->addrs[bn]) == 0) { + ip->addrs[bn] = addr = balloc(ip->dev); + } + + return addr; + } + + bn -= NDIRECT; + + if (bn < NINDIRECT) { + // Load indirect block, allocating if necessary. + if ((addr = ip->addrs[NDIRECT]) == 0) { + ip->addrs[NDIRECT] = addr = balloc(ip->dev); + } + + bp = bread(ip->dev, addr); + a = (uint*) bp->data; + + if ((addr = a[bn]) == 0) { + a[bn] = addr = balloc(ip->dev); + log_write(bp); + } + + brelse(bp); + return addr; + } + + panic("bmap: out of range"); +} + + +__code readi_loop(struct fs_impl* fs_impl, struct inode* ip, struct buf* bp, uint tot, uint m, char* dst, uint off, uint n, __code next(...)){ //:skip + bp = bread(ip->dev, bmap(ip, off / BSIZE)); + m = min(n - tot, BSIZE - off%BSIZE); + memmove(dst, bp->data + off % BSIZE, m); + brelse(bp); + tot += m; + off += m; + dst += m; + goto readi_loopcheck(fs_impl, tot, m, dst, off, n, next(...)); +} + +__code readi_noloop(struct fs_impl* fs_impl, uint n, __code next(int ret, ...)){ + ret = n; + goto next(ret, ...); +} + +__code writei_check_diskinode(struct fs_impl* fs_impl,struct inode* ip, char* src, uint n, __code next(int ret, ...)){ + if (ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].write) { + ret = -1; + goto next(ret, ...); + } + + ret = devsw[ip->major].write(ip, src, n); + goto next(ret, ...); +} + +__code writei_loopcheck(struct fs_impl* fs_impl, uint tot, uint m, char* src, uint off, uint n, __code next(...)){ + if(tot < n){ + goto writei_loop(fs_impl, ip, bp, tot, m, src, off, n, next(...)); + } + goto writei_noloop(fs_impl, next(...)); +} + +__code writei_loop(struct fs_impl* fs_impl, struct inode* ip, struct buf* bp, uint tot, uint m, char* src, uint off, uint n, __code next(...)){ //:skip + bp = bread(ip->dev, bmap(ip, off / BSIZE)); + m = min(n - tot, BSIZE - off%BSIZE); + memmove(bp->data + off % BSIZE, src, m); + log_write(bp); + brelse(bp); + tot += m; + off += m; + src += m; + goto writei_loopcheck(fs_impl, tot, m, src, off, n, next(...)); +} + +__code writei_noloop(struct fs_impl* fs_impl, struct inode* ip, uint n, uint off, __code next(int ret, ...)){ + if (n > 0 && off > ip->size) { + ip->size = off; + iupdate(ip); + } + ret = n; + goto next(ret, ...); +} +typedef struct dirent dirent; +__code dirlookup_loopcheck(struct fs_impl* fs_impl, struct inode* dp, char* name, uint off, uint* poff, dirent* de, __code next(...)){ //:skip + if(off < dp->size){ + goto dirlookup_loop(fs_impl, dp, name, off, inum, poff, de, next(...)); + } + goto dirlookup_noloop(fs_impl, next(...)); +} + +__code dirlookup_loop(struct fs_impl* fs_impl, struct inode* dp, char* name, uint off, uint inum, uint* poff, dirent* de, __code next(int ret, ...)){ + if (readi(dp, (char*) &de, off, sizeof(de)) != sizeof(de)) { + char* msg = "dirlink read"; + struct Err* err = createKernelError(&proc->cbc_context); + Gearef(cbc_context, Err)->msg = msg; + goto meta(cbc_context, err->panic); + } + + if (de->inum == 0) { + off += sizeof(de); + goto dirlookup_loopcheck(fs_impl, dp, name, poff, de, next(...)); + } + + if (namecmp(name, de->name) == 0) { + // entry matches path element + if (poff) { + *poff = off; + } + + inum = de->inum; + ret = iget(dp->dev, inum); + goto next(ret, ...); + } + + off += sizeof(de); + goto dirlookup_loopcheck(fs_impl, dp, name, poff, de, next(...)); +} + +__code dirlookup_noloop(struct fs_impl* fs_impl, __code next(int ret, ...)){ + ret = 0; + goto next(ret, ...); +} + +__code dirlink_namecheck(struct fs_impl* fs_impl, struct inode* ip, __code next(int ret, ...)){ + iput(ip); + ret = -1; + goto next(ret, ...); +} + +__code dirlink_loopcheck(struct fs_impl* fs_impl, struct dirent* de, struct inode* dp, uint off, __code next(...)){ //:skip + if(off < dp->size){ + goto dirlink_loop(fs_impl, de, dp, off, inum, next(...)); + } + goto dirlink_noloop(fs_impl, de, dp, off, inum, name, next(...)); +} + +__code dirlink_loop(struct fs_impl* fs_impl, struct dirent* de, struct inode* dp, uint off, uint inum, __code next(...)){ //:skip + if (readi(dp, (char*) &de, off, sizeof(de)) != sizeof(de)) { + char* msg = "dirlink read"; + struct Err* err = createKernelError(&proc->cbc_context); + Gearef(cbc_context, Err)->msg = msg; + goto meta(cbc_context, err->panic); + } + + if (de->inum == 0) { + goto dirlink_noloop(fs_impl, de, dp, off, inum, name, next(...)); + } + + goto dirlink_loopcheck(fs_impl, de, dp, off + sizeof(de), next(...)); +} + +__code dirlink_noloop(struct fs_impl* fs_impl, struct dirent* de, struct inode* dp, uint off, uint inum, char* name, __code next(int ret, ...)){ //:skip + strncpy(de->name, name, DIRSIZ); + de->inum = inum; + + if (writei(dp, (char*) &de, off, sizeof(de)) != sizeof(de)) { + char* msg = "dirlink read"; + struct Err* err = createKernelError(&proc->cbc_context); + Gearef(cbc_context, Err)->msg = msg; + goto meta(cbc_context, err->panic); + } + ret = 0; + goto next(ret, ...); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/impl/inode_impl.h Sat Feb 08 20:45:42 2020 +0900 @@ -0,0 +1,11 @@ +typedef struct inode_impl<Impl, Isa> impl file { + +struct inode* ip; +struct stat* st; +int ret; + +__code cbc_statinode(struct inode* ip, struct stat* st, __code next(int ret, ...)); + +//__code next(...); + +} inode_impl;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/impl/none.h Sat Feb 08 20:45:42 2020 +0900 @@ -0,0 +1,3 @@ +typedef struct none<Impl, Isa> impl file { + +} none;
--- a/src/interface/file.dg Sat Feb 08 20:42:57 2020 +0900 +++ b/src/interface/file.dg Sat Feb 08 20:45:42 2020 +0900 @@ -1,5 +1,6 @@ typedef struct file <Impl> { union Data* file; + union Data* inode_impl; enum { FD_NONE, FD_PIPE, FD_INODE } type; int ref; // reference count char readable; @@ -11,7 +12,9 @@ char* addr; int n; int fd; + __code stat(struct inode* ip, struct stat* st, __code next(...)); __code read(Impl* file, char* addr, __code next(...)); __code write(Impl* file, char* addr, int n, __code next(...)); __code close(Impl* file,int fd, __code next(...)); + __code next(...); } file;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/interface/fs.dg Sat Feb 08 20:45:42 2020 +0900 @@ -0,0 +1,42 @@ +typedef struct fs<Type,Impl> { + union Data* fs; + struct superblock* sb; + uint dev; + short type; + struct inode* ip; + struct stat* st; + char* dst; + uint off; + uint n; + const char* s; + const char* t; + struct inode* dp; + char* name; + uint* poff; + uint inum; + char* path; + char* src; + int namex_val; + int strncmp_val; + dirent* de; + int ret; + uint tot; + __code readsb(Impl* fs, uint dev, struct superblock* sb, __code next(...)); + __code iinit(Impl* fs, __code next(...)); + __code ialloc(Impl* fs, uint dev, short type, __code next(...)); + __code iupdate(Impl* fs, struct inode* ip, __code next(...)); + __code idup(Impl* fs, struct inode* ip, __code next(...)); + __code ilock(Impl* fs, struct inode* ip, __code next(...)); + __code iunlock(Impl* fs, struct inode* ip, __code next(...)); + __code iput(Impl* fs, struct inode* ip, __code next(...)); + __code iunlockput(Impl* fs, struct inode* ip, __code next(...)); + __code stati(Impl* fs , struct inode* ip, struct stat* st, __code next(...)); + __code readi(Impl* fs, struct inode* ip, char* dst, uint off, uint tot, uint n, __code next(int ret, ...)); + __code writei(Impl* fs, struct inode* ip, char* src, uint off, uint tot, uint n, __code next(int ret, ...)); + __code namecmp(Impl* fs, const char* s, const char* t, __code next(int strncmp_val, ...)); + __code dirlookup(Impl* fs, struct inode* dp, char* name, uint off, uint* poff, dirent* de, __code next(int ret, ...)); + __code dirlink(struct fs_impl* fs, struct inode* ip, struct dirent* de, struct inode* dp, char* name, uint off, uint inum, __code next(...)); + __code namei(Impl* fs, char* path, __code next(int namex_val, ...)); + __code nameiparent(Impl* fs, char* path, char* name, __code next(int namex_val, ...)); + __code next(...); +} fs;