A bunch of random kernlet/pread hacking

上级 39024ea6
struct ipcctl { #define IPC_NMSG 16
typedef u32 msgid_t;
#define NULL_MSGID (-1)
#define IPC_NPAGE ((KSHAREDSIZE/PGSIZE) - 1)
typedef u32 pageid_t;
#define NULL_PAGEID (-1)
struct ipcmsg {
volatile char done:1; volatile char done:1;
volatile char submitted:1; volatile char submitted:1;
pageid_t pageid;
off_t off; off_t off;
volatile long result; volatile long result;
}; };
struct ipcctl {
int msghead;
int msgtail;
struct ipcmsg msg[IPC_NMSG];
int pagehead;
int pagetail;
};
#include "mmu.h" #include "mmu.h"
#include "lib.h" #include "lib.h"
struct ipcmsg;
// console.c // console.c
void consoleintr(int(*)(void)); void consoleintr(int(*)(void));
...@@ -44,7 +46,7 @@ long sys_bind(int, void*, int); ...@@ -44,7 +46,7 @@ long sys_bind(int, void*, int);
long sys_listen(int, int); long sys_listen(int, int);
long sys_accept(int, void*, void*); long sys_accept(int, void*, void*);
long sys_pread(int fd, void *ubuf, size_t count, off_t offset); long sys_pread(int fd, void *ubuf, size_t count, off_t offset);
long sys_kernlet(int, size_t, off_t); long sys_kernlet(int, size_t, off_t, u32, u32);
extern long (*syscalls[])(u64, u64, u64, u64, u64, u64); extern long (*syscalls[])(u64, u64, u64, u64, u64, u64);
// other exported/imported functions // other exported/imported functions
......
...@@ -335,7 +335,7 @@ long sys_bind(int, void*, int); ...@@ -335,7 +335,7 @@ long sys_bind(int, void*, int);
long sys_listen(int, int); long sys_listen(int, int);
long sys_accept(int, void*, void*); long sys_accept(int, void*, void*);
long sys_pread(int fd, void *ubuf, size_t count, off_t offset); long sys_pread(int fd, void *ubuf, size_t count, off_t offset);
long sys_kernlet(int, size_t, off_t); long sys_kernlet(int, size_t, off_t, u32, u32);
extern long (*syscalls[])(u64, u64, u64, u64, u64, u64); extern long (*syscalls[])(u64, u64, u64, u64, u64, u64);
// other exported/imported functions // other exported/imported functions
......
...@@ -10,56 +10,67 @@ ...@@ -10,56 +10,67 @@
#include "vm.hh" #include "vm.hh"
#include "file.hh" #include "file.hh"
static_assert(sizeof(struct ipcctl) < PGSIZE, "struct ipcctl too large");
static void static void
pread_work(struct work *w, void *a0, void *a1, void *a2, void *a3) pread_work(struct work *w, void *a0, void *a1, void *a2,
void *a3, void *a4)
{ {
struct inode *ip = (inode*) a0; struct inode *ip = (inode*) a0;
void *kshared = (void*) a1; size_t count = (uptr)a1;
struct ipcctl *ipc = (ipcctl*) kshared; off_t off = (uptr)a2;
size_t count = (uptr)a2; struct ipcmsg *msg = (struct ipcmsg*) a3;
off_t off = (uptr)a3; void *ubuf = (void*) a4;
int r; int r;
if (count > KSHAREDSIZE-PGSIZE)
panic("pread_work");
//cprintf("1: %p %p %lu %lu\n", ip, buf, count, off);
ilock(ip, 0); ilock(ip, 0);
r = readi(ip, ((char*)kshared)+PGSIZE, off, count); r = readi(ip, (char*)ubuf, off, count);
iunlock(ip); iunlock(ip);
ipc->result = r; msg->result = r;
barrier(); barrier();
ipc->done = 1; msg->done = 1;
iput(ip); iput(ip);
} }
static struct work * static struct work *
pread_allocwork(struct inode *ip, void *buf, size_t count, off_t off) pread_allocwork(struct inode *ip, size_t count, off_t off,
struct ipcmsg *msg, void *ubuf)
{ {
struct work *w = allocwork(); struct work *w = allocwork();
if (w == NULL) if (w == NULL)
return 0; return 0;
//cprintf("0: %p %p %lu %lu\n", ip, buf, count, off);
w->rip = (void*) pread_work; w->rip = (void*) pread_work;
w->arg0 = ip; w->arg0 = ip;
w->arg1 = buf; w->arg1 = (void*)count;
w->arg2 = (void*)count; w->arg2 = (void*)off;
w->arg3 = (void*)off; w->arg3 = msg;
w->arg4 = ubuf;
return w; return w;
} }
long long
sys_kernlet(int fd, size_t count, off_t off) sys_kernlet(int fd, size_t count, off_t off,
msgid_t msgid, pageid_t pageid)
{ {
struct file *f; struct file *f;
struct work *w; struct work *w;
struct ipcctl *ipc = (struct ipcctl *)myproc()->vmap->kshared;
char *kshared = myproc()->vmap->kshared;
struct ipcctl *ipcctl = (struct ipcctl*)kshared;
struct ipcmsg *msg;
void *ubuf;
if (msgid > IPC_NMSG)
return -1;
if (pageid > IPC_NPAGE)
return -1;
msg = &ipcctl->msg[msgid];
ubuf = (kshared+PGSIZE+(pageid*PGSIZE));
if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0) if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0)
return -1; return -1;
...@@ -67,7 +78,7 @@ sys_kernlet(int fd, size_t count, off_t off) ...@@ -67,7 +78,7 @@ sys_kernlet(int fd, size_t count, off_t off)
return -1; return -1;
f->ip->ref++; f->ip->ref++;
w = pread_allocwork(f->ip, myproc()->vmap->kshared, count, off); w = pread_allocwork(f->ip, count, off, msg, ubuf);
if (w == NULL) { if (w == NULL) {
iput(f->ip); iput(f->ip);
return -1; return -1;
...@@ -77,7 +88,7 @@ sys_kernlet(int fd, size_t count, off_t off) ...@@ -77,7 +88,7 @@ sys_kernlet(int fd, size_t count, off_t off)
freework(w); freework(w);
return -1; return -1;
} }
ipc->off = off; msg->off = off;
ipc->submitted = 1; msg->submitted = 1;
return 0; return 0;
} }
#define PGSIZE 4096
#include "types.h" #include "types.h"
#include "stat.h" #include "stat.h"
#include "fcntl.h" #include "fcntl.h"
...@@ -19,36 +20,106 @@ static char buf[BSIZE]; ...@@ -19,36 +20,106 @@ static char buf[BSIZE];
struct ipcctl *ipcctl = (struct ipcctl*)KSHARED; struct ipcctl *ipcctl = (struct ipcctl*)KSHARED;
static msgid_t
ipc_msg_alloc(void)
{
if (ipcctl->msghead - ipcctl->msgtail == IPC_NMSG)
return NULL_MSGID;
msgid_t i = ipcctl->msghead % IPC_NMSG;
ipcctl->msghead++;
return i;
}
static void
ipc_msg_free(int msgid)
{
msgid_t i;
i = ipcctl->msgtail % IPC_NMSG;
if (i != msgid)
die("ipc_free_msg: oops");
ipcctl->msgtail++;
}
static pageid_t
ipc_page_alloc(void)
{
if (ipcctl->pagehead - ipcctl->pagetail == IPC_NPAGE)
return NULL_PAGEID;
pageid_t i = ipcctl->pagehead % IPC_NPAGE;
ipcctl->pagehead++;
return i;
}
static void
ipc_page_free(pageid_t pageid)
{
pageid_t i;
i = ipcctl->pagetail % IPC_NPAGE;
if (i != pageid)
die("ipc_free_page: oops");
ipcctl->pagetail++;
}
static void static void
kernlet_pread(int fd, size_t count, off_t off) kernlet_pread(int fd, size_t count, off_t off)
{ {
ipcctl->done = 0; struct ipcmsg *msg;
if (kernlet(fd, count, off) != 0) msgid_t msgid;
pageid_t pageid;
msgid = ipc_msg_alloc();
if (msgid == NULL_MSGID) {
printf(2, "kernlet_pread: ipc_alloc_msg failed");
return;
}
if (count > PGSIZE)
die("kernlet_pread: count oops");
pageid = ipc_page_alloc();
if (pageid == NULL_PAGEID) {
printf(2, "kernlet_pread: ipc_alloc_page failed");
return;
}
msg = &ipcctl->msg[msgid];
msg->done = 0;
msg->pageid = pageid;
if (kernlet(fd, count, off, msgid, pageid) != 0)
die("kernlet"); die("kernlet");
} }
static ssize_t static ssize_t
xpread(int fd, void *buf, size_t count, off_t off) xpread(int fd, void *buf, size_t count, off_t off)
{ {
if (ipcctl->submitted) { struct ipcmsg *msg;
while (ipcctl->done == 0) int msgid;
msgid = ipcctl->msgtail % IPC_NMSG;
msg = &ipcctl->msg[msgid];
if (msg->submitted) {
while (msg->done == 0)
nop_pause(); nop_pause();
if (ipcctl->result == -1) if (msg->result == -1)
goto slow; die("xpread: result oops");
if (off < ipcctl->off) if (msg->off != off)
goto slow; die("xpread: off oops");
if (off > ipcctl->off + ipcctl->result)
goto slow;
char *kbuf = (char*) (KSHARED+4096); char *kbuf = (char*) (KSHARED+PGSIZE+(msg->pageid*PGSIZE));
off_t kbufoff = off - ipcctl->off; off_t kbufoff = off - msg->off;
size_t kbufcount = MIN(count, ipcctl->result - kbufoff); size_t kbufcount = MIN(count, msg->result - kbufoff);
memmove(buf, kbuf+kbufoff, kbufcount); memmove(buf, kbuf+kbufoff, kbufcount);
ipc_msg_free(msgid);
ipc_page_free(msg->pageid);
return kbufcount; return kbufcount;
} }
slow:
return pread(fd, buf, count, off); return pread(fd, buf, count, off);
} }
...@@ -56,8 +127,10 @@ int ...@@ -56,8 +127,10 @@ int
main(int ac, char **av) main(int ac, char **av)
{ {
u64 t0, t1; u64 t0, t1;
int i, k;
int fd; int fd;
int i;
memset(ipcctl, 0, sizeof(*ipcctl));
if (ac > 1) if (ac > 1)
usekernlet = av[1][0] == 'k'; usekernlet = av[1][0] == 'k';
...@@ -71,12 +144,11 @@ main(int ac, char **av) ...@@ -71,12 +144,11 @@ main(int ac, char **av)
die("write failed"); die("write failed");
t0 = rdtsc(); t0 = rdtsc();
for (k = 0; k < FSIZE; k+=PSIZE) { kernlet_pread(fd, BSIZE, 0);
kernlet_pread(fd, PSIZE, k); for (i = 0; i < FSIZE; i+=BSIZE) {
if (xpread(fd, buf, BSIZE, i) != BSIZE)
for (i = k; i < k+PSIZE; i+=BSIZE) die("pread failed");
if (xpread(fd, buf, BSIZE, i) != BSIZE) kernlet_pread(fd, BSIZE, i+BSIZE);
die("pread failed");
} }
t1 = rdtsc(); t1 = rdtsc();
......
BEGIN_DECLS BEGIN_DECLS
struct stat; struct stat;
struct ipcmsg;
// system calls // system calls
int fork(int); int fork(int);
...@@ -27,7 +28,7 @@ int map(void *addr, int len); ...@@ -27,7 +28,7 @@ int map(void *addr, int len);
int unmap(void *addr, int len); int unmap(void *addr, int len);
void halt(void); void halt(void);
ssize_t pread(int, void*, size_t, off_t); ssize_t pread(int, void*, size_t, off_t);
int kernlet(int, size_t, off_t); int kernlet(int, size_t, off_t, u32, u32);
// ulib.c // ulib.c
int stat(char*, struct stat*); int stat(char*, struct stat*);
......
...@@ -163,8 +163,9 @@ __wq_steal(int c) ...@@ -163,8 +163,9 @@ __wq_steal(int c)
static void static void
__wq_run(struct work *w) __wq_run(struct work *w)
{ {
void (*fn)(struct work*, void*, void*, void*, void*) = (void(*)(work*,void*,void*,void*,void*))w->rip; void (*fn)(struct work*, void*, void*, void*, void*, void*) =
fn(w, w->arg0, w->arg1, w->arg2, w->arg3); (void(*)(work*,void*,void*,void*,void*,void*))w->rip;
fn(w, w->arg0, w->arg1, w->arg2, w->arg3, w->arg4);
freework(w); freework(w);
} }
......
...@@ -4,5 +4,6 @@ struct work { ...@@ -4,5 +4,6 @@ struct work {
void *arg1; void *arg1;
void *arg2; void *arg2;
void *arg3; void *arg3;
void *arg4;
char data[]; char data[];
}; };
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论