Async syscall handling
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 6 May 2009 02:27:09 +0000 (19:27 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 6 May 2009 18:42:18 +0000 (11:42 -0700)
Separate function that processes generic async syscalls.  The backring
is in the env_t.  Currently pushes responses back to userspace, though
userspace doesn't know how to get responses.  All syscalls are processed
synchronously once actually in the kernel.

inc/env.h
kern/env.c
kern/init.c
kern/syscall.c
kern/syscall.h
lib/syscall.c

index 537555f..bdb6909 100644 (file)
--- a/inc/env.h
+++ b/inc/env.h
@@ -8,6 +8,8 @@
 #include <inc/trap.h>
 #include <inc/memlayout.h>
 
 #include <inc/trap.h>
 #include <inc/memlayout.h>
 
+#include <inc/syscall.h>
+
 struct Env;
 typedef struct Env env_t;
 
 struct Env;
 typedef struct Env env_t;
 
@@ -45,6 +47,8 @@ struct Env {
        envid_t env_parent_id;          // env_id of this env's parent
        unsigned env_status;            // Status of the environment
        uint32_t env_runs;                      // Number of times environment has run
        envid_t env_parent_id;          // env_id of this env's parent
        unsigned env_status;            // Status of the environment
        uint32_t env_runs;                      // Number of times environment has run
+       // Note this is the actual backring, not a pointer to it somewhere else
+       syscall_back_ring_t env_sysbackring;    // BackRing for generic syscalls
 
        // Address space
        pde_t *env_pgdir;                       // Kernel virtual address of page dir
 
        // Address space
        pde_t *env_pgdir;                       // Kernel virtual address of page dir
index d1aecb6..df4ae80 100644 (file)
@@ -142,6 +142,8 @@ env_setup_vm(env_t *e)
 
        // Initialize the generic syscall ring buffer
        SHARED_RING_INIT((syscall_sring_t*)e->env_procdata);
 
        // Initialize the generic syscall ring buffer
        SHARED_RING_INIT((syscall_sring_t*)e->env_procdata);
+       // Initialize the backend of the ring buffer
+       BACK_RING_INIT(&e->env_sysbackring, (syscall_sring_t*)e->env_procdata, PGSIZE);
 
        // should be able to do this so long as boot_pgdir never has
        // anything put below UTOP
 
        // should be able to do this so long as boot_pgdir never has
        // anything put below UTOP
index 6887d7f..071ac1b 100644 (file)
@@ -80,7 +80,7 @@ void kernel_init(multiboot_info_t *mboot_info)
        //ENV_CREATE(user_divzero);
        //ENV_CREATE(user_buggyhello);
        ENV_CREATE(user_hello);
        //ENV_CREATE(user_divzero);
        //ENV_CREATE(user_buggyhello);
        ENV_CREATE(user_hello);
-       //ENV_CREATE(user_hello);
+       ENV_CREATE(user_hello);
        //ENV_CREATE(user_evilhello);
 
        // We only have one user environment for now, so just run it.
        //ENV_CREATE(user_evilhello);
 
        // We only have one user environment for now, so just run it.
@@ -88,43 +88,17 @@ void kernel_init(multiboot_info_t *mboot_info)
        // run_env_handler just runs the first env, like the prev command
        // need a way to have call_func to pass a pointer to a struct for arguments
        smp_call_function_single(2, run_env_handler, &envs[0], 0);
        // run_env_handler just runs the first env, like the prev command
        // need a way to have call_func to pass a pointer to a struct for arguments
        smp_call_function_single(2, run_env_handler, &envs[0], 0);
-       //smp_call_function_single(4, run_env_handler, &envs[1], 0);
+       smp_call_function_single(4, run_env_handler, &envs[1], 0);
 
        // wait 5 sec, then print what's in shared mem
        udelay(5000000);
 
        // wait 5 sec, then print what's in shared mem
        udelay(5000000);
-       /*
-       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 two syscalls at the beginning of procdata for env 0:\n\n");
-       // need to switch to the right context, so we can handle the user pointer
-       // that points to a data payload of the syscall
-       lcr3(envs[0].env_cr3);
-       syscall_back_ring_t sysbackring;
-       BACK_RING_INIT(&sysbackring, (syscall_sring_t*)envs[0].env_procdata, PGSIZE);
-
-       // not really enough, mostly just testing
-       while (!(RING_HAS_UNCONSUMED_REQUESTS(&sysbackring)))
+
+       printk("Attempting to run two syscalls at the beginning of procdata for env 0 and 1:\n\n");
+       while (1) {
+               process_generic_syscalls(&envs[0], 1);
+               process_generic_syscalls(&envs[1], 1);
                cpu_relax();
                cpu_relax();
-       syscall_async((syscall_req_t*)(RING_GET_REQUEST(&sysbackring, 0)));
-       printk("\n");
-       syscall_async((syscall_req_t*)(RING_GET_REQUEST(&sysbackring, 1)));
-       printk("\n");
-       syscall_async((syscall_req_t*)(RING_GET_REQUEST(&sysbackring, 2)));
-       printk("\n");
-       syscall_async((syscall_req_t*)(RING_GET_REQUEST(&sysbackring, 3)));
-       printk("\n");
-       /*
-       printk("Attempting to run the syscall at the beginning of procdata for env 1:\n\n");
-       lcr3(envs[1].env_cr3);
-       syscall_async((syscall_req_t*)(envs[1].env_procdata));
-       printk("\n");
-       */
+       }
        panic("Don't Panic");
 }
 
        panic("Don't Panic");
 }
 
index b96fe82..e29e384 100644 (file)
@@ -1,4 +1,8 @@
 /* See COPYRIGHT for copyright information. */
 /* See COPYRIGHT for copyright information. */
+#ifdef __DEPUTY__
+#pragma nodeputy
+#endif
+
 #include <inc/x86.h>
 #include <inc/error.h>
 #include <inc/string.h>
 #include <inc/x86.h>
 #include <inc/error.h>
 #include <inc/string.h>
@@ -102,7 +106,7 @@ syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,
                        return sys_env_destroy((envid_t)a1);
                default:
                        // or just return -E_INVAL
                        return sys_env_destroy((envid_t)a1);
                default:
                        // or just return -E_INVAL
-                       panic("invalid syscall number!");
+                       panic("invalid syscall number (%d)!", syscallno);
        }
        return 0xdeadbeef;
 }
        }
        return 0xdeadbeef;
 }
@@ -112,3 +116,33 @@ uint32_t syscall_async(syscall_req_t *call)
        return syscall(call->num, call->args[0], call->args[1],
                       call->args[2], call->args[3], call->args[4]);
 }
        return syscall(call->num, call->args[0], call->args[1],
                       call->args[2], call->args[3], call->args[4]);
 }
+
+uint32_t process_generic_syscalls(env_t* e, uint32_t max)
+{
+       uint32_t count = 0;
+       syscall_back_ring_t* sysbr = &e->env_sysbackring;
+
+       // need to switch to the right context, so we can handle the user pointer
+       // that points to a data payload of the syscall
+       lcr3(e->env_cr3);
+       // max is the most we'll process.  max = 0 means do as many as possible
+       while (RING_HAS_UNCONSUMED_REQUESTS(sysbr) && ((!max)||(count < max)) ) {
+               count++;
+               //printk("DEBUG PRE: sring->req_prod: %d, sring->rsp_prod: %d\n",\
+                          sysbr->sring->req_prod, sysbr->sring->rsp_prod);
+               // might want to think about 0-ing this out, if we aren't
+               // going to explicitly fill in all fields
+               syscall_resp_t rsp;
+               // this assumes we get our answer immediately for the syscall.
+               syscall_req_t* req = RING_GET_REQUEST(sysbr, ++(sysbr->req_cons));
+               rsp.retval = syscall_async(req);
+               // write response into the slot it came from
+               memcpy(req, &rsp, sizeof(syscall_resp_t));
+               // update our counter for what we've produced (assumes we went in order!)
+               (sysbr->rsp_prod_pvt)++;
+               RING_PUSH_RESPONSES(sysbr);
+               //printk("DEBUG POST: sring->req_prod: %d, sring->rsp_prod: %d\n",\
+                          sysbr->sring->req_prod, sysbr->sring->rsp_prod);
+       }
+       return count;
+}
index 8ace012..1cc829c 100644 (file)
@@ -5,9 +5,11 @@
 #endif
 
 #include <inc/syscall.h>
 #endif
 
 #include <inc/syscall.h>
+#include <inc/env.h>
 
 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_req_t *syscall);
 
 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_req_t *syscall);
+uint32_t process_generic_syscalls(env_t* e, uint32_t max);
 
 #endif /* !ROS_KERN_SYSCALL_H */
 
 #endif /* !ROS_KERN_SYSCALL_H */
index b050c0d..cf45c1d 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <inc/syscall.h>
 #include <inc/lib.h>
 
 #include <inc/syscall.h>
 #include <inc/lib.h>
+#include <inc/x86.h>
 
 static inline uint32_t
 syscall(int num, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5)
 
 static inline uint32_t
 syscall(int num, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5)
@@ -36,15 +37,20 @@ syscall(int num, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5
 
 static inline error_t async_syscall(syscall_req_t *syscall)
 {
 
 static inline error_t async_syscall(syscall_req_t *syscall)
 {
-       static uint8_t next = 0; // should make sure this never goes too high
-       syscall_req_t* req = RING_GET_REQUEST(&sysfrontring, next++);   
+       // spin til there is room for our request.  ring size is currently 64.
+       while (RING_FULL(&sysfrontring))
+               cpu_relax();
+       // req_prod_pvt comes in as the previously produced item.  need to
+       // increment to the next available spot, which is the one we'll work on.
+       syscall_req_t* req = RING_GET_REQUEST(&sysfrontring, ++(sysfrontring.req_prod_pvt));
        memcpy(req, syscall, sizeof(syscall_req_t));
        memcpy(req, syscall, sizeof(syscall_req_t));
-       syscall_req_t* req = RING_GET_REQUEST(&sysfrontring, next++);   
-       memcpy(req, syscall, sizeof(syscall_req_t));
-       // need to actually update our sysfrontring.req_prod_pvt
-       sysfrontring.req_prod_pvt++;
+       // push our updates to sysfrontring.req_prod_pvt
        RING_PUSH_REQUESTS(&sysfrontring);
        RING_PUSH_REQUESTS(&sysfrontring);
+       //cprintf("DEBUG: sring->req_prod: %d, sring->rsp_prod: %d\n", \
+               sysfrontring.sring->req_prod, sysfrontring.sring->rsp_prod);
        return 0;
        return 0;
+       // at some point, we need to listen for the responses.  pass back a
+       // reference of some sort, probably via a parameter.
 }
 
 void sys_cputs_async(const char *s, size_t len)
 }
 
 void sys_cputs_async(const char *s, size_t len)