Beginnings of an implementation of channels for ROS
authorKevin Klues <klueska@eecs.berkeley.edu>
Thu, 30 Jul 2009 18:10:39 +0000 (11:10 -0700)
committerKevin Klues <klueska@eecs.berkeley.edu>
Sat, 1 Aug 2009 00:56:50 +0000 (17:56 -0700)
The channel implementation uses shared memory for the communication channel. The create / delete API consists of user level library code that makes system calls to set up shared memory pages between 2 processes (environments).  For each direction of the channel 2 pages are needed.  One for holding the ring buffer, and one for storing the data.  The ring buffer page is mapped in as read/write by both processes, while the data page is read/write for the creator of the channel, but read only by the listener on the channel.  For bidirectional channels, two of these single directional channels are necessary.

To support channels in this way, a range of addresses in the virtual address space has now been reserved for sysevents, much like the space reserved for asynchronous system calls that we had before.  The space reserved for sysevents contains a ring buffer that the user space program can poll on to see if the kernel has tried sending it any events.  Eventntually we will want to allow the user space process to register events of interest with the kernel so that it will be interrupted if they come in, rather than needing to explicitly poll for them.

Additionally, the directory structure and proper symlinks, etc. for getting everything to compile for parlib with the new directory structure is now in place.

39 files changed:
.gitignore
GNUmakefile
kern/include/listable.h [new file with mode: 0644]
kern/include/pmap.h
kern/include/ros/env.h
kern/include/ros/memlayout.h
kern/include/ros/ring_buffer.h
kern/include/ros/syscall.h
kern/include/ros/sysevent.h [new file with mode: 0644]
kern/src/Makefrag
kern/src/env.c
kern/src/manager.c
kern/src/pmap.c
kern/src/syscall.c
kern/src/sysevent.c [new file with mode: 0644]
user/Makefrag
user/apps/parlib/Makefrag
user/apps/parlib/channel_test_client.c [new file with mode: 0644]
user/apps/parlib/channel_test_server.c [new file with mode: 0644]
user/parlib/Makefrag
user/parlib/inc/arch
user/parlib/inc/channel.h [new file with mode: 0644]
user/parlib/inc/parlib.h
user/parlib/inc/ros
user/parlib/ivy/Makefrag [new file with mode: 0644]
user/parlib/ivy/deputy.c [new file with mode: 0644]
user/parlib/src/Makefrag
user/parlib/src/channel.c [new file with mode: 0644]
user/parlib/src/entry.S [deleted file]
user/parlib/src/entry_i386.S [new file with mode: 0644]
user/parlib/src/entry_sparc.S [new file with mode: 0644]
user/parlib/src/newlib_backend.c
user/parlib/src/syscall.c
user/parlib/src/syscall_i386.c [new file with mode: 0644]
user/parlib/src/syscall_sparc.c [new file with mode: 0644]
user/roslib/Makefrag
user/roslib/src/entry_i386.S
user/roslib/src/entry_sparc.S
user/roslib/src/syscall.c

index 03ab5fd..a5dde3b 100644 (file)
@@ -11,3 +11,4 @@ cscope.out
 hdd.img
 *.*~
 Makelocal
+ros-project.tmproj
index eaf4abe..7b8e140 100644 (file)
@@ -12,6 +12,9 @@ OBJDIR := obj
 # User defined constants passed on the command line 
 TARGET_ARCH := i386
 
+# Make sure that 'all' is the first target
+all: symlinks
+
 -include Makelocal
 
 TOP_DIR := .
@@ -80,9 +83,6 @@ endif
 # List of directories that the */Makefrag makefile fragments will add to
 OBJDIRS :=
 
-# Make sure that 'all' is the first target
-all: symlinks
-
 kern/boot/Makefrag: symlinks
 
 symlinks:
diff --git a/kern/include/listable.h b/kern/include/listable.h
new file mode 100644 (file)
index 0000000..ece51ea
--- /dev/null
@@ -0,0 +1,32 @@
+/* Copyright (c) 2009 The Regents of the University  of California. 
+ * See the COPYRIGHT files at the top of this source tree for full 
+ * license information.
+ * 
+ * Kevin Klues <klueska@cs.berkeley.edu>    
+ */
+#ifndef ROS_LISTABLE_H
+#define ROS_LISTABLE_H
+#include <arch/types.h>
+#include <sys/queue.h>
+
+#define DECLARE_LISTABLE_ITEM(name, link, item)   \
+struct name;                                      \
+struct name {                                     \
+       LIST_ENTRY(name) link;                        \
+       item;                                         \
+};                                                \
+LIST_HEAD(name##_list, name);                     \
+typedef struct name name##_t;                     \
+typedef struct name##_list name##_list_t;
+
+#endif //ROS_LISTABLE_H
+
+
+
+
+
+
+
+
index 14188dd..e3b56a5 100644 (file)
@@ -91,6 +91,8 @@ int     page_alloc_specific(page_t **pp_store, size_t ppn);
 void   page_free(page_t *pp);
 int            page_is_free(size_t ppn);
 int        page_insert(pde_t *COUNT(NPDENTRIES) pgdir, page_t *pp, void *SNT va, int perm);
+void*   page_insert_in_range(pde_t *COUNT(NPDENTRIES) pgdir, page_t *pp, 
+                             void *SNT vab, void *SNT vae, int perm);
 void   page_remove(pde_t *COUNT(NPDENTRIES) pgdir, void *SNT va);
 page_t* page_lookup(pde_t *COUNT(NPDENTRIES) pgdir, void *va, pte_t **pte_store);
 error_t        pagetable_remove(pde_t *COUNT(NPDENTRIES) pgdir, void *va);
index 57f2333..f893632 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <ros/memlayout.h>
 #include <ros/syscall.h>
+#include <ros/sysevent.h>
 #include <arch/types.h>
 #include <sys/queue.h>
 #include <arch/trap.h>
@@ -54,16 +55,27 @@ struct Env {
        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_sysbackring;    // BackRing for generic syscalls
+       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 these two proper types (pointers to structs)
+       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)
-       void*COUNT(PGSIZE) env_procdata;                // KVA of per-process shared data table (RW)
+       
+       // 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
 };
index 5c2390f..8e4e6e9 100644 (file)
@@ -31,7 +31,7 @@
  *                     |         Kernel Stack         | RW/--  KSTKSIZE   |
  *                     | - - - - - - - - - - - - - - -|                 PTSIZE
  *                     |      Invalid Memory (*)      | --/--             |
- *    ULIM     ------> +------------------------------+ 0xbf800000      --+
+ *    ULIM      ----> +------------------------------+ 0xbf800000      --+
  *                     |  Cur. Page Table (User R-)   | R-/R-  PTSIZE
  *    UVPT      ---->  +------------------------------+ 0xbf400000
  *                     |          RO PAGES            | R-/R-  PTSIZE
  *                     +------------------------------+ 0xbec01000      PTSIZE
  *                     |     Per-Process R/O Info     | R-/R-  PGSIZE     |
  * UTOP, UINFO  ---->  +------------------------------+ 0xbec00000      --+
+ *                     |     Async Syscall Ring       | RW/RW  PGSIZE     |
+ *   USYSCALL   ---->  +------------------------------+ 0xbebff000        |
+ *                     |     Async Sysevent Ring      | RW/RW  PGSIZE     |
+ *   USYSEVENT  ---->  +------------------------------+ 0xbebfe000      PTSIZE
  *                     |      Global Shared Page      | RW/RW  PGSIZE     |
- *      UGDATA  ---->  +------------------------------+ 0xbebff000        |
+ *     UGDATA   ---->  +------------------------------+ 0xbebfd000        |
  *                     |  Unmapped (future expansion) | --/--             |
- *                     +------------------------------+ 0xbe801000      PTSIZE
- *                     |     Per-Process R/W Data     | RW/RW  PGSIZE     |
- * UDATA,UXSTACKTOP--> +------------------------------+ 0xbe800000      --+
+ *   UXSTACKTOP ---->  +------------------------------+ 0xbe800000      --+
  *                     |     User Exception Stack     | RW/RW  PGSIZE
  *                     +------------------------------+ 0xbe7ff000
  *                     |       Empty Memory (*)       | --/--  PGSIZE
 // Top of user-accessible VM
 #define UTOP           UINFO
 
-// Read-write, global page.  Shared by all processes.  Can't be trusted.
-#define UGDATA         (UTOP - PGSIZE)
+// Read-write, per-process shared page for sending asynchronous 
+// syscalls to the kernel
+#define USYSCALL    (UTOP - PGSIZE)
+
+// Read-write, per-process shared page for receiving asynchronous 
+// sysevents from the kernel
+#define USYSEVENT   (USYSCALL - PGSIZE)
 
-// Read-write, per-process shared data structures
-#define UDATA          (UTOP - PTSIZE)
-#define UDATA_PAGES 1
+// Read-write, global page.  Shared by all processes.  Can't be trusted.
+#define UGDATA   (USYSEVENT - PGSIZE)
 
 // Top of one-page user exception stack
-#define UXSTACKTOP     UDATA
+#define UXSTACKTOP     (UTOP - PTSIZE)
 // Next page left invalid to guard against exception stack overflow; then:
 // Top of normal user stack
 #define USTACKTOP      (UXSTACKTOP - 2*PGSIZE)
index 87242e4..ca4a836 100644 (file)
@@ -27,6 +27,7 @@
 #ifndef ROS_INC_RING_BUFFER_H
 #define ROS_INC_RING_BUFFER_H
 
+#include <string.h>
 #include <arch/atomic.h>
 
 #define xen_mb()  mb()
@@ -90,7 +91,7 @@ typedef unsigned int RING_IDX;
 union __name##_sring_entry {                                            \
     __req_t req;                                                        \
     __rsp_t rsp;                                                        \
-};                                                                      \
+} TRUSTED;                                                              \
                                                                         \
 /* Shared ring page */                                                  \
 struct __name##_sring {                                                 \
index e7e4520..128ff43 100644 (file)
@@ -17,6 +17,8 @@ enum
        SYS_getcpuid,
        SYS_serial_write,
        SYS_serial_read,
+       SYS_shared_page_alloc,
+       SYS_shared_page_free,
        SYS_getenvid,
        SYS_env_destroy,
        SYS_yield,
@@ -36,11 +38,11 @@ enum
 #define BUSTER_PRINT_TICKS             0x0008
 #define BUSTER_JUST_LOCKS              0x0010 // unimplemented
 
-#define NUM_SYS_ARGS 6
+#define NUM_SYSCALL_ARGS 6
 typedef struct syscall_req {
        uint32_t num;
        uint32_t flags;
-       uint32_t args[NUM_SYS_ARGS];
+       uint32_t args[NUM_SYSCALL_ARGS];
 } syscall_req_t;
 
 typedef struct syscall_rsp {
diff --git a/kern/include/ros/sysevent.h b/kern/include/ros/sysevent.h
new file mode 100644 (file)
index 0000000..dc9d06a
--- /dev/null
@@ -0,0 +1,36 @@
+/* Copyright (c) 2009 The Regents of the University of California. 
+ * See the COPYRIGHT files at the top of this source tree for full 
+ * license information.
+ * 
+ * Kevin Klues <klueska@cs.berkeley.edu>    
+ */
+
+#ifndef ROS_SYSEVENT_H
+#define ROS_SYSEVENT_H
+
+#include <ros/error.h>
+#include <ros/ring_buffer.h>
+
+typedef enum {
+       SYS_begofevents, //Should always be first
+       
+       SYS_shared_page_alloc_event, 
+       SYS_shared_page_free_event, 
+
+       SYS_endofevents //Should always be last
+} sysevent_type_t;
+
+#define NUM_SYSEVENT_ARGS 6
+typedef struct sysevent {
+       sysevent_type_t type;
+       uint32_t args[NUM_SYSEVENT_ARGS];
+} sysevent_t;
+
+typedef struct sysevent_rsp {
+       error_t rsp;
+} sysevent_rsp_t;
+
+// Generic Syscall Ring Buffer
+DEFINE_RING_TYPES(sysevent, sysevent_t, sysevent_rsp_t);
+
+#endif //ROS_SYSEVENT_H
\ No newline at end of file
index 30f7a08..2729cf9 100644 (file)
@@ -38,9 +38,10 @@ KERN_APPFILES := \
                     $(USER_APPS_ROSLIB_DIR)/fptest \
                     $(USER_APPS_ROSLIB_DIR)/null \
                     $(USER_APPS_ROSLIB_DIR)/hello \
-                    $(USER_APPS_ROSLIB_DIR)/measurements \
-#                    $(USER_APPS_PARLIB_DIR)/matrix \
-#                    $(USER_APPS_PARLIB_DIR)/draw_nanwan \
+                    $(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
 
index 8882038..1705425 100644 (file)
@@ -109,21 +109,39 @@ env_init(void)
 //
 static int
 env_setup_vm(env_t *e)
-WRITES(e->env_pgdir, e->env_cr3, e->env_procinfo, e->env_procdata,
-       e->env_sysbackring)
+WRITES(e->env_pgdir, e->env_cr3, e->env_procinfo, e->env_syscallring,
+       e->env_syseventring, e->env_syscallbackring, e->env_syseventfrontring)
 {
        int i, r;
-       page_t *pgdir = NULL, *pginfo = NULL, *pgdata = NULL;
-
-       // Allocate pages for the page directory, shared info, and shared data pages
+       page_t *pgdir = NULL;
+       page_t *pginfo = NULL; 
+       page_t *pgsyscallring = NULL;
+       page_t *pgsyseventring = NULL;
+
+       /* 
+        * Allocate pages for the page directory, shared info, shared data, 
+        * and kernel message pages
+        */
        r = page_alloc(&pgdir);
+       if(r < 0) return r;
        r = page_alloc(&pginfo);
-       r = page_alloc(&pgdata);
+       if (r < 0) {
+               page_free(pgdir);
+               return r;
+       }       
+       r = page_alloc(&pgsyscallring);
        if (r < 0) {
                page_free(pgdir);
                page_free(pginfo);
                return r;
        }
+       r = page_alloc(&pgsyseventring);
+       if (r < 0) {
+               page_free(pgdir);
+               page_free(pginfo);
+               page_free(pgsyscallring);
+               return r;
+       }
 
        // Now, set e->env_pgdir and e->env_cr3,
        // and initialize the page directory.
@@ -146,17 +164,23 @@ WRITES(e->env_pgdir, e->env_cr3, e->env_procinfo, e->env_procdata,
        e->env_pgdir = page2kva(pgdir);
        e->env_cr3 = page2pa(pgdir);
        e->env_procinfo = page2kva(pginfo);
-       e->env_procdata = page2kva(pgdata);
+       e->env_syscallring = page2kva(pgsyscallring);
+       e->env_syseventring = page2kva(pgsyseventring);
 
        memset(page2kva(pgdir), 0, PGSIZE);
        memset(e->env_procinfo, 0, PGSIZE);
-       memset(e->env_procdata, 0, PGSIZE);
+       memset((void*COUNT(PGSIZE)) TC(e->env_syscallring), 0, PGSIZE);
+       memset((void*COUNT(PGSIZE)) TC(e->env_syseventring), 0, PGSIZE);
 
        // Initialize the generic syscall ring buffer
-       SHARED_RING_INIT((syscall_sring_t *SAFE)e->env_procdata);
-       // Initialize the backend of the ring buffer
-       BACK_RING_INIT(&e->env_sysbackring, (syscall_sring_t *SAFE)e->env_procdata,
-                      PGSIZE);
+       SHARED_RING_INIT(e->env_syscallring);
+       // Initialize the backend of the syscall ring buffer
+       BACK_RING_INIT(&e->env_syscallbackring, e->env_syscallring, PGSIZE);
+                      
+       // Initialize the generic sysevent ring buffer
+       SHARED_RING_INIT(e->env_syseventring);
+       // Initialize the frontend of the sysevent ring buffer
+       FRONT_RING_INIT(&e->env_syseventfrontring, e->env_syseventring, PGSIZE);
 
        // should be able to do this so long as boot_pgdir never has
        // anything put below UTOP
@@ -172,20 +196,28 @@ WRITES(e->env_pgdir, e->env_cr3, e->env_procinfo, e->env_procdata,
        e->env_pgdir[PDX(VPT)]  = PTE(PPN(e->env_cr3), PTE_P | PTE_KERN_RW);
        e->env_pgdir[PDX(UVPT)] = PTE(PPN(e->env_cr3), PTE_P | PTE_USER_RO);
 
-       // Insert the per-process info and data pages into this process's pgdir
-       // I don't want to do these two pages later (like with the stack), since
-       // the kernel wants to keep pointers to it easily.
+       // Insert the per-process info and ring buffer pages into this process's 
+       // pgdir.  I don't want to do these two pages later (like with the stack), 
+       // since the kernel wants to keep pointers to it easily.
        // Could place all of this with a function that maps a shared memory page
        // that can work between any two address spaces or something.
        r = page_insert(e->env_pgdir, pginfo, (void*SNT)UINFO, PTE_USER_RO);
-       r = page_insert(e->env_pgdir, pgdata, (void*SNT)UDATA, PTE_USER_RW);
+       if (r < 0) {
+               page_free(pgdir);
+               page_free(pginfo);
+               page_free(pgsyscallring);
+               page_free(pgsyseventring);
+               return r;
+       }
+       r = page_insert(e->env_pgdir, pgsyscallring, (void*SNT)USYSCALL, PTE_USER_RW);
        if (r < 0) {
                // note that we can't currently deallocate the pages created by
                // pgdir_walk (inside insert).  should be able to gather them up when
                // we destroy environments and their page tables.
                page_free(pgdir);
                page_free(pginfo);
-               page_free(pgdata);
+               page_free(pgsyscallring);
+               page_free(pgsyseventring);
                return r;
        }
 
index df7b077..f76eb0e 100644 (file)
@@ -29,6 +29,12 @@ void manager(void)
 
        switch (progress++) {
                case 0:
+                       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:
                        envs[0] = ENV_CREATE(roslib_proctests);
                        envs[1] = ENV_CREATE(roslib_proctests);
                        envs[2] = ENV_CREATE(roslib_proctests);
@@ -43,6 +49,7 @@ void manager(void)
                case 1:
                case 2:
                case 3:
+               #endif
                #if 0
                case 0:
                        printk("Beginning Tests\n");
index ff2a013..fedb453 100644 (file)
@@ -182,6 +182,40 @@ page_insert(pde_t *pgdir, page_t *pp, void *va, int perm)
 }
 
 //
+// Map the physical page 'pp' at the first virtual address that is free 
+// in the range 'vab' to 'vae'.
+// The permissions (the low 12 bits) of the page table entry get set to 
+// 'perm|PTE_P'.
+//
+// Details
+//   - If there is no free entry in the range 'vab' to 'vae' this 
+//     function returns -ENOMEM.
+//   - If necessary, on demand, this function will allocate a page table 
+//     and inserts it into 'pgdir'.
+//   - pp->pp_ref should be incremented if the insertion succeeds.
+//
+// RETURNS: 
+//   NULL, if no free va in the range (vab, vae) could be found
+//   va,   the virtual address where pp has been mapped in the 
+//         range (vab, vae)
+//
+void* page_insert_in_range(pde_t *pgdir, page_t *pp, 
+                           void *vab, void *vae, int perm) 
+{
+       pte_t* pte = NULL;
+       void* new_va;
+       
+       for(new_va = vab; new_va <= vae; new_va+= PGSIZE) {
+               pte = pgdir_walk(pgdir, new_va, 1);
+               if(pte != NULL && !(*pte & PTE_P)) break;
+               else pte = NULL;
+       }
+       if (!pte) return NULL;
+       *pte = page2pa(pp) | PTE_P | perm;
+       return new_va;
+}
+
+//
 // Return the page mapped at virtual address 'va'.
 // If pte_store is not zero, then we store in it the address
 // of the pte for this page.  This is used by page_remove
index c98999c..73336d4 100644 (file)
@@ -53,6 +53,38 @@ static ssize_t sys_serial_read(env_t* e, char *DANGEROUS buf, size_t len)
        #endif
 }
 
+static ssize_t sys_shared_page_alloc(env_t* p1, 
+                                     void** addr, envid_t p2_id, 
+                                     int p1_flags, int p2_flags
+                                    ) 
+{
+       if (!VALID_USER_PERMS(p1_flags)) return -EPERM;
+       if (!VALID_USER_PERMS(p2_flags)) return -EPERM;
+
+       page_t* page;
+       env_t* p2 = &(envs[ENVX(p2_id)]);
+       error_t e = page_alloc(&page);
+       if(e < 0) return e;
+       
+       void* p2_addr = page_insert_in_range(p2->env_pgdir, page, 
+                                            (void*)UTEXT, (void*)UTOP, p2_flags);
+       if(p2_addr == NULL) 
+               return -EFAIL;
+               
+       void* p1_addr = page_insert_in_range(p1->env_pgdir, page, 
+                                           (void*)UTEXT, (void*)UTOP, p1_flags);
+       if(p1_addr == NULL) {
+               page_remove(p2->env_pgdir, p2_addr);
+               return -EFAIL;
+       }
+       *addr = p1_addr;
+       return ESUCCESS;
+}
+
+static void sys_shared_page_free(env_t* p1, void* addr, envid_t p2)
+{
+}
+
 // Invalidate the cache of this core
 static void sys_cache_invalidate(void)
 {
@@ -195,7 +227,7 @@ static error_t sys_env_destroy(env_t* e, envid_t envid)
        else
                printk("[%08x] destroying %08x\n", e->env_id, env_to_die->env_id);
        env_destroy(env_to_die);
-       return 0;
+       return ESUCCESS;
 }
 
 /*
@@ -231,13 +263,19 @@ intreg_t syscall(env_t* e, uint32_t syscallno, uint32_t a1, uint32_t a2,
        switch (syscallno) {
                case SYS_null:
                        sys_null();
-                       return 0;
+                       return ESUCCESS;
                case SYS_cache_buster:
                        sys_cache_buster(e, a1, a2, a3);
                        return 0;
                case SYS_cache_invalidate:
                        sys_cache_invalidate();
                        return 0;
+               case SYS_shared_page_alloc:
+                       return sys_shared_page_alloc(e, (void** DANGEROUS) a1, 
+                                                a2, (int) a3, (int) a4);
+               case SYS_shared_page_free:
+                       sys_shared_page_free(e, (void* DANGEROUS) a1, a2);
+                   return ESUCCESS;
                case SYS_cputs:
                        return sys_cputs(e, (char *DANGEROUS)a1, (size_t)a2);
                case SYS_cgetc:
@@ -254,7 +292,7 @@ intreg_t syscall(env_t* e, uint32_t syscallno, uint32_t a1, uint32_t a2,
                        return sys_env_destroy(e, (envid_t)a1);
                case SYS_yield:
                        sys_yield(e);
-                       return 0;
+                       return ESUCCESS;
                case SYS_proc_create:
                case SYS_proc_run:
                        panic("Not implemented");
@@ -274,11 +312,12 @@ intreg_t syscall_async(env_t* e, syscall_req_t *call)
 intreg_t process_generic_syscalls(env_t* e, size_t max)
 {
        size_t count = 0;
-       syscall_back_ring_t* sysbr = &e->env_sysbackring;
+       syscall_back_ring_t* sysbr = &e->env_syscallbackring;
 
-       // make sure the env is still alive.  incref will return 0 on success.
+       // make sure the env is still alive.  
+       // incref will return ESUCCESS on success.
        if (env_incref(e))
-               return -1;
+               return -EFAIL;
 
        // max is the most we'll process.  max = 0 means do as many as possible
        while (RING_HAS_UNCONSUMED_REQUESTS(sysbr) && ((!max)||(count < max)) ) {
diff --git a/kern/src/sysevent.c b/kern/src/sysevent.c
new file mode 100644 (file)
index 0000000..f67e3ce
--- /dev/null
@@ -0,0 +1,7 @@
+/* Copyright (c) 2009 The Regents of the University of California. 
+ * See the COPYRIGHT files at the top of this source tree for full 
+ * license information.
+ * 
+ * Kevin Klues <klueska@cs.berkeley.edu>    
+ */
index bc4188d..0596f5e 100644 (file)
@@ -3,10 +3,6 @@ USER_DIR = user
 USER_CFLAGS  := $(CFLAGS) -DROS_USER 
 USER_LDFLAGS := $(LDFLAGS)
 
-# This is defined here because it is need by both
-# roslib and parlib for compiling, but not by apps
-USER_ROSLIB_INCLUDE_DIR  := $(USER_DIR)/roslib/inc
-
 include $(USER_DIR)/roslib/Makefrag
 include $(USER_DIR)/parlib/Makefrag
 include $(USER_DIR)/apps/Makefrag
index 8ab9070..761f312 100644 (file)
@@ -1,7 +1,7 @@
 USER_APPS_PARLIB_DIR = $(USER_APPS_DIR)/parlib
 OBJDIRS += $(USER_APPS_PARLIB_DIR)
 
-USER_APPS_PARLIB_CFLAGS    := $(USER_CFLAGS) --nodeputy \
+USER_APPS_PARLIB_CFLAGS    := $(USER_CFLAGS) --nodeputy --nopatch \
                               -I$(USER_PARLIB_NEWLIB_DIR)/include \
                               -I$(USER_PARLIB_DIR)/inc
 
@@ -11,9 +11,9 @@ USER_APPS_PARLIB_LDFLAGS   := $(USER_LDFLAGS) -static \
 USER_APPS_PARLIB_LDDIRS    := -L$(OBJDIR)/$(USER_PARLIB_DIR) \
                               -L$(USER_PARLIB_NEWLIB_DIR)/lib
 
-USER_APPS_PARLIB_LDLIBS    := --start-group -lc -lm -lg -lparlib --end-group
+USER_APPS_PARLIB_LDLIBS    := --start-group -lc -lm -lg -lparlib -livyparlib --end-group
 
-USER_APPS_PARLIB_LDOBJS    := $(OBJDIR)/$(USER_PARLIB_DIR)/entry.o \
+USER_APPS_PARLIB_LDOBJS    := $(OBJDIR)/$(USER_PARLIB_DIR)/entry_$(TARGET_ARCH).o \
                               $(OBJDIR)/$(USER_APPS_PARLIB_DIR)/readline.o \
                               $(OBJDIR)/$(USER_APPS_PARLIB_DIR)/file_io.o \
                               $(OBJDIR)/$(USER_APPS_PARLIB_DIR)/file_error.o \
@@ -24,6 +24,7 @@ USER_APPS_PARLIB_LDOBJS    := $(OBJDIR)/$(USER_PARLIB_DIR)/entry.o \
 
 USER_APPS_PARLIB_LDDEPENDS := $(USER_APPS_PARLIB_LDOBJS) \
                               $(OBJDIR)/$(USER_PARLIB_DIR)/libparlib.a \
+                              $(OBJDIR)/$(USER_PARLIB_DIR)/libivyparlib.a \
                               $(OBJDIR)/$(USER_APPS_PARLIB_DIR)/%.o       
 
 USER_APPS_PARLIB_GCC_LIB   := $(GCC_LIB)
diff --git a/user/apps/parlib/channel_test_client.c b/user/apps/parlib/channel_test_client.c
new file mode 100644 (file)
index 0000000..23b7118
--- /dev/null
@@ -0,0 +1,30 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <parlib.h>
+#include <channel.h>
+
+#define SERVER_ID     1
+#define MSG_LENGTH   25
+
+int main(int argc, char** argv)
+{
+       printf("Beginning of channel test client.\n");
+       channel_t ch;
+       channel_attr_t ch_attr;
+       
+       //Create the channel
+       channel_create(SERVER_ID, &ch, &ch_attr);
+       
+       //Send a message over the channel
+       #define MSG_LENGTH    25
+       uint8_t* buf[MSG_LENGTH]; //eventually replace with a call to channel_malloc()
+       channel_msg_t msg;
+       msg.len = MSG_LENGTH;
+       msg.buf = buf;
+       channel_sendmsg(&ch, &msg);
+       
+       channel_destroy(&ch);
+       
+       printf("End of channel test client.\n");
+       return 0;
+}
diff --git a/user/apps/parlib/channel_test_server.c b/user/apps/parlib/channel_test_server.c
new file mode 100644 (file)
index 0000000..3916407
--- /dev/null
@@ -0,0 +1,25 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <parlib.h>
+#include <channel.h>
+
+int main(int argc, char** argv)
+{
+       channel_t ch;
+       channel_attr_t ch_attr;
+       
+       //Wait for a channel to be created with me
+       channel_create_wait(&ch, &ch_attr);
+       
+       //Receive a message over that channel
+       #define MSG_LENGTH    25
+       uint8_t* buf[MSG_LENGTH];
+       channel_msg_t msg;
+       msg.buf = buf;
+       channel_recvmsg(&ch, &msg);
+       
+       //Print the message
+       printf("%s", msg.buf);  
+       
+       return 0;
+}
index 6b56ce2..88d6103 100644 (file)
@@ -1,8 +1,10 @@
 USER_PARLIB_DIR := $(USER_DIR)/parlib
+USER_PARLIB_INCLUDE_DIR  := $(USER_PARLIB_DIR)/inc
 
 # This is defined here for use by the parlib library
 USER_PARLIB_NEWLIB_DIR := $(USER_PARLIB_DIR)/newlib
 
 include $(USER_PARLIB_DIR)/src/Makefrag
+include $(USER_PARLIB_DIR)/ivy/Makefrag
 
 .PRECIOUS: $(OBJDIR)/$(USER_PARLIB_DIR)/%.o 
index 6a4a3e0..83d177a 120000 (symlink)
@@ -1 +1 @@
-../../../include/arch
\ No newline at end of file
+../../../kern/include/arch
\ No newline at end of file
diff --git a/user/parlib/inc/channel.h b/user/parlib/inc/channel.h
new file mode 100644 (file)
index 0000000..e2231bb
--- /dev/null
@@ -0,0 +1,82 @@
+/* Copyright (c) 2009 The Regents of the University  of California. 
+ * See the COPYRIGHT files at the top of this source tree for full 
+ * license information.
+ * 
+ * Kevin Klues <klueska@cs.berkeley.edu>    
+ */
+#ifndef ROS_CHANNEL_H
+#define ROS_CHANNEL_H
+#include <stdint.h>
+#include <arch/types.h>
+#include <ros/error.h>
+#include <ros/env.h>
+#include <ros/ring_buffer.h>
+
+/***************** Channel related constants *****************/
+
+enum {
+       CHANNEL_POLL   = 0,
+//     CHANNEL_NOTIFY = 1,
+};
+
+/*************************************************************/
+
+/***************** Channel related structures *****************/
+
+typedef struct channel_msg {
+       size_t len;
+       void* buf;
+} channel_msg_t;
+
+typedef struct channel_ack {
+       int32_t ack;
+} channel_ack_t;
+
+// Generic Syscall Ring Buffer
+DEFINE_RING_TYPES(channel, channel_msg_t, channel_ack_t);
+
+typedef enum {
+       CHANNEL_CLIENT = 1,
+       CHANNEL_SERVER = 2,
+} channel_type_t;
+
+typedef struct channel {
+       size_t id;
+       channel_type_t type;
+       envid_t endpoint;
+       void *COUNT(PGSIZE) data_addr;
+       channel_sring_t *COUNT(1) ring_addr;
+       union {
+               channel_front_ring_t front WHEN(type == CHANNEL_CLIENT);
+               channel_back_ring_t back WHEN(type == CHANNEL_SERVER);
+       } ring_side;
+} channel_t;
+
+typedef struct channel_attr {
+} channel_attr_t;
+
+/*************************************************************/
+
+/***************** Channel related functions *****************/
+
+error_t channel_create(envid_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);
+
+error_t channel_sendmsg(channel_t* ch, channel_msg_t* msg);
+error_t channel_recvmsg(channel_t* ch, channel_msg_t* msg);
+
+/*************************************************************/
+
+
+#endif //ROS_CHANNEL_H
+
+
+
+
+
+
+
+
index f27c2a6..eb00ac9 100644 (file)
 #include <ros/error.h>
 #include <newlib_backend.h>
 
+enum {
+       PG_RDONLY = 4,
+       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)[];
 extern volatile uint8_t (COUNT(PGSIZE * UDATA_PAGES) procdata)[];
 
+intreg_t syscall(uint16_t num, intreg_t a1,
+                intreg_t a2, intreg_t a3,
+                intreg_t a4, intreg_t a5);
+
 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 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);
index 7b34b6a..c266d86 120000 (symlink)
@@ -1 +1 @@
-../../../include/ros
\ No newline at end of file
+../../../kern/include/ros
\ No newline at end of file
diff --git a/user/parlib/ivy/Makefrag b/user/parlib/ivy/Makefrag
new file mode 100644 (file)
index 0000000..43b55c6
--- /dev/null
@@ -0,0 +1,21 @@
+USER_PARLIB_IVY_DIR := $(USER_PARLIB_DIR)/ivy
+OBJDIRS += $(USER_PARLIB_IVY_DIR)
+
+USER_PARLIB_IVY_CFLAGS   := $(USER_CFLAGS) --nodeputy \
+                            -I$(USER_PARLIB_NEWLIB_DIR)/include \
+                            -I$(USER_PARLIB_INCLUDE_DIR)
+
+USER_PARLIB_IVY_SRCFILES := $(USER_PARLIB_IVY_DIR)/deputy.c
+
+USER_PARLIB_IVY_OBJFILES := $(patsubst $(USER_PARLIB_IVY_DIR)/%.c, \
+                            $(OBJDIR)/$(USER_PARLIB_DIR)/%.o, \
+                            $(USER_PARLIB_IVY_SRCFILES))
+
+$(OBJDIR)/$(USER_PARLIB_DIR)/deputy.o: $(USER_PARLIB_IVY_SRCFILES)
+       @echo + cc [PARLIB IVY] $<
+       @mkdir -p $(@D)
+       $(V)$(CC) $(USER_PARLIB_IVY_CFLAGS) -c -o $@ $<
+
+$(OBJDIR)/$(USER_PARLIB_DIR)/libivyparlib.a: $(USER_PARLIB_IVY_OBJFILES)
+       @echo + ar [PARLIB IVY] $@
+       $(V)$(AR) r $@ $(USER_PARLIB_IVY_OBJFILES) 2>/dev/null
diff --git a/user/parlib/ivy/deputy.c b/user/parlib/ivy/deputy.c
new file mode 100644 (file)
index 0000000..17ba2d6
--- /dev/null
@@ -0,0 +1,171 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <parlib.h>
+
+// Use inline even when not optimizing for speed, since it prevents
+// warnings that would occur due to unused static functions.
+#ifdef DEPUTY_ALWAYS_STOP_ON_ERROR
+  #define INLINE inline __attribute__((always_inline))
+#else
+  #define INLINE inline
+#endif
+
+#define __LOCATION__        __FILE__, __LINE__, __FUNCTION__
+#define __LOCATION__FORMALS const char* file, int line, const char* func
+#define __LOCATION__ACTUALS file, line, func
+
+#ifndef asmlinkage
+#define asmlinkage __attribute__((regparm(0)))
+#endif
+
+#ifndef noreturn
+#define noreturn __attribute__((noreturn))
+#endif
+
+#define IN_DEPUTY_LIBRARY
+
+#include "deputy/checks.h"
+
+// If Deputy fails, it checks to see if you have specified special handling
+// for failed checks.
+enum handlerKind {
+    HANDLE_DEFAULT, // no handler specified
+    HANDLE_IGNORE,  // ignore
+    HANDLE_STOP,    // warn and stop
+    HANDLE_WARN,    // warn but do not stop
+    HANDLE_SLEEP,   // sleep and wait for the the debugger
+};
+
+static enum handlerKind deputyErrorHandler = HANDLE_DEFAULT;
+
+static int deputyInited = 0;
+static void deputyInitOnFirstFailure(void) {
+    // Cache the result of environment lookup
+    //char *onerror = getenv("DEPUTY_ONERROR");
+    deputyErrorHandler = HANDLE_DEFAULT;
+/*
+    if (onerror) {
+        if (!strcasecmp(onerror, "stop")) {
+            deputyErrorHandler = HANDLE_STOP;
+        } else if (!strcasecmp(onerror, "ignore")) {
+            deputyErrorHandler = HANDLE_IGNORE;
+        } else if (!strcasecmp(onerror, "warn")) {
+            deputyErrorHandler = HANDLE_WARN;
+        } else if (!strcasecmp(onerror, "sleep")) {
+            deputyErrorHandler = HANDLE_SLEEP;
+        } else {
+            fprintf(stderr, "Unexpected value for env var DEPUTY_ONERROR\n");
+        }
+    }
+*/
+}
+
+// This function is called directly from the checks unless the code was
+// compiled with --deputyAlwaysStopOnError . It is also called from
+// deputy_fail_noreturn to do the real work.
+asmlinkage
+void deputy_fail_mayreturn(const char *check, const char *text,
+                           __LOCATION__FORMALS) {
+    if (!deputyInited) {
+        deputyInitOnFirstFailure(); deputyInited = 1;
+    }
+    if (deputyErrorHandler != HANDLE_IGNORE) {
+        printf("%s:%d: %s: Assertion failed in %s:\n  %s\n",
+                __LOCATION__ACTUALS, check, text);
+    }
+    // Now look whether we should return or not
+    switch (deputyErrorHandler) {
+        case HANDLE_DEFAULT:
+        case HANDLE_STOP:
+            printf("Execution aborted.\n");
+            exit(1);
+#if 0
+        case HANDLE_SLEEP:
+#if defined(_MSVC)
+            // On Windows, this will fire the just-in-time debugger.
+            _asm { int 3 }
+#else
+            // Pause for debugging multithreaded code.
+            // (Trick due to Ben Liblit, via Dan Wilkerson.)
+            {
+                volatile int stopped = 1;
+
+                fprintf(stderr, "Execution paused for debugging (pid = %d).\n",
+                        getpid());
+                fflush(stderr);
+
+                while (stopped) {
+                    // 1. Execution will stop here.
+                    sleep(1);
+                }
+
+                // 2. Set breakpoint here, and set stopped to 0.
+                // (This statement exists so we have a place to put
+                // that breakpoint.)
+                stopped ++;
+            }
+#endif
+            break;
+#endif /* 0 */
+        default:
+            break;
+    }
+}
+
+// This function must NOT return. This is the function that is called
+// by the checks if we compiled with --alwaysStopOnError
+asmlinkage noreturn
+void deputy_fail_noreturn(const char *check, const char *text,
+                          __LOCATION__FORMALS) {
+    deputy_fail_mayreturn(check, text, __LOCATION__ACTUALS);
+    printf("Deputy check failed; execution aborted.\n");
+    exit(1);
+}
+
+// This function must NOT return. This is the function that is called
+// by the checks if we compiled with --alwaysStopOnError and --deputyFastChecks
+asmlinkage noreturn
+void deputy_fail_noreturn_fast(void) {
+    printf("Deputy check failed; execution aborted.\n");
+    printf("Detailed error report suppressed (--deputyFastChecks).\n");
+    exit(1);
+}
+
+/* Search for a NULL starting at e and return its index */
+asmlinkage
+int deputy_findnull(const void *e, unsigned int bytes) {
+#define NULLCHECK(type) \
+    do { \
+        type *p = (type*) e; \
+        while (*p != 0) { \
+            p++; \
+        } \
+        length = (p - (type*) e); \
+    } while (0)
+
+    int length = 0;
+
+    switch (bytes) {
+        case 1:
+            NULLCHECK(char);
+            break;
+        case 2:
+            NULLCHECK(short);
+            break;
+        case 4:
+            NULLCHECK(long);
+            break;
+        default:
+           printf("Invalid byte size for nullcheck.\n");
+           exit(1);
+    }
+
+    return length;
+#undef NULLCHECK
+}
+
+asmlinkage
+void *__deputy_memset(void *s, int c, unsigned int n) {
+  return memset(s, c, n);
+}
index e2814e7..b5120cc 100644 (file)
@@ -9,7 +9,9 @@ USER_PARLIB_SRC_SRCFILES := $(USER_PARLIB_SRC_DIR)/newlib_backend.c \
                             $(USER_PARLIB_SRC_DIR)/debug.c \
                             $(USER_PARLIB_SRC_DIR)/debugfmt.c \
                             $(USER_PARLIB_SRC_DIR)/syscall.c \
+                            $(USER_PARLIB_SRC_DIR)/syscall_$(TARGET_ARCH).c \
                             $(USER_PARLIB_SRC_DIR)/parlibmain.c \
+                            $(USER_PARLIB_SRC_DIR)/channel.c \
                             $(USER_PARLIB_SRC_DIR)/entry_$(TARGET_ARCH).S  
 
 USER_PARLIB_SRC_OBJFILES := $(patsubst $(USER_PARLIB_SRC_DIR)/%.c, \
diff --git a/user/parlib/src/channel.c b/user/parlib/src/channel.c
new file mode 100644 (file)
index 0000000..d242ea1
--- /dev/null
@@ -0,0 +1,190 @@
+/* Copyright (c) 2009 The Regents of the University  of California. 
+ * See the COPYRIGHT files at the top of this source tree for full 
+ * license information.
+ * 
+ * Kevin Klues <klueska@cs.berkeley.edu>    
+ */
+
+#include <parlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <channel.h>
+#include <ros/env.h>
+#include <ros/syscall.h>
+#include <arch/arch.h>
+
+void simulate_rsp(channel_t* ch) {
+       channel_t ch_server;
+       channel_msg_t msg;
+       ch_server.endpoint = ch->endpoint;
+       ch_server.type = CHANNEL_SERVER;
+       ch_server.ring_addr = ch->ring_addr;
+       ch_server.data_addr = ch->data_addr;    
+       BACK_RING_INIT(&(ch_server.ring_side.back), (ch_server.ring_addr), PGSIZE);
+       
+       channel_recvmsg(&ch_server, &msg);
+}
+
+error_t channel_create(envid_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;
+       
+       /*
+        * Attempt to create two shared pages with the 'server' partition.
+        * One for holding our ring buffer, and one for holding our data.
+        * If there is an error at any point during this process, we need
+        * to cleanup and abort, returning the proper error code.  First we
+        * do the page for the ring buffer, deferring the data page till later.
+        */
+       e = sys_shared_page_alloc(&ring_addr, server, PG_RDWR, PG_RDWR);
+       if(e < 0) return e;
+       
+       /* 
+        * If we've made it to here, then we know the shared memory page
+        * for our ring buffer has been mapped successfully into both our own 
+        * address space as well as the server's.  We also know that the 
+        * server has been notified of its creation.  We still haven't mapped in 
+        * our data page, but we will do that after this page has been initialized
+        * properly.  We do this because we need to somehow synchronize the 
+        * the initilization of the ring buffer on this page with 
+        * the server being able to access it.  We do this by forcing the 
+        * initialization now on this end, and only accessing it on the server side
+        * after our data page has been created.
+        */
+       memset((void*SAFE) TC(ch), 0, sizeof(channel_t));
+       ch->endpoint = server;
+       ch->ring_addr = (channel_sring_t *COUNT(1)) TC(ring_addr);
+       ch->type = CHANNEL_CLIENT;
+               
+       /*
+        * As the creator of this channel, we take on the responsibility of 
+        * setting up the ring buffer itself, as well as setting up our own front 
+        * ring so we can push requests (a.ka. messages) out for the server to 
+        * process.  It is the job of the server to setup its back ring so it can
+        * push responses (a.k.a acks) back for us to know the message has been 
+        * processed.
+        */
+       SHARED_RING_INIT(ch->ring_addr);
+       FRONT_RING_INIT(&(ch->ring_side.front), (ch->ring_addr), PGSIZE);
+       
+       /* 
+        * Now we map in the data page on both ends and add a pointer to it in 
+        * our channel struct.
+        */
+       e = sys_shared_page_alloc(&data_addr, server, PG_RDWR, PG_RDONLY);
+       if(e < 0) {
+               sys_shared_page_free(ring_addr, server);
+               return e;
+       }
+       ch->data_addr = data_addr;
+       
+       /* 
+        * Once both pages have been mapped, our data structures have been set up, 
+        * and everything is ready to go, we push an empty message out into the 
+        * ring indicating we are ready on our end.  This implicitly waits for the 
+        * server  to push a response indicating it has finished setting up the other 
+        * side of the channel.
+        */
+       channel_msg_t msg;
+       channel_sendmsg(ch, &msg);
+    
+    /*
+     * If everything has gone according to plan, both ends have set up 
+     * their respective ends of the channel and we can return successfully
+     */
+       return ESUCCESS;
+}
+
+error_t channel_destroy(channel_t* ch) {
+       sys_shared_page_free(ch->data_addr, ch->endpoint);
+       sys_shared_page_free((void *COUNT(PGSIZE)) TC(ch->ring_addr), ch->endpoint);
+       return ESUCCESS;
+}
+
+error_t channel_sendmsg(channel_t* ch, channel_msg_t* msg) {
+       /*
+        * As a first cut implementation, just copy the message handed to 
+        * us into our ring buffer and copy the buffer pointed to in 
+        * the message at the first address in our shared data page.
+        */
+       channel_msg_t* msg_copy;
+       msg_copy = RING_GET_REQUEST(&(ch->ring_side.front), 
+                                   ch->ring_side.front.req_prod_pvt++);
+       msg_copy->len = msg->len;
+       msg_copy->buf = 0;
+       memcpy(ch->data_addr + (size_t)(msg_copy->buf), msg->buf, msg->len);
+       
+       /*
+        * Now that we have copied the message properly, we push the request out
+        * and wait for a response from the server.
+        */
+       RING_PUSH_REQUESTS(&(ch->ring_side.front));
+       
+       while (!(RING_HAS_UNCONSUMED_RESPONSES(&(ch->ring_side.front))))
+               cpu_relax();
+       RING_GET_RESPONSE(&(ch->ring_side.front), ch->ring_side.front.rsp_cons++);
+       
+       return ESUCCESS;
+}
+
+error_t channel_create_wait(channel_t* ch, channel_attr_t* ch_attr) {
+#if 0
+       error_t e;
+       envid_t* client;
+       void *COUNT(PGSIZE) ring_addr = NULL;
+       void *COUNT(PGSIZE) data_addr = NULL;
+
+       /* 
+        * Set the type of the channel to the server
+        */
+       ch->type = CHANNEL_SERVER;
+       
+       /*
+        * Wait for the shared ring page to be established and set up
+        * the channel struct with its properties
+        */
+       sysevent_shared_page_alloc_wait(client, ring_addr);
+       ch->endpoint = *client;
+       ch->ring_addr = ring_addr;
+       
+       /*
+        * Now wait for the shared data page to be established and then set up
+        * the backring of the shared ring buffer.
+        */
+       sysevent_shared_page_alloc_wait(client, data_addr);
+       ch->data_addr = data_addr;      
+       BACK_RING_INIT(&(ch->ring_side.back), (ch->ring_addr), PGSIZE);
+       
+       /*
+        * If we've reached this point, then the creating side should already
+        * have a message sitting in the ring buffer waiting for use to 
+        * process.  Now we pull that message off and acknowledge it.
+        */
+       channel_msg_t msg;
+       channel_recvmsg(&ch, &msg);
+#endif 
+       return ESUCCESS;
+}
+
+error_t channel_recvmsg(channel_t* ch, channel_msg_t* msg) {
+       /*
+        * First copy the data contained in the message from shared page pointed 
+        * to by the entry in the ring buffer to the msg struct passedinto this 
+        * function
+        */
+       channel_msg_t* msg_copy = RING_GET_REQUEST(&(ch->ring_side.back), 
+                                                 ch->ring_side.back.req_cons++);
+       msg->len = msg_copy->len; 
+       memcpy(msg->buf, ch->data_addr + (size_t)(msg_copy->buf), msg->len);
+       
+       /*
+        * Then acknowledge that its been serviced / in the process of being 
+        * serviced.
+        */     
+       channel_ack_t* ack = RING_GET_RESPONSE(&(ch->ring_side.back), 
+                                              ch->ring_side.back.rsp_prod_pvt++);      
+       RING_PUSH_RESPONSES(&(ch->ring_side.back));     
+
+       return ESUCCESS;
+}
diff --git a/user/parlib/src/entry.S b/user/parlib/src/entry.S
deleted file mode 100644 (file)
index 4734b02..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <arch/mmu.h>
-#include <ros/memlayout.h>
-
-.data
-
-
-// Define the global symbols 'envs', 'pages', 'vpt', and 'vpd'
-// so that they can be used in C as if they were ordinary global arrays.
-       .globl procinfo
-       .set procinfo, UINFO
-       .globl procdata
-       .set procdata, UDATA
-       .globl pages
-       .set pages, UPAGES
-       .globl vpt
-       .set vpt, UVPT
-       .globl vpd
-       .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.
-.text
-.globl _start
-_start:
-       // 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:
-       call parlibmain
-1:      jmp 1b
-
diff --git a/user/parlib/src/entry_i386.S b/user/parlib/src/entry_i386.S
new file mode 100644 (file)
index 0000000..aa6e18e
--- /dev/null
@@ -0,0 +1,39 @@
+#include <arch/mmu.h>
+#include <ros/memlayout.h>
+
+.data
+
+
+// Define the global symbols 'envs', 'pages', 'vpt', and 'vpd'
+// so that they can be used in C as if they were ordinary global arrays.
+       .globl procinfo
+       .set procinfo, UINFO
+       .globl procdata
+       .set procdata, USYSCALL
+       .globl pages
+       .set pages, UPAGES
+       .globl vpt
+       .set vpt, UVPT
+       .globl vpd
+       .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.
+.text
+.globl _start
+_start:
+       // 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:
+       call parlibmain
+1:      jmp 1b
+
diff --git a/user/parlib/src/entry_sparc.S b/user/parlib/src/entry_sparc.S
new file mode 100644 (file)
index 0000000..0ae2bcf
--- /dev/null
@@ -0,0 +1,43 @@
+#include <arch/mmu.h>
+#include <ros/memlayout.h>
+
+.data
+
+
+// Define the global symbols 'envs', 'pages', 'vpt', and 'vpd'
+// so that they can be used in C as if they were ordinary global arrays.
+       .globl procinfo
+       .set procinfo, UINFO
+       .globl procdata
+       .set procdata, USYSCALL
+       .globl pages
+       .set pages, UPAGES
+       .globl vpt
+       .set vpt, UVPT
+       .globl vpd
+       .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.
+.text
+.globl _start
+_start:
+       // 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
+
+1:     ba      1b
+        nop
+
index 1e347de..d737617 100644 (file)
@@ -119,9 +119,9 @@ int fstat(int file, struct stat *st)
        st->st_mode = S_IFCHR;
        
        // stdout hack
-//     if (file == 1)
-//             st->st_mode = 8592;
-//     return 0;
+       if (file == 1)
+               st->st_mode = 8592;
+       return 0;
 
 
        // Allocate a new buffer of proper size
@@ -182,9 +182,9 @@ int isatty(int file)
        debug_in_out("ISATTY\n");
 
        // Cheap hack to avoid sending serial comm for stuff we know
-//     if ((STDIN_FILENO == file) || (STDOUT_FILENO == file) 
-//                                 || (STDERR_FILENO == file))
-//             return 1;
+       if ((STDIN_FILENO == file) || (STDOUT_FILENO == file) 
+                               || (STDERR_FILENO == file))
+               return 1;
 
        
        // Allocate a new buffer of proper size
index cab3792..aab6dc4 100644 (file)
@@ -3,77 +3,8 @@
 #pragma nodeputy
 #endif
 
-#include <arch/x86.h>
 #include <parlib.h>
 
-// TODO: modify to take only four parameters
-static intreg_t syscall_sysenter(uint16_t num, intreg_t a1,
-                                 intreg_t a2, intreg_t a3,
-                                 intreg_t a4, intreg_t a5)
-{
-       intreg_t ret;
-       asm volatile(
-           "pushl %%ebp\n\t"
-           "pushl %%esi\n\t"
-           "movl %%esp, %%ebp\n\t"
-           "leal after_sysenter, %%esi\n\t"
-           "sysenter\n\t"
-           "after_sysenter:\n\t"
-           "\tpopl %%esi\n"
-           "\tpopl %%ebp\n"
-           :"=a" (ret)
-           : "a" (num),
-             "d" (a1),
-             "c" (a2),
-             "b" (a3),
-             "D" (a4)
-           : "cc", "memory", "%esp");
-       return ret;
-}
-
-static intreg_t syscall_trap(uint16_t num, intreg_t a1,
-                             intreg_t a2, intreg_t a3,
-                             intreg_t a4, intreg_t a5)
-{
-       intreg_t ret;
-
-       // Generic system call: pass system call number in AX,
-       // up to five parameters in DX, CX, BX, DI, SI.
-       // Interrupt kernel with T_SYSCALL.
-       //
-       // The "volatile" tells the assembler not to optimize
-       // this instruction away just because we don't use the
-       // return value.
-       //
-       // The last clause tells the assembler that this can
-       // potentially change the condition codes and arbitrary
-       // memory locations.
-
-       asm volatile("int %1\n"
-               : "=a" (ret)
-               : "i" (T_SYSCALL),
-                 "a" (num),
-                 "d" (a1),
-                 "c" (a2),
-                 "b" (a3),
-                 "D" (a4),
-                 "S" (a5)
-               : "cc", "memory");
-
-       return ret;
-}
-
-static intreg_t syscall(uint16_t num, intreg_t a1,
-                        intreg_t a2, intreg_t a3,
-                        intreg_t a4, intreg_t a5)
-{
-       #ifndef SYSCALL_TRAP
-               return syscall_sysenter(num, a1, a2, a3, a4, a5);
-       #else
-               return syscall_trap(num, a1, a2, a3, a4, a5);
-       #endif
-}
-
 void sys_env_destroy(envid_t envid)
 {
        syscall(SYS_env_destroy, envid, 0, 0, 0, 0);
@@ -100,6 +31,19 @@ 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, 
+                              int p1_flags, int p2_flags
+                             ) 
+{
+       return syscall(SYS_shared_page_alloc, (intreg_t)addr, 
+                      p2, p1_flags, p2_flags, 0);
+}
+
+ssize_t sys_shared_page_free(void* addr, envid_t p2) 
+{
+       return syscall(SYS_shared_page_free, (intreg_t)addr, p2, 0,0,0);
+}
+
 //Write a buffer over the serial port
 ssize_t sys_serial_write(void* buf, size_t len) 
 {
diff --git a/user/parlib/src/syscall_i386.c b/user/parlib/src/syscall_i386.c
new file mode 100644 (file)
index 0000000..d4ef7ab
--- /dev/null
@@ -0,0 +1,73 @@
+// System call stubs.
+#ifdef __DEPUTY__
+#pragma nodeputy
+#endif
+
+#include <arch/types.h>
+#include <arch/arch.h>
+
+// TODO: fix sysenter to take all 5 params
+static inline intreg_t syscall_sysenter(uint16_t num, intreg_t a1,
+                                 intreg_t a2, intreg_t a3,
+                                 intreg_t a4, intreg_t a5)
+{
+       intreg_t ret;
+       asm volatile ("  pushl %%ebp;        "
+                     "  pushl %%esi;        "
+                     "  movl %%esp, %%ebp;  "
+                     "  leal 1f, %%esi;     "
+                     "  sysenter;           "
+                     "1:                    "
+                     "  popl %%esi;         "
+                     "  popl %%ebp;         "
+                     : "=a" (ret)
+                     : "a" (num),
+                       "d" (a1),
+                       "c" (a2),
+                       "b" (a3),
+                       "D" (a4)
+                     : "cc", "memory");
+       return ret;
+}
+
+static inline intreg_t syscall_trap(uint16_t num, intreg_t a1,
+                             intreg_t a2, intreg_t a3,
+                             intreg_t a4, intreg_t a5)
+{
+       uint32_t ret;
+
+       // Generic system call: pass system call number in AX,
+       // up to five parameters in DX, CX, BX, DI, SI.
+       // Interrupt kernel with T_SYSCALL.
+       //
+       // The "volatile" tells the assembler not to optimize
+       // this instruction away just because we don't use the
+       // return value.
+       //
+       // The last clause tells the assembler that this can
+       // potentially change the condition codes and arbitrary
+       // memory locations.
+
+       asm volatile("int %1"
+                    : "=a" (ret)
+                    : "i" (T_SYSCALL),
+                      "a" (num),
+                      "d" (a1),
+                      "c" (a2),
+                      "b" (a3),
+                      "D" (a4),
+                      "S" (a5)
+                    : "cc", "memory");
+       return ret;
+}
+
+intreg_t syscall(uint16_t num, intreg_t a1,
+                intreg_t a2, intreg_t a3,
+                intreg_t a4, intreg_t a5)
+{
+       #ifndef SYSCALL_TRAP
+               return syscall_sysenter(num, a1, a2, a3, a4, a5);
+       #else
+               return syscall_trap(num, a1, a2, a3, a4, a5);
+       #endif
+}
diff --git a/user/parlib/src/syscall_sparc.c b/user/parlib/src/syscall_sparc.c
new file mode 100644 (file)
index 0000000..2528869
--- /dev/null
@@ -0,0 +1,10 @@
+__asm__ (".global syscall              \n\t"
+         "syscall:                     \n\t"
+         "mov %o0,%g1          \n\t"
+         "mov %o1,%o0          \n\t"
+         "mov %o2,%o1          \n\t"
+         "mov %o3,%o2          \n\t"
+         "mov %o4,%o3          \n\t"
+         "mov %o5,%o4          \n\t"
+         "retl                 \n\t"
+         "ta 8                 \n\t");
index 7dada70..c8aae22 100644 (file)
@@ -1,4 +1,5 @@
 USER_ROSLIB_DIR := $(USER_DIR)/roslib
+USER_ROSLIB_INCLUDE_DIR  := $(USER_ROSLIB_DIR)/inc
 
 include $(USER_ROSLIB_DIR)/src/Makefrag
 include $(USER_ROSLIB_DIR)/ivy/Makefrag
index cc33ea3..7b3a7e8 100644 (file)
@@ -9,7 +9,7 @@
        .globl procinfo
        .set procinfo, UINFO
        .globl procdata
-       .set procdata, UDATA
+       .set procdata, USYSCALL
        .globl pages
        .set pages, UPAGES
        .globl vpt
index f31e73d..cd64677 100644 (file)
@@ -9,7 +9,7 @@
        .globl procinfo
        .set procinfo, UINFO
        .globl procdata
-       .set procdata, UDATA
+       .set procdata, USYSCALL
        .globl pages
        .set pages, UPAGES
        .globl vpt
index 8de9c21..cd91a0a 100644 (file)
@@ -61,7 +61,7 @@ void sys_null()
 
 error_t sys_null_async(syscall_desc_t* desc)
 {
-       syscall_req_t syscall = {SYS_null, 0, {[0 ... (NUM_SYS_ARGS-1)] 0}};
+       syscall_req_t syscall = {SYS_null, 0, {[0 ... (NUM_SYSCALL_ARGS-1)] 0}};
        desc->cleanup = NULL;
        desc->data = NULL;
        return async_syscall(&syscall, desc);
@@ -76,7 +76,7 @@ error_t       sys_cache_buster_async(syscall_desc_t* desc, uint32_t num_writes,
                                               uint32_t num_pages, uint32_t flags)
 {
        syscall_req_t syscall = {SYS_cache_buster, 0, {num_writes, num_pages, flags,
-                                                      [3 ... (NUM_SYS_ARGS-1)] 0}};
+                                                      [3 ... (NUM_SYSCALL_ARGS-1)] 0}};
        // just to be safe, 0 these out.  they should have been 0'd right after
        // the desc was POOL_GET'd
        desc->cleanup = NULL;
@@ -98,7 +98,7 @@ error_t sys_cputs_async(const char *s, size_t len, syscall_desc_t* desc,
                         void (*cleanup_handler)(void*), void* cleanup_data)
 {
        // could just hardcode 4 0's, will eventually wrap this marshaller anyway
-       syscall_req_t syscall = {SYS_cputs, 0, {(uint32_t)s, len, [2 ... (NUM_SYS_ARGS-1)] 0} };
+       syscall_req_t syscall = {SYS_cputs, 0, {(uint32_t)s, len, [2 ... (NUM_SYSCALL_ARGS-1)] 0} };
        desc->cleanup = cleanup_handler;
        desc->data = cleanup_data;
        return async_syscall(&syscall, desc);