proc_mgmt: get status query implemented
authorRoni Häcki <roni.haecki@inf.ethz.ch>
Mon, 9 Oct 2017 15:27:16 +0000 (17:27 +0200)
committerRoni Häcki <roni.haecki@inf.ethz.ch>
Mon, 9 Oct 2017 15:27:16 +0000 (17:27 +0200)
Signed-off-by: Roni Häcki <roni.haecki@inf.ethz.ch>

if/proc_mgmt.if
lib/barrelfish/spawn_client.c
usr/fish/fish_common.c
usr/proc_mgmt/domain.c
usr/proc_mgmt/domain.h
usr/proc_mgmt/service.c
usr/tests/proc_mgmt_test/main.c

index ca3a39f..eea3d9b 100644 (file)
@@ -49,8 +49,8 @@ interface proc_mgmt "Process management service" {
   rpc wait(in cap domain_cap, in bool nohang, out errval err, out uint8 status);
 
 
-  rpc status(in uint32 domainid, out ps_entry ps_entry, out char argv[len, 2048],
-            out errval err);
+  rpc get_status(in uint32 domainid, out ps_entry ps_entry, 
+                 out char argv[len, 2048], out errval err);
 
   // 4 uint8 are merged to a 32 bit domaind.
   rpc get_domainlist(out uint8 domains[len, 4096]);
index f1a3ff1..d636b6b 100644 (file)
@@ -920,7 +920,7 @@ errval_t spawn_get_domain_list(bool sorted, domainid_t **domains, size_t *len)
     size_t length;
     err = b->rpc_tx_vtbl.get_domainlist(b, reply.domains, &length);
     if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "get_domainlist");
+        return err;
     }
 
     // length is in bytes
@@ -940,26 +940,25 @@ errval_t spawn_get_domain_list(bool sorted, domainid_t **domains, size_t *len)
 errval_t spawn_get_status(domainid_t domain_id, struct spawn_ps_entry *pse,
                           char **argbuf, size_t *arglen, errval_t *reterr)
 {
-/*
-    errval_t err;
 
-    struct spawn_binding *cl;
-    err = spawn_binding(disp_get_core_id(), &cl);
+    errval_t err;
+    err = proc_mgmt_bind_client();
     if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "spawn_binding");
+        return err;
     }
-    assert(cl != NULL);
 
-    struct spawn_status_response__rx_args reply;
-    err = cl->rpc_tx_vtbl.status(cl, domain, (spawn_ps_entry_t *)pse, reply.argv,
-                          arglen, reterr);
+    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
+    assert(b != NULL);
+
+    struct proc_mgmt_get_status_response__rx_args reply;
+    err = b->rpc_tx_vtbl.get_status(b, domain_id, (proc_mgmt_ps_entry_t*) pse, 
+                                    reply.argv, arglen, reterr);
     if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "status");
+        return err;
     }
 
     *argbuf = memdup(reply.argv, *arglen);
-    
-*/
+
     return SYS_ERR_OK;
 }
 
index 9f977b5..691fe6b 100644 (file)
@@ -403,11 +403,19 @@ static int ps(int argc, char *argv[])
 
         switch(pse.status) {
         case 0:
-            status = 'R';
+            status = 'N';
             break;
 
         case 1:
-            status = 'Z';
+            status = 'R';
+            break;
+
+        case 2:
+            status = 'S';
+            break;
+
+        case 3:
+            status = 'S';
             break;
 
         default:
index 7552ed3..bcc46bc 100644 (file)
@@ -93,8 +93,8 @@ struct domain_cap_node *next_cap_node(void)
  * \param cap_node  preallocated domain cap node.
  * \param ret_entry returned domain entry, must be passed in non-NULL.
  */
-errval_t domain_new(struct domain_cap_node *cap_node,
-                    struct domain_entry **ret_entry)
+errval_t domain_new(struct domain_cap_node *cap_node, const char* argbuf, 
+                    size_t argbytes, struct domain_entry **ret_entry)
 {
     assert(ret_entry != NULL);
 
@@ -114,6 +114,9 @@ errval_t domain_new(struct domain_cap_node *cap_node,
     entry->domainid = domain_alloc;
     domain_alloc++;
 
+    entry->argbuf = memdup(argbuf, argbytes);
+    entry->argbytes = argbytes;
+
     if (domain_table == NULL) {
         collections_hash_create_with_buckets(&domain_table, HASH_INDEX_BUCKETS,
                                              NULL);
@@ -155,6 +158,36 @@ errval_t domain_get_by_cap(struct capref domain_cap,
     return SYS_ERR_OK;
 }
 
+errval_t domain_get_by_id(domainid_t domain_id,
+                          struct domain_entry **ret_entry)
+{
+    // XXX slow since we traverse the whole hash map 
+    collections_hash_traverse_start(domain_table);
+
+    uint64_t key;
+    void* ele = collections_hash_traverse_next(domain_table, &key);
+    
+    // get all domain ids and store in list
+    // XXX traverse whole hash table since it seems to not
+    // reset the internal lists when resetting the traversal of the hash table
+    while (ele != NULL) {
+        struct domain_entry *entry = (struct domain_entry*) ele;
+    
+        if (entry->domainid == domain_id) {
+            *ret_entry = entry;
+        }
+
+        ele = collections_hash_traverse_next(domain_table, &key);
+    }
+
+    collections_hash_traverse_end(domain_table);
+    if (ret_entry == NULL) {
+        return PROC_MGMT_ERR_DOMAIN_TABLE_FIND;
+    } else {
+        return SYS_ERR_OK;
+    }
+}
+
 /**
  * \brief Adds a new core to the list of cores where the given domain runs.
  *
@@ -175,16 +208,18 @@ void domain_run_on_core(struct domain_entry *entry, coreid_t core_id)
     ++entry->num_spawnds_resources;
 }
 
+
 /**
  * \brief Creates a new domain entry for the given cap node and core.
  *
  * \param cap_node preallocated capability node for the new domain.
  * \param core_id  core that runs the new domain.
  */
-errval_t domain_spawn(struct domain_cap_node *cap_node, coreid_t core_id)
+errval_t domain_spawn(struct domain_cap_node *cap_node, coreid_t core_id,
+                      const char* argbuf, size_t argbytes)
 {
     struct domain_entry *entry = NULL;
-    errval_t err = domain_new(cap_node, &entry);
+    errval_t err = domain_new(cap_node, argbuf, argbytes, &entry);
     if (err_is_fail(err)) {
         if (entry != NULL) {
             free(entry);
@@ -224,40 +259,35 @@ void domain_get_all_ids(domainid_t** domains, size_t* len)
         return;
     }
 
-    if (collections_hash_traverse_start(domain_table) > 0) {
+    collections_hash_traverse_start(domain_table);
     
-        collections_listnode* start;
-        collections_list_create(&start, NULL);
+    collections_listnode* start;
+    collections_list_create(&start, NULL);
+
+    uint64_t key;
+    void* ele = collections_hash_traverse_next(domain_table, &key);
+    // get all domain ids and store in list
+    while (ele != NULL) {
+        struct domain_entry *entry = (struct domain_entry*) ele;
     
-        uint64_t key;
-        void* ele = collections_hash_traverse_next(domain_table, &key);
-        
-        // get all domain ids and store in list
-        while (ele != NULL) {
-            struct domain_entry *entry = (struct domain_entry*) ele;
-        
-            if (entry->status != DOMAIN_STATUS_CLEANED) {
-                collections_list_insert(start, &entry->domainid);
-            }
-
-            ele = collections_hash_traverse_next(domain_table, &key);
+        if (entry->status != DOMAIN_STATUS_CLEANED) {
+            collections_list_insert(start, &entry->domainid);
         }
 
-        collections_hash_traverse_end(domain_table);
-
-        domainid_t* doms = (domainid_t*) calloc(1, sizeof(domainid_t)*
-                                                 collections_list_size(start));
+        ele = collections_hash_traverse_next(domain_table, &key);
+    }
 
-        *len = collections_list_size(start);
-        // copy domain ids
-        for (int i = 0; i < collections_list_size(start); i++) {
-            doms[i] = *((domainid_t*) collections_list_get_ith_item(start, i));
-        }
-    
-        collections_list_release(start);        
-        *domains = doms;
+    domainid_t* doms = (domainid_t*) calloc(1, sizeof(domainid_t)*
+                                             collections_list_size(start));
 
-    } else {
-        *len = 0;
+    *len = collections_list_size(start);
+    // copy domain ids
+    for (int i = 0; i < collections_list_size(start); i++) {
+        doms[i] = *((domainid_t*) collections_list_get_ith_item(start, i));
     }
+
+    collections_list_release(start);        
+    *domains = doms;
+    collections_hash_traverse_end(domain_table);
 }
index 6417f77..f51ee19 100644 (file)
@@ -47,24 +47,28 @@ struct domain_entry {
     coreid_t num_spawnds_running;
     coreid_t num_spawnds_resources;
 
-    domainid_t domainid; // Mainly used for ps like command
 
     struct domain_waiter *waiters;  // Clients waiting after this domain.
 
+    /* Mainly used for ps like command (XXX currently duplicated also in spawnd) */
+    domainid_t domainid;
+    char *argbuf;
+    size_t argbytes;
+
     uint8_t exit_status;
 };
 
 bool domain_should_refill_caps(void);
 errval_t domain_prealloc_caps(void);
 struct domain_cap_node *next_cap_node(void);
-
-errval_t domain_new(struct domain_cap_node *cap_node,
-                    struct domain_entry **ret_entry);
 errval_t domain_get_by_cap(struct capref domain_cap,
                            struct domain_entry **ret_entry);
 void domain_run_on_core(struct domain_entry *entry, coreid_t core_id);
 
-errval_t domain_spawn(struct domain_cap_node *cap_node, coreid_t core_id);
+errval_t domain_new(struct domain_cap_node *cap_node, const char* argbuf, 
+                    size_t argbytes, struct domain_entry **ret_entry);
+errval_t domain_spawn(struct domain_cap_node *cap_node, coreid_t core_id,
+                      const char* argbuf, size_t argbytes);
 errval_t domain_can_span(struct capref domain_cap, coreid_t core_id);
 errval_t domain_span(struct capref domain_cap, coreid_t core_id);
 void domain_get_all_ids(domainid_t** domains, size_t* len);
@@ -74,5 +78,8 @@ static inline void domain_stop_pending(struct domain_entry *entry)
     entry->status = DOMAIN_STATUS_STOP_PEND;
 }
 
+errval_t domain_get_by_id(domainid_t,
+                          struct domain_entry **ret_entry);
+
 
 #endif  // PROC_MGMT_DOMAIN_H
index 4593162..4178ffc 100644 (file)
@@ -86,7 +86,8 @@ static void spawn_reply_handler(struct spawn_binding *b, errval_t spawn_err)
             spawn = (struct pending_spawn*) cl->st;
             err = spawn_err;
             if (err_is_ok(spawn_err)) {
-                err = domain_spawn(spawn->cap_node, spawn->core_id);
+                err = domain_spawn(spawn->cap_node, spawn->core_id, spawn->argvbuf,
+                                   spawn->argvbytes);
                 if (cl->type == ClientType_Spawn) {
                     resp_err = cl->b->tx_vtbl.spawn_response(cl->b, NOP_CONT,
                             err, spawn->cap_node->domain_cap);
@@ -662,6 +663,34 @@ static void get_domainlist_handler(struct proc_mgmt_binding *b)
     }
 }
 
+/**
+ * \brief Handler for rpc get_status.
+ */
+static void get_status_handler(struct proc_mgmt_binding *b, domainid_t domain)
+{
+    errval_t err;
+    struct domain_entry* entry;
+    proc_mgmt_ps_entry_t pse;
+    memset(&pse, 0, sizeof(pse));
+
+    err = domain_get_by_id(domain, &entry);
+    if (err_is_fail(err)) {
+        err = b->tx_vtbl.get_status_response(b, NOP_CONT, pse, NULL, 0,
+                                             err);
+        if(err_is_fail(err)) {
+            DEBUG_ERR(err, "status_response");
+        }
+    }
+
+    pse.status = entry->status;
+
+    err = b->tx_vtbl.get_status_response(b, NOP_CONT, pse, entry->argbuf, entry->argbytes,
+                                         SYS_ERR_OK);
+    if(err_is_fail(err)) {
+        DEBUG_ERR(err, "status_response");
+    }
+}
+
 static struct proc_mgmt_rx_vtbl monitor_vtbl = {
     .add_spawnd           = add_spawnd_handler,
     .spawn_call           = spawn_handler,
@@ -680,7 +709,8 @@ static struct proc_mgmt_rx_vtbl non_monitor_vtbl = {
     .kill_call            = kill_handler,
     .exit_call            = exit_handler,
     .wait_call            = wait_handler,
-    .get_domainlist_call  = get_domainlist_handler
+    .get_domainlist_call  = get_domainlist_handler,
+    .get_status_call      = get_status_handler
 };
 
 /**
index 30417dd..18ae4ef 100644 (file)
@@ -72,6 +72,59 @@ static inline cycles_t calculate_time(cycles_t tsc_start, cycles_t tsc_end)
     return result;
 }
 
+static void print_ps(domainid_t* domains, size_t len)
+{
+    errval_t err;
+    for(size_t i = 0; i < len; i++) {
+        struct spawn_ps_entry pse;
+        char *argbuf, status;
+        size_t arglen;
+        errval_t reterr;
+
+        err = spawn_get_status(domains[i], &pse, &argbuf, &arglen, &reterr);
+        if (err_is_fail(err)) {
+            USER_PANIC("PS FAILED \n");
+        }
+        if(err_is_fail(reterr)) {
+            USER_PANIC("PS FAILED \n");
+        }
+
+        switch(pse.status) {
+        case 0:
+            status = 'N';
+            break;
+
+        case 1:
+            status = 'R';
+            break;
+
+        case 2:
+            status = 'S';
+            break;
+
+        case 3:
+            status = 'S';
+            break;
+
+        default:
+            status = '?';
+            break;
+        }
+
+        printf("%-8u\t%c\t", domains[i], status);
+        size_t pos = 0;
+        for(int p = 0; pos < arglen && p < MAX_CMDLINE_ARGS;) {
+            printf("%s ", &argbuf[pos]);
+            char *end = memchr(&argbuf[pos], '\0', arglen - pos);
+            assert(end != NULL);
+            pos = end - argbuf + 1;
+        }
+        printf("\n");
+
+        free(argbuf);
+    }
+}
+
 static void run_benchmark_spawn(coreid_t target_core)
 {
     bench_init();
@@ -245,30 +298,28 @@ int main(int argc, char **argv)
     printf("Running benchmarks core 3 \n");
     run_benchmark_spawn(3);
 
-    domainid_t* domains;
-    size_t len;
-    printf("Get domain list sorted \n");
-    err = spawn_get_domain_list(true, &domains, &len);
-    if (err_is_fail(err)){
-        USER_PANIC("Failed getting domain ids \n");
-    }
+    for (int j = 0; j < 10; j++) {
+        domainid_t* domains;
+        size_t len;
+        printf("Get domain list sorted \n");
+        err = spawn_get_domain_list(true, &domains, &len);
+        if (err_is_fail(err)){
+            USER_PANIC("Failed getting domain ids \n");
+        }
 
-    for (int i = 0; i < len; i++) {
-        printf("Domain id %d \n", domains[i]);
-    }
+        print_ps(domains, len);
+        free(domains);
 
-    free(domains);
+        printf("Get domain list unsorted \n");
+        err = spawn_get_domain_list(false, &domains, &len);
+        if (err_is_fail(err)){
+            USER_PANIC("Failed getting domain ids \n");
+        }
 
-    printf("Get domain list unsorted \n");
-    err = spawn_get_domain_list(false, &domains, &len);
-    if (err_is_fail(err)){
-        USER_PANIC("Failed getting domain ids \n");
-    }
+        print_ps(domains, len);
 
-    for (int i = 0; i < len; i++) {
-        printf("Domain id %d \n", domains[i]);
+        free(domains);
     }
-
     printf("TEST DONE\n");
     return 0;
 }