Merge branch 'master' into proc-work
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 4 Aug 2009 02:44:41 +0000 (19:44 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 4 Aug 2009 02:44:41 +0000 (19:44 -0700)
Conflicts:
kern/src/Makefrag
kern/src/manager.c

60 files changed:
GNUmakefile
kern/arch/i386/apic.c
kern/arch/i386/apic.h
kern/arch/i386/atomic.h
kern/arch/i386/cpuinfo.c
kern/arch/i386/env.c
kern/arch/i386/kdebug.c
kern/arch/i386/pmap.c
kern/arch/i386/smp.c
kern/arch/i386/smp.h
kern/arch/i386/smp_boot.c
kern/arch/i386/trap.c
kern/include/env.h
kern/include/kfs.h [new file with mode: 0644]
kern/include/monitor.h
kern/include/pmap.h
kern/include/process.h [new file with mode: 0644]
kern/include/ros/env.h [deleted file]
kern/include/ros/error.h
kern/include/ros/syscall.h
kern/include/smp.h
kern/include/syscall.h
kern/include/workqueue.h
kern/src/Makefrag
kern/src/env.c
kern/src/init.c
kern/src/kfs.c [new file with mode: 0644]
kern/src/manager.c
kern/src/monitor.c
kern/src/pmap.c
kern/src/process.c [new file with mode: 0644]
kern/src/smp.c
kern/src/syscall.c
kern/src/testing.c
kern/src/workqueue.c
user/apps/roslib/buggyhello.c
user/apps/roslib/evilhello.c
user/apps/roslib/hello.c
user/apps/roslib/measurements.c
user/apps/roslib/print_tests.c
user/apps/roslib/proctests.c
user/apps/roslib/spawn.c [new file with mode: 0644]
user/apps/roslib/testpmap.c
user/parlib/inc/channel.h
user/parlib/inc/parlib.h
user/parlib/src/channel.c
user/parlib/src/debug.c
user/parlib/src/newlib_backend.c
user/parlib/src/parlibmain.c
user/parlib/src/syscall.c
user/roslib/inc/lib.h
user/roslib/inc/measure.h
user/roslib/inc/syswrapper.h
user/roslib/src/entry_i386.S
user/roslib/src/entry_sparc.S
user/roslib/src/exit.c
user/roslib/src/libmain.c
user/roslib/src/printf.c
user/roslib/src/syscall.c
user/roslib/src/syswrapper.c

index 352b068..399da63 100644 (file)
@@ -111,9 +111,10 @@ $(OBJDIR)/.deps: $(foreach dir, $(OBJDIRS), $(wildcard $(OBJDIR)/$(dir)/*.d))
 
 # For deleting the build
 clean:
-       rm -rf $(OBJDIR)
-       rm -f kern/boot
-       rm -f kern/include/arch
+       @rm -rf $(OBJDIR)
+       @rm -f kern/boot
+       @rm -f kern/include/arch
+       @echo All clean and pretty!
 
 always:
        @:
index ee4817e..8edc67e 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
  * See LICENSE for details.
  */
 
index 1df0369..2a5863f 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
  * See LICENSE for details.
  */
 
@@ -110,6 +111,7 @@ static inline void lapic_send_eoi(void);
 static inline uint32_t lapic_get_version(void);
 static inline uint32_t lapic_get_error(void);
 static inline uint32_t lapic_get_id(void);
+static inline void lapic_set_id(uint8_t id); // Careful, may not actually work
 static inline uint8_t lapic_get_logid(void);
 static inline void lapic_set_logid(uint8_t id);
 static inline void lapic_disable(void);
@@ -156,6 +158,11 @@ static inline uint32_t lapic_get_id(void)
        return read_mmreg32(LAPIC_ID) >> 24;
 }
 
+static inline void lapic_set_id(uint8_t id)
+{
+       write_mmreg32(LAPIC_ID, id << 24);
+}
+
 static inline uint8_t lapic_get_logid(void)
 {
        return read_mmreg32(LAPIC_LOGICAL_ID) >> 24;
index 9ba650d..932887c 100644 (file)
@@ -7,33 +7,47 @@
 #define rmb() ({ asm volatile("lfence"); })
 #define wmb() 
 
-//linux style atomic ops
-typedef struct {volatile uint32_t real_num;} atomic_t;
-#define atomic_read(atom) ((atom)->real_num)
-#define atomic_set(atom, val) (((atom)->real_num) = (val))
-#define atomic_init(i) {(i)}
-//and the atomic incs, etc take an atomic_t ptr, deref inside
-
-static inline void atomic_inc(atomic_t* number);
-static inline void atomic_dec(atomic_t* number);
+typedef void* atomic_t;
+
+static inline void atomic_init(atomic_t *number, int32_t val);
+static inline int32_t atomic_read(atomic_t *number);
+static inline void atomic_set(atomic_t *number, int32_t val);
+static inline void atomic_inc(atomic_t *number);
+static inline void atomic_dec(atomic_t *number);
 static inline void atomic_andb(volatile uint8_t* number, uint8_t mask);
 static inline void spin_lock(volatile uint32_t* lock);
 static inline void spin_unlock(volatile uint32_t* lock);
 
 /* Inlined functions declared above */
+static inline void atomic_init(atomic_t *number, int32_t val)
+{
+       asm volatile("movl %1,%0" : "=m"(*number) : "r"(val));
+}
+
+static inline int32_t atomic_read(atomic_t *number)
+{
+       int32_t val;
+       asm volatile("movl %1,%0" : "=r"(val) : "m"(*number));
+       return val;
+}
+
+static inline void atomic_set(atomic_t *number, int32_t val)
+{
+       asm volatile("movl %1,%0" : "=m"(*number) : "r"(val));
+}
 
 // need to do this with pointers and deref.  %0 needs to be the memory address
-static inline void atomic_inc(atomic_tnumber)
+static inline void atomic_inc(atomic_t *number)
 {
-       asm volatile("lock incl %0" : "=m"(number->real_num) : : "cc");
+       asm volatile("lock incl %0" : "=m"(*number) : : "cc");
 }
 
-static inline void atomic_dec(atomic_tnumber)
+static inline void atomic_dec(atomic_t *number)
 {
-       asm volatile("lock decl %0" : "=m"(number->real_num) : : "cc");
+       asm volatile("lock decl %0" : "=m"(*number) : : "cc");
 }
 
-static inline void atomic_andb(uint8_t* number, uint8_t mask)
+static inline void atomic_andb(volatile uint8_t *number, uint8_t mask)
 {
        asm volatile("lock andb %1,%0" : "=m"(*number) : "r"(mask) : "cc");
 }
index 077f0fb..61f1f82 100644 (file)
@@ -1,4 +1,8 @@
-/* See COPYRIGHT for copyright information. */
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ */
 
 #ifdef __DEPUTY__
 #pragma nodeputy
@@ -14,8 +18,8 @@
 #include <kdebug.h>
 #include <string.h>
 
-void
-print_cpuinfo(void) {
+void print_cpuinfo(void)
+{
        uint32_t eax, ebx, ecx, edx;
        uint32_t model, family;
        uint64_t msr_val;
@@ -109,8 +113,7 @@ void show_mapping(uintptr_t start, size_t size)
        }
 }
 
-void
-backtrace(void)
+void backtrace(void)
 {
        uint32_t* ebp, eip;
        eipdebuginfo_t debuginfo;
index 4f4f57f..42df5a8 100644 (file)
 //
 void env_pop_tf(trapframe_t *tf)
 {
-       if(tf->tf_cs)
-       {
+       /*
+        * If the process entered the kernel via sysenter, we need to leave via
+        * sysexit.  sysenter trapframes have 0 for a CS, which is pushed in
+        * sysenter_handler.
+        */
+       if(tf->tf_cs) {
+               /*
+                * Restores the register values in the Trapframe with the 'iret'
+                * instruction.  This exits the kernel and starts executing some
+                * environment's code.  This function does not return.
+                */
                asm volatile ("movl %0,%%esp;           "
                              "popal;                   "
                              "popl %%es;               "
@@ -25,9 +34,8 @@ void env_pop_tf(trapframe_t *tf)
                              "iret                     "
                              : : "g" (tf) : "memory");
                panic("iret failed");  /* mostly to placate the compiler */
-       }
-       else
-       {
+       } else {
+               /* Return path of sysexit.  See sysenter_handler's asm for details. */
                asm volatile ("movl %0,%%esp;           "
                              "popal;                   "
                              "popl %%es;               "
index 43371f9..77ad476 100644 (file)
@@ -7,7 +7,7 @@
 #include <assert.h>
 #include <kdebug.h>
 #include <pmap.h>
-#include <env.h>
+#include <process.h>
 
 #include <ros/memlayout.h>
 
index fe1f651..df67a96 100644 (file)
@@ -449,7 +449,7 @@ vm_init(void)
        pgdir[0] = 0;
 
        // Flush the TLB for good measure, to kill the pgdir[0] mapping.
-       lcr3(boot_cr3);
+       tlb_flush_global();
 }
 
 //
index dd3cf0d..c585d02 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ */
+
 #ifdef __DEPUTY__
 #pragma nodeputy
 #endif
index 8eedef4..4f7c092 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ */
+
 #ifndef ROS_ARCH_SMP_H
 #define ROS_ARCH_SMP_H
 
index 1c27a44..20c479e 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ */
+
 #ifdef __DEPUTY__
 #pragma nodeputy
 #endif
index 498022f..c06c489 100644 (file)
@@ -12,7 +12,7 @@
 #include <pmap.h>
 #include <trap.h>
 #include <monitor.h>
-#include <env.h>
+#include <process.h>
 
 #include <syscall.h>
 
@@ -143,7 +143,7 @@ void
 void
 (IN_HANDLER print_trapframe)(trapframe_t *tf)
 {
-       cprintf("TRAP frame at %p on core %d\n", tf, lapic_get_id());
+       cprintf("TRAP frame at %p on core %d\n", tf, core_id());
        print_regs(&tf->tf_regs);
        cprintf("  es   0x----%04x\n", tf->tf_es);
        cprintf("  ds   0x----%04x\n", tf->tf_ds);
@@ -159,8 +159,6 @@ void
 static void
 (IN_HANDLER trap_dispatch)(trapframe_t *tf)
 {
-       env_t* curenv = curenvs[core_id()];
-
        // Handle processor exceptions.
        switch(tf->tf_trapno) {
                case T_BRKPT:
@@ -175,10 +173,10 @@ static void
                        // check for userspace, for now
                        assert(tf->tf_cs != GD_KT);
                        tf->tf_regs.reg_eax =
-                               syscall(curenv, tf->tf_regs.reg_eax, tf->tf_regs.reg_edx,
+                               syscall(current, tf->tf_regs.reg_eax, tf->tf_regs.reg_edx,
                                        tf->tf_regs.reg_ecx, tf->tf_regs.reg_ebx,
                                        tf->tf_regs.reg_edi, tf->tf_regs.reg_esi);
-                       env_run(curenv);
+                       proc_startcore(current, tf); // Note the comment in syscall.c
                        break;
                default:
                        // Unexpected trap: The user process or the kernel has a bug.
@@ -187,7 +185,7 @@ static void
                                panic("Damn Damn!  Unhandled trap in the kernel!");
                        else {
                                warn("Unexpected trap from userspace");
-                               env_destroy(curenv);
+                               env_destroy(current);
                                return;
                        }
        }
@@ -211,9 +209,7 @@ void
 {
        //cprintf("Incoming TRAP frame at %p\n", tf);
 
-       env_t* curenv = curenvs[lapic_get_id()];
-
-       env_push_ancillary_state(curenv);
+       env_push_ancillary_state(current);
 
        if ((tf->tf_cs & ~3) != GD_UT && (tf->tf_cs & ~3) != GD_KT) {
                print_trapframe(tf);
@@ -224,12 +220,12 @@ void
                // Trapped from user mode.
                // TODO: this will change when an env has more than one context
                // Copy trap frame (which is currently on the stack)
-               // into 'curenv->env_tf', so that running the environment
+               // into 'current->env_tf', so that running the environment
                // will restart at the trap point.
-               assert(curenv);
-               curenv->env_tf = *tf;
+               assert(current);
+               current->env_tf = *tf;
                // The trapframe on the stack should be ignored from here on.
-               tf = &curenv->env_tf;
+               tf = &current->env_tf;
        }
 
        // Dispatch based on what type of trap occurred
@@ -238,16 +234,15 @@ void
        // should this be if == 3?  Sort out later when we handle traps.
        // so far we never get here
        assert(0);
-        // Return to the current environment, which should be runnable.
-        assert(curenv && curenv->env_status == ENV_RUNNABLE);
-        env_run(curenv);
+       // Return to the current environment, which should be runnable.
+       proc_startcore(current, tf); // Note the comment in syscall.c
 }
 
 void
 (IN_HANDLER irq_handler)(trapframe_t *tf)
 {
-       //if (lapic_get_id())
-       //      cprintf("Incoming IRQ, ISR: %d on core %d\n", tf->tf_trapno, lapic_get_id());
+       //if (core_id())
+       //      cprintf("Incoming IRQ, ISR: %d on core %d\n", tf->tf_trapno, core_id());
        // merge this with alltraps?  other than the EOI... or do the same in all traps
 
        extern handler_wrapper_t handler_wrappers[NUM_HANDLER_WRAPPERS];
@@ -302,7 +297,7 @@ page_fault_handler(trapframe_t *tf)
 
        // Call the environment's page fault upcall, if one exists.  Set up a
        // page fault stack frame on the user exception stack (below
-       // UXSTACKTOP), then branch to curenv->env_pgfault_upcall.
+       // UXSTACKTOP), then branch to current->env_pgfault_upcall.
        //
        // The page fault upcall might cause another page fault, in which case
        // we branch to the page fault upcall recursively, pushing another
@@ -322,17 +317,16 @@ page_fault_handler(trapframe_t *tf)
        //
        // Hints:
        //   user_mem_assert() and env_run() are useful here.
-       //   To change what the user environment runs, modify 'curenv->env_tf'
-       //   (the 'tf' variable points at 'curenv->env_tf').
+       //   To change what the user environment runs, modify 'current->env_tf'
+       //   (the 'tf' variable points at 'current->env_tf').
 
        // LAB 4: Your code here.
 
        // Destroy the environment that caused the fault.
-       env_t* curenv = curenvs[lapic_get_id()];
        cprintf("[%08x] user fault va %08x ip %08x from core %d\n",
-               curenv->env_id, fault_va, tf->tf_eip, lapic_get_id());
+               current->env_id, fault_va, tf->tf_eip, core_id());
        print_trapframe(tf);
-       env_destroy(curenv);
+       env_destroy(current);
 }
 
 void sysenter_init(void)
@@ -345,17 +339,22 @@ void sysenter_init(void)
 /* This is called from sysenter's asm, with the tf on the kernel stack. */
 void sysenter_callwrapper(struct Trapframe *tf)
 {
-       env_t* curenv = curenvs[lapic_get_id()];
-       curenv->env_tf = *tf;
+       current->env_tf = *tf;
        
        // The trapframe on the stack should be ignored from here on.
-       tf = &curenv->env_tf;
-       tf->tf_regs.reg_eax = (intreg_t) syscall(curenv,
+       tf = &current->env_tf;
+       tf->tf_regs.reg_eax = (intreg_t) syscall(current,
                                                 tf->tf_regs.reg_eax,
                                                 tf->tf_regs.reg_edx,
                                                 tf->tf_regs.reg_ecx,
                                                 tf->tf_regs.reg_ebx,
                                                 tf->tf_regs.reg_edi,
                                                 0);
-       env_run(curenv);
+       /*
+        * careful here - we need to make sure that this current is the right
+        * process, which could be weird if the syscall blocked.  it would need to
+        * restore the proper value in current before returning to here.
+        * likewise, tf could be pointing to random gibberish.
+        */
+       proc_startcore(current, tf);
 }
index da6a102..54ebf75 100644 (file)
@@ -2,10 +2,81 @@
 
 #ifndef ROS_KERN_ENV_H
 #define ROS_KERN_ENV_H
+/* Note that the old include/ros/env.h is merged into this file */
 
-#include <ros/env.h>
+#include <ros/memlayout.h>
+#include <ros/syscall.h>
+#include <ros/sysevent.h>
 #include <ros/error.h>
+#include <arch/trap.h>
+#include <arch/types.h>
 #include <arch/arch.h>
+#include <sys/queue.h>
+
+struct Env;
+typedef struct Env env_t;
+
+typedef int32_t envid_t;
+
+// An environment ID 'envid_t' has three parts:
+//
+// +1+---------------21-----------------+--------10--------+
+// |0|          Uniqueifier             |   Environment    |
+// | |                                  |      Index       |
+// +------------------------------------+------------------+
+//                                       \--- ENVX(eid) --/
+//
+// The environment index ENVX(eid) equals the environment's offset in the
+// 'envs[]' array.  The uniqueifier distinguishes environments that were
+// created at different times, but share the same environment index.
+//
+// All real environments are greater than 0 (so the sign bit is zero).
+// envid_ts less than 0 signify errors.  The envid_t == 0 is special, and
+// stands for the current environment.
+
+#define LOG2NENV               10
+#define NENV                   (1 << LOG2NENV)
+#define ENVX(envid)            ((envid) & (NENV - 1))
+
+// TODO: clean this up.
+struct Env {
+       LIST_ENTRY(Env) env_link NOINIT;        // Free list link pointers
+       uint32_t lock;
+       trapframe_t env_tf                                              // Saved registers
+         __attribute__((aligned (8)));                 // for sparc --asw
+       ancillary_state_t env_ancillary_state   // State saved when descheduled
+         __attribute__((aligned (8)));                 // for sparc --asw
+       envid_t env_id;                         // Unique environment identifier
+       envid_t env_parent_id;          // env_id of this env's parent
+       uint32_t state;                         // Status of the process
+       uint32_t env_runs;                      // Number of times environment has run
+       uint32_t env_refcnt;            // Reference count of kernel contexts using this
+       uint32_t env_flags;
+       // The backring for processing asynchronous system calls from the user
+       // Note this is the actual backring, not a pointer to it somewhere else
+       syscall_back_ring_t env_syscallbackring;
+       // The front ring for pushing asynchronous system events out to the user
+       // Note this is the actual frontring, not a pointer to it somewhere else
+       sysevent_front_ring_t env_syseventfrontring;
+
+       // Address space
+       pde_t *COUNT(NPDENTRIES) env_pgdir;                     // Kernel virtual address of page dir
+       physaddr_t env_cr3;                     // Physical address of page dir
+
+       // TODO - give this a proper type (pointers to a struct)
+       // - not always going to be PGSIZE either!
+       void*COUNT(PGSIZE) env_procinfo;                // KVA of per-process shared info table (RO)
+       // TODO - do we really want to get rid of procdata?
+       //void*COUNT(PGSIZE) env_procdata;              // KVA of per-process shared data table (RW)
+       
+       // Do we need these and the above back/front rings?
+       // Ring buffers for communicating with user space
+       syscall_sring_t*SAFE env_syscallring;   // Per-process ring buffer for async syscalls
+       sysevent_sring_t*SAFE env_syseventring; // Per-process ring buffer for async sysevents
+};
+
+/* Process Flags */
+// None yet
 
 extern env_t *COUNT(NENV) envs;                // All environments
 extern atomic_t num_envs;              // Number of envs
@@ -15,11 +86,11 @@ LIST_HEAD(env_list, Env);           // Declares 'struct env_list'
 typedef struct env_list env_list_t;
 
 void   env_init(void);
+int            env_alloc(env_t *SAFE*SAFE e, envid_t parent_id);
 void   env_init_trapframe(env_t* e);
 void   env_set_program_counter(env_t* e, uintptr_t pc);
 void   env_push_ancillary_state(env_t* e);
 void   env_pop_ancillary_state(env_t* e);
-int    env_alloc(env_t **e, envid_t parent_id);
 void   env_free(env_t *SAFE e);
 void   env_user_mem_free(env_t* e);
 error_t        env_incref(env_t* e);
@@ -29,6 +100,12 @@ void        (IN_HANDLER env_destroy)(env_t *SAFE e);        // Does not return if e == curenv
 // Temporary scheduler function
 void   schedule(void);
 
+/*
+ * Allows the kernel to figure out what process is running on its core.
+ * Can be used just like a pointer to a struct process.
+ */
+#define current (curenvs[core_id()])
+
 int    envid2env(envid_t envid, env_t **env_store, bool checkperm);
 // The following three functions do not return
 void   (IN_HANDLER env_run)(env_t *e) __attribute__((noreturn));
@@ -38,11 +115,14 @@ void       env_pop_tf(trapframe_t *tf) __attribute__((noreturn));
 /* Helper handler for smp_call to dispatch jobs to other cores */
 void run_env_handler(trapframe_t *tf, void* data);
 
+// TODO remove this legacy crap
 #define ENV_CREATE(x)                  ({                                             \
        extern uint8_t _binary_obj_user_apps_##x##_start[],                        \
                _binary_obj_user_apps_##x##_size[];                                    \
-       env_create(_binary_obj_user_apps_##x##_start,                              \
+       env_t *e = env_create(_binary_obj_user_apps_##x##_start,                   \
                (int)_binary_obj_user_apps_##x##_size);                                \
+       proc_set_state(e, PROC_RUNNABLE_S);                                        \
+       e;                                                                         \
 })
 
 #endif // !ROS_KERN_ENV_H
diff --git a/kern/include/kfs.h b/kern/include/kfs.h
new file mode 100644 (file)
index 0000000..60fadc1
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * KFS (Kernel File System)
+ *
+ * This gives runtime access to the binary blobs (usually userspace programs)
+ * linked at the end of the kernel.  Extremely rudimentary.
+ * Also allows for process creation from file (can consider moving this).
+ *
+ * Add the files you want in KFS in kfs.c.
+ */
+
+#ifndef ROS_KERN_KFS_H
+#define ROS_KERN_KFS_H
+
+#include <arch/types.h>
+#include <process.h>
+
+#pragma nodeputy
+
+struct kfs_entry {
+       char name[256];
+       uint8_t *start;
+       size_t size;
+};
+
+#define MAX_KFS_FILES 10
+extern struct kfs_entry kfs[MAX_KFS_FILES];
+
+ssize_t kfs_lookup_path(char* path);
+struct proc *kfs_proc_create(int kfs_inode);
+
+#endif // !ROS_KERN_KFS_H
index 7fb653c..114e56f 100644 (file)
@@ -18,6 +18,8 @@ int mon_showmapping(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_setmapperm(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_cpuinfo(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_nanwan(int argc, char **argv, trapframe_t *tf);
+int mon_kfs_ls(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
+int mon_kfs_run(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_manager(int argc, char **argv, trapframe_t *tf);
 
 #endif // !ROS_KERN_MONITOR_H
index e3b56a5..2248621 100644 (file)
@@ -9,7 +9,7 @@
 #include <ros/memlayout.h>
 #include <multiboot.h>
 #include <atomic.h>
-#include <env.h>
+#include <process.h>
 #include <assert.h>
 #include <sys/queue.h>
 
diff --git a/kern/include/process.h b/kern/include/process.h
new file mode 100644 (file)
index 0000000..4975a15
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * All things processes!  As we move away from the old envs to processes,
+ * we'll move things into here that are designed for multicore processes.
+ */
+
+#ifndef ROS_KERN_PROCESS_H
+#define ROS_KERN_PROCESS_H
+
+#include <arch/types.h>
+
+/* Process States.  Not 100% on the names yet. */
+#define PROC_CREATED                   0x01
+#define PROC_RUNNABLE_S                        0x02
+#define PROC_RUNNING_S                 0x04
+#define PROC_WAITING                   0x08  // can split out to INT and UINT
+#define PROC_DYING                             0x10
+#define PROC_RUNNABLE_M                        0x20 // ready, needs all of its resources (cores)
+#define PROC_RUNNING_M                 0x40 // running, manycore style
+// TODO don't use this shit for process allocation flagging
+#define ENV_FREE                               0x80
+
+#include <env.h>
+
+// Till we remove the old struct Env
+#define proc Env
+
+int proc_set_state(struct proc *p, uint32_t state) WRITES(p->state);
+struct proc *get_proc(unsigned pid);
+bool proc_controls(struct proc *actor, struct proc *target);
+void proc_startcore(struct proc *p, trapframe_t *tf) __attribute__((noreturn));
+
+#endif // !ROS_KERN_PROCESS_H
diff --git a/kern/include/ros/env.h b/kern/include/ros/env.h
deleted file mode 100644 (file)
index f893632..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/* See COPYRIGHT for copyright information. */
-
-#ifndef ROS_INC_ENV_H
-#define ROS_INC_ENV_H
-
-#include <ros/memlayout.h>
-#include <ros/syscall.h>
-#include <ros/sysevent.h>
-#include <arch/types.h>
-#include <sys/queue.h>
-#include <arch/trap.h>
-
-struct Env;
-typedef struct Env env_t;
-
-typedef int32_t envid_t;
-
-// An environment ID 'envid_t' has three parts:
-//
-// +1+---------------21-----------------+--------10--------+
-// |0|          Uniqueifier             |   Environment    |
-// | |                                  |      Index       |
-// +------------------------------------+------------------+
-//                                       \--- ENVX(eid) --/
-//
-// The environment index ENVX(eid) equals the environment's offset in the
-// 'envs[]' array.  The uniqueifier distinguishes environments that were
-// created at different times, but share the same environment index.
-//
-// All real environments are greater than 0 (so the sign bit is zero).
-// envid_ts less than 0 signify errors.  The envid_t == 0 is special, and
-// stands for the current environment.
-
-#define LOG2NENV               10
-#define NENV                   (1 << LOG2NENV)
-#define ENVX(envid)            ((envid) & (NENV - 1))
-
-// Values of env_status in struct Env
-#define ENV_FREE                       0
-#define ENV_RUNNING                    1
-#define ENV_RUNNABLE           2
-#define ENV_NOT_RUNNABLE       3
-#define ENV_DYING                      4
-
-struct Env {
-       LIST_ENTRY(Env) env_link NOINIT;        // Free list link pointers
-       uint32_t lock;
-       trapframe_t env_tf                      // Saved registers
-         __attribute__((aligned (8)));         // for sparc --asw
-       ancillary_state_t env_ancillary_state   // State saved when descheduled
-         __attribute__((aligned (8)));         // for sparc --asw
-       envid_t env_id;                         // Unique environment identifier
-       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
-       uint32_t env_refcnt;            // Reference count of kernel contexts using this
-       uint32_t env_flags;
-       
-       // The backring for processing asynchronous system calls from the user
-       // Note this is the actual backring, not a pointer to it somewhere else
-       syscall_back_ring_t env_syscallbackring;
-       
-       // The front ring for pushing asynchronous system events out to the user
-       // Note this is the actual frontring, not a pointer to it somewhere else
-       sysevent_front_ring_t env_syseventfrontring;
-
-       // Address space
-       pde_t *COUNT(NPDENTRIES) env_pgdir;  // Kernel virtual address of page dir
-       physaddr_t env_cr3;                              // Physical address of page dir
-       
-       // TODO - give this a proper type (pointers to a struct)
-       // TODO - not always going to be PGSIZE either!
-       void*COUNT(PGSIZE) env_procinfo;                // KVA of per-process shared info table (RO)
-       
-       // Ring buffers for communicating with user space
-       syscall_sring_t*SAFE env_syscallring;   // Per-process ring buffer for async syscalls
-       sysevent_sring_t*SAFE env_syseventring; // Per-process ring buffer for async sysevents
-       
-       // Eventually want to move this to a per-system shared-info page
-       uint64_t env_tscfreq;           // Frequency of the TSC for measurements
-};
-
-/* Process Flags */
-// None yet
-
-#endif // !ROS_INC_ENV_H
index ed0ec3a..6c34999 100644 (file)
@@ -17,6 +17,7 @@ typedef enum {
        EBADENV,                 // Bad environment 
        ENOFREEENV,              // No free environment
        EUNSPECIFIED,            // Unspecified
+       EMORON,                  // Moron
        NUMERRORS,               // Total number of error codes
 } error_t;
 
@@ -35,11 +36,12 @@ static const char * const error_string[NUMERRORS] =
        "Would cause deadlock",
        "Currently busy, try again later",
        "No memory available",
-       "Invalid arguments"
-       "Segmentation fault"
-       "Bad environment"
-       "No free environment"
-       "Unspecified"
+       "Invalid arguments",
+       "Segmentation fault",
+       "Bad environment",
+       "No free environment",
+       "You are a moron",
+       "Unspecified",
 };
 
 #endif // !ROS_INC_ERROR_H */
index 128ff43..b0696cd 100644 (file)
@@ -17,10 +17,10 @@ enum
        SYS_getcpuid,
        SYS_serial_write,
        SYS_serial_read,
+       SYS_getpid,
+       SYS_proc_destroy,
        SYS_shared_page_alloc,
        SYS_shared_page_free,
-       SYS_getenvid,
-       SYS_env_destroy,
        SYS_yield,
        SYS_proc_create,
        SYS_proc_run,
index 975693b..d8c1fb0 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ */
+
 #ifndef ROS_INC_SMP_H
 #define ROS_INC_SMP_H
 
 #include <atomic.h>
 #include <workqueue.h>
 
-#ifdef __BOCHS__
-#define SMP_CALL_FUNCTION_TIMEOUT    0x00ffffff
-#define SMP_BOOT_TIMEOUT             0x0000ffff
-#else
-#define SMP_CALL_FUNCTION_TIMEOUT    0x7ffffff0
-#define SMP_BOOT_TIMEOUT             0x002fffff
-#endif
-
-typedef struct per_cpu_info {
+// will want this padded out to cacheline alignment
+struct per_cpu_info {
        uint32_t lock;
-       // Once we have a real kmalloc, we can make this dynamic.  Want a queue.
-       work_t delayed_work;
-       // will want it padded out to an even cacheline
-} per_cpu_info_t;
-
-extern per_cpu_info_t per_cpu_info[MAX_NUM_CPUS];
+       struct workqueue workqueue;
+};
+extern struct per_cpu_info  per_cpu_info[MAX_NUM_CPUS];
 extern volatile uint8_t num_cpus;
 
 /* SMP bootup functions */
index 3b8240b..5677a99 100644 (file)
@@ -5,7 +5,7 @@
 #endif
 
 #include <ros/syscall.h>
-#include <env.h>
+#include <process.h>
 
 int32_t (SYNCHRONOUS syscall)(env_t* e, uint32_t num, uint32_t a1, uint32_t a2,
                               uint32_t a3, uint32_t a4, uint32_t a5);
index c06d39c..ba7dc15 100644 (file)
@@ -1,21 +1,34 @@
 /*
  * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
  * See LICENSE for details.
+ *
+ * Workqueue: This is a todo list of func, void* that get executed whenever
+ * process_workqueue is called.  Typically, this is called from smp_idle().
+ * Note that every core will run this, so be careful with dynamic memory mgmt.
  */
 
 #ifndef ROS_KERN_WORKQUEUE_H
 #define ROS_KERN_WORKQUEUE_H
-#ifndef ROS_KERNEL
-# error "This is an ROS kernel header; user programs should not #include it"
-#endif
 
-// Once we have a real kmalloc, we can make this dynamic.  Want a list.
-typedef void (*func_t)(void* data);
-typedef struct work {
+#include <sys/queue.h>
+#include <arch/types.h>
+
+typedef void (*func_t)(void *data);
+struct work {
+       LIST_ENTRY(work) work_link;
        func_t func;
-       void* data;
-} work_t;
+       void *data;
+};
+
+// TODO make these dynamic and hold more than 1.  might want better list macros.
+#define WORKQUEUE_ELEMENTS 1
+struct workqueue {
+       struct work statics[WORKQUEUE_ELEMENTS];
+};
 
 void process_workqueue(void);
+// For now, the caller should free their struct work after this call
+int enqueue_work(struct workqueue *queue, struct work *job);
 
 #endif /* ROS_KERN_WORKQUEUE_H */
index 87e1654..724d6bf 100644 (file)
@@ -27,6 +27,8 @@ KERN_SRCFILES := $(KERN_ARCH_SRCFILES) \
                  $(KERN_SRC_DIR)/manager.c \
                  $(KERN_SRC_DIR)/syscall.c \
                  $(KERN_SRC_DIR)/timer.c \
+                 $(KERN_SRC_DIR)/kfs.c \
+                 $(KERN_SRC_DIR)/process.c \
                  $(KERN_SRC_DIR)/kmalloc.c \
                  $(KERN_SRC_DIR)/testing.c
 
@@ -34,19 +36,20 @@ KERN_SRCFILES := $(KERN_ARCH_SRCFILES) \
 KERN_SRCFILES := $(wildcard $(KERN_SRCFILES))
 
 KERN_APPFILES := \
-                    $(USER_APPS_ROSLIB_DIR)/proctests \
-                    $(USER_APPS_ROSLIB_DIR)/fptest \
-                    $(USER_APPS_ROSLIB_DIR)/null \
-                    $(USER_APPS_ROSLIB_DIR)/hello
+                 $(USER_APPS_ROSLIB_DIR)/proctests \
+                 $(USER_APPS_ROSLIB_DIR)/fptest \
+                 $(USER_APPS_ROSLIB_DIR)/null \
+                 $(USER_APPS_ROSLIB_DIR)/spawn \
+                 $(USER_APPS_ROSLIB_DIR)/hello
 
 ifeq ($(TARGET_ARCH),i386)
        KERN_APPFILES += \
-                           $(USER_APPS_PARLIB_DIR)/channel_test_client \
-                           $(USER_APPS_PARLIB_DIR)/channel_test_server \
-                           $(USER_APPS_ROSLIB_DIR)/measurements
-       #                    $(USER_APPS_PARLIB_DIR)/draw_nanwan
-       #                    $(USER_APPS_PARLIB_DIR)/open_read \
-       #                    $(USER_APPS_PARLIB_DIR)/hello
+                        $(USER_APPS_PARLIB_DIR)/channel_test_client \
+                        $(USER_APPS_PARLIB_DIR)/channel_test_server \
+                        $(USER_APPS_ROSLIB_DIR)/measurements
+#                       $(USER_APPS_PARLIB_DIR)/draw_nanwan \
+#                       $(USER_APPS_PARLIB_DIR)/open_read \
+#                       $(USER_APPS_PARLIB_DIR)/hello
 endif
 
 KERN_LDFLAGS   := $(KERN_LDFLAGS) -L$(OBJDIR)/$(KERN_DIR) \
@@ -79,7 +82,6 @@ $(OBJDIR)/$(KERN_DIR)/%.o: $(KERN_DIR)/%.S
        $(V)$(CC) $(KERN_CFLAGS) -c -o $@ $<
 
 $(OBJDIR)/$(KERN_DIR)/kernel: $(KERN_LDDEPENDS)
-       echo $(KERN_SRCFILES)
        @echo + ld [KERN] $@
        $(V)$(LD) -o $@ $(KERN_LDFLAGS) $(KERN_OBJFILES) $(KERN_LDLIBS) \
                        $(KERN_GCC_LIB) -b binary $(KERN_APPFILES)
index 1705425..fa5fd05 100644 (file)
@@ -12,7 +12,7 @@
 #include <atomic.h>
 #include <string.h>
 #include <assert.h>
-#include <env.h>
+#include <process.h>
 #include <pmap.h>
 #include <trap.h>
 #include <monitor.h>
@@ -22,7 +22,7 @@
 #include <ros/error.h>
 
 env_t *envs = NULL;            // All environments
-atomic_t num_envs = atomic_init(0);
+atomic_t num_envs;
 // TODO: make this a struct of info including the pointer and cacheline-align it
 // This lets the kernel know what process is running on the core it traps into.
 // A lot of the Env business, including this and its usage, will change when we
@@ -44,11 +44,10 @@ int
 envid2env(envid_t envid, env_t **env_store, bool checkperm)
 {
        env_t *e;
-       env_t* curenv = curenvs[core_id()];
 
        // If envid is zero, return the current environment.
        if (envid == 0) {
-               *env_store = curenv;
+               *env_store = current;
                return 0;
        }
 
@@ -58,7 +57,7 @@ envid2env(envid_t envid, env_t **env_store, bool checkperm)
        // (i.e., does not refer to a _previous_ environment
        // that used the same slot in the envs[] array).
        e = &envs[ENVX(envid)];
-       if (e->env_status == ENV_FREE || e->env_id != envid) {
+       if (e->state == ENV_FREE || e->env_id != envid) {
                *env_store = 0;
                return -EBADENV;
        }
@@ -68,7 +67,8 @@ envid2env(envid_t envid, env_t **env_store, bool checkperm)
        // If checkperm is set, the specified environment
        // must be either the current environment
        // or an immediate child of the current environment.
-       if (checkperm && e != curenv && e->env_parent_id != curenv->env_id) {
+       // TODO: should check for current being null
+       if (checkperm && e != current && e->env_parent_id != current->env_id) {
                *env_store = 0;
                return -EBADENV;
        }
@@ -82,16 +82,19 @@ envid2env(envid_t envid, env_t **env_store, bool checkperm)
 // and insert them into the env_free_list.
 // Insert in reverse order, so that the first call to env_alloc()
 // returns envs[0].
+// TODO: get rid of this whole array bullshit
 //
 void
 env_init(void)
 {
        int i;
+
+       atomic_init(&num_envs, 0);
        LIST_INIT(&env_free_list);
        assert(envs != NULL);
        for (i = NENV-1; i >= 0; i--) { TRUSTEDBLOCK // asw ivy workaround
                // these should already be set from when i memset'd the array to 0
-               envs[i].env_status = ENV_FREE;
+               envs[i].state = ENV_FREE;
                envs[i].env_id = 0;
                LIST_INSERT_HEAD(&env_free_list, &envs[i], env_link);
        }
@@ -184,6 +187,9 @@ WRITES(e->env_pgdir, e->env_cr3, e->env_procinfo, e->env_syscallring,
 
        // should be able to do this so long as boot_pgdir never has
        // anything put below UTOP
+       // TODO check on this!  had a nasty bug because of it
+       // this is a bit wonky, since if it's not PGSIZE, lots of other things are
+       // screwed up...
        memcpy(e->env_pgdir, boot_pgdir, NPDENTRIES*sizeof(pde_t));
 
        // something like this.  TODO, if you want
@@ -257,8 +263,6 @@ env_alloc(env_t **newenv_store, envid_t parent_id)
        if (!(e = LIST_FIRST(&env_free_list)))
                return -ENOFREEENV;
        
-       //memset((void*)e + sizeof(e->env_link), 0, sizeof(*e) - sizeof(e->env_link));
-
     { INITSTRUCT(*e)
 
        // Allocate and set up the page directory for this environment.
@@ -274,13 +278,13 @@ env_alloc(env_t **newenv_store, envid_t parent_id)
        // Set the basic status variables.
     e->lock = 0;
        e->env_parent_id = parent_id;
-       e->env_status = ENV_RUNNABLE;
+       proc_set_state(e, PROC_CREATED);
        e->env_runs = 0;
        e->env_refcnt = 1;
        e->env_flags = 0;
 
-       memset(&e->env_ancillary_state,0,sizeof(e->env_ancillary_state));
-       memset(&e->env_tf,0,sizeof(e->env_tf));
+       memset(&e->env_ancillary_state, 0, sizeof(e->env_ancillary_state));
+       memset(&e->env_tf, 0, sizeof(e->env_tf));
        env_init_trapframe(e);
 
        // commit the allocation
@@ -288,16 +292,7 @@ env_alloc(env_t **newenv_store, envid_t parent_id)
        *newenv_store = e;
        atomic_inc(&num_envs);
 
-       e->env_tscfreq = system_timing.tsc_freq;
-       // TODO: for now, the only info at procinfo is this env's struct
-       // note that we need to copy this over every time we make a change to env
-       // that we want userspace to see.  also note that we don't even want to
-       // show them all of env, only specific things like PID, PPID, etc
-       memcpy(e->env_procinfo, e, sizeof(env_t));
-
-       env_t* curenv = curenvs[core_id()];
-
-       printk("[%08x] new env %08x\n", curenv ? curenv->env_id : 0, e->env_id);
+       printk("[%08x] new env %08x\n", current ? current->env_id : 0, e->env_id);
        } // INIT_STRUCT
        return 0;
 }
@@ -346,8 +341,6 @@ segment_alloc(env_t *e, void *SNT va, size_t len)
 //
 // Set up the initial program binary, stack, and processor flags
 // for a user process.
-// This function is ONLY called during kernel initialization,
-// before running the first user-mode environment.
 //
 // This function loads all loadable segments from the ELF binary image
 // into the environment's user memory, starting at the appropriate
@@ -356,51 +349,14 @@ segment_alloc(env_t *e, void *SNT va, size_t len)
 // that are marked in the program header as being mapped
 // but not actually present in the ELF file - i.e., the program's bss section.
 //
-// All this is very similar to what our boot loader does, except the boot
-// loader also needs to read the code from disk.  Take a look at
-// boot/main.c to get ideas.
-//
 // Finally, this function maps one page for the program's initial stack.
-//
-// load_icode panics if it encounters problems.
-//  - How might load_icode fail?  What might be wrong with the given input?
-//
 static void
-load_icode(env_t *e, uint8_t *COUNT(size) binary, size_t size)
+load_icode(env_t *SAFE e, uint8_t *COUNT(size) binary, size_t size)
 {
-       // Hints:
-       //  Load each program segment into virtual memory
-       //  at the address specified in the ELF section header.
-       //  You should only load segments with ph->p_type == ELF_PROG_LOAD.
-       //  Each segment's virtual address can be found in ph->p_va
-       //  and its size in memory can be found in ph->p_memsz.
-       //  The ph->p_filesz bytes from the ELF binary, starting at
-       //  'binary + ph->p_offset', should be copied to virtual address
-       //  ph->p_va.  Any remaining memory bytes should be cleared to zero.
-       //  (The ELF header should have ph->p_filesz <= ph->p_memsz.)
-       //  Use functions from the previous lab to allocate and map pages.
-       //
-       //  All page protection bits should be user read/write for now.
-       //  ELF segments are not necessarily page-aligned, but you can
-       //  assume for this function that no two segments will touch
-       //  the same virtual page.
-       //
-       //  You may find a function like segment_alloc useful.
-       //
-       //  Loading the segments is much simpler if you can move data
-       //  directly into the virtual addresses stored in the ELF binary.
-       //  So which page directory should be in force during
-       //  this function?
-       //
-       // Hint:
-       //  You must also do something with the program's entry point,
-       //  to make sure that the environment starts executing there.
-       //  What?  (See env_run() and env_pop_tf() below.)
-
        // asw: copy the headers because they might not be aligned.
        elf_t elfhdr;
        proghdr_t phdr;
-       memcpy(&elfhdr,binary,sizeof(elfhdr));
+       memcpy(&elfhdr, binary, sizeof(elfhdr));
 
        int i, r;
 
@@ -411,15 +367,26 @@ load_icode(env_t *e, uint8_t *COUNT(size) binary, size_t size)
 
        // to actually access any pages alloc'd for this environment, we
        // need to have the hardware use this environment's page tables.
-       // we can use e's tables as long as we want, since it has the same
-       // mappings for the kernel as does boot_pgdir
+       uintreg_t old_cr3 = rcr3();
+       /*
+        * Even though we'll decref later and no one should be killing us at this
+        * stage, we're still going to wrap the lcr3s with incref/decref.
+        *
+        * Note we never decref on the old_cr3, since we aren't willing to let it
+        * die.  It's also not clear who the previous process is - sometimes it
+        * isn't even a process (when the kernel loads on its own, and not in
+        * response to a syscall).  Probably need to think more about this (TODO)
+        *
+        * This can get a bit tricky if this code blocks (will need to think about a
+        * decref then), if we try to change states, etc.
+        */
+       env_incref(e);
        lcr3(e->env_cr3);
 
        // TODO: how do we do a runtime COUNT?
-       {TRUSTEDBLOCK
+       {TRUSTEDBLOCK // zra: TRUSTEDBLOCK until validation is done.
        for (i = 0; i < elfhdr.e_phnum; i++) {
-               memcpy(&phdr,binary+elfhdr.e_phoff+i*sizeof(phdr),sizeof(phdr));
-        // zra: TRUSTEDBLOCK until validation is done.
+               memcpy(&phdr, binary + elfhdr.e_phoff + i*sizeof(phdr), sizeof(phdr));
                if (phdr.p_type != ELF_PROG_LOAD)
                        continue;
         // TODO: validate elf header fields!
@@ -430,12 +397,15 @@ load_icode(env_t *e, uint8_t *COUNT(size) binary, size_t size)
                memset((void*)phdr.p_va + phdr.p_filesz, 0, phdr.p_memsz - phdr.p_filesz);
        }}
 
-       env_set_program_counter(e,elfhdr.e_entry);
+       env_set_program_counter(e, elfhdr.e_entry);
 
        // Now map one page for the program's initial stack
        // at virtual address USTACKTOP - PGSIZE.
-
        segment_alloc(e, (void*SNT)(USTACKTOP - PGSIZE), PGSIZE);
+
+       // reload the original address space
+       lcr3(old_cr3);
+       env_decref(e);
 }
 
 //
@@ -445,8 +415,10 @@ env_t* env_create(uint8_t *binary, size_t size)
 {
        env_t *e;
        int r;
-
-       if ((r = env_alloc(&e, 0)) < 0)
+       envid_t curid;
+       
+       curid = (current ? current->env_id : 0);        
+       if ((r = env_alloc(&e, curid)) < 0)
                panic("env_create: %e", r);
        load_icode(e, binary, size);
        return e;
@@ -461,16 +433,13 @@ env_free(env_t *e)
        physaddr_t pa;
 
        // Note the environment's demise.
-       env_t* curenv = curenvs[core_id()];
-       cprintf("[%08x] free env %08x\n", curenv ? curenv->env_id : 0, e->env_id);
+       printk("[%08x] free env %08x\n", current ? current->env_id : 0, e->env_id);
+       // All parts of the kernel should have decref'd before env_free was called. 
+       assert(e->env_refcnt == 0);
 
        // Flush all mapped pages in the user portion of the address space
        env_user_mem_free(e);
 
-       // Moved to page_decref
-       // need a known good pgdir before releasing the old one
-       //lcr3(PADDR(boot_pgdir));
-
        // free the page directory
        pa = e->env_cr3;
        e->env_pgdir = 0;
@@ -478,70 +447,101 @@ env_free(env_t *e)
        page_decref(pa2page(pa));
 
        // return the environment to the free list
-       e->env_status = ENV_FREE;
+       e->state = ENV_FREE;
        LIST_INSERT_HEAD(&env_free_list, e, env_link);
 }
 
 /*
- * This allows the kernel to keep this process around, in case it is being used
- * in some asynchronous processing.
+ * The process refcnt is the number of places the process 'exists' in the
+ * system.  Creation counts as 1.  Having your page tables loaded somewhere
+ * (lcr3) counts as another 1.  A non-RUNNING_* process should have refcnt at
+ * least 1.  If the kernel is on another core and in a processes address space
+ * (like processing its backring), that counts as another 1.
+ *
+ * Note that the actual loading and unloading of cr3 is up to the caller, since
+ * that's not the only use for this (and decoupling is more flexible).
+ *
  * The refcnt should always be greater than 0 for processes that aren't dying.
  * When refcnt is 0, the process is dying and should not allow any more increfs.
- * TODO: Make sure this is never called from an interrupt handler (irq_save)
+ * A process can be dying with a refcnt greater than 0, since it could be
+ * waiting for other cores to "get the message" to die, or a kernel core can be
+ * finishing work in the processes's address space.
+ *
+ * Implementation aside, the important thing is that we atomically increment
+ * only if it wasn't already 0.  If it was 0, then we shouldn't be attaching to
+ * the process, so we return an error, which should be handled however is
+ * appropriate.  We currently use spinlocks, but some sort of clever atomics
+ * would work too.
+ *
+ * Also, no one should ever update the refcnt outside of these functions.
+ * Eventually, we'll have Ivy support for this. (TODO)
  */
 error_t env_incref(env_t* e)
 {
        error_t retval = 0;
-       spin_lock(&e->lock);
+       spin_lock_irqsave(&e->lock);
        if (e->env_refcnt)
                e->env_refcnt++;
        else
                retval = -EBADENV;
-       spin_unlock(&e->lock);
+       spin_unlock_irqsave(&e->lock);
        return retval;
 }
 
 /*
  * When the kernel is done with a process, it decrements its reference count.
  * When the count hits 0, no one is using it and it should be freed.
- * env_destroy calls this.
- * TODO: Make sure this is never called from an interrupt handler (irq_save)
+ * "Last one out" actually finalizes the death of the process.  This is tightly
+ * coupled with the previous function (incref)
+ * Be sure to load a different cr3 before calling this!
  */
 void env_decref(env_t* e)
 {
-       // need a known good pgdir before releasing the old one
-       // sometimes env_free is called on a different core than decref
-       lcr3(PADDR(boot_pgdir));
-
-       spin_lock(&e->lock);
+       spin_lock_irqsave(&e->lock);
        e->env_refcnt--;
-       spin_unlock(&e->lock);
+       spin_unlock_irqsave(&e->lock);
        // if we hit 0, no one else will increment and we can check outside the lock
        if (e->env_refcnt == 0)
                env_free(e);
 }
 
 
-//
-// Frees environment e.
-// If e was the current env, then runs a new environment (and does not return
-// to the caller).
-//
+/*
+ * Destroys the given process.  Can be called by a different process (checked
+ * via current), though that's unable to handle an async call (TODO current does
+ * not work asyncly, though it could be made to in the async processing
+ * function. 
+ */
 void
 env_destroy(env_t *e)
 {
-       // TODO: race condition with env statuses, esp when running / destroying
-       e->env_status = ENV_DYING;
-
-       env_decref(e);
+       // TODO: XME race condition with env statuses, esp when running / destroying
+       proc_set_state(e, PROC_DYING);
+
+       /*
+        * If we are currently running this address space on our core, we need a
+        * known good pgdir before releasing the old one.  This is currently the
+        * major practical implication of the kernel caring about a processes
+        * existence (the inc and decref).  This decref corresponds to the incref in
+        * proc_startcore (though it's not the only one).
+        */
+       if (current == e) {
+               lcr3(boot_cr3);
+               env_decref(e); // this decref is for the cr3
+       }
+       env_decref(e); // this decref is for the process in general
        atomic_dec(&num_envs);
 
+       /*
+        * Could consider removing this from destroy and having the caller specify
+        * these actions
+        */
        // for old envs that die on user cores.  since env run never returns, cores
        // never get back to their old hlt/relaxed/spin state, so we need to force
        // them back to an idle function.
        uint32_t id = core_id();
-       // There is no longer a curenv for this core. (TODO: Think about this.)
-       curenvs[id] = NULL;
+       // There is no longer a current process for this core. (TODO: Think about this.)
+       current = NULL;
        if (id) {
                smp_idle();
                panic("should never see me");
@@ -569,10 +569,10 @@ void schedule(void)
        
        for (int i = 0, j = last_picked + 1; i < NENV; i++, j = (j + 1) % NENV) {
                e = &envs[ENVX(j)];
-               // TODO: race here, if another core is just about to start this env.
+               // TODO: XME race here, if another core is just about to start this env.
                // Fix it by setting the status in something like env_dispatch when
                // we have multi-contexted processes
-               if (e && e->env_status == ENV_RUNNABLE) {
+               if (e && e->state == PROC_RUNNABLE_S) {
                        last_picked = j;
                        env_run(e);
                }
@@ -591,45 +591,26 @@ void schedule(void)
 void
 env_run(env_t *e)
 {
-       // Step 1: If this is a context switch (a new environment is running),
-       //         then set 'curenv' to the new environment,
-       //         update its 'env_runs' counter, and
-       //         and use lcr3() to switch to its address space.
-       // Step 2: Use env_pop_tf() to restore the environment's
-       //         registers and drop into user mode in the
-       //         environment.
-
-       // Hint: This function loads the new environment's state from
-       //      e->env_tf.  Go back through the code you wrote above
-       //      and make sure you have set the relevant parts of
-       //      e->env_tf to sensible values.
-
-       // TODO: race here with env destroy on the status and refcnt
+       // TODO: XME race here with env destroy on the status and refcnt
        // Could up the refcnt and down it when a process is not running
-       e->env_status = ENV_RUNNING;
-       if (e != curenvs[core_id()]) {
-               curenvs[core_id()] = e;
-               e->env_runs++;
-               lcr3(e->env_cr3);
-       }
-
-       env_pop_ancillary_state(e);
-
-       env_pop_tf(&e->env_tf);
+       
+       proc_set_state(e, PROC_RUNNING_S);
+       proc_startcore(e, &e->env_tf);
 }
 
 /* This is the top-half of an interrupt handler, where the bottom half is
  * env_run (which never returns).  Just add it to the delayed work queue,
- * which isn't really a queue yet.
+ * which (incidentally) can only hold one item at this point.
  */
-void run_env_handler(trapframe_t *tf, voiddata)
+void run_env_handler(trapframe_t *tf, void *data)
 {
        assert(data);
-       per_cpu_info_t *cpuinfo = &per_cpu_info[core_id()];
-       spin_lock_irqsave(&cpuinfo->lock);
+       struct work job;
+       struct workqueue *workqueue = &per_cpu_info[core_id()].workqueue;
        { TRUSTEDBLOCK // TODO: how do we make this func_t cast work?
-       cpuinfo->delayed_work.func = (func_t)env_run;
-       cpuinfo->delayed_work.data = data;
+       job.func = (func_t)env_run;
+       job.data = data;
        }
-       spin_unlock_irqsave(&cpuinfo->lock);
+       if (enqueue_work(workqueue, &job))
+               panic("Failed to enqueue work!");
 }
index 4417fe1..76481bd 100644 (file)
@@ -20,8 +20,8 @@
 #include <assert.h>
 #include <monitor.h>
 #include <pmap.h>
-#include <env.h>
-#include <testing.h>
+#include <process.h>
+#include <trap.h>
 #include <syscall.h>
 #include <kclock.h>
 #include <manager.h>
@@ -57,15 +57,6 @@ void kernel_init(multiboot_info_t *mboot_info)
 
        // this returns when all other cores are done and ready to receive IPIs
        smp_boot();
-       test_smp_call_functions();
-       test_checklists();
-       test_barrier();
-       test_print_info();
-       /*
-       test_lapic_status_bit();
-       test_ipi_sending();
-       test_pit();
-       */
 
        manager();
 }
diff --git a/kern/src/kfs.c b/kern/src/kfs.c
new file mode 100644 (file)
index 0000000..df853fb
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ */
+
+#include <kfs.h>
+#include <string.h>
+#include <assert.h>
+#include <ros/error.h>
+
+#define DECL_PROG(x) extern uint8_t _binary_obj_user_apps_##x##_start[], _binary_obj_user_apps_##x##_size[];      
+
+#define KFS_ENTRY(x) {#x, _binary_obj_user_apps_##x##_start, (size_t) _binary_obj_user_apps_##x##_size},
+
+/*
+ * Hardcode the files included in the KFS.  This needs to be in sync with the
+ * userapps in kern/src/Makefrag.
+ * Make sure to declare it, and add an entry.  Keep MAX_KFS_FILES big enough too
+ */
+DECL_PROG(roslib_proctests);
+DECL_PROG(roslib_fptest);
+DECL_PROG(roslib_null);
+DECL_PROG(roslib_spawn);
+DECL_PROG(roslib_hello);
+
+#ifdef __i386__
+DECL_PROG(parlib_channel_test_client);
+DECL_PROG(parlib_channel_test_server);
+DECL_PROG(roslib_measurements);
+#endif
+
+struct kfs_entry kfs[MAX_KFS_FILES] = {
+       KFS_ENTRY(roslib_proctests)
+       KFS_ENTRY(roslib_fptest)
+       KFS_ENTRY(roslib_null)
+       KFS_ENTRY(roslib_spawn)
+       KFS_ENTRY(roslib_hello)
+       #ifdef __i386__
+       KFS_ENTRY(parlib_channel_test_client)
+       KFS_ENTRY(parlib_channel_test_server)
+       KFS_ENTRY(roslib_measurements)
+       #endif
+};
+
+ssize_t kfs_lookup_path(char* path)
+{
+       for (int i = 0; i < MAX_KFS_FILES; i++)
+               // need to think about how to copy-in something of unknown length
+               if (!strncmp(kfs[i].name, path, strlen(path)))
+                       return i;
+       return -EINVAL;
+}
+
+/*
+ * Creates a process from the file pointed to by the KFS inode (index)
+ * This should take a real inode or something to point to the real location,
+ * and env_create shouldn't assume everything is contiguous
+ */
+struct proc *kfs_proc_create(size_t kfs_inode)
+{
+       if (kfs_inode < 0 || kfs_inode >= MAX_KFS_FILES)
+               panic("Invalid kfs_inode.  Check you error codes!");
+       return env_create(kfs[kfs_inode].start, kfs[kfs_inode].size);
+}
index c722a71..be5306e 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
  * See LICENSE for details.
  */
 
 
 #include <assert.h>
 #include <manager.h>
-#include <env.h>
+#include <process.h>
 #include <workqueue.h>
 #include <syscall.h>
 #include <testing.h>
+#include <kfs.h>
 
 /*
  * Currently, if you leave this function by way of env_run (process_workqueue
@@ -28,28 +30,24 @@ void manager(void)
        env_t *envs[256];
 
        switch (progress++) {
-       
-       #ifdef __i386__
-
                case 0:
+                       envs[0] = kfs_proc_create(kfs_lookup_path("roslib_hello"));
+                       proc_set_state(envs[0], PROC_RUNNABLE_S);
+                       env_run(envs[0]);
+                       break;
+       #ifdef __i386__
+               case 1:
+                       panic("Do not panic");
                        envs[0] = ENV_CREATE(parlib_channel_test_client);
                        envs[1] = ENV_CREATE(parlib_channel_test_server);
                        smp_call_function_single(1, run_env_handler, envs[0], 0);
                        smp_call_function_single(2, run_env_handler, envs[1], 0);
-
-       #if 0
-               case 0:
-                       printk("Beginning Tests\n");
-                       test_run_measurements(progress-1);  // should never return
                        break;
-       #endif
-
-               case 1:
                case 2:
                case 3:
-       #else
-
-               case 0:
+       #else // sparc
+               case 1:
+                       panic("Do not panic");
                        envs[0] = ENV_CREATE(roslib_proctests);
                        envs[1] = ENV_CREATE(roslib_proctests);
                        envs[2] = ENV_CREATE(roslib_proctests);
@@ -58,16 +56,43 @@ void manager(void)
                        envs[4] = ENV_CREATE(roslib_fptest);
                        envs[5] = ENV_CREATE(roslib_hello);
                        envs[6] = ENV_CREATE(roslib_null);
-                       //envs[6] = ENV_CREATE(roslib_measurements);
                        env_run(envs[0]);
                        break;
-               case 1:
                case 2:
+                       #if 0
+                       // reminder of how to spawn remotely
+                       for (int i = 0; i < 8; i++) {
+                               envs[i] = kfs_proc_create(kfs_lookup_path("roslib_hello"));
+                               proc_set_state(envs[i], PROC_RUNNABLE_S);
+                               smp_call_function_single(i, run_env_handler, envs[i], 0);
+                       }
+                       process_workqueue();
+                       #endif
                case 3:
-
        #endif
 
+               #if 0
+               case 4:
+                       printk("Beginning Tests\n");
+                       test_run_measurements(progress-1);  // should never return
+                       break;
+               case 5:
+                       envs[0] = ENV_CREATE(parlib_channel_test_client);
+                       envs[1] = ENV_CREATE(parlib_channel_test_server);
+                       smp_call_function_single(1, run_env_handler, envs[0], 0);
+                       smp_call_function_single(2, run_env_handler, envs[1], 0);
+               case 6:
+               #endif
                case 4:
+                       /*
+                       test_smp_call_functions();
+                       test_checklists();
+                       test_barrier();
+                       test_print_info();
+                       test_lapic_status_bit();
+                       test_ipi_sending();
+                       test_pit();
+                       */
                case 5:
                case 6:
                case 7:
@@ -79,7 +104,6 @@ void manager(void)
                case 13:
                case 14:
                        //test_run_measurements(progress-1);
-                       break;
                default:
                        printk("Manager Progress: %d\n", progress);
                        schedule();
index d7d7481..44064ca 100644 (file)
@@ -18,6 +18,7 @@
 #include <pmap.h>
 #include <kdebug.h>
 #include <testing.h>
+#include <kfs.h>
 #include <manager.h>
 
 #include <ros/memlayout.h>
@@ -40,6 +41,8 @@ static command_t commands[] = {
        { "setmapperm", "Sets permissions on a VA->PA mapping", mon_setmapperm},
        { "cpuinfo", "Prints CPU diagnostics", mon_cpuinfo},
        { "nanwan", "Meet Nanwan!!", mon_nanwan},
+       { "kfs_ls", "List files in KFS", mon_kfs_ls},
+       { "kfs_run", "Create and run a program from KFS", mon_kfs_run},
        { "manager", "Run the manager", mon_manager},
 };
 #define NCOMMANDS (sizeof(commands)/sizeof(commands[0]))
@@ -228,6 +231,36 @@ int mon_nanwan(int argc, char **argv, trapframe_t *tf)
        return 0;
 }
 
+int mon_kfs_ls(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
+{
+       printk("Files in KFS:\n-------------------------------\n");
+       for (int i = 0; i < MAX_KFS_FILES; i++)
+               if (kfs[i].name[0])
+                       printk("%s\n", kfs[i].name);
+       return 0;
+}
+
+int mon_kfs_run(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
+{
+       if (argc != 2) {
+               printk("Usage: kfs_run FILENAME\n");
+               return 1;
+       }
+       int kfs_inode = kfs_lookup_path(argv[1]);
+       if (kfs_inode < 0) {
+               printk("Bad filename!\n");
+               return 1;
+       }
+       struct proc *p = kfs_proc_create(kfs_inode);
+       // go from PROC_CREATED->PROC_RUNNABLE_S
+       proc_set_state(p, PROC_RUNNABLE_S);
+       // Should never return from schedule (env_pop in there)
+       // also note you may not get the process you created, in the event there
+       // are others floating around that are runnable
+       schedule();
+       return 0;
+}
+
 /***** Kernel monitor command interpreter *****/
 
 #define WHITESPACE "\t\r\n "
@@ -275,8 +308,8 @@ static int runcmd(char *COUNT(CMDBUF_SIZE) real_buf, trapframe_t *tf) {
 void monitor(trapframe_t *tf) {
        char *buf;
 
-       cprintf("Welcome to the ROS kernel monitor!\n");
-       cprintf("Type 'help' for a list of commands.\n");
+       printk("Welcome to the ROS kernel monitor on core %d!\n", core_id());
+       printk("Type 'help' for a list of commands.\n");
 
        if (tf != NULL)
                print_trapframe(tf);
index fedb453..595209c 100644 (file)
@@ -13,7 +13,7 @@
 #include <assert.h>
 #include <pmap.h>
 #include <kclock.h>
-#include <env.h>
+#include <process.h>
 
 //
 // Allocate n bytes of physical memory aligned on an 
@@ -296,7 +296,7 @@ static void *DANGEROUS user_mem_check_addr;
 // erroneous virtual address.
 //
 // Returns 0 if the user program can access this range of addresses,
-// and -E_FAULT otherwise.
+// and -EFAULT otherwise.
 //
 // Hint: The TA solution uses pgdir_walk.
 //
diff --git a/kern/src/process.c b/kern/src/process.c
new file mode 100644 (file)
index 0000000..5f9686a
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ */
+
+#include <process.h>
+#include <atomic.h>
+#include <assert.h>
+
+/*
+ * While this could be done with just an assignment, this gives us the
+ * opportunity to check for bad transitions.  Might compile these out later, so
+ * we shouldn't rely on them for sanity checking from userspace.
+ */
+int proc_set_state(struct proc *p, uint32_t state)
+{
+       uint32_t curstate = p->state;
+       /* Valid transitions:
+        * C   -> RBS
+        * RBS -> RGS
+        * RGS -> RBS
+        * RGS -> W
+        * W   -> RBS
+        * RGS -> RBM
+        * RBM -> RGM
+        * RGM -> RBM
+        * RGM -> RBS
+        * RGS -> D
+        * RGM -> D
+        * 
+        * These ought to be implemented later (allowed, not thought through yet).
+        * RBS -> D
+        * RBM -> D
+        *
+        * This isn't allowed yet, may be later.
+        * C   -> D
+        */
+       #if 1 // some sort of correctness flag
+       switch (curstate) {
+               case PROC_CREATED:
+                       if (state != PROC_RUNNABLE_S)
+                               panic("Invalid State Transition! PROC_CREATED to %d", state);
+                       break;
+               case PROC_RUNNABLE_S:
+                       if (!(state & (PROC_RUNNING_S | PROC_DYING)))
+                               panic("Invalid State Transition! PROC_RUNNABLE_S to %d", state);
+                       break;
+               case PROC_RUNNING_S:
+                       if (!(state & (PROC_RUNNABLE_S | PROC_RUNNABLE_M | PROC_WAITING |
+                                      PROC_DYING)))
+                               panic("Invalid State Transition! PROC_RUNNING_S to %d", state);
+                       break;
+               case PROC_WAITING:
+                       if (state != PROC_RUNNABLE_S)
+                               panic("Invalid State Transition! PROC_WAITING to %d", state);
+                       break;
+               case PROC_DYING:
+                       if (state != PROC_CREATED) // when it is reused (TODO)
+                               panic("Invalid State Transition! PROC_DYING to %d", state);
+                       break;
+               case PROC_RUNNABLE_M:
+                       if (!(state & (PROC_RUNNING_M | PROC_DYING)))
+                               panic("Invalid State Transition! PROC_RUNNABLE_M to %d", state);
+                       break;
+               case PROC_RUNNING_M:
+                       if (!(state & (PROC_RUNNABLE_S | PROC_RUNNABLE_M | PROC_DYING)))
+                               panic("Invalid State Transition! PROC_RUNNING_M to %d", state);
+                       break;
+       }
+       #endif
+       p->state = state;
+       return 0;
+}
+
+/* Change this when we aren't using an array */
+struct proc *get_proc(unsigned pid)
+{
+       // should have some error checking when we do this for real
+       return &envs[ENVX(pid)];
+}
+
+/* Whether or not actor can control target */
+bool proc_controls(struct proc *actor, struct proc *target)
+{
+       return target->env_parent_id == actor->env_id;
+}
+
+/*
+ * Runs the given context (trapframe) of process p on the core this code
+ * executes on.  The refcnt tracks how many cores have "an interest" in this
+ * process, which so far just means it uses the process's page table.  See the
+ * massive comments around the incref function
+ *
+ * TODO: think about how an interrupt could abort this, esp when we want to
+ * destroy it.  need a way to not lose the kernel stack.  For example, we could
+ * receive an IPI that tells us to preempt this process (or even kill it) and
+ * run something different.
+ * TODO: in general, think about when we no longer need the stack, in case we
+ * are preempted and expected to run again from somewhere else.  we can't
+ * expect to have the kernel stack around anymore.
+ *
+ * I think we need to make it such that the kernel in "process context"
+ * never gets removed from the core (displaced from its stack)
+ * would like to leave interrupts on too, so long as we come back.
+ * Consider a moveable flag or something.
+ *
+ * Perhaps we could have a workqueue with the todo item put there by the
+ * interrupt handler when it realizes we were in the kernel in the first place.
+ * disable ints before checking the queue and deciding to pop out or whatever to
+ * ensure atomicity.
+ */
+void proc_startcore(struct proc *p, trapframe_t *tf) {
+       /*
+        * TODO: okay, we have this.  now handle scenarios based on these
+        * assumptions (transitions from these states) like:
+        *              death attempt
+        *              preempt attempt
+        */
+       assert(p->state & (PROC_RUNNING_S | PROC_RUNNING_M));
+       /* If the process wasn't here, then we need to load its address space. */
+       if (p != current) {
+               if (env_incref(p))
+                       // getting here would mean someone tried killing this while we tried
+                       // to start one of it's contexts (from scratch, o/w we had it's CR3
+                       // loaded already)
+                       panic("Proc is dying, handle me!"); lcr3(p->env_cr3);
+               // we unloaded the old cr3, so decref it (if it exists)
+               // TODO: Consider moving this to wherever we really "mean to leave the
+               // process's context".
+               if (current)
+                       env_decref(current);
+               current = p;
+               /* also need to load our silly state, though this implies it's the same
+                * context, and not just the same process
+                * TODO: this is probably a lie, think about page faults
+                * for now, we load this silly state down below
+                */
+               // load_our_silly_state();
+       }
+       env_pop_ancillary_state(p);
+       env_pop_tf(&p->env_tf);
+}
index 8b7c38b..c25bfdb 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ */
+
 #ifdef __DEPUTY__
 #pragma nodeputy
 #endif
 #include <arch/arch.h>
 #include <atomic.h>
 #include <smp.h>
+#include <ros/error.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <pmap.h>
+#include <process.h>
+#include <trap.h>
+
+struct per_cpu_info per_cpu_info[MAX_NUM_CPUS];
 
 // tracks number of global waits on smp_calls, must be <= NUM_HANDLER_WRAPPERS
 atomic_t outstanding_calls = 0;
 
-per_cpu_info_t per_cpu_info[MAX_NUM_CPUS];
-
 /* All non-zero cores call this at the end of their boot process.  They halt,
  * and wake up when interrupted, do any work on their work queue, then halt
  * when there is nothing to do.  
@@ -24,4 +37,3 @@ void smp_idle(void)
                cpu_halt();
        }
 }
-
index 7278f4b..537e42c 100644 (file)
 
 #include <string.h>
 #include <assert.h>
-#include <env.h>
+#include <process.h>
 #include <pmap.h>
 #include <trap.h>
 #include <syscall.h>
+#include <kfs.h> // eventually replace this with vfs.h
 
 //Do absolutely nothing.  Used for profiling.
 static void sys_null(void)
@@ -85,12 +86,10 @@ static void sys_shared_page_free(env_t* p1, void* addr, envid_t p2)
 {
 }
 
-// Invalidate the cache of this core
+// Invalidate the cache of this core.  Only useful if you want a cold cache for
+// performance testing reasons.
 static void sys_cache_invalidate(void)
 {
-       // why is this necessary with cache coherence?
-       // is it for coherence with respect to i/o?  --asw
-
        #ifdef __i386__
                wbinvd();
        #endif
@@ -210,6 +209,7 @@ static envid_t sys_getcpuid(void)
        return core_id();
 }
 
+// TODO FIX Me!!!! for processes
 // Destroy a given environment (possibly the currently running environment).
 //
 // Returns 0 on success, < 0 on error.  Errors are:
@@ -233,20 +233,76 @@ static error_t sys_env_destroy(env_t* e, envid_t envid)
 /*
  * Current process yields its remaining "time slice".  Currently works for
  * single-core processes.
+ * TODO: think about how this works with async calls and multicored procs.
+ * Want it to only be callable locally.
  */
-static void sys_yield(env_t *e)
+static void sys_yield(struct proc *p)
 {
        // TODO: watch for races throughout anything related to process statuses
        // and schedule/yielding
-       assert(e->env_status == ENV_RUNNING);
-       e->env_status = ENV_RUNNABLE;
+       assert(p->state == PROC_RUNNING_S);
+       p->state = PROC_RUNNABLE_S;
+       // the implied thing here is that all state has been saved.  and you need
+       // todo that before changing the state to RUNNABLE_S, since the process can
+       // get picked up somewhere else. TODO
        schedule();
+
+       /* TODO
+        * if running_s, give up your time slice (schedule, save silly state, block)
+        * if running_m and 2+ cores are left, give yours up, stay runnable_m
+        * if running_m and last core, switch to runnable_s
+        */
+}
+
+/*
+ * Creates a process found at the user string 'path'.  Currently uses KFS.
+ * Not runnable by default, so it needs it's status to be changed so that the
+ * next call to schedule() will try to run it.
+ * TODO: once we have a decent VFS, consider splitting this up
+ * and once there's an mmap, can have most of this in process.c
+ */
+static int sys_proc_create(struct proc *p, const char *DANGEROUS path)
+{
+       #define MAX_PATH_LEN 256 // totally arbitrary
+       int pid = 0;
+       char tpath[MAX_PATH_LEN];
+       /*
+        * There's a bunch of issues with reading in the path, which we'll
+        * need to sort properly in the VFS.  Main concerns are TOCTOU (copy-in),
+        * whether or not it's a big deal that the pointer could be into kernel
+        * space, and resolving both of these without knowing the length of the
+        * string. (TODO)
+        * Change this so that all syscalls with a pointer take a length.
+        */
+       strncpy(tpath, path, MAX_PATH_LEN);
+       int kfs_inode = kfs_lookup_path(tpath);
+       if (kfs_inode < 0)
+               return -EINVAL;
+       struct proc *new_p = kfs_proc_create(kfs_inode);
+       return new_p->env_id; // TODO replace this with a real proc_id
+}
+
+/* Makes process PID runnable.  Consider moving the functionality to env.c */
+static error_t sys_proc_run(struct proc *p, unsigned pid)
+{
+       struct proc *target = get_proc(pid);
+       error_t retval = 0;
+       spin_lock(&p->lock); // note we can get interrupted here.  it's not bad.
+       // make sure we have access and it's in the right state to be activated
+       if (!proc_controls(p, target))
+               retval = -EPERM;
+       else if (target->state != PROC_CREATED)
+               retval = -EINVAL;
+       else
+               proc_set_state(target, PROC_RUNNABLE_S);
+       spin_unlock(&p->lock);
+       return retval;
 }
 
 // TODO: Build a dispatch table instead of switching on the syscallno
 // Dispatches to the correct kernel function, passing the arguments.
 intreg_t syscall(env_t* e, uint32_t syscallno, uint32_t a1, uint32_t a2,
-                uint32_t a3, uint32_t a4, uint32_t a5)
+                 uint32_t a3, uint32_t a4, uint32_t a5)
 {
        // Call the function corresponding to the 'syscallno' parameter.
        // Return any appropriate return value.
@@ -286,16 +342,17 @@ intreg_t syscall(env_t* e, uint32_t syscallno, uint32_t a1, uint32_t a2,
                        return sys_serial_write(e, (char *DANGEROUS)a1, (size_t)a2);
                case SYS_serial_read:
                        return sys_serial_read(e, (char *DANGEROUS)a1, (size_t)a2);
-               case SYS_getenvid:
+               case SYS_getpid:
                        return sys_getenvid(e);
-               case SYS_env_destroy:
+               case SYS_proc_destroy:
                        return sys_env_destroy(e, (envid_t)a1);
                case SYS_yield:
                        sys_yield(e);
                        return ESUCCESS;
                case SYS_proc_create:
+                       return sys_proc_create(e, (char *DANGEROUS)a1);
                case SYS_proc_run:
-                       panic("Not implemented");
+                       return sys_proc_run(e, (size_t)a1);
                default:
                        // or just return -EINVAL
                        panic("Invalid syscall number %d for env %x!", syscallno, *e);
@@ -345,6 +402,8 @@ intreg_t process_generic_syscalls(env_t* e, size_t max)
                //printk("DEBUG POST: sring->req_prod: %d, sring->rsp_prod: %d\n",\
                           sysbr->sring->req_prod, sysbr->sring->rsp_prod);
        }
+       // load sane page tables (and don't rely on decref to do it for you).
+       lcr3(boot_cr3);
        env_decref(e);
        return (intreg_t)count;
 }
index 722f7a1..021a06e 100644 (file)
 #include <string.h>
 #include <testing.h>
 #include <trap.h>
-#include <env.h>
+#include <process.h>
 #include <syscall.h>
 
 #define test_vector 0xeb
 
-#if 0
+#ifdef __i386__
 
 void test_ipi_sending(void)
 {
@@ -74,7 +74,7 @@ void test_pic_reception(void)
        while(1);
 }
 
-#endif
+#endif // __i386__
 
 void test_print_info(void)
 {
@@ -228,9 +228,8 @@ checklist_t* the_global_list;
 
 void test_checklist_handler(trapframe_t *tf, void* data)
 {
-       for (int i = 0; i < SMP_BOOT_TIMEOUT; i++);
-       for (int i = 0; i < SMP_BOOT_TIMEOUT; i++);
-       cprintf("down_checklist(%x,%d)\n",the_global_list,core_id());
+       udelay(1000000);
+       cprintf("down_checklist(%x,%d)\n", the_global_list, core_id());
        down_checklist(the_global_list);
 }
 
@@ -269,7 +268,7 @@ void test_checklists(void)
 
 }
 
-atomic_t a = atomic_init(0), b = atomic_init(0), c = atomic_init(0);
+atomic_t a, b, c;
 
 void test_incrementer_handler(trapframe_t *tf, void* data)
 {
@@ -285,6 +284,9 @@ void test_null_handler(trapframe_t *tf, void* data)
 void test_smp_call_functions(void)
 {
        int i;
+       atomic_init(&a, 0);
+       atomic_init(&b, 0);
+       atomic_init(&c, 0);
        handler_wrapper_t *waiter0 = 0, *waiter1 = 0, *waiter2 = 0, *waiter3 = 0,
                          *waiter4 = 0, *waiter5 = 0;
        uint8_t me = core_id();
@@ -385,7 +387,7 @@ void test_smp_call_functions(void)
        printk("Done\n");
 }
 
-#if 0
+#ifdef __i386__
 void test_lapic_status_bit(void)
 {
        register_interrupt_handler(interrupt_handlers, test_vector,
@@ -402,7 +404,7 @@ void test_lapic_status_bit(void)
        printk("IPIs received (should be %d): %d\n", a, NUM_IPI);
        // hopefully that handler never fires again.  leaving it registered for now.
 }
-#endif
+#endif // __i386__
 
 /******************************************************************************/
 /*            Test Measurements: Couples with measurement.c                   */
@@ -536,7 +538,7 @@ void test_run_measurements(uint32_t job_num)
        panic("Error in test setup!!");
 }
 
-#endif
+#endif // __i386__
 
 /************************************************************/
 /* ISR Handler Functions */
@@ -553,7 +555,7 @@ void test_hello_world_handler(trapframe_t *tf, void* data)
        #endif
 
        cprintf("Incoming IRQ, ISR: %d on core %d with tf at 0x%08x\n",
-               trapno, core_id(), tf);
+               trapno, core_id(), tf);
 }
 
 uint32_t print_info_lock = 0;
@@ -563,7 +565,7 @@ void test_print_info_handler(trapframe_t *tf, void* data)
        spin_lock_irqsave(&print_info_lock);
        cprintf("----------------------------\n");
        cprintf("This is Core %d\n", core_id());
-#if 0
+#ifdef __i386__
        cprintf("MTRR_DEF_TYPE = 0x%08x\n", read_msr(IA32_MTRR_DEF_TYPE));
        cprintf("MTRR Phys0 Base = 0x%016llx, Mask = 0x%016llx\n",
                read_msr(0x200), read_msr(0x201));
@@ -581,7 +583,7 @@ void test_print_info_handler(trapframe_t *tf, void* data)
                read_msr(0x20c), read_msr(0x20d));
        cprintf("MTRR Phys7 Base = 0x%016llx, Mask = 0x%016llx\n",
                read_msr(0x20e), read_msr(0x20f));
-#endif
+#endif // __i386__
        cprintf("----------------------------\n");
        spin_unlock_irqsave(&print_info_lock);
 }
@@ -607,7 +609,7 @@ static void test_waiting_handler(trapframe_t *tf, void* data)
        {HANDLER_ATOMIC atomic_dec((atomic_t*)data);}
 }
 
-#if 0
+#ifdef __i386__
 void test_pit(void)
 {
        cprintf("Starting test for PIT now (10s)\n");
@@ -621,11 +623,12 @@ void test_pit(void)
        enable_irq();
        lapic_set_timer(10000000, FALSE);
 
-       atomic_t waiting = atomic_init(1);
+       atomic_t waiting;
+       atomic_init(&waiting, 1);
        register_interrupt_handler(interrupt_handlers, test_vector,
                                   test_waiting_handler, &waiting);
        while(atomic_read(&waiting))
                cpu_relax();
        cprintf("End now\n");
 }
-#endif
+#endif // __i386__
index ecb6843..e0952d6 100644 (file)
@@ -1,13 +1,16 @@
 /*
  * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
  * See LICENSE for details.
  */
 
 #include <atomic.h>
 #include <smp.h>
 
-#include <atomic.h>
+#include <ros/error.h>
 
+#include <atomic.h>
+#include <stdio.h>
 #include <workqueue.h>
 
 /*
  */
 void process_workqueue()
 {
-       work_t work;
-       per_cpu_info_t *cpuinfo = &per_cpu_info[core_id()];
+       struct work work;
+       struct per_cpu_info *cpuinfo = &per_cpu_info[core_id()];
+
        // copy the work in, since we may never return to this stack frame
        spin_lock_irqsave(&cpuinfo->lock);
-       work = cpuinfo->delayed_work;
+       work = cpuinfo->workqueue.statics[0];
        spin_unlock_irqsave(&cpuinfo->lock);
        if (work.func) {
                // TODO: possible race with this.  sort it out when we have a queue.
                spin_lock_irqsave(&cpuinfo->lock);
-               cpuinfo->delayed_work.func = 0;
+               cpuinfo->workqueue.statics[0].func = 0;
                spin_unlock_irqsave(&cpuinfo->lock);
                // We may never return from this (if it is env_run)
                work.func(work.data);
        }
 }
+
+int enqueue_work(struct workqueue *queue, struct work *job)
+{
+       error_t retval = 0;
+       struct per_cpu_info *cpuinfo = &per_cpu_info[core_id()];
+
+       spin_lock_irqsave(&cpuinfo->lock);
+       printd("Enqueuing func 0x%08x and data 0x%08x on core %d.\n",
+              job->func, job->data, core_id());
+       if (queue->statics[0].func)
+               retval = -ENOMEM;
+       else
+               queue->statics[0] = *job;
+       spin_unlock_irqsave(&cpuinfo->lock);
+       return retval;
+}
index dc1b82a..e021da3 100644 (file)
@@ -1,5 +1,5 @@
 // buggy hello world -- unmapped pointer passed to kernel
-// kernel should destroy user environment in response
+// kernel should destroy user process in response
 
 #include <inc/lib.h>
 
index 19b30aa..254d992 100644 (file)
@@ -1,5 +1,5 @@
 // evil hello world -- kernel pointer passed to kernel
-// kernel should destroy user environment in response
+// kernel should destroy user process in response
 
 #include <inc/lib.h>
 
index 1db1943..fadc6a6 100644 (file)
@@ -2,6 +2,6 @@
 
 int main(int argc, char** argv)
 {
-       cprintf("goodbye, world!\n");
+       cprintf("Goodbye, world, from PID: %d!\n", sys_getpid());
        return 0;
 }
index a7c1c0e..446f577 100644 (file)
@@ -274,7 +274,7 @@ int main(int argc, char** argv)
                                cprintf("Bug in Job Selection!!!\n");
        }
        waiton_barrier(bar);
-       //cprintf("Env %x, on core %d, finishes\n", env->env_id, coreid);
+       //cprintf("Env %x, on core %d, finishes\n", sys_getpid(), coreid);
        return 0;
        /* Options for Cache Buster:
         * BUSTER_SHARED
index 3d1ff85..79fb480 100644 (file)
@@ -7,28 +7,29 @@
 
 int main(int argc, char** argv)
 {
-       cprintf("i am environment %08x, running on core %d\n", env->env_id, getcpuid());
+       int pid = sys_getpid();
+       cprintf("i am process %08x, running on core %d\n", pid, getcpuid());
 
        async_desc_t *desc1, *desc2, *desc3;
        async_rsp_t rsp1, rsp2, rsp3;
-       cprintf_async(&desc1, "Cross-Core call 1, coming from env %08x\n", env->env_id);
-       cprintf_async(&desc1, "Cross-Core call 1, coming from env %08x\n", env->env_id);
-       cprintf_async(&desc1, "Cross-Core call 1, coming from env %08x\n", env->env_id);
-       cprintf_async(&desc1, "Cross-Core call 1, coming from env %08x\n", env->env_id);
-       cprintf_async(&desc1, "Cross-Core call 1, coming from env %08x\n", env->env_id);
+       cprintf_async(&desc1, "Cross-Core call 1, coming from process %08x\n", pid);
+       cprintf_async(&desc1, "Cross-Core call 1, coming from process %08x\n", pid);
+       cprintf_async(&desc1, "Cross-Core call 1, coming from process %08x\n", pid);
+       cprintf_async(&desc1, "Cross-Core call 1, coming from process %08x\n", pid);
+       cprintf_async(&desc1, "Cross-Core call 1, coming from process %08x\n", pid);
        //cprintf("Call 1 is sent!\n");
-       //cprintf_async(&desc2, "Cross-Core call 2, coming from env %08x\n", env->env_id);
-       //cprintf_async(&desc2, "1111111111111111111111111111111122222222222222222222222222222222333333333333333333333333333333334444444444444444444444444444444455555555555555555555555555555555666666666666666666666666666666667777777777777777777777777777777788888888888888888888888888888888Cross-Core call 2, coming from env %08x\n", env->env_id);
+       //cprintf_async(&desc2, "Cross-Core call 2, coming from process %08x\n", pid);
+       //cprintf_async(&desc2, "1111111111111111111111111111111122222222222222222222222222222222333333333333333333333333333333334444444444444444444444444444444455555555555555555555555555555555666666666666666666666666666666667777777777777777777777777777777788888888888888888888888888888888Cross-Core call 2, coming from process %08x\n", pid);
        //cprintf("Call 2 is sent!\n");
        //cprintf("Waiting on Call 1\n");
        waiton_async_call(desc1, &rsp1);
        //cprintf("Received 1\n");
        //waiton_async_call(desc2, &rsp2);
-//     cprintf_async(&desc3, "Cross-Core call 3, coming from env %08x\n", env->env_id);
+//     cprintf_async(&desc3, "Cross-Core call 3, coming from process %08x\n", pid);
 //     cprintf("Call 3 is sent!\n");
 //     waiton_async_call(desc3, &rsp3);
        // might as well spin, just to make sure nothing gets deallocated
        // while we're waiting to test the async call
        //while (1);
-       //cprintf("DYING: environment %08x\n", env->env_id);
+       //cprintf("DYING: process %08x\n", pid);
 }
index 979a318..787423e 100644 (file)
@@ -4,12 +4,13 @@
 
 int main(int argc, char** argv)
 {
-       cprintf("Process %x, Starting and yielding.\n", env->env_id);
+       int pid = sys_getpid();
+       cprintf("Process %x, Starting and yielding.\n", pid);
        yield();
-       cprintf("Process %x, Return from yield1, starting yield2.\n", env->env_id);
+       cprintf("Process %x, Return from yield1, starting yield2.\n", pid);
        yield();
-       cprintf("Process %x, Return from yield2, starting yield3.\n", env->env_id);
+       cprintf("Process %x, Return from yield2, starting yield3.\n", pid);
        yield();
-       cprintf("Process %x, Return from yield3, exiting.\n", env->env_id);
+       cprintf("Process %x, Return from yield3, exiting.\n", pid);
        return 0;
 }
diff --git a/user/apps/roslib/spawn.c b/user/apps/roslib/spawn.c
new file mode 100644 (file)
index 0000000..f5658f5
--- /dev/null
@@ -0,0 +1,29 @@
+#include <lib.h>
+#include <syswrapper.h>
+
+int main(int argc, char** argv)
+{
+       /* try some bad combos */
+       int pid = proc_create("garbagexxx");
+       cprintf("Garbage pid result: %d\n", pid);
+
+       error_t err = proc_run(2342);
+       cprintf("proc_run(2342) error: %e\n", err);
+
+       err = proc_run(-1);
+       cprintf("proc_run(-1) error: %e\n", err);
+
+
+       #define NUM_KIDS 5
+       int child_pid[NUM_KIDS];
+       cprintf("U: attempting to create hello(s)\n");
+       for (int i = 0; i < NUM_KIDS; i++)
+               child_pid[i] = proc_create("roslib_hello");
+
+       for (int i = 0; i < NUM_KIDS; i++) {
+               cprintf("U: attempting to run hello (pid: %d)\n", child_pid[i]);
+               proc_run(child_pid[i]);
+       }
+
+       return 0;
+}
index 0a9ecde..9c574b3 100644 (file)
@@ -56,7 +56,7 @@ alloc_range(int initaddr, int maxpa, int startn) {
   initva = initaddr;
   maxva = initva + maxpa;
   
-  cprintf ("[%08x] trying to alloc pages in range [%08x, %08x]\n", env->env_id, initva, maxva);
+  cprintf ("[%08x] trying to alloc pages in range [%08x, %08x]\n", sys_getpid(), initva, maxva);
 
   // how many pages can I alloc? 
   // - limit to 256 M worth of pages
@@ -76,7 +76,7 @@ alloc_range(int initaddr, int maxpa, int startn) {
   }
   cprintf("\n");
 
-  cprintf("[%08x] able to allocate [%d] pages of requested [%d] pages\n", env->env_id, n, maxnum);
+  cprintf("[%08x] able to allocate [%d] pages of requested [%d] pages\n", sys_getpid(), n, maxnum);
 
   maxva = va;
   return n;
@@ -85,14 +85,14 @@ alloc_range(int initaddr, int maxpa, int startn) {
 int
 test_range(int startva, int endva, int startn) {
   int c;
-  cprintf("[%08x] testing pages in [%08x, %08x] to see if they look okay\n", env->env_id, startva, endva);
+  cprintf("[%08x] testing pages in [%08x, %08x] to see if they look okay\n", sys_getpid(), startva, endva);
   n = startn;
   failures = 0;  
   for (va = startva, c = 0; va < endva; va += PGSIZE, n++, c++) { 
     page_id = (int*)va;
 
     if (test_page((int*)va, n)) {
-      cprintf("\n[%08x] unexpected value at [%08x]:\n  {", env->env_id, va);
+      cprintf("\n[%08x] unexpected value at [%08x]:\n  {", sys_getpid(), va);
       print_marked_page((int*)va);
       cprintf("} should be\n  {");
       print_expected_mark(n);
@@ -104,7 +104,7 @@ test_range(int startva, int endva, int startn) {
       int perm = (PTE_U | PTE_P | PTE_W | PTE_AVAIL);
 
       if ((pte & perm) != perm) {
-       cprintf("\n[%08x] unexpected PTE permissions [04x] for address [%08x]\n {", env->env_id, pte & perm, va);
+       cprintf("\n[%08x] unexpected PTE permissions [04x] for address [%08x]\n {", sys_getpid(), pte & perm, va);
        failures++;
       }
 
@@ -120,29 +120,29 @@ test_range(int startva, int endva, int startn) {
   }
   cprintf("\n");
 
-  cprintf("[%08x] tested %d pages: %d failed assertions.\n", env->env_id, c, failures);
+  cprintf("[%08x] tested %d pages: %d failed assertions.\n", sys_getpid(), c, failures);
 
   return failures;
 }
 
 void
 unmap_range(int startva, int endva) {
-  cprintf("[%08x] unmapping range [%08x, %08x].\n", env->env_id, startva, endva);
+  cprintf("[%08x] unmapping range [%08x, %08x].\n", sys_getpid(), startva, endva);
   int xva, z;
   for (z=0, xva = startva; xva < endva; xva += PGSIZE, z++) { 
     sys_mem_unmap(0, xva);
   }
-  cprintf("[%08x] unmapped %d pages.\n", env->env_id, z);
+  cprintf("[%08x] unmapped %d pages.\n", sys_getpid(), z);
 }
 
 int
 duplicate_range(int startva, int dupeva, int nbytes) {
   cprintf("[%08x] duplicating range [%08x, %08x] at [%08x, %08x]\n", 
-        env->env_id, startva, startva+nbytes, dupeva, dupeva+nbytes);
+        sys_getpid(), startva, startva+nbytes, dupeva, dupeva+nbytes);
   int xva, r, k;
   for (xva = 0, k = 0; xva < nbytes; xva += PGSIZE, k+=PGSIZE) { 
     if ((r = sys_mem_map(0, startva+xva, 0, dupeva+xva, PTE_P | PTE_U | PTE_W | PTE_USER)) < 0) {
-      cprintf ("[%08x] duplicate_range FAILURE: %e\n", env->env_id, r);
+      cprintf ("[%08x] duplicate_range FAILURE: %e\n", sys_getpid(), r);
       return r;
     }
   }
@@ -158,7 +158,7 @@ int main(int argc, char** argv)
   int max, max2, k, j, i, dupesize, dupen;
 
   for (i = 0; i < 2; i++) { // might as well do this multiple times to stress the system...
-    cprintf("PMAPTEST[%08x] starting ROUND %d.\n", env->env_id, i);
+    cprintf("PMAPTEST[%08x] starting ROUND %d.\n", sys_getpid(), i);
 
     // Try to allocate as many pages as possible...
     k = alloc_range(UTEXT+PDMAP, (256 * 1024 * 1024), 0);       // alloc as many as possible
@@ -166,17 +166,17 @@ int main(int argc, char** argv)
     test_range(UTEXT+PDMAP, max, 0);                            // test if all are unique pages
 
     // If we've corrupted kernel memory, a yield might expose a problem.
-    cprintf("PMAPTEST[%08x] yielding...\n", env->env_id);
+    cprintf("PMAPTEST[%08x] yielding...\n", sys_getpid());
     sys_yield();
-    cprintf("PMAPTEST[%08x] back.\n", env->env_id);
+    cprintf("PMAPTEST[%08x] back.\n", sys_getpid());
 
-    // Free a couple of pages for use by page tables and other envs...
+    // Free a couple of pages for use by page tables and other processes...
     unmap_range(max-16 * PGSIZE, max);                           // free some pages so we have wiggle room, if extra
     max -= 16 * PGSIZE;                                          // pages are needed for page tables...
     
     // Unmap last 1024 pages and then try to reallocate them in the same place
     unmap_range(max - PDMAP, max);                              // unmap last 1024 pages
-    j = alloc_range(max - PDMAP, PDMAP, 0);                     // try to realloc them (<1024 if other envs alloc'd)
+    j = alloc_range(max - PDMAP, PDMAP, 0);                     // try to realloc them (<1024 if other processes alloc'd)
     max2 = maxva; // max2 <= max && max2 >= (max - PDMAP)
     test_range(max - PDMAP, max2, 0);                           // test if new pages are unique
   
@@ -188,7 +188,7 @@ int main(int argc, char** argv)
   
     // Remove one of the duplicate mappings and then unmap and realloc the last 1024 pages
     unmap_range(max2-PDMAP, max2-PDMAP+dupesize);           // unmap lower mapping
-    j = alloc_range(max2-PDMAP, PDMAP, 0);                  // try to alloc something, should be below 1024 (really? other envs?)
+    j = alloc_range(max2-PDMAP, PDMAP, 0);                  // try to alloc something, should be below 1024 (really? other processes?)
     unmap_range(max2-2*PDMAP, max2 - PDMAP);                // free 1024 pages
     j = alloc_range(max2-2*PDMAP, PDMAP, 0);                // alloc new pages for free'd 1024
     //max2 = maxva; // max2 <= old_max2 - PDMAP
index e2231bb..e26d2a1 100644 (file)
@@ -11,7 +11,6 @@
 #include <stdint.h>
 #include <arch/types.h>
 #include <ros/error.h>
-#include <ros/env.h>
 #include <ros/ring_buffer.h>
 
 /***************** Channel related constants *****************/
@@ -45,7 +44,7 @@ typedef enum {
 typedef struct channel {
        size_t id;
        channel_type_t type;
-       envid_t endpoint;
+       pid_t endpoint;
        void *COUNT(PGSIZE) data_addr;
        channel_sring_t *COUNT(1) ring_addr;
        union {
@@ -61,7 +60,7 @@ typedef struct channel_attr {
 
 /***************** Channel related functions *****************/
 
-error_t channel_create(envid_t server, channel_t* ch, channel_attr_t* attr);
+error_t channel_create(pid_t server, channel_t* ch, channel_attr_t* attr);
 error_t channel_create_wait(channel_t* ch, channel_attr_t* attr);
 error_t channel_destroy(channel_t* ch);
 
index eb00ac9..b02cfa5 100644 (file)
@@ -10,7 +10,6 @@
 #include <arch/types.h>
 #include <ros/memlayout.h>
 #include <ros/syscall.h>
-#include <ros/env.h>
 #include <ros/error.h>
 #include <newlib_backend.h>
 
@@ -19,7 +18,6 @@ enum {
        PG_RDWR   = 6,
 };
 
-extern volatile env_t *env;
 // will need to change these types when we have real structs
 // seems like they need to be either arrays [] or functions () for it to work
 extern volatile uint8_t (COUNT(PGSIZE * UINFO_PAGES) procinfo)[];
@@ -33,11 +31,11 @@ ssize_t     sys_cputs(const uint8_t *s, size_t len);
 uint16_t    sys_cgetc(void);
 ssize_t     sys_serial_write(void* buf, size_t len); 
 ssize_t     sys_serial_read(void* buf, size_t len);
-ssize_t     sys_shared_page_alloc(void *COUNT(PGSIZE) *addr, envid_t p2, 
+int         sys_getpid(void);
+size_t      sys_getcpuid(void);
+error_t     sys_proc_destroy(int pid);
+ssize_t     sys_shared_page_alloc(void *COUNT(PGSIZE) *addr, pid_t p2, 
                                   int p1_flags, int p2_flags);
-ssize_t     sys_shared_page_free(void *COUNT(PGSIZE) addr, envid_t p2);
-envid_t     sys_getenvid(void);
-envid_t     sys_getcpuid(void);
-void        sys_env_destroy(envid_t);
+ssize_t     sys_shared_page_free(void *COUNT(PGSIZE) addr, pid_t p2);
 
 #endif // !ROS_INC_LIB_H
index d242ea1..9417a91 100644 (file)
@@ -9,7 +9,6 @@
 #include <stdio.h>
 #include <string.h>
 #include <channel.h>
-#include <ros/env.h>
 #include <ros/syscall.h>
 #include <arch/arch.h>
 
@@ -25,7 +24,7 @@ void simulate_rsp(channel_t* ch) {
        channel_recvmsg(&ch_server, &msg);
 }
 
-error_t channel_create(envid_t server, channel_t* ch, channel_attr_t* ch_attr) {
+error_t channel_create(pid_t server, channel_t* ch, channel_attr_t* ch_attr) {
        error_t e;
        void *COUNT(PGSIZE) ring_addr = NULL;
        void *COUNT(PGSIZE) data_addr = NULL;
@@ -131,7 +130,7 @@ error_t channel_sendmsg(channel_t* ch, channel_msg_t* msg) {
 error_t channel_create_wait(channel_t* ch, channel_attr_t* ch_attr) {
 #if 0
        error_t e;
-       envid_t* client;
+       pid_t* client;
        void *COUNT(PGSIZE) ring_addr = NULL;
        void *COUNT(PGSIZE) data_addr = NULL;
 
index bfa2981..534faf1 100644 (file)
@@ -1,4 +1,4 @@
-// Implementation of cprintf console output for user environments,
+// Implementation of cprintf console output for user processes,
 // based on printfmt() and the sys_cputs() system call.
 //
 // cprintf is a debugging statement, not a generic output statement.
index d737617..1011086 100644 (file)
@@ -23,7 +23,6 @@
  */
 char *__env[1] = { 0 };
 char **environ = __env;
-extern env_t* env;
 
 /* _exit()
  * Exit a program without cleaning up files. 
@@ -32,7 +31,7 @@ extern env_t* env;
  */
 void _exit(int __status) _ATTRIBUTE ((noreturn))
 {
-       sys_env_destroy(env->env_id);
+       sys_proc_destroy(sys_getpid()); // TODO: can run getpid and cache it
        while(1); //Should never get here...
 }
     
@@ -168,7 +167,7 @@ int fstat(int file, struct stat *st)
  */
 int getpid(void) 
 {
-       return env->env_id;
+       return sys_getpid(); // TODO: can run getpid and cache it
 }
 
 /* isatty()
index 25d9e46..e8a1718 100644 (file)
@@ -1,24 +1,22 @@
 // Called from entry.S to get us going.
-// entry.S already took care of defining envs, pages, vpd, and vpt.
 #ifdef __DEPUTY__
 #pragma nodeputy
 #endif
 
 #include <parlib.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <debug.h>
 
-volatile env_t *env;
 extern int main(int argc, char **argv);
 
 void parlibmain(int argc, char **argv)
 {
-       // set env to point at our env structure in envs[].
-       // TODO: for now, the kernel just copies our env struct to the beginning of
-       // procinfo.  When we figure out what we want there, change this.
-       env = (env_t*)procinfo; 
+       /* This is a good time to connect a global var to the procinfo structure
+        * like we used to do with env_t */
+       //env = (env_t*)procinfo;       
 
-       debug("Hello from env %d!\n", env->env_id);
+       debug("Hello from process %d!\n", getpid());
        // call user main routine
        int r = main(argc, argv);
 
index aab6dc4..cbe5fca 100644 (file)
@@ -5,18 +5,17 @@
 
 #include <parlib.h>
 
-void sys_env_destroy(envid_t envid)
+error_t sys_proc_destroy(int pid)
 {
-       syscall(SYS_env_destroy, envid, 0, 0, 0, 0);
-       while(1); //Should never get here...
+       return syscall(SYS_proc_destroy, pid, 0, 0, 0, 0);
 }
 
-envid_t sys_getenvid(void)
+int sys_getpid(void)
 {
-        return syscall(SYS_getenvid, 0, 0, 0, 0, 0);
+        return syscall(SYS_getpid, 0, 0, 0, 0, 0);
 }
 
-envid_t sys_getcpuid(void)
+size_t sys_getcpuid(void)
 {
         return syscall(SYS_getcpuid, 0, 0, 0, 0, 0);
 }
@@ -31,7 +30,7 @@ uint16_t sys_cgetc(void)
     return syscall(SYS_cgetc, 0, 0, 0, 0, 0);
 }
 
-ssize_t sys_shared_page_alloc(void** addr, envid_t p2, 
+ssize_t sys_shared_page_alloc(void** addr, pid_t p2, 
                               int p1_flags, int p2_flags
                              ) 
 {
@@ -39,7 +38,7 @@ ssize_t sys_shared_page_alloc(void** addr, envid_t p2,
                       p2, p1_flags, p2_flags, 0);
 }
 
-ssize_t sys_shared_page_free(void* addr, envid_t p2) 
+ssize_t sys_shared_page_free(void* addr, pid_t p2) 
 {
        return syscall(SYS_shared_page_free, (intreg_t)addr, p2, 0,0,0);
 }
index d6c2186..712ede5 100644 (file)
@@ -12,7 +12,6 @@
 #include <ros/error.h>
 #include <ros/memlayout.h>
 #include <ros/syscall.h>
-#include <ros/env.h>
 
 #include <stdarg.h>
 #include <string.h>
@@ -23,7 +22,6 @@
 
 // libos.c or entry.S
 extern char *binaryname;
-extern volatile env_t *env;
 // will need to change these types when we have real structs
 // seems like they need to be either arrays [] or functions () for it to work
 extern volatile uint8_t (COUNT(PGSIZE * UINFO_PAGES) procinfo)[];
@@ -60,13 +58,13 @@ ssize_t     sys_cputs(const char *string, size_t len);
 error_t     sys_cputs_async(const char *s, size_t len, syscall_desc_t* desc,
                             void (*cleanup_handler)(void*), void* cleanup_data);
 uint16_t    sys_cgetc(void);
-envid_t     sys_getcpuid(void);
+size_t     sys_getcpuid(void);
 /* Process Management */
-envid_t     sys_getenvid(void);
-error_t     sys_env_destroy(envid_t);
-void           sys_yield(void);
-int                    sys_proc_create(char* path);
-error_t                sys_proc_run(int pid);
+int         sys_getpid(void);
+error_t     sys_proc_destroy(int pid);
+void        sys_yield(void);
+int         sys_proc_create(char* path);
+error_t     sys_proc_run(int pid);
 /* Generic Async Call */
 error_t     waiton_syscall(syscall_desc_t* desc, syscall_rsp_t* rsp);
 
index 9f44f0a..6184004 100644 (file)
@@ -46,6 +46,7 @@
        cpuid(0, 0, 0, 0, 0);                                                      \
        ticks = read_tsc() - ticks;                                                \
        /* Compute the average and print it */                                     \
+       /* env->whatever doesn't work, but these functions are never used. */      \
        uint64_t a = (1000000000LL/(iters) * ticks) / (env->env_tscfreq);          \
        if ((name))                                                                \
                cprintf("Measuring %s:\n"                                              \
index 89a5298..0b0a093 100644 (file)
@@ -10,7 +10,7 @@ error_t cache_buster_async(async_desc_t** desc, uint32_t num_writes,
                            uint32_t num_pages, uint32_t flags);
 uint32_t getcpuid(void);
 void yield(void);
-int proc_create(char* path);
+int proc_create(char *NT path);
 error_t proc_run(int pid);
 
 #endif // ROS_INC_SYSWRAPPER_H
index 7b3a7e8..02cb4f3 100644 (file)
@@ -4,7 +4,7 @@
 .data
 
 
-// Define the global symbols 'envs', 'pages', 'vpt', and 'vpd'
+// Define the global symbols 'procinfo', 'procdata', 'pages', 'vpt', and 'vpd'
 // so that they can be used in C as if they were ordinary global arrays.
        .globl procinfo
        .set procinfo, UINFO
@@ -18,8 +18,8 @@
        .set vpd, (UVPT+(UVPT>>12)*4)
 
 
-// Entrypoint - this is where the kernel (or our parent environment)
-// starts us running when we are initially loaded into a new environment.
+// Entrypoint - this is where the kernel (or our parent process)
+// starts us running when we are initially created and run
 .text
 .globl _start
 _start:
index cd64677..ae19a6c 100644 (file)
@@ -4,7 +4,7 @@
 .data
 
 
-// Define the global symbols 'envs', 'pages', 'vpt', and 'vpd'
+// Define the global symbols 'procinfo', 'procdata', 'pages', 'vpt', and 'vpd'
 // so that they can be used in C as if they were ordinary global arrays.
        .globl procinfo
        .set procinfo, UINFO
@@ -18,8 +18,8 @@
        .set vpd, (UVPT+(UVPT>>12)*4)
 
 
-// Entrypoint - this is where the kernel (or our parent environment)
-// starts us running when we are initially loaded into a new environment.
+// Entrypoint - this is where the kernel (or our parent process)
+// starts us running when we are initially created and run
 .text
 .globl _start
 _start:
index 7556ec2..fbaa67e 100644 (file)
@@ -1,11 +1,8 @@
 #include <lib.h>
 
-extern env_t* env;
-
 void exit(void) __attribute__((noreturn))
 {
-       sys_env_destroy(env->env_id);
+       sys_proc_destroy(sys_getpid());
        //Shouldn't get here, but include anyway so the compiler is happy.. 
        while(1);
 }
-
index 41976eb..de138b8 100644 (file)
@@ -1,5 +1,4 @@
 // Called from entry.S to get us going.
-// entry.S already took care of defining envs, pages, vpd, and vpt.
 #ifdef __DEPUTY__
 #pragma nodeputy
 #endif
@@ -9,7 +8,6 @@
 
 extern int main(int argc, char **argv);
 
-volatile env_t *env;
 char *binaryname = "(PROGRAM NAME UNKNOWN)";
 syscall_front_ring_t sysfrontring;
 syscall_desc_pool_t syscall_desc_pool;
@@ -22,10 +20,9 @@ async_desc_t* current_async_desc;
 void
 libmain(int argc, char **argv)
 {
-       // set env to point at our env structure in envs[].
-       // TODO: for now, the kernel just copies our env struct to the beginning of
-       // procinfo.  When we figure out what we want there, change this.
-       env = (env_t*)procinfo; 
+       /* This is a good time to connect a global var to the procinfo structure
+        * like we used to do with env_t */
+       //env = (env_t*)procinfo;       
 
        // Set up the front ring for the general syscall ring
        // TODO: Reorganize these global variables
index 9757da5..ea36552 100644 (file)
@@ -1,4 +1,4 @@
-// Implementation of cprintf console output for user environments,
+// Implementation of cprintf console output for user processes,
 // based on printfmt() and the sys_cputs() system call.
 //
 // cprintf is a debugging statement, not a generic output statement.
index cd91a0a..2254cb2 100644 (file)
@@ -109,19 +109,19 @@ uint16_t sys_cgetc(void)
        return syscall(SYS_cgetc, 0, 0, 0, 0, 0);
 }
 
-envid_t sys_getcpuid(void)
+size_t sys_getcpuid(void)
 {
        return syscall(SYS_getcpuid, 0, 0, 0, 0, 0);
 }
 
-envid_t sys_getenvid(void)
+int sys_getpid(void)
 {
-       return syscall(SYS_getenvid, 0, 0, 0, 0, 0);
+       return syscall(SYS_getpid, 0, 0, 0, 0, 0);
 }
 
-error_t sys_env_destroy(envid_t envid)
+error_t sys_proc_destroy(int pid)
 {
-       return syscall(SYS_env_destroy, envid, 0, 0, 0, 0);
+       return syscall(SYS_proc_destroy, pid, 0, 0, 0, 0);
 }
 
 void sys_yield(void)
index 2f7dc4e..4742a30 100644 (file)
@@ -46,7 +46,7 @@ void yield(void)
        return;
 }
 
-int proc_create(char* path)
+int proc_create(char *NT path)
 {
        return sys_proc_create(path);
 }