proc_restartcore() only used for current_tf, etc
[akaros.git] / kern / src / process.c
index 13d3c15..af3c7ba 100644 (file)
@@ -27,6 +27,7 @@
 #include <resource.h>
 #include <elf.h>
 #include <arsc_server.h>
+#include <devfs.h>
 
 /* Process Lists */
 struct proc_list proc_runnablelist = TAILQ_HEAD_INITIALIZER(proc_runnablelist);
@@ -320,7 +321,7 @@ error_t proc_alloc(struct proc **pp, struct proc *parent)
        kref_get(&default_ns.kref, 1);
        p->ns = &default_ns;
        spinlock_init(&p->fs_env.lock);
-       p->fs_env.umask = parent ? parent->fs_env.umask : 0002;
+       p->fs_env.umask = parent ? parent->fs_env.umask : S_IWGRP | S_IWOTH;
        p->fs_env.root = p->ns->root->mnt_root;
        kref_get(&p->fs_env.root->d_kref, 1);
        p->fs_env.pwd = parent ? parent->fs_env.pwd : p->fs_env.root;
@@ -331,12 +332,6 @@ error_t proc_alloc(struct proc **pp, struct proc *parent)
        p->open_files.max_fdset = NR_FILE_DESC_DEFAULT;
        p->open_files.fd = p->open_files.fd_array;
        p->open_files.open_fds = (struct fd_set*)&p->open_files.open_fds_init;
-       /* TODO: 0, 1, and 2 are reserved, but prob shouldn't do it this way.
-        * Whatever we do for stdin/out/err, we need to keep it in sync for created
-        * processes and forked processes (clone_files). */
-       p->open_files.next_fd = 3;
-       for (int i = 0; i < 3; i++)
-               SET_BITMASK_BIT(p->open_files.open_fds->fds_bits, i);
 
        atomic_inc(&num_envs);
        frontend_proc_init(p);
@@ -367,6 +362,10 @@ struct proc *proc_create(struct file *prog, char **argv, char **envp)
                panic("proc_create: %e", r);    /* one of 3 quaint usages of %e */
        procinfo_pack_args(p->procinfo, argv, envp);
        assert(load_elf(p, prog) == 0);
+       /* Connect to stdin, stdout, stderr */
+       assert(insert_file(&p->open_files, dev_stdin,  0) == 0);
+       assert(insert_file(&p->open_files, dev_stdout, 0) == 1);
+       assert(insert_file(&p->open_files, dev_stderr, 0) == 2);
        __proc_ready(p);
        return p;
 }
@@ -379,16 +378,18 @@ static void __proc_free(struct kref *kref)
        struct proc *p = container_of(kref, struct proc, kref);
        physaddr_t pa;
 
-       printk("[PID %d] freeing proc: %d\n", current ? current->pid : 0, p->pid);
+       printd("[PID %d] freeing proc: %d\n", current ? current->pid : 0, p->pid);
        // All parts of the kernel should have decref'd before __proc_free is called
        assert(kref_refcnt(&p->kref) == 0);
 
        close_all_files(&p->open_files, FALSE);
+       kref_put(&p->fs_env.root->d_kref);
+       kref_put(&p->fs_env.pwd->d_kref);
        destroy_vmrs(p);
        frontend_proc_free(p);  /* TODO: please remove me one day */
        /* Free any colors allocated to this process */
-       if(p->cache_colors_map != global_cache_colors_map) {
-               for(int i=0; i<llc_cache->num_colors; i++)
+       if (p->cache_colors_map != global_cache_colors_map) {
+               for(int i = 0; i < llc_cache->num_colors; i++)
                        cache_color_free(llc_cache, p->cache_colors_map);
                cache_colors_map_free(p->cache_colors_map);
        }
@@ -421,6 +422,28 @@ bool proc_controls(struct proc *actor, struct proc *target)
        return ((actor == target) || (target->ppid == actor->pid));
 }
 
+/* Helper, makes p the 'current' process, dropping the old current/cr3.  Don't
+ * incref - this assumes the passed in reference already counted 'current'. */
+static void __set_proc_current(struct proc *p)
+{
+       /* We use the pcpui to access 'current' to cut down on the core_id() calls,
+        * though who know how expensive/painful they are. */
+       struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
+       /* If the process wasn't here, then we need to load its address space. */
+       if (p != pcpui->cur_proc) {
+               /* Do not incref here.  We were given the reference to current,
+                * pre-upped. */
+               lcr3(p->env_cr3);
+               /* This is "leaving the process context" of the previous proc.  The
+                * previous lcr3 unloaded the previous proc's context.  This should
+                * rarely happen, since we usually proactively leave process context,
+                * but this is the fallback. */
+               if (pcpui->cur_proc)
+                       kref_put(&pcpui->cur_proc->kref);
+               pcpui->cur_proc = p;
+       }
+}
+
 /* Dispatches a process to run, either on the current core in the case of a
  * RUNNABLE_S, or on its partition in the case of a RUNNABLE_M.  This should
  * never be called to "restart" a core.  This expects that the "instructions"
@@ -459,19 +482,19 @@ void proc_run(struct proc *p)
                        p->procinfo->num_vcores = 0;
                        __map_vcore(p, 0, core_id()); // sort of.  this needs work.
                        __seq_end_write(&p->procinfo->coremap_seqctr);
-                       /* __proc_startcore assumes the reference we give it is for current.
-                        * Decref if current is already properly set. */
+                       /* __set_proc_current assumes the reference we give it is for
+                        * current.  Decref if current is already properly set, otherwise
+                        * ensure current is set. */
                        if (p == current)
                                kref_put(&p->kref);
-                       /* We don't want to process routine messages here, since it's a bit
-                        * different than when we perform a syscall in this process's
-                        * context.  We want interrupts disabled so that if there was a
-                        * routine message on the way, we'll get the interrupt once we pop
-                        * back to userspace.  */
+                       else
+                               __set_proc_current(p);
+                       /* We restartcore, instead of startcore, since startcore is a bit
+                        * lower level and we want a chance to process kmsgs before starting
+                        * the process. */
                        spin_unlock(&p->proc_lock);
-                       disable_irq();
-
-                       __proc_startcore(p, &p->env_tf);
+                       current_tf = &p->env_tf;
+                       proc_restartcore();
                        break;
                case (PROC_RUNNABLE_M):
                        /* vcoremap[i] holds the coreid of the physical core allocated to
@@ -527,19 +550,7 @@ void proc_run(struct proc *p)
 static void __proc_startcore(struct proc *p, trapframe_t *tf)
 {
        assert(!irq_is_enabled());
-       /* If the process wasn't here, then we need to load its address space. */
-       if (p != current) {
-               /* Do not incref here.  We were given the reference to current,
-                * pre-upped. */
-               lcr3(p->env_cr3);
-               /* This is "leaving the process context" of the previous proc.  The
-                * previous lcr3 unloaded the previous proc's context.  This should
-                * rarely happen, since we usually proactively leave process context,
-                * but is the fallback. */
-               if (current)
-                       kref_put(&current->kref);
-               set_current_proc(p);
-       }
+       __set_proc_current(p);
        /* need to load our silly state, preferably somewhere other than here so we
         * can avoid the case where the context was just running here.  it's not
         * sufficient to do it in the "new process" if-block above (could be things
@@ -551,12 +562,13 @@ static void __proc_startcore(struct proc *p, trapframe_t *tf)
         * __startcore.  */
        if (p->state == PROC_RUNNING_S)
                env_pop_ancillary_state(p);
-       
+       /* Clear the current_tf, since it is no longer used */
+       current_tf = 0;
        env_pop_tf(tf);
 }
 
-/* Restarts the given context (trapframe) of process p on the core this code
- * executes on.  Calls an internal function to do the work.
+/* Restarts/runs the current_tf, which must be for the current process, on the
+ * core this code executes on.  Calls an internal function to do the work.
  *
  * In case there are pending routine messages, like __death, __preempt, or
  * __notify, we need to run them.  Alternatively, if there are any, we could
@@ -566,16 +578,23 @@ static void __proc_startcore(struct proc *p, trapframe_t *tf)
  * Refcnting: this will not return, and it assumes that you've accounted for
  * your reference as if it was the ref for "current" (which is what happens when
  * returning from local traps and such. */
-void proc_restartcore(struct proc *p, trapframe_t *tf)
+void proc_restartcore(void)
 {
-       // TODO: proc_restartcore shouldn't ever be called with tf != current_tf,
-       // so the parameter should probably be removed outright.
-       assert(current_tf == tf);
-
+       struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
+       /* If there is no cur_tf, it is because the old one was already restarted
+        * (and we weren't interrupting another one to finish).  In which case, we
+        * should just smp_idle() */
+       if (!pcpui->cur_tf) {
+               assert(!current);       /* might be wrong, but i want to know if it is */
+               smp_idle();
+       }
+       /* TODO: this is where we can decide to smp_idle() if there is no cur_tf */
        /* Need ints disabled when we return from processing (race) */
        disable_irq();
-       process_routine_kmsg();
-       __proc_startcore(p, tf);
+       /* Need to be current (set by the caller), in case a kmsg is there that
+        * tries to clobber us. */
+       process_routine_kmsg(pcpui->cur_tf);
+       __proc_startcore(pcpui->cur_proc, pcpui->cur_tf);
 }
 
 /*
@@ -721,6 +740,16 @@ static uint32_t get_pcoreid(struct proc *p, uint32_t vcoreid)
        return p->procinfo->vcoremap[vcoreid].pcoreid;
 }
 
+/* Helper function: yields / wraps up current_tf and schedules the _S */
+void __proc_yield_s(struct proc *p, struct trapframe *tf)
+{
+       assert(p->state == PROC_RUNNING_S);
+       p->env_tf= *tf;
+       env_push_ancillary_state(p);                    /* TODO: (HSS) */
+       __proc_set_state(p, PROC_RUNNABLE_S);
+       schedule_proc(p);
+}
+
 /* Yields the calling core.  Must be called locally (not async) for now.
  * - If RUNNING_S, you just give up your time slice and will eventually return.
  * - If RUNNING_M, you give up the current vcore (which never returns), and
@@ -761,10 +790,7 @@ void proc_yield(struct proc *SAFE p, bool being_nice)
 
        switch (p->state) {
                case (PROC_RUNNING_S):
-                       p->env_tf= *current_tf;
-                       env_push_ancillary_state(p); // TODO: (HSS)
-                       __proc_set_state(p, PROC_RUNNABLE_S);
-                       schedule_proc(p);
+                       __proc_yield_s(p, current_tf);  /* current_tf 0'd in abandon core */
                        break;
                case (PROC_RUNNING_M):
                        printd("[K] Process %d (%p) is yielding on vcore %d\n", p->pid, p,
@@ -804,6 +830,7 @@ void proc_yield(struct proc *SAFE p, bool being_nice)
        /* Clean up the core and idle.  For mgmt cores, they will ultimately call
         * manager, which will call schedule() and will repick the yielding proc. */
        abandon_core();
+       smp_idle();
 }
 
 /* If you expect to notify yourself, cleanup state and process_routine_kmsg() */
@@ -1265,7 +1292,7 @@ void __proc_kmsg_pending(struct proc *p, bool ipi_pending)
 {
        if (ipi_pending) {
                kref_put(&p->kref);
-               process_routine_kmsg();
+               process_routine_kmsg(0);
                panic("stack-killing kmsg not found in %s!!!", __FUNCTION__);
        }
 }
@@ -1293,9 +1320,10 @@ void __unmap_vcore(struct proc *p, uint32_t vcoreid)
  * process's context. */
 void abandon_core(void)
 {
-       if (current)
+       if (current) {
+               current_tf = 0;
                __abandon_core();
-       smp_idle();
+       }
 }
 
 /* Will send a TLB shootdown message to every vcore in the main address space
@@ -1313,13 +1341,24 @@ void abandon_core(void)
 void __proc_tlbshootdown(struct proc *p, uintptr_t start, uintptr_t end)
 {
        uint32_t active_vcoreid = 0;
-       /* TODO: (TLB) sanity checks and rounding on the ranges */
-       for (int i = 0; i < p->procinfo->num_vcores; i++) {
-               /* find next active vcore */
-               active_vcoreid = get_busy_vcoreid(p, active_vcoreid);
-               send_kernel_message(get_pcoreid(p, active_vcoreid), __tlbshootdown,
-                                   (void*)start, (void*)end, 0, KMSG_IMMEDIATE);
-               active_vcoreid++; /* for the next loop, skip the one we just used */
+       switch (p->state) {
+               case (PROC_RUNNING_S):
+                       tlbflush();
+                       break;
+               case (PROC_RUNNING_M):
+                       /* TODO: (TLB) sanity checks and rounding on the ranges */
+                       for (int i = 0; i < p->procinfo->num_vcores; i++) {
+                               /* find next active vcore */
+                               active_vcoreid = get_busy_vcoreid(p, active_vcoreid);
+                               send_kernel_message(get_pcoreid(p, active_vcoreid),
+                                                   __tlbshootdown, (void*)start, (void*)end,
+                                                   0, KMSG_IMMEDIATE);
+                               active_vcoreid++; /* next loop, skip the one we just used */
+                       }
+                       break;
+               default:
+                       /* will probably get this when we have the short handlers */
+                       warn("Unexpected case in %s\n", __FUNCTION__);
        }
 }
 
@@ -1433,6 +1472,7 @@ void __preempt(trapframe_t *tf, uint32_t srcid, void *a0, void *a1, void *a2)
        __seq_start_write(&vcpd->preempt_tf_valid);
        __unmap_vcore(p, vcoreid);
        abandon_core();
+       smp_idle();
 }
 
 /* Kernel message handler to clean up the core when a process is dying.
@@ -1450,6 +1490,7 @@ void __death(trapframe_t *tf, uint32_t srcid, void *SNT a0, void *SNT a1,
                __unmap_vcore(current, vcoreid);
        }
        abandon_core();
+       smp_idle();
 }
 
 /* Kernel message handler, usually sent IMMEDIATE, to shoot down virtual
@@ -1518,9 +1559,10 @@ void print_proc_info(pid_t pid)
        struct files_struct *files = &p->open_files;
        spin_lock(&files->lock);
        for (int i = 0; i < files->max_files; i++)
-               if (files->fd_array[i]) {
+               if (files->fd_array[i].fd_file) {
                        printk("\tFD: %02d, File: %08p, File name: %s\n", i,
-                              files->fd_array[i], file_name(files->fd_array[i]));
+                              files->fd_array[i].fd_file,
+                              file_name(files->fd_array[i].fd_file));
                }
        spin_unlock(&files->lock);
        /* No one cares, and it clutters the terminal */