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