From 18727027ccceadce5b1a9193c62498e4cb785e57 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Mon, 5 Oct 2015 10:12:34 +0200 Subject: [PATCH] add support of remote read and lseek system calls - reduce latency by disabling the Nagl algorithm --- hermit/kernel/syscall.c | 170 +++++++++++++++++++++++++++++++--------- hermit/tools/proxy.c | 122 +++++++++++++++++++++++++--- 2 files changed, 241 insertions(+), 51 deletions(-) diff --git a/hermit/kernel/syscall.c b/hermit/kernel/syscall.c index cafc66897..d02e37689 100644 --- a/hermit/kernel/syscall.c +++ b/hermit/kernel/syscall.c @@ -61,17 +61,21 @@ static void sys_yield(void) void NORETURN do_exit(int arg); +typedef struct { + int sysnr; + int arg; +} __attribute__((packed)) sys_exit_t; + /** @brief To be called by the systemcall to exit tasks */ void NORETURN sys_exit(int arg) { task_t* task = per_core(current_task); - int sysnr = __NR_exit; + sys_exit_t sysargs = {__NR_exit, arg}; if (task->sd >= 0) { spinlock_lock(&lwip_lock); - write(task->sd, &sysnr, sizeof(int)); - write(task->sd, &arg, sizeof(int)); + write(task->sd, &sysargs, sizeof(sysargs)); spinlock_unlock(&lwip_lock); closesocket(task->sd); @@ -81,11 +85,58 @@ void NORETURN sys_exit(int arg) do_exit(arg); } -static int sys_write(int fd, const char* buf, size_t len) +typedef struct { + int sysnr; + int fd; + size_t len; +} __attribute__((packed)) sys_read_t; + +static ssize_t sys_read(int fd, char* buf, size_t len) { task_t* task = per_core(current_task); - int ret, sysnr = __NR_write; - size_t i; + sys_read_t sysargs = {__NR_read, fd, len}; + ssize_t j, ret; + + if (task->sd < 0) + return -ENOSYS; + + spinlock_lock(&lwip_lock); + write(task->sd, &sysargs, sizeof(sysargs)); + + read(task->sd, &j, sizeof(j)); + if (j > 0) + { + ssize_t i = 0; + + while(i < j) + { + ret = read(task->sd, buf+i, j-i); + if (ret < 0) { + spinlock_unlock(&lwip_lock); + return ret; + } + + i += ret; + } + } + + spinlock_unlock(&lwip_lock); + + return j; +} + +typedef struct { + int sysnr; + int fd; + size_t len; +} __attribute__((packed)) sys_write_t; + +static ssize_t sys_write(int fd, const char* buf, size_t len) +{ + task_t* task = per_core(current_task); + ssize_t i, ret; + int flag; + sys_write_t sysargs = {__NR_write, fd, len}; if (BUILTIN_EXPECT(!buf, 0)) return -1; @@ -100,33 +151,35 @@ static int sys_write(int fd, const char* buf, size_t len) spinlock_lock(&lwip_lock); - ret = write(task->sd, &sysnr, sizeof(int)); - if (ret < 0) - goto out; + flag = 0; + setsockopt(task->sd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(flag)); - ret = write(task->sd, &fd, sizeof(int)); - if (ret < 0) - goto out; - - ret = write(task->sd, &len, sizeof(size_t)); - if (ret < 0) - goto out; + write(task->sd, &sysargs, sizeof(sysargs)); i=0; - while(isd, (char*)buf+i, len-i); - if (ret < 0) - goto out; + if (ret < 0) { + spinlock_unlock(&lwip_lock); + return ret; + } + i += ret; } - ret = len; + flag = 1; + setsockopt(task->sd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(flag)); + + if (fd > 2) { + ret = read(task->sd, &i, sizeof(i)); + if (ret < 0) + i = ret; + } else i = len; -out: spinlock_unlock(&lwip_lock); - return ret; + return i; } static ssize_t sys_sbrk(int incr) @@ -159,20 +212,23 @@ static int sys_open(const char* name, int flags, int mode) { task_t* task = per_core(current_task); int i, ret, sysnr = __NR_open; - size_t len = strlen(name+1); + size_t len; if (task->sd < 0) return 0; - len = strlen(name+1); + len = strlen(name)+1; spinlock_lock(&lwip_lock); - ret = write(task->sd, &sysnr, sizeof(int)); + i = 0; + setsockopt(task->sd, IPPROTO_TCP, TCP_NODELAY, (char *) &i, sizeof(i)); + + ret = write(task->sd, &sysnr, sizeof(sysnr)); if (ret < 0) goto out; - ret = write(task->sd, &len, sizeof(size_t)); + ret = write(task->sd, &len, sizeof(len)); if (ret < 0) goto out; @@ -185,15 +241,18 @@ static int sys_open(const char* name, int flags, int mode) i += ret; } - ret = write(task->sd, &flags, sizeof(int)); + ret = write(task->sd, &flags, sizeof(flags)); if (ret < 0) goto out; - ret = write(task->sd, &mode, sizeof(int)); + ret = write(task->sd, &mode, sizeof(mode)); if (ret < 0) goto out; - read(task->sd, &ret, sizeof(int)); + i = 1; + setsockopt(task->sd, IPPROTO_TCP, TCP_NODELAY, (char *) &i, sizeof(i)); + + read(task->sd, &ret, sizeof(ret)); out: spinlock_unlock(&lwip_lock); @@ -201,23 +260,26 @@ out: return ret; } +typedef struct { + int sysnr; + int fd; +} __attribute__((packed)) sys_close_t; + static int sys_close(int fd) { + int ret; task_t* task = per_core(current_task); - int ret, sysnr = __NR_close; + sys_close_t sysargs = {__NR_close, fd}; if (task->sd < 0) return 0; spinlock_lock(&lwip_lock); - ret = write(task->sd, &sysnr, sizeof(int)); - if (ret < 0) + ret = write(task->sd, &sysargs, sizeof(sysargs)); + if (ret != sizeof(sysargs)) goto out; - ret = write(task->sd, &fd, sizeof(int)); - if (ret < 0) - goto out; - read(task->sd, &ret, sizeof(int)); + read(task->sd, &ret, sizeof(ret)); out: spinlock_unlock(&lwip_lock); @@ -295,10 +357,42 @@ static int sys_clone(tid_t* id, void* ep, void* argv) return clone_task(id, ep, argv, per_core(current_task)->prio); } +typedef struct { + int sysnr; + int fd; + off_t offset; + int whence; +} __attribute__((packed)) sys_lseek_t; + +static off_t sys_lseek(int fd, off_t offset, int whence) +{ + off_t off; + task_t* task = per_core(current_task); + sys_lseek_t sysargs = {__NR_lseek, fd, offset, whence}; + + if (task->sd < 0) + return -ENOSYS; + + spinlock_lock(&lwip_lock); + + write(task->sd, &sysargs, sizeof(sysargs)); + read(task->sd, &off, sizeof(off)); + + spinlock_unlock(&lwip_lock); + + return off; +} + static int default_handler(void) { +#if 0 kprintf("Invalid system call\n"); +#else + uint64_t rax; + asm volatile ("mov %%rax, %0" : "=m"(rax) :: "memory"); + kprintf("Invalid system call: %zd\n", rax); +#endif return -ENOSYS; } @@ -307,8 +401,8 @@ size_t syscall_table[] = { (size_t) sys_write, /* __NR_write */ (size_t) sys_open, /* __NR_open */ (size_t) sys_close, /* __NR_close */ - (size_t) default_handler, /* __NR_read */ - (size_t) default_handler, /* __NR_lseek */ + (size_t) sys_read, /* __NR_read */ + (size_t) sys_lseek, /* __NR_lseek */ (size_t) default_handler, /* __NR_unlink */ (size_t) sys_getpid, /* __NR_getpid */ (size_t) default_handler, /* __NR_kill */ diff --git a/hermit/tools/proxy.c b/hermit/tools/proxy.c index 5c2929046..a8133e6e2 100644 --- a/hermit/tools/proxy.c +++ b/hermit/tools/proxy.c @@ -35,6 +35,7 @@ #include #include #include +#include #define HERMIT_PORT 0x494F #define HERMIT_MAGIC 0x7E317 @@ -44,6 +45,7 @@ #define __HERMIT_open 2 #define __HERMIT_close 3 #define __HERMIT_read 4 +#define __HERMIT_lseek 5 static char saddr[16] = "192.168.28.2"; static int sobufsize = 131072; @@ -69,7 +71,7 @@ int handle_syscalls(int s) switch(sysnr) { case __HERMIT_exit: { - int arg; + int arg = 0; ret = read(s, &arg, sizeof(arg)); if (ret < 0) @@ -80,7 +82,8 @@ int handle_syscalls(int s) } case __HERMIT_write: { int fd; - size_t j, len; + ssize_t j; + size_t len; char* buff; ret = read(s, &fd, sizeof(fd)); @@ -105,18 +108,52 @@ int handle_syscalls(int s) j += len; } - j=0; - while(j < len) - { - ret = write(fd, buff+j, len-j); - if (ret < 0) - goto out; - j += len; - } + j = write(fd, buff, len); + if (fd > 2) + write(s, &j, sizeof(j)); free(buff); break; } + case __HERMIT_open: { + size_t j, len; + char* fname; + int flags, mode; + + ret = read(s, &len, sizeof(len)); + if (ret < 0) + goto out; + + fname = malloc(len); + if (!fname) + goto out; + + j = 0; + while(j < len) + { + ret = read(s, fname+j, len-j); + if (ret < 0) + goto out; + + j += ret; + } + + ret = read(s, &flags, sizeof(flags)); + if (ret < 0) + goto out; + + ret = read(s, &mode, sizeof(mode)); + if (ret < 0) + goto out; + + //printf("flags 0x%x, mode 0x%x\n", flags, mode); + + ret = open(fname, flags, mode); + write(s, &ret, sizeof(ret)); + + free(fname); + break; + } case __HERMIT_close: { int fd; @@ -134,6 +171,63 @@ int handle_syscalls(int s) goto out; break; } + case __HERMIT_read: { + int fd, flag; + size_t len; + ssize_t j; + char* buff; + + ret = read(s, &fd, sizeof(fd)); + if (ret < 0) + goto out; + + ret = read(s, &len, sizeof(len)); + if (ret < 0) + goto out; + + buff = malloc(len); + if (!buff) + goto out; + + j = read(fd, buff, len); + + flag = 0; + setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)); + + write(s, &j, sizeof(j)); + + if (j > 0) + { + ssize_t i = 0; + + while(i < j) + { + ret = write(s, buff+i, j-i); + if (ret < 0) + break; + + i += ret; + } + } + + flag = 1; + setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)); + + free(buff); + break; + } + case __HERMIT_lseek: { + int fd, whence; + off_t offset; + + read(s, &fd, sizeof(fd)); + read(s, &offset, sizeof(offset)); + read(s, &whence, sizeof(whence)); + + offset = lseek(fd, offset, whence); + write(s, &offset, sizeof(offset)); + break; + } default: fprintf(stderr, "Proxy: invalid syscall number %d\n", sysnr); break; @@ -141,7 +235,7 @@ int handle_syscalls(int s) } out: - perror("Proxy: communication error"); + perror("Proxy -- communication error"); return 1; } @@ -162,6 +256,8 @@ int main(int argc, char **argv) setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize)); setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize)); + i = 1; + setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &i, sizeof(i)); /* server address */ memset((char *) &serv_name, 0x00, sizeof(serv_name)); @@ -172,7 +268,7 @@ int main(int argc, char **argv) ret = connect(s, (struct sockaddr*)&serv_name, sizeof(serv_name)); if (ret < 0) { - perror("Proxy: connection error"); + perror("Proxy -- connection error"); close(s); exit(1); } @@ -226,7 +322,7 @@ int main(int argc, char **argv) return ret; out: - perror("Proxy: communication error"); + perror("Proxy -- communication error"); close(s); return 1; }