Mercurial > hg > Papers > 2019 > mitsuki-master
changeset 37:ae5601060567
update
author | mir3636 |
---|---|
date | Thu, 07 Feb 2019 11:40:31 +0900 |
parents | 68f10de82b87 |
children | 1d8c163b7255 |
files | paper/master_paper.pdf paper/xv6.tex |
diffstat | 2 files changed, 91 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/paper/xv6.tex Thu Feb 07 11:03:10 2019 +0900 +++ b/paper/xv6.tex Thu Feb 07 11:40:31 2019 +0900 @@ -115,3 +115,94 @@ } \end{lstlisting} +ソースコード \ref{sys_read} は CbC で書き換えた read システムコールである。 +Code Gear であるため関数呼び出しではなく goto による継続となる。 + +\begin{lstlisting}[frame=lrbt,label=sys_read,caption={\footnotesize read システムコール}] +__code cbc_read(__code (*next)(int ret)){ + struct file *f; + int n; + char *p; + + if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) { + goto next(-1); + } + goto cbc_fileread(f, p, n, next); +} + +int sys_read(void) +{ + struct file *f; + int n; + char *p; + + if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) { + return -1; + } + + return fileread(f, p, n); +} +\end{lstlisting} + +継続で Code Gear 間を遷移するため関数呼び出しとは違い元の関数には戻ってこない。 +このため、書き換えの際には ソースコード \ref{fileread} のように分割する必要がある。 + +\begin{lstlisting}[frame=lrbt,label=fileread,caption={\footnotesize fileread の CbC 書き換えの例}] +__code cbc_fileread1 (int r) +{ + struct file *f = proc->cbc_arg.cbc_console_arg.f; + __code (*next)(int ret) = cbc_ret; + if (r > 0) + f->off += r; + iunlock(f->ip); + goto next(r); +} + +__code cbc_fileread (struct file *f, char *addr, int n, __code (*next)(int ret)) +{ + if (f->readable == 0) { + goto next(-1); + } + + if (f->type == FD_PIPE) { + goto cbc_piperead(f->pipe, addr, n, next); + goto next(-1); + } + + if (f->type == FD_INODE) { + ilock(f->ip); + proc->cbc_arg.cbc_console_arg.f = f; + goto cbc_readi(f->ip, addr, f->off, n, cbc_fileread1); + } + + goto cbc_panic("fileread"); +} + +// Read from file f. +int fileread (struct file *f, char *addr, int n) +{ + int r; + + if (f->readable == 0) { + return -1; + } + + if (f->type == FD_PIPE) { + return piperead(f->pipe, addr, n); + } + + if (f->type == FD_INODE) { + ilock(f->ip); + + if ((r = readi(f->ip, addr, f->off, n)) > 0) { + f->off += r; + } + + iunlock(f->ip); + + return r; + } + + panic("fileread"); +} +\end{lstlisting}