Split pcpui->syscalls into a current and next
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 12 Nov 2010 22:46:47 +0000 (14:46 -0800)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:56 +0000 (17:35 -0700)
Instead of using pcpui->syscalls for both who to run next as well as
which call is currently being serviced.

Now it's more clear that a kthread is running a syscall (or none if ==
0), and we now can use signal_current_sc() after a block point (which
could happen (sys_exec()), though it is rare).

And since there is a cur_sysc active during each syscall, we can use
that struct for errno, instead of the errno_loc (which was originally
used for accessing inside an arch-dependent TF, back when we used a
register for errno).

kern/include/smp.h
kern/src/arsc.c
kern/src/kthread.c
kern/src/smp.c
kern/src/syscall.c

index a0c32b6..9e60344 100644 (file)
@@ -29,10 +29,9 @@ struct per_cpu_info {
        trapframe_t *cur_tf;
        struct kthread *spare;          /* useful when restarting */
        /* Syscall management */
-       // TODO: 2 sysc
-       struct syscall *syscalls;       /* ptr is into cur_proc's address space */
-       unsigned int nr_calls;
-       int *errno_loc;
+       struct syscall *cur_sysc;       /* ptr is into cur_proc's address space */
+       struct syscall *next_syscs;     /* other batched ones to do next */
+       unsigned int nr_syscs;
        uintreg_t *tf_retval_loc;
 
 #ifdef __SHARC__
index 5c1a98e..7487556 100644 (file)
@@ -94,9 +94,14 @@ static intreg_t process_generic_syscalls(struct proc *p, size_t max)
                // print req
                printd("req no %d, req arg %c\n", req->num, *((char*)req->args[0]));
                
-               coreinfo->errno_loc = (int*)&(rsp.syserr);
+               /* 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!)
index cb2c6fb..5698c91 100644 (file)
@@ -70,10 +70,8 @@ void sleep_on(struct semaphore *sem)
         * code. */
        kthread->proc = current;
        /* kthread tracks the syscall it is working on, which implies errno */
-       if (pcpui->syscalls)
-               kthread->sysc = pcpui->syscalls - 1;    // TODO: 2 sysc
-       else
-               kthread->sysc = 0;
+       kthread->sysc = pcpui->cur_sysc;
+       pcpui->cur_sysc = 0;                            /* catch bugs */
        if (kthread->proc)
                kref_get(&kthread->proc->kref, 1);
        /* Save the context, toggle blocking for the reactivation */
@@ -146,16 +144,14 @@ void restart_kthread(struct kthread *kthread)
                assert(current == kthread->proc);
                /* no longer need this ref, current holds it */
                kref_put(&kthread->proc->kref);
-
        } else {
                /* ref gets transfered (or it was 0 (no ref held)) */
                current = kthread->proc;
                if (kthread->proc)
                        lcr3(kthread->proc->env_cr3);
        }
-       // TODO: 2 sysc (set the syscall in progress to kthread->sysc */
-       if (kthread->sysc)
-               pcpui->errno_loc = &kthread->sysc->err;
+       /* Tell the core which syscall we are running (if any) */
+       pcpui->cur_sysc = kthread->sysc;
        /* Finally, restart our thread */
        pop_kernel_tf(&kthread->context);
 }
index 3311904..4392997 100644 (file)
@@ -47,7 +47,7 @@ void smp_idle(void)
        if (pcpui->cur_tf) {                    /* aka, current_tf */
                assert(pcpui->cur_proc);        /* aka, current */
                /* We also check in run_local_syscall().  This is for sys_exec() */
-               if (pcpui->nr_calls)
+               if (pcpui->nr_syscs)
                        run_local_syscall();
                /* Now we're done, so return */
                proc_restartcore(pcpui->cur_proc, pcpui->cur_tf);
index 0e85dff..9e99c60 100644 (file)
@@ -69,28 +69,21 @@ static bool proc_is_traced(struct proc *p)
  * don't trust an async fork).
  *
  * *sysc is in user memory, and should be pinned (TODO: UMEM).  There may be
- * issues with unpinning this if we never return.
- *
- * Note, this is currently tied to how cores execute syscall batches: pcpui
- * telling them what to do *next*, which should be advanced one past the call we
- * are currently working on.  If this sucks too much in the future, we can have
- * two separate struct syscall *s. */
+ * issues with unpinning this if we never return. */
 static void signal_current_sc(int retval)
 {
-       // TODO 2 sysc
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
-       struct syscall *sysc = pcpui->syscalls - 1;     /* it was already advanced */
-       sysc->retval = retval;
-       sysc->flags |= SC_DONE;
+       pcpui->cur_sysc->retval = retval;
+       pcpui->cur_sysc->flags |= SC_DONE;
 }
 
 /* Callable by any function while executing a syscall (or otherwise, actually).
- * Prep this by setting the errno_loc in advance. */
+ */
 void set_errno(int errno)
 {
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
-       if (pcpui->errno_loc)
-               *(pcpui->errno_loc) = errno;
+       if (pcpui->cur_sysc)
+               pcpui->cur_sysc->err = errno;
 }
 
 /************** Utility Syscalls **************/
@@ -527,8 +520,8 @@ success:
 all_out:
        /* When we idle, we don't want to try executing other syscalls.  If exec
         * succeeded (or the proc was destroyed) it'd just be wrong. */
-       pcpui->syscalls = 0;
-       pcpui->nr_calls = 0;
+       pcpui->next_syscs = 0;
+       pcpui->nr_syscs = 0;
        /* we can't return, since we'd write retvals to the old location of the
         * sycall struct (which has been freed and is in the old userspace) (or has
         * already been written to).*/
@@ -1389,22 +1382,21 @@ intreg_t syscall(struct proc *p, uintreg_t sc_num, uintreg_t a0, uintreg_t a1,
 
 /* A process can trap and call this function, which will set up the core to
  * handle all the syscalls.  a.k.a. "sys_debutante(needs, wants)" */
-void prep_syscalls(struct proc *p, struct syscall *sysc, unsigned int nr_calls)
+void prep_syscalls(struct proc *p, struct syscall *sysc, unsigned int nr_syscs)
 {
        int retval;
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
-       /* TODO: (UMEM) assert / pin the memory range sysc for nr_calls.  Not sure
+       /* TODO: (UMEM) assert / pin the memory range sysc for nr_syscs.  Not sure
         * how we'll know it is done to unpin it. (might need to handle it in
         * abandon_core() or smp_idle(). */
-       user_mem_assert(p, sysc, nr_calls * sizeof(struct syscall), PTE_USER_RW);
+       user_mem_assert(p, sysc, nr_syscs * sizeof(struct syscall), PTE_USER_RW);
        /* TEMP! */
-       if (nr_calls != 1)
-               warn("Debutante calls: %d\n", nr_calls);
+       if (nr_syscs != 1)
+               warn("Debutante calls: %d\n", nr_syscs);
        /* Set up this core to process the local call */
        *pcpui->tf_retval_loc = 0;      /* current_tf's retval says how many are done */
-       // TODO: 2 sysc
-       pcpui->syscalls = sysc;
-       pcpui->nr_calls = nr_calls;
+       pcpui->next_syscs = sysc;
+       pcpui->nr_syscs = nr_syscs;
 }
 
 /* This returns if there are no syscalls to do, o/w it always calls smp_idle()
@@ -1414,17 +1406,16 @@ void run_local_syscall(void)
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        struct syscall *sysc;
 
-       if (!pcpui->nr_calls) {
+       if (!pcpui->nr_syscs) {
                /* TODO: UMEM - stop pinning their memory.  Note, we may need to do this
                 * in other places.  This also will be tricky with exec, which doesn't
                 * have the same memory map anymore */
                return;
        }
-       // TODO 2 sysc
-       sysc = pcpui->syscalls++;               /* get the next */
-       pcpui->nr_calls--;                              /* one less to do */
+       sysc = pcpui->next_syscs++;             /* get the next */
+       pcpui->cur_sysc = sysc;                 /* let the core know which sysc it is */
+       pcpui->nr_syscs--;                              /* one less to do */
        (*pcpui->tf_retval_loc)++;              /* one more started */
-       pcpui->errno_loc = &sysc->err;
        sysc->retval = syscall(pcpui->cur_proc, sysc->num, sysc->arg0, sysc->arg1,
                               sysc->arg2, sysc->arg3, sysc->arg4, sysc->arg5);
        sysc->flags |= SC_DONE;