Can run batches of processes repeatedly.
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 22 May 2009 07:03:34 +0000 (00:03 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Tue, 26 May 2009 04:57:38 +0000 (21:57 -0700)
Created a manager function that runs on core 0, which can create batches
of environments, run one on core 0, and then continue.  It's a bit
hacky, since there's the issue of not being able to return from env_run
(yet).

include/env.h
include/manager.h [new file with mode: 0644]
include/workqueue.h
kern/src/Makefrag
kern/src/env.c
kern/src/init.c
kern/src/manager.c [new file with mode: 0644]
kern/src/workqueue.c
user/apps/roslib/measurements.c

index 067016d..7f76553 100644 (file)
@@ -6,10 +6,6 @@
 #include <arch/x86.h>
 #include <ros/env.h>
 
-#ifndef ROS_MULTIENV
-#define ROS_MULTIENV 0
-#endif
-
 extern env_t *envs;            // All environments
 extern env_t* NORACE curenvs[MAX_NUM_CPUS];
 
@@ -18,7 +14,7 @@ LIST_HEAD(env_list_t, env_t);         // Declares 'struct Env_list'
 void   env_init(void);
 int            env_alloc(env_t **e, envid_t parent_id);
 void   env_free(env_t *e);
-void   env_create(uint8_t *binary, size_t size);
+env_t* env_create(uint8_t *binary, size_t size);
 void   (IN_HANDLER env_destroy)(env_t *e);     // Does not return if e == curenv
 
 int    envid2env(envid_t envid, env_t **env_store, bool checkperm);
@@ -26,17 +22,11 @@ int envid2env(envid_t envid, env_t **env_store, bool checkperm);
 void   (IN_HANDLER env_run)(env_t *e) __attribute__((noreturn));
 void   env_pop_tf(trapframe_t *tf) __attribute__((noreturn));
 
-// For the grading script
-#define ENV_CREATE2(start, size)       {               \
-       extern uint8_t start[], size[];                 \
-       env_create(start, (int)size);                   \
-}
-
-#define ENV_CREATE(x)                  {               \
+#define ENV_CREATE(x)                  ({              \
        extern uint8_t _binary_obj_##x##_start[],       \
                _binary_obj_##x##_size[];               \
        env_create(_binary_obj_##x##_start,             \
                (int)_binary_obj_##x##_size);           \
-}
+})
 
 #endif // !ROS_KERN_ENV_H
diff --git a/include/manager.h b/include/manager.h
new file mode 100644 (file)
index 0000000..b333893
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
+
+#ifndef ROS_KERN_MANAGER_H
+#define ROS_KERN_MANAGER_H
+
+/*
+ * The manager is the "asymmetric control unit", that runs on core 0 for now
+ * and controls the actions of the whole system.
+ */
+
+void manager(void);
+
+#endif /* ROS_KERN_MANAGER_H */
index 7010d74..c06d39c 100644 (file)
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
+
 #ifndef ROS_KERN_WORKQUEUE_H
 #define ROS_KERN_WORKQUEUE_H
 #ifndef ROS_KERNEL
index 4e323ee..6ccaee6 100644 (file)
@@ -29,6 +29,7 @@ KERN_SRCFILES := $(KERN_SRC_DIR)/entry.S \
                  $(KERN_SRC_DIR)/apic.c \
                  $(KERN_SRC_DIR)/testing.c \
                  $(KERN_SRC_DIR)/workqueue.c \
+                 $(KERN_SRC_DIR)/manager.c \
                  $(KERN_SRC_DIR)/atomic.c \
                  $(KERN_SRC_DIR)/smp.c \
                  $(KERN_SRC_DIR)/printfmt.c \
index ce56600..53fd138 100644 (file)
@@ -16,6 +16,7 @@
 #include <pmap.h>
 #include <trap.h>
 #include <monitor.h>
+#include <manager.h>
 
 #include <ros/syscall.h>
 
@@ -383,16 +384,8 @@ load_icode(env_t *e, uint8_t *binary, size_t size)
 
 //
 // Allocates a new env and loads the named elf binary into it.
-// This function is ONLY called during kernel initialization,
-// before running the first user-mode environment.
-// The new env's parent ID is set to 0.
 //
-// Where does the result go?
-// By convention, envs[0] is the first environment allocated, so
-// whoever calls env_create simply looks for the newly created
-// environment there.
-void
-env_create(uint8_t *binary, size_t size)
+env_t* env_create(uint8_t *binary, size_t size)
 {
        env_t *e;
        int r;
@@ -400,6 +393,7 @@ env_create(uint8_t *binary, size_t size)
        if ((r = env_alloc(&e, 0)) < 0)
                panic("env_create: %e", r);
        load_icode(e, binary, size);
+       return e;
 }
 
 //
@@ -468,14 +462,23 @@ env_destroy(env_t *e)
        // never get back to their old hlt/relaxed/spin state, so we need to force
        // them back to an idle function.
        uint32_t id = lapic_get_id();
+       // There is no longer a curenv for this core. (TODO: Think about this.)
+       curenvs[id] = NULL;
        if (id) {
                smp_idle();
                panic("should never see me");
        }
        // else we're core 0 and can do the usual
 
-//TODO: consider returning to a dispatching function instead of this, since we
-//can't get back to init.
+       /* Instead of picking a new environment to run, or defaulting to the monitor
+        * like before, for now we'll hop into the manager() function, which
+        * dispatches jobs.  Note that for now we start the manager from the top,
+        * and not from where we left off the last time we called manager.  That
+        * would require us to save some context (and a stack to work on) here.
+        */
+       manager();
+       assert(0); // never get here
+
        // ugly, but for now just linearly search through all possible
        // environments for a runnable one.
        for (int i = 0; i < NENV; i++) {
index a83efe0..d03e01c 100644 (file)
 #include <testing.h>
 #include <syscall.h>
 #include <kclock.h>
+#include <kern/manager.h>
 
 static void print_cpuinfo(void);
 
-static void work_env_run(void* data)
-{
-       env_run((env_t*)data);
-}
-
-static void run_env_handler(trapframe_t *tf, void* data)
-{
-       assert(data);
-       per_cpu_info[lapic_get_id()].delayed_work.func = work_env_run;
-       per_cpu_info[lapic_get_id()].delayed_work.data = data;
-}
-
 void kernel_init(multiboot_info_t *mboot_info)
 {
        extern char (BND(__this, end) edata)[], (SNT end)[];
@@ -77,57 +66,7 @@ void kernel_init(multiboot_info_t *mboot_info)
        test_ipi_sending();
        test_pit();
        */
-
-       //ENV_CREATE(user_faultread);
-       //ENV_CREATE(user_faultreadkernel);
-       //ENV_CREATE(user_faultwrite);
-       //ENV_CREATE(user_faultwritekernel);
-       //ENV_CREATE(user_breakpoint);
-       //ENV_CREATE(user_badsegment);
-       //ENV_CREATE(user_divzero);
-       //ENV_CREATE(user_buggyhello);
-       //ENV_CREATE(user_evilhello);
-       //ENV_CREATE(user_hello);
-       //ENV_CREATE(user_apps_parlib_hello);
-       //ENV_CREATE(user_apps_roslib_hello);
-       //ENV_CREATE(user_hello);
-       //ENV_CREATE(user_hello);
-       //ENV_CREATE(user_hello);
-       ENV_CREATE(user_null);
-       ENV_CREATE(user_null);
-       ENV_CREATE(user_null);
-       ENV_CREATE(user_null);
-       ENV_CREATE(user_null);
-       ENV_CREATE(user_null);
-       ENV_CREATE(user_null);
-       ENV_CREATE(user_null);
-
-       //env_run(&envs[0]);
-       //env_run(&envs[1]);
-       smp_call_function_single(0, run_env_handler, &envs[0], 0);
-       smp_call_function_single(1, run_env_handler, &envs[1], 0);
-       smp_call_function_single(2, run_env_handler, &envs[2], 0);
-       smp_call_function_single(3, run_env_handler, &envs[3], 0);
-       smp_call_function_single(4, run_env_handler, &envs[4], 0);
-       smp_call_function_single(5, run_env_handler, &envs[5], 0);
-       smp_call_function_single(6, run_env_handler, &envs[6], 0);
-       smp_call_function_single(7, run_env_handler, &envs[7], 0);
-       process_workqueue();
-       udelay(5000000);
-       panic("Don't Panic");
-
-       /*
-       // wait 5 sec, then print what's in shared mem
-       udelay(5000000);
-       printk("Servicing syscalls from Core 0:\n\n");
-       while (1) {
-               process_generic_syscalls(&envs[0], 1);
-               //process_generic_syscalls(&envs[1], 1);
-               //process_generic_syscalls(&envs[2], 1);
-               cpu_relax();
-       }
-       panic("Don't Panic");
-       */
+       manager();
 }
 
 /*
diff --git a/kern/src/manager.c b/kern/src/manager.c
new file mode 100644 (file)
index 0000000..bf50ee6
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
+
+#ifdef __DEPUTY__
+#pragma nodeputy
+#endif
+
+#include <inc/types.h>
+#include <inc/assert.h>
+
+#include <kern/manager.h>
+#include <kern/smp.h>
+#include <kern/env.h>
+#include <kern/apic.h>
+#include <kern/workqueue.h>
+
+/* Helper handlers for smp_call to dispatch jobs to other cores */
+static void work_env_run(void* data)
+{
+       env_run((env_t*)data);
+}
+
+static void run_env_handler(trapframe_t *tf, void* data)
+{
+       assert(data);
+       per_cpu_info[lapic_get_id()].delayed_work.func = work_env_run;
+       per_cpu_info[lapic_get_id()].delayed_work.data = data;
+}
+
+/*
+ * Currently, if you leave this function by way of env_run (process_workqueue
+ * that env_runs), you will never come back to where you left off, and the
+ * function will start from the top.  Hence the hack 'progress'.
+ */
+void manager(void)
+{
+       static uint8_t progress = 0;
+       env_t* env_batch[64]; // Fairly arbitrary, just the max I plan to use.
+
+       switch (progress++) {
+               case 0:
+                       for (int i = 0; i < 8; i++)
+                               env_batch[i] = ENV_CREATE(user_null);
+                       for (int i = 0; i < 8; i++)
+                               smp_call_function_single(i, run_env_handler, env_batch[i], 0);
+                       process_workqueue(); // Will run this core (0)'s env
+                       break;
+               case 1:
+                       for (int i = 0; i < 4; i++)
+                               env_batch[i] = ENV_CREATE(user_null);
+                       for (int i = 0; i < 4; i++)
+                               smp_call_function_single(i, run_env_handler, env_batch[i], 0);
+                       //env_t* an_env = ENV_CREATE(user_null);
+                       //env_run(an_env);
+                       //smp_call_function_single(2, run_env_handler, an_env, 0);
+                       process_workqueue();
+                       break;
+               default:
+                       printk("Waiting 5 sec for whatever reason\n");
+                       udelay(5000000);
+                       panic("Don't Panic");
+       }
+       panic("If you see me, then you probably screwed up");
+
+       /*
+       printk("Servicing syscalls from Core 0:\n\n");
+       while (1) {
+               process_generic_syscalls(&envs[0], 1);
+               cpu_relax();
+       }
+       */
+}
+
index ca0e691..80bcd40 100644 (file)
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
+
 #include <inc/x86.h>
 
 #include <kern/workqueue.h>
index 100b86d..311ac2f 100644 (file)
 #pragma nodeputy
 #endif
 
-#define NUM_ITERATIONS 100000
-uint64_t times[NUM_ITERATIONS];
-
-uint64_t total(uint64_t (COUNT(length) array)[], int length)
-{
-       uint64_t sum = 0;
-       for(int i=0; i<length; i++) {
-               sum+=array[i];
-       }
-       return sum;
-       //return (length > 0) ? sum/((uint64_t)length) : 0;
-}
-
 int main(int argc, char** argv)
 {
+       /*
        TAGGED_TIMING_BEGIN(tst);
        async_desc_t *desc1, *desc2;
        async_rsp_t rsp1, rsp2;
+       cprintf ("training result %llu\n", timing_overhead);
        cache_buster_async(&desc1, 20, 0xdeadbeef);
        cache_buster_async(&desc2, 10, 0xcafebabe);
        waiton_async_call(desc1, &rsp1);
@@ -41,9 +30,13 @@ int main(int argc, char** argv)
        // Note this won't actually do 100 inner runs (first parameter).  will stop
        // making calls beyond the ring size and won't wait on any extra calls.
        measure_async_call(null_async(&desc), desc, 100, 100, "Async Null");
-       
-    TAGGED_TIMING_END(tst);
+       for (int i=0; i<100;i++){
+               TAGGED_TIMING_BEGIN(umain);
+               TAGGED_TIMING_END(umain);
+       }
+       POOL_FOR_EACH(&timer_pool, print_timer);
        // Spin to make sure we don't have any resources deallocated before done
        while(1);
-       return 0;
+       */
+       cprintf("Env %x says hi and quits\n", env->env_id);
 }