proc_mgmt: getting domain list implemented
authorRoni Häcki <roni.haecki@inf.ethz.ch>
Mon, 9 Oct 2017 11:58:49 +0000 (13:58 +0200)
committerRoni Häcki <roni.haecki@inf.ethz.ch>
Mon, 9 Oct 2017 11:58:49 +0000 (13:58 +0200)
Signed-off-by: Roni Häcki <roni.haecki@inf.ethz.ch>

if/proc_mgmt.if
include/barrelfish/spawn_client.h
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 8024932..ca3a39f 100644 (file)
@@ -49,9 +49,9 @@ interface proc_mgmt "Process management service" {
   rpc wait(in cap domain_cap, in bool nohang, out errval err, out uint8 status);
 
 
-  rpc status(in domainid domain_id, out ps_entry ps_entry, out char argv[len, 2048],
+  rpc status(in uint32 domainid, out ps_entry ps_entry, out char argv[len, 2048],
             out errval err);
 
-  // XXX: Should be domainid instead of uint8, but it's not yet supported
-  rpc get_domainlist(out uint8 domains[len, 2048]);
+  // 4 uint8 are merged to a 32 bit domaind.
+  rpc get_domainlist(out uint8 domains[len, 4096]);
 };
index 65191d8..9fa2a4d 100644 (file)
@@ -71,7 +71,7 @@ errval_t spawn_wait_core(coreid_t coreid, struct capref domainid,
                          uint8_t *exitcode, bool nohang);
 errval_t spawn_binding(coreid_t coreid, struct spawn_binding **ret_client);
 errval_t spawn_bind_iref(iref_t iref, struct spawn_binding **ret_client);
-errval_t spawn_get_domain_list(uint8_t **domains, size_t *len);
+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);
 
index 27e0067..f1a3ff1 100644 (file)
@@ -894,10 +894,18 @@ errval_t spawn_wait_compat(uint8_t domainid,
     return reterr;
 }
 
+static int compare_domainid(const void *a, const void *b)
+{
+  const domainid_t *da = (const domainid_t *) a;
+  const domainid_t *db = (const domainid_t *) b;
+
+  return (*da > *db) - (*da < *db);
+}
+
 /**
  * \brief Get the list of domains for ps like implementation
  */
-errval_t spawn_get_domain_list(uint8_t **domains, size_t *len)
+errval_t spawn_get_domain_list(bool sorted, domainid_t **domains, size_t *len)
 {
     errval_t err;
     err = proc_mgmt_bind_client();
@@ -909,12 +917,20 @@ errval_t spawn_get_domain_list(uint8_t **domains, size_t *len)
     assert(b != NULL);
 
     struct proc_mgmt_get_domainlist_response__rx_args reply;
-    err = b->rpc_tx_vtbl.get_domainlist(b, reply.domains, 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");
     }
 
-    *domains = memdup(reply.domains, *len);
+    // length is in bytes
+    *len = length/sizeof(domainid_t);
+    if (sorted) {
+        qsort(reply.domains, *len, sizeof(domainid_t), compare_domainid);
+    }
+
+    *domains = memdup(reply.domains, length);
+
     return SYS_ERR_OK;
 }
 
@@ -924,7 +940,7 @@ errval_t spawn_get_domain_list(uint8_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;
index c540fa5..9f977b5 100644 (file)
@@ -371,11 +371,11 @@ static int spawnpixels(int argc, char *argv[])
 
 static int ps(int argc, char *argv[])
 {
-    uint8_t *domains;
+    domainid_t *domains;
     size_t len;
     errval_t err;
 
-    err = spawn_get_domain_list(&domains, &len);
+    err = spawn_get_domain_list(true, &domains, &len);
     if (err_is_fail(err)) {
         DEBUG_ERR(err, "spawn_get_domain_list");
         return EXIT_FAILURE;
index 9ff3ba0..7552ed3 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <barrelfish/barrelfish.h>
 #include <collections/hash_table.h>
+#include <collections/list.h>
 #include <if/spawn_defs.h>
 
 #include "domain.h"
@@ -22,6 +23,7 @@ static collections_hash_table* domain_table = NULL;
 #define DOMAIN_CAP_REFILL_COUNT L2_CNODE_SLOTS//1
 static struct domain_cap_node *domain_cap_list = NULL;
 static uint32_t free_domain_caps = 0;
+static domainid_t domain_alloc = 0;
 
 inline bool domain_should_refill_caps(void) {
     return free_domain_caps == 0;
@@ -109,6 +111,9 @@ errval_t domain_new(struct domain_cap_node *cap_node,
     entry->num_spawnds_resources = 0;
     entry->waiters = NULL;
 
+    entry->domainid = domain_alloc;
+    domain_alloc++;
+
     if (domain_table == NULL) {
         collections_hash_create_with_buckets(&domain_table, HASH_INDEX_BUCKETS,
                                              NULL);
@@ -211,3 +216,48 @@ errval_t domain_span(struct capref domain_cap, coreid_t core_id)
 
     return SYS_ERR_OK;
 }
+
+void domain_get_all_ids(domainid_t** domains, size_t* len)
+{
+    if (domain_table == NULL) {
+        *len = 0;
+        return;
+    }
+
+    if (collections_hash_traverse_start(domain_table) > 0) {
+    
+        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;
+        
+            if (entry->status != DOMAIN_STATUS_CLEANED) {
+                collections_list_insert(start, &entry->domainid);
+            }
+
+            ele = collections_hash_traverse_next(domain_table, &key);
+        }
+
+        collections_hash_traverse_end(domain_table);
+
+        domainid_t* doms = (domainid_t*) calloc(1, sizeof(domainid_t)*
+                                                 collections_list_size(start));
+
+        *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;
+
+    } else {
+        *len = 0;
+    }
+}
index f226958..6417f77 100644 (file)
@@ -47,6 +47,8 @@ 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.
 
     uint8_t exit_status;
@@ -65,10 +67,12 @@ 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_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);
 static inline void domain_stop_pending(struct domain_entry *entry)
 {
     assert(entry != NULL);
     entry->status = DOMAIN_STATUS_STOP_PEND;
 }
 
-#endif  // PROC_MGMT_DOMAIN_H
\ No newline at end of file
+
+#endif  // PROC_MGMT_DOMAIN_H
index 924bcba..4593162 100644 (file)
@@ -646,7 +646,20 @@ respond:
  */
 static void get_domainlist_handler(struct proc_mgmt_binding *b)
 {
-    
+    errval_t resp_err;
+    size_t len;
+    domainid_t* domains;
+
+    domain_get_all_ids(&domains, &len);
+
+    // 4096 hardcoded limit in flounder interface
+    assert(sizeof(domainid_t)/sizeof(uint8_t)*len < 4096);
+
+    resp_err = b->tx_vtbl.get_domainlist_response(b, NOP_CONT, (uint8_t*) domains, 
+                                                  sizeof(domainid_t)/sizeof(uint8_t)*len);
+    if (err_is_fail(resp_err)) {
+        DEBUG_ERR(resp_err, "failed to send wait_response");
+    }
 }
 
 static struct proc_mgmt_rx_vtbl monitor_vtbl = {
index 09e1ccc..30417dd 100644 (file)
@@ -245,6 +245,30 @@ 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 i = 0; i < len; i++) {
+        printf("Domain id %d \n", domains[i]);
+    }
+
+    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");
+    }
+
+    for (int i = 0; i < len; i++) {
+        printf("Domain id %d \n", domains[i]);
+    }
+
     printf("TEST DONE\n");
     return 0;
 }