Rough asynchronous syscalls
authorBarret Rhoden <brho@cs.berkeley.edu>
Sat, 25 Apr 2009 00:34:14 +0000 (17:34 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sat, 25 Apr 2009 02:49:14 +0000 (19:49 -0700)
Creates an async mechanism to pass syscalls through the UDATA mapping.
Right now, it's just a struct Syscall right at the beginning of UDATA.
There's a cprintf_async userspace function that uses the sys_cputs_async
call (which is the only async call for now).  However, the userspace
printf functions aren't built to have multiple printfs in flight (async
or otherwise), so be careful.

inc/lib.h
inc/stdio.h
inc/syscall.h
kern/init.c
kern/syscall.c
kern/syscall.h
lib/libmain.c
lib/printf.c
lib/syscall.c
user/hello.c

index e9921b4..fb49328 100644 (file)
--- a/inc/lib.h
+++ b/inc/lib.h
@@ -34,6 +34,7 @@ char* readline(const char *buf);
 
 // syscall.c
 void   sys_cputs(const char *string, size_t len);
+void   sys_cputs_async(const char *string, size_t len);
 int    sys_cgetc(void);
 envid_t        sys_getenvid(void);
 int    sys_env_destroy(envid_t);
index 41e9997..395cb7a 100644 (file)
@@ -26,6 +26,7 @@ void  vprintfmt(void (*putch)(int, TV(t)), TV(t) putdat, const char *NTS fmt, va_
 
 // lib/printf.c
 int    cprintf(const char * NTS fmt, ...);
+int    cprintf_async(const char * NTS fmt, ...);
 int    vcprintf(const char * NTS fmt, va_list);
 
 // lib/sprintf.c
index 3306cff..bdcee2b 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef ROS_INC_SYSCALL_H
 #define ROS_INC_SYSCALL_H
 
+#include <inc/types.h>
+
 /* system call numbers */
 enum
 {
@@ -11,4 +13,11 @@ enum
        NSYSCALLS
 };
 
+#define NUM_SYS_ARGS 6
+typedef struct Syscall {
+       uint32_t num;
+       uint32_t flags;
+       uint32_t args[NUM_SYS_ARGS];
+} syscall_t;
+
 #endif /* !ROS_INC_SYSCALL_H */
index 9957b7e..f1498f4 100644 (file)
@@ -25,6 +25,7 @@
 #include <kern/testing.h>
 #include <kern/atomic.h>
 #include <kern/smp.h>
+#include <kern/syscall.h>
 
 static void print_cpuinfo(void);
 
@@ -91,8 +92,18 @@ void kernel_init(multiboot_info_t *mboot_info)
 
        // wait 5 sec, then print what's in shared mem
        udelay(5000000);
-       printk("Reading from shared mem from hello on core 2:\n");
-       printk(envs[0].env_procdata); // horrible for security!
+       /*
+       printk("Dumping from shared mem from hello on core 2:\n");
+       printk("%08x%08x%08x%08x\n",
+               *(uint32_t*)(envs[0].env_procdata),
+               *(uint32_t*)(envs[0].env_procdata + 4),
+               *(uint32_t*)(envs[0].env_procdata + 8),
+               *(uint32_t*)(envs[0].env_procdata + 12));
+               */
+       printk("Attempting to run the syscall at the beginning of procdata:\n");
+       printk("\n");
+       syscall_async((syscall_t*)(envs[0].env_procdata));
+       printk("\n");
        panic("Don't Panic");
 }
 
index b5fc6e2..d741991 100644 (file)
@@ -82,18 +82,24 @@ syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,
                return -E_INVAL;
        
        switch (syscallno) {
-               case 0:
+               case SYS_cputs:
                        sys_cputs((char *DANGEROUS)a1, (size_t)a2);
                        return 0;
-               case 1:
+               case SYS_cgetc:
                        return sys_cgetc();
-               case 2:
+               case SYS_getenvid:
                        return sys_getenvid();
-               case 3:
+               case SYS_env_destroy:
                        return sys_env_destroy((envid_t)a1);
                default:
+                       // or just return -E_INVAL
                        panic("invalid syscall number!");
        }
        return 0xdeadbeef;
 }
 
+uint32_t syscall_async(syscall_t *call)
+{
+       return syscall(call->num, call->args[0], call->args[1],
+                      call->args[2], call->args[3], call->args[4]);
+}
index 67639bc..6476720 100644 (file)
@@ -8,5 +8,6 @@
 
 uint32_t (SYNCHRONOUS syscall)(uint32_t num, uint32_t a1, uint32_t a2,
                                uint32_t a3, uint32_t a4, uint32_t a5);
+uint32_t syscall_async(syscall_t *syscall);
 
 #endif /* !ROS_KERN_SYSCALL_H */
index afdc74d..1996c78 100644 (file)
@@ -13,7 +13,7 @@ libmain(int argc, char **argv)
 {
        // set env to point at our env structure in envs[].
        // TODO: for now, the kernel just copies our env struct to the beginning of
-       // proc_info.  When we figure out what we want there, change this.
+       // procinfo.  When we figure out what we want there, change this.
        env = (env_t*)procinfo;
 
        // save the name of the program so that panic() can use it
index 4098984..07a2a6c 100644 (file)
@@ -60,3 +60,39 @@ cprintf(const char *fmt, ...)
        return cnt;
 }
 
+// Temp async varieties
+static void
+putch_async(int ch, printbuf_t *b)
+{
+       b->buf[b->idx++] = ch;
+       if (b->idx == 256-1) {
+               sys_cputs_async(b->buf, b->idx);
+               b->idx = 0;
+       }
+       b->cnt++;
+}
+
+static int vcprintf_async(const char *fmt, va_list ap)
+{
+       printbuf_t b;
+
+       b.idx = 0;
+       b.cnt = 0;
+       vprintfmt((void*)putch_async, &b, fmt, ap);
+       sys_cputs_async(b.buf, b.idx);
+
+       return b.cnt;
+}
+
+int cprintf_async(const char *fmt, ...)
+{
+       va_list ap;
+       int cnt;
+
+       va_start(ap, fmt);
+       cnt = vcprintf_async(fmt, ap);
+       va_end(ap);
+
+       return cnt;
+}
+
index 061ac21..00fe08e 100644 (file)
@@ -34,6 +34,21 @@ syscall(int num, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5
        return ret;
 }
 
+static inline error_t async_syscall(syscall_t *syscall)
+{
+       // testing just one syscall at a time, and just put it at the beginning of
+       // the shared data page
+       memcpy(procdata, syscall, sizeof(syscall_t));
+       return 0;
+}
+
+void sys_cputs_async(const char *s, size_t len)
+{
+       // could just hardcode 4 0's, will eventually wrap this marshaller anyway
+       syscall_t syscall = {SYS_cputs, 0, {(uint32_t)s, len, [2 ... (NUM_SYS_ARGS-1)] 0} };
+       async_syscall(&syscall);
+}
+
 void
 sys_cputs(const char *s, size_t len)
 {
index f1fea0f..d201968 100644 (file)
@@ -7,8 +7,16 @@ void umain(void)
        // this is just their way of generating a pagefault..., until now!
        cprintf("i am environment %08x\n", env->env_id);
 
-       // hello via shared mem
-       const char* hello = "Is there anybody in there?\n";
-       memcpy(procdata, hello, strlen(hello));
-       cprintf("wrote to shared mem.  just nod if you can hear me.\n");
+       // async via shared mem
+       char* hello = "First cross-chip async syscall success!  Shiver me timbers!\n";
+       cprintf("about to write to shared mem.  hope it gets printed.  blimey! \n");
+       // note that when using the cprintf family, we can't currently call again,
+       // since the library functions use the same buffer.  the last used string
+       // will be the one printed when the syscall is serviced, regardless of
+       // whether the actual syscall can handle multiples in flight.
+       cprintf_async(hello);
+
+       // might as well spin, just to make sure nothing gets deallocated
+       // while we're waiting to test the async call
+       while (1);
 }