Added (temporary) mechanism to pass argc/argv
authorAndrew Waterman <waterman@r53.millennium.berkeley.edu>
Tue, 27 Oct 2009 05:24:03 +0000 (22:24 -0700)
committerAndrew Waterman <waterman@r53.millennium.berkeley.edu>
Tue, 27 Oct 2009 05:24:03 +0000 (22:24 -0700)
Obviously, the kernel should not be responsible for passing
args to user programs; that's a job for the runtime system.
However, to run real programs from within the manager, this
is a necessary evil.

I pass argc/argv inside of the procinfo struct.  They
are set using a call to proc_init_argc_argv(), and they
are read out by user programs within parlibmain().  The
latter no longer expects to be passed argc/argv; instead,
it grabs them from procinfo.

kern/include/process.h
kern/include/ros/procdata.h
kern/src/env.c
user/apps/parlib/pthread/blackscholes.c
user/parlib/src/i386/entry.S
user/parlib/src/parlibmain.c
user/parlib/src/sparc/entry.S

index 85e36b0..fa3bf32 100644 (file)
@@ -71,6 +71,9 @@ void proc_startcore(struct proc *SAFE p, trapframe_t *SAFE tf)
 void proc_destroy(struct proc *SAFE p);
 void proc_yield(struct proc *SAFE p);
 
+/* argc/argv.  TODO: figure out how to move this out of the kernel. */
+size_t proc_init_argc_argv(struct proc* p, size_t nargs, ...);
+
 /* Process core management.  Only call these if you are RUNNING_M or RUNNABLE_M.
  * These all adjust the vcoremap and take appropriate actions (like __startcore
  * if you were already RUNNING_M.  You could be RUNNABLE_M with no vcores when
index b48feb0..72b51a1 100644 (file)
@@ -9,9 +9,16 @@
 #include <ros/error.h>
 #include <ros/common.h>
 
+#define PROCINFO_MAX_ARGC 32
+#define PROCINFO_MAX_ARGV_SIZE 1024
+
 typedef struct procinfo {
        pid_t id;
        size_t max_harts;
+
+       size_t argc;
+       char* argv[PROCINFO_MAX_ARGC];
+       char argv_buf[PROCINFO_MAX_ARGV_SIZE];
 } procinfo_t;
 #define PROCINFO_NUM_PAGES  ((sizeof(procinfo_t)-1)/PGSIZE + 1)        
 
index 8c1edaf..b9ee4d5 100644 (file)
@@ -242,6 +242,56 @@ proc_init_procinfo(struct proc* p)
        p->env_procinfo->max_harts = num_cpus-1;
 }
 
+// Sets up argc/argv in procinfo.  Returns number of
+// args successfully imported (because of size restrictions).
+// The procinfo pages must have been mapped into the user's
+// address space before this function can be called.
+static size_t
+proc_init_argc_argv_v(struct proc* p, size_t nargs, va_list args)
+{
+       // TODO: right now we assume procinfo can be directly addressed
+       // by the kernel (i.e. it's continguous.
+       static_assert(sizeof(struct procinfo) <= PGSIZE);
+
+       if(nargs > PROCINFO_MAX_ARGC)
+               nargs = PROCINFO_MAX_ARGC;
+
+       char* argv[PROCINFO_MAX_ARGC] = {0};
+       static_assert(sizeof(argv) == sizeof(p->env_procinfo->argv));
+
+       size_t size = 0, argc;
+       for(argc = 0; argc < nargs; argc++)
+       {
+               const char* arg = va_arg(args,const char*);
+               size_t len = strnlen(arg,PROCINFO_MAX_ARGV_SIZE);
+               if(size+len+1 > PROCINFO_MAX_ARGV_SIZE)
+                       break;
+               memcpy(&p->env_procinfo->argv_buf[size],arg,len+1);
+               argv[argc] = (char*)(UINFO+offsetof(struct procinfo,argv_buf)+size);
+               size += len+1;
+       }
+
+       p->env_procinfo->argc = argc;
+       memcpy(p->env_procinfo->argv,argv,sizeof(argv));
+
+       return argc;
+}
+
+size_t
+proc_init_argc_argv(struct proc* p, size_t nargs, ...)
+{
+       size_t ret;
+
+       va_list list;
+       va_start(list,nargs);
+
+       ret = proc_init_argc_argv_v(p,nargs,list);
+
+       va_end(list);
+
+       return ret;
+}
+
 //
 // Allocates and initializes a new environment.
 // On success, the new environment is stored in *newenv_store.
index 09d3b8e..e91a262 100644 (file)
@@ -70,6 +70,8 @@
 #include <math.h>
 #include <string.h>
 
+#define ENABLE_THREADS
+
 #ifdef ENABLE_PARSEC_HOOKS
 #include <hooks.h>
 #endif
index ab5b4ec..21e044d 100644 (file)
@@ -31,19 +31,11 @@ _start:
        test    %eax,%eax
        jne     notcore0
 
-       // See if we were started with arguments on the stack
-       cmpl $USTACKTOP, %esp
-       jne args_exist
-
-       // If not, push dummy argc/argv arguments.
-       // This happens when we are loaded by the kernel,
-       // because the kernel does not know about passing arguments.
-       pushl $0
-       pushl $0
-
-args_exist:
+       // argc/argv are provided by procinfo and are accessed in parlibmain
        call parlibmain
-1:      jmp 1b
+
+       // illegal instruction in case parlibmain accidentally returns
+       mov     (0),%eax
 
 notcore0:
        mov     stack_ptr_array,%edx
@@ -53,4 +45,5 @@ notcore0:
 
        call    hart_yield
 
-1:     jmp     1b
+       // illegal instruction in case hart_yield accidentally returns
+       mov     (0),%eax
index 992d32b..f2d1efb 100644 (file)
@@ -5,13 +5,11 @@
 #include <unistd.h>
 #include <debug.h>
 
-extern int main(int argc, char * NTS * COUNT(argc) NT argv);
-
-void parlibmain(int argc, char * NTS * COUNT(argc) NT argv)
+void parlibmain()
 {
-       debug("Hello from process %d!\n", getpid());
        // call user main routine
-       int r = main(argc, argv);
+       extern int main(int argc, char * NTS * COUNT(argc) NT argv);
+       int r = main(procinfo.argc, procinfo.argv);
 
        // exit gracefully
        exit(r);
index 4eb7cc9..09a68b1 100644 (file)
@@ -33,21 +33,6 @@ _start:
        bne     notcore0
         nop
 
-       // Save top 256 bytes of stack for other threads to allocate their stacks
-       //sub   %sp,256,%sp
-
-       // See if we were started with arguments on the stack
-       tst     %o0
-       bne     args_exist
-        nop
-
-       // If not, push dummy argc/argv arguments.
-       // This happens when we are loaded by the kernel,
-       // because the kernel does not know about passing arguments.
-       mov     0,%o0
-       mov     0,%o1
-
-args_exist:
        call    parlibmain
         nop