Proc refcnting wrappers
[akaros.git] / kern / src / arsc.c
index afb7aee..6fed271 100644 (file)
 #include <pmap.h>
 #include <stdio.h>
 #include <hashtable.h>
+#include <smp.h>
 #include <arsc_server.h>
+#include <kref.h>
 
 
 
 struct proc_list arsc_proc_list = TAILQ_HEAD_INITIALIZER(arsc_proc_list);
 spinlock_t arsc_proc_lock = SPINLOCK_INITIALIZER;
 
-intreg_t syscall_async(struct proc *p, syscall_req_t *call)
+intreg_t inline syscall_async(struct proc *p, syscall_req_t *call)
 {
        return syscall(p, call->num, call->args[0], call->args[1],
-                      call->args[2], call->args[3], call->args[4]);
+                      call->args[2], call->args[3], call->args[4], call->args[5]);
 }
 
-intreg_t sys_init_arsc(struct procp)
+intreg_t sys_init_arsc(struct proc *p)
 {
+       proc_incref(p, 1);              /* we're storing an external ref here */
        spin_lock_irqsave(&arsc_proc_lock);
        TAILQ_INSERT_TAIL(&arsc_proc_list, p, proc_arsc_link);
        spin_unlock_irqsave(&arsc_proc_lock);
        return ESUCCESS;
 }
 
-
-void arsc_server(trapframe_t *tf)
+void arsc_server(struct trapframe *tf)
 {
        struct proc *p = NULL;
        TAILQ_INIT(&arsc_proc_list);
-       while (true)
-       {
+       while (1) {
                while (TAILQ_EMPTY(&arsc_proc_list))
                        cpu_relax();
 
-               TAILQ_FOREACH(p, &arsc_proc_list, proc_link)
-               {
-                       // TODO: we may need an atomic swap to inc ref count
-                       if (p->state != PROC_DYING)
-                               process_generic_syscalls (p, MAX_ASRC_BATCH); 
+               TAILQ_FOREACH(p, &arsc_proc_list, proc_link) {
+                       /* Probably want to try to process a dying process's syscalls.  If
+                        * not, just move it to an else case */
+                       process_generic_syscalls (p, MAX_ASRC_BATCH); 
+                       if (p->state == PROC_DYING) {
+                               TAILQ_REMOVE(&arsc_proc_list, p, proc_arsc_link);
+                               proc_decref(p);
+                               /* Need to break out, so the TAILQ_FOREACH doesn't flip out.
+                                * It's not fair, but we're not dealing with that yet anyway */
+                               break;
+                       }
                }
        }
 }
@@ -61,18 +68,11 @@ static intreg_t process_generic_syscalls(struct proc *p, size_t max)
 {
        size_t count = 0;
        syscall_back_ring_t* sysbr = &p->syscallbackring;
+       struct per_cpu_info* coreinfo = &per_cpu_info[core_id()];
        // looking at a process not initialized to perform arsc. 
        if (sysbr == NULL) 
                return count;
 
-       /* make sure the proc is still alive, and keep it from dying from under us
-        * incref will return ESUCCESS on success.  This might need some thought
-        * regarding when the incref should have happened (like by whoever passed us
-        * the *p). */
-       // TODO: ought to be unnecessary, if you called this right, kept here for
-       // now in case anyone actually uses the ARSCs.
-       kref_get(&p->kref, 1);
-
        // max is the most we'll process.  max = 0 means do as many as possible
        // TODO: check for initialization of the ring. 
        while (RING_HAS_UNCONSUMED_REQUESTS(sysbr) && ((!max)||(count < max)) ) {
@@ -93,7 +93,15 @@ static intreg_t process_generic_syscalls(struct proc *p, size_t max)
                syscall_req_t* req = RING_GET_REQUEST(sysbr, ++(sysbr->req_cons));
                // print req
                printd("req no %d, req arg %c\n", req->num, *((char*)req->args[0]));
+               
+               /* TODO: when the remote syscall stuff can handle the new async
+                * syscalls, they need to use a real sysc.  This might at least stop it
+                * from crashing. */
+               struct syscall sysc = {0};
+               coreinfo->cur_sysc = &sysc;
+               
                rsp.retval = syscall_async(p, req);
+               rsp.syserr = sysc.err;
                // write response into the slot it came from
                memcpy(req, &rsp, sizeof(syscall_rsp_t));
                // update our counter for what we've produced (assumes we went in order!)
@@ -104,7 +112,6 @@ static intreg_t process_generic_syscalls(struct proc *p, size_t max)
        }
        // load sane page tables (and don't rely on decref to do it for you).
        lcr3(boot_cr3);
-       kref_put(&p->kref);
        return (intreg_t)count;
 }