Async call tweaks
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 7 May 2009 21:06:38 +0000 (14:06 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 7 May 2009 21:09:00 +0000 (14:09 -0700)
Can run a cleanup function for an entire async call.  Also manages POOL
memory better (frees and 0's).

inc/lib.h
inc/pool.h
inc/syscall.h
kern/syscall.c
lib/asynccall.c
lib/libmain.c
lib/printf.c
lib/syscall.c
user/null.c

index a4893fc..e89eba2 100644 (file)
--- a/inc/lib.h
+++ b/inc/lib.h
@@ -48,8 +48,12 @@ error_t waiton_syscall(syscall_desc_t* desc, syscall_rsp_t* rsp);
 // async callback
 #define MAX_SYSCALLS 100
 #define MAX_ASYNCCALLS 10
-// This is the high-level object a process waits, with multiple syscalls within.
-typedef syscall_desc_list_t async_desc_t;
+// The high-level object a process waits on, with multiple syscalls within.
+typedef struct async_desc {
+       syscall_desc_list_t syslist;
+       void (*cleanup)(void* data);
+       void* data;
+} async_desc_t;
 // This is per-thread, and used when entering a async library call to properly
 // group syscall_desc_t used during the processing of that async call
 extern async_desc_t* current_async_desc;
index 68dcfa1..31d9d3b 100644 (file)
@@ -2,7 +2,7 @@
 /* Kevin Klues <klueska@cs.berkeley.edu>       */
 
 #ifndef ROS_INC_POOL_H
-#define ROS_INC_POOL_H   
+#define ROS_INC_POOL_H
 
 #include <inc/string.h>
 
index 81b88cd..822ad02 100644 (file)
@@ -41,6 +41,6 @@ struct syscall_desc {
        void (*cleanup)(void* data);
        void* data;
 };
-LIST_HEAD(syscall_desc_list_t, syscall_desc_t); 
+LIST_HEAD(syscall_desc_list_t, syscall_desc_t);
 
 #endif /* !ROS_INC_SYSCALL_H */
index 904641d..993e598 100644 (file)
@@ -14,8 +14,8 @@
 #include <kern/syscall.h>
 #include <kern/console.h>
 
-//Do absolutely nothing.  Used for profiling.  
-static void sys_null() 
+//Do absolutely nothing.  Used for profiling.
+static void sys_null()
 {
        return;
 }
@@ -90,7 +90,7 @@ syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,
 
        if (INVALID_SYSCALL(syscallno))
                return -E_INVAL;
-       
+
        switch (syscallno) {
                case SYS_null:
                        sys_null();
index 29de80b..e5d7ba0 100644 (file)
@@ -4,24 +4,40 @@
 
 async_desc_t* get_async_desc(void)
 {
-       return POOL_GET(&async_desc_pool);
+       async_desc_t* desc = POOL_GET(&async_desc_pool);
+       if (desc)
+               // Clear out any data that was in the old desc
+               memset(desc, 0, sizeof(*desc));
+       return desc;
 }
 
 error_t waiton_async_call(async_desc_t* desc)
 {
        syscall_rsp_t rsp;
-       while (!(LIST_EMPTY(desc))) {
-               waiton_syscall(LIST_FIRST(desc), &rsp);
-               // consider processing the retval out of rsp
-               LIST_REMOVE(LIST_FIRST(desc), next);
+       syscall_desc_t* d;
+       while (!(LIST_EMPTY(&desc->syslist))) {
+               d = LIST_FIRST(&desc->syslist);
+               waiton_syscall(d, &rsp);
+               // consider processing the retval out of rsp here (TODO)
+               // remove from the list and free the syscall desc
+               LIST_REMOVE(d, next);
+               POOL_PUT(&syscall_desc_pool, d);
        }
+       // run a cleanup function for this desc, if available
+       if (desc->cleanup)
+               desc->cleanup(desc->data);
+       // free the asynccall desc
+       POOL_PUT(&async_desc_pool, desc);
        return 0;
 }
 
 syscall_desc_t* get_sys_desc(async_desc_t* desc)
 {
        syscall_desc_t* d = POOL_GET(&syscall_desc_pool);
-       if (d)
-       LIST_INSERT_TAIL(desc, d, next);
+       if (d) {
+               // Clear out any data that was in the old desc
+               memset(d, 0, sizeof(*d));
+       LIST_INSERT_TAIL(&desc->syslist, d, next);
+       }
        return d;
 }
index 430d63d..3dd0899 100644 (file)
@@ -23,9 +23,9 @@ libmain(int argc, char **argv)
        env = (env_t*)procinfo;
 
        // Set up the front ring for the general syscall ring
-       FRONT_RING_INIT(&sysfrontring, (syscall_sring_t*)procdata, PGSIZE);     
-       POOL_INIT(&syscall_desc_pool, MAX_SYSCALLS);            
-       POOL_INIT(&async_desc_pool, MAX_ASYNCCALLS);            
+       FRONT_RING_INIT(&sysfrontring, (syscall_sring_t*)procdata, PGSIZE);
+       POOL_INIT(&syscall_desc_pool, MAX_SYSCALLS);
+       POOL_INIT(&async_desc_pool, MAX_ASYNCCALLS);
 
        // save the name of the program so that panic() can use it
        if (argc > 0)
index f4669d8..b07487e 100644 (file)
@@ -2,7 +2,7 @@
 // based on printfmt() and the sys_cputs() system call.
 //
 // cprintf is a debugging statement, not a generic output statement.
-// It is very important that it always go to the console, especially when 
+// It is very important that it always go to the console, especially when
 // debugging file descriptor code!
 
 #include <inc/types.h>
@@ -87,7 +87,7 @@ static void putch_async(int ch, printbuf_t **b)
        if ((*b)->idx == BUF_SIZE) {
                // will need some way to track the result of the syscall
                sys_cputs_async((*b)->buf, (*b)->idx, get_sys_desc(current_async_desc),
-                               cputs_async_cleanup, *b); 
+                               cputs_async_cleanup, *b);
                // TODO - this isn't getting passed back properly
                // TODO - should check for a return value
                *b = get_free_buffer();
@@ -105,7 +105,7 @@ static int vcprintf_async(const char *fmt, va_list ap)
        b->cnt = 0;
        vprintfmt((void*)putch_async, (void**)&b, fmt, ap);
        sys_cputs_async(b->buf, b->idx, get_sys_desc(current_async_desc),
-                       cputs_async_cleanup, b); 
+                       cputs_async_cleanup, b);
 
        return b->cnt; // this is lying if we used more than one buffer
 }
@@ -114,16 +114,18 @@ int cprintf_async(async_desc_t** desc, const char *fmt, ...)
 {
        va_list ap;
        int cnt;
+
+       // This async call has some housekeeping it needs to do once, ever.
        static bool initialized = 0;
        if (!initialized) {
                init_printf();
        initialized = TRUE;
        }
+       // get a free async_desc for this async call, and save it in the per-thread
+       // tracking variable (current_async_desc).  then pass it back out.
        current_async_desc = get_async_desc();
        *desc = current_async_desc;
-
-       cprintf("Pool size: %d\n", POOL_SIZE(&print_buf_pool));
-
+       // This is the traditional (sync) cprintf code
        va_start(ap, fmt);
        cnt = vcprintf_async(fmt, ap);
        va_end(ap);
index 0123620..2abfa97 100644 (file)
@@ -16,7 +16,7 @@ syscall(int num, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5
        // 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.
@@ -31,7 +31,7 @@ syscall(int num, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5
                  "D" (a4),
                  "S" (a5)
                : "cc", "memory");
-       
+
        return ret;
 }
 
index 2e370a1..4f398f9 100644 (file)
@@ -8,7 +8,7 @@
 #define NUM_ITERATIONS 100000
 uint64_t times[NUM_ITERATIONS];
 
-uint64_t total(uint64_t (COUNT(length) array)[], int length) 
+uint64_t total(uint64_t (COUNT(length) array)[], int length)
 {
        uint64_t sum = 0;
        for(int i=0; i<length; i++) {