kth: Remove irq_state from sem_.*irqsave's interface
[akaros.git] / kern / src / process.c
index d1b617d..7197e11 100644 (file)
@@ -25,6 +25,7 @@
 #include <kmalloc.h>
 #include <ros/procinfo.h>
 #include <init.h>
+#include <rcu.h>
 
 struct kmem_cache *proc_cache;
 
@@ -392,11 +393,8 @@ error_t proc_alloc(struct proc **pp, struct proc *parent, int flags)
                cv_unlock(&parent->child_wait);
        } else {
                p->ppid = 0;
-               memset(p->user.name, 0, sizeof(p->user.name));
-               if (strcmp(p->user.name, eve.name) != 0) {
-                       printk("Parentless process assigned username \"\"\n");
-                       printk("User \"\" does not have hostowner privileges\n");
-               }
+               strlcpy(p->user.name, eve.name, sizeof(p->user.name));
+               printk("Parentless process assigned username '%s'\n", p->user.name);
        }
        TAILQ_INIT(&p->children);
        cv_init(&p->child_wait);
@@ -424,14 +422,7 @@ error_t proc_alloc(struct proc **pp, struct proc *parent, int flags)
                        SYSEVENTRINGSIZE);
 
        /* Init FS structures TODO: cleanup (might pull this out) */
-       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 : 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;
-       kref_get(&p->fs_env.pwd->d_kref, 1);
+       p->umask = parent ? parent->umask : S_IWGRP | S_IWOTH;
        memset(&p->open_files, 0, sizeof(p->open_files));       /* slightly ghetto */
        spinlock_init(&p->open_files.lock);
        p->open_files.max_files = NR_OPEN_FILES_DEFAULT;
@@ -477,7 +468,7 @@ void __proc_ready(struct proc *p)
 }
 
 /* Creates a process from the specified file, argvs, and envps. */
-struct proc *proc_create(struct file *prog, char **argv, char **envp)
+struct proc *proc_create(struct file_or_chan *prog, char **argv, char **envp)
 {
        struct proc *p;
        error_t r;
@@ -522,8 +513,6 @@ static void __proc_free(struct kref *kref)
        cclose(p->dot);
        cclose(p->slash);
        p->dot = p->slash = 0; /* catch bugs */
-       kref_put(&p->fs_env.root->d_kref);
-       kref_put(&p->fs_env.pwd->d_kref);
        /* now we'll finally decref files for the file-backed vmrs */
        unmap_and_destroy_vmrs(p);
        /* Remove us from the pid_hash and give our PID back (in that order). */
@@ -588,6 +577,8 @@ 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()];
+       struct proc *old_proc;
+
        /* If the process wasn't here, then we need to load its address space. */
        if (p != pcpui->cur_proc) {
                proc_incref(p, 1);
@@ -596,9 +587,10 @@ static void __set_proc_current(struct proc *p)
                 * 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)
-                       proc_decref(pcpui->cur_proc);
+               old_proc = pcpui->cur_proc;
                pcpui->cur_proc = p;
+               if (old_proc)
+                       proc_decref(old_proc);
        }
 }
 
@@ -795,27 +787,18 @@ void __proc_startcore(struct proc *p, struct user_context *ctx)
 }
 
 /* Restarts/runs the current_ctx, which must be for the current process, on the
- * core this code executes on.  Calls an internal function to do the work.
+ * core this code executes on.
  *
- * In case there are pending routine messages, like __death, __preempt, or
- * __notify, we need to run them.  Alternatively, if there are any, we could
- * self_ipi, and run the messages immediately after popping back to userspace,
- * but that would have crappy overhead. */
+ * For now, we just smp_idle.  We used to do something similar, but customized
+ * for expecting to return to the process.  But it was a source of bugs.  If we
+ * want to optimize for the case where we know we had a process current, then we
+ * can do so here.
+ *
+ * Note that PRKM currently calls smp_idle() if it ever has a message, so the
+ * value of optimizing may depend on the semantics of PRKM. */
 void proc_restartcore(void)
 {
-       struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
-
-       assert(!pcpui->cur_kthread->sysc);
-       process_routine_kmsg();
-       /* If there is no owning process, just idle, since we don't know what to do.
-        * This could be because the process had been restarted a long time ago and
-        * has since left the core, or due to a KMSG like __preempt or __death. */
-       if (!pcpui->owning_proc) {
-               abandon_core();
-               smp_idle();
-       }
-       assert(pcpui->cur_ctx);
-       __proc_startcore(pcpui->owning_proc, pcpui->cur_ctx);
+       smp_idle();
 }
 
 /* Helper for proc_destroy.  Disowns any children. */
@@ -889,11 +872,11 @@ void proc_destroy(struct proc *p)
                        // here's how to do it manually
                        if (current == p) {
                                lcr3(boot_cr3);
-                               proc_decref(p);         /* this decref is for the cr3 */
                                current = NULL;
+                               proc_decref(p);         /* this decref is for the cr3 */
                        }
                        #endif
-                       send_kernel_message(get_pcoreid(p, 0), __death, 0, 0, 0,
+                       send_kernel_message(get_pcoreid(p, 0), __death, (long)p, 0, 0,
                                            KMSG_ROUTINE);
                        __seq_start_write(&p->procinfo->coremap_seqctr);
                        __unmap_vcore(p, 0);
@@ -1703,7 +1686,7 @@ static void __proc_revoke_core(struct proc *p, uint32_t vcoreid, bool preempt)
                atomic_or(&vcpd->flags, VC_K_LOCK);
                send_kernel_message(pcoreid, __preempt, (long)p, 0, 0, KMSG_ROUTINE);
        } else {
-               send_kernel_message(pcoreid, __death, 0, 0, 0, KMSG_ROUTINE);
+               send_kernel_message(pcoreid, __death, (long)p, 0, 0, KMSG_ROUTINE);
        }
 }
 
@@ -1820,16 +1803,21 @@ void __unmap_vcore(struct proc *p, uint32_t vcoreid)
  * Note this leaves no trace of what was running. This "leaves the process's
  * context.
  *
- * This does not clear the owning proc.  Use the other helper for that. */
-void abandon_core(void)
+ * This does not clear the owning proc.  Use the other helper for that.
+ *
+ * Returns whether or not there was a process present. */
+bool abandon_core(void)
 {
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        /* Syscalls that don't return will ultimately call abadon_core(), so we need
         * to make sure we don't think we are still working on a syscall. */
        pcpui->cur_kthread->sysc = 0;
        pcpui->cur_kthread->errbuf = 0; /* just in case */
-       if (pcpui->cur_proc)
+       if (pcpui->cur_proc) {
                __abandon_core();
+               return true;
+       }
+       return false;
 }
 
 /* Helper to clear the core's owning processor and manage refcnting.  Pass in
@@ -2294,18 +2282,24 @@ void __death(uint32_t srcid, long a0, long a1, long a2)
 {
        uint32_t vcoreid, coreid = core_id();
        struct per_cpu_info *pcpui = &per_cpu_info[coreid];
-       struct proc *p = pcpui->owning_proc;
-       if (p) {
-               vcoreid = pcpui->owning_vcoreid;
-               printd("[kernel] death on physical core %d for process %d's vcore %d\n",
-                      coreid, p->pid, vcoreid);
-               vcore_account_offline(p, vcoreid);      /* in case anyone is counting */
-               /* We won't restart the process later.  current gets cleared later when
-                * we notice there is no owning_proc and we have nothing to do
-                * (smp_idle, restartcore, etc). */
-               arch_finalize_ctx(pcpui->cur_ctx);
-               clear_owning_proc(coreid);
+       struct proc *p = (struct proc*)a0;
+
+       assert(p);
+       if (p != pcpui->owning_proc) {
+               /* Older versions of Akaros thought it was OK to have a __death hit a
+                * core that no longer had a process.  I think it's a bug now. */
+               panic("__death arrived for a process (%p) that was not owning (%p)!",
+                     p, pcpui->owning_proc);
        }
+       vcoreid = pcpui->owning_vcoreid;
+       printd("[kernel] death on physical core %d for process %d's vcore %d\n",
+              coreid, p->pid, vcoreid);
+       vcore_account_offline(p, vcoreid);      /* in case anyone is counting */
+       /* We won't restart the process later.  current gets cleared later when
+        * we notice there is no owning_proc and we have nothing to do
+        * (smp_idle, restartcore, etc). */
+       arch_finalize_ctx(pcpui->cur_ctx);
+       clear_owning_proc(coreid);
 }
 
 /* Kernel message handler, usually sent IMMEDIATE, to shoot down virtual
@@ -2394,6 +2388,7 @@ void print_proc_info(pid_t pid, int verbosity)
                return;
        }
        vcpd = &p->procdata->vcore_preempt_data[0];
+       print_lock();
        spinlock_debug(&p->proc_lock);
        //spin_lock(&p->proc_lock); // No locking!!
        printk("struct proc: %p\n", p);
@@ -2445,6 +2440,7 @@ void print_proc_info(pid_t pid, int verbosity)
        if (spin_locked(&files->lock)) {
                spinlock_debug(&files->lock);
                printk("FILE LOCK HELD, ABORTING\n");
+               print_unlock();
                proc_decref(p);
                return;
        }
@@ -2452,19 +2448,15 @@ void print_proc_info(pid_t pid, int verbosity)
        for (int i = 0; i < files->max_files; i++) {
                if (GET_BITMASK_BIT(files->open_fds->fds_bits, i)) {
                        printk("\tFD: %02d, ", i);
-                       if (files->fd[i].fd_file) {
-                               printk("File: %p, File name: %s\n", files->fd[i].fd_file,
-                                      file_name(files->fd[i].fd_file));
-                       } else {
-                               assert(files->fd[i].fd_chan);
-                               print_chaninfo(files->fd[i].fd_chan);
-                       }
+                       assert(files->fd[i].fd_chan);
+                       print_chaninfo(files->fd[i].fd_chan);
                }
        }
        spin_unlock(&files->lock);
        printk("Children: (PID (struct proc *))\n");
        TAILQ_FOREACH(child, &p->children, sibling_link)
                printk("\t%d (%p)\n", child->pid, child);
+       print_unlock();
        /* no locking / unlocking or refcnting */
        // spin_unlock(&p->proc_lock);
        proc_decref(p);