DeviceQueues: extended region pool managment to return fixed size buffers of regions
authorRoni Häcki <roni.haecki@inf.ethz.ch>
Fri, 15 Jul 2016 13:21:45 +0000 (15:21 +0200)
committerRoni Häcki <roni.haecki@inf.ethz.ch>
Fri, 15 Jul 2016 13:21:45 +0000 (15:21 +0200)
Signed-off-by: Roni Häcki <roni.haecki@inf.ethz.ch>

lib/device_interfaces/Hakefile
lib/device_interfaces/device_queue_interface.c
lib/device_interfaces/region.c [new file with mode: 0644]
lib/device_interfaces/region.h [new file with mode: 0644]
lib/device_interfaces/region_pool.c
lib/device_interfaces/region_pool.h

index 308f6a6..96114c9 100644 (file)
@@ -15,7 +15,8 @@
 [
     build library { 
         target = "device_interface",
-        cFiles = ["device_queue_interface.c", "region_pool.c"],
+        cFiles = ["device_queue_interface.c", "region_pool.c", 
+                  "region.c"],
         addCFlags = [ "-DLIBRARY" ]
     }
 ]
index 6634416..2221c2c 100644 (file)
@@ -10,6 +10,7 @@
 #include <barrelfish/barrelfish.h>
 #include <device_interfaces/device_queue_interface.h>
 #include "region_pool.h"
+#include "dqi_debug.h"
  /*
  * ===========================================================================
  * Device queue creation and destruction
@@ -33,18 +34,26 @@ errval_t device_queue_create(struct device_queue **q,
                              char* device_name,
                              char* misc)
 {
+    /*
     struct region_pool* pool;
     region_pool_init(&pool);
     struct capref cap;
     uint32_t region_ids[100];
-    
+
     for (int i = 0; i < 100; i++) {
         region_ids[i] = -1;
     }
 
     srand(rdtsc());
 
-    for (int i = 0; i < 10000000; i++) {
+    errval_t err = frame_alloc(&cap, 131072, NULL);
+    assert(err_is_ok(err));
+    
+    void* va;
+    err = vspace_map_one_frame_attr(&va, 131072, cap, 
+                                    VREGION_FLAGS_READ_WRITE, NULL, NULL);
+
+    for (int i = 0; i < 100; i++) {
         int id = rand() % 100;
         if (region_ids[id] == -1) {
             region_pool_add_region(pool, cap, 0x1222222, &region_ids[id]);
@@ -53,19 +62,32 @@ errval_t device_queue_create(struct device_queue **q,
             region_ids[id] = -1;
         }
     }
-/*
-    for (int i = 0; i < 32; i++) {
-        region_pool_add_region(pool, cap, 0x1222222, &region_ids[i]);
-        printf("Region_id[%d]=%d \n", i, region_ids[i]);
-    }
 
-    region_pool_remove_region(pool, region_ids[0], &cap);
-    region_pool_remove_region(pool, region_ids[15], &cap);
+    // Buffer ids are from 0 to 16
+    for (int i = 0; i < 100; i++) {
+        if (region_ids[i] == -1) {      
+            region_pool_add_region(pool, cap, 0x1222222, &region_ids[i]);
+        }
+    }
 
-    region_pool_add_region(pool, cap, 0x1222222, &region_ids[0]);
-    region_pool_add_region(pool, cap, 0x1222222, &region_ids[15]);
-*/
-    //USER_PANIC("NIY\n");
+    for (int i = 0; i < 2; i++) {
+        lpaddr_t addr;
+        uint32_t buffer_id;
+        for (int j = 0; j < 32; j++) {
+            region_pool_get_buffer_from_region(pool, region_ids[i], &buffer_id, &addr);
+        }
+    
+        for (int j = 0; j < 100; j++) {
+            uint32_t index = rand() % 32;
+            if (region_pool_buffer_of_region_in_use(pool, region_ids[i], index)) {
+                region_pool_return_buffer_to_region(pool, region_ids[i], index);
+            } else {
+                region_pool_get_buffer_from_region(pool, region_ids[i], &index, &addr);
+            }
+        }
+    }   
+    */
+    USER_PANIC("NIY\n");
     return SYS_ERR_OK;
 }
 
diff --git a/lib/device_interfaces/region.c b/lib/device_interfaces/region.c
new file mode 100644 (file)
index 0000000..e4f2b72
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2016 ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <barrelfish/barrelfish.h>
+#include "region.h"
+#include "dqi_debug.h"
+
+/**
+ * @brief initialized a region
+ *
+ * @param region                Return pointer to the region
+ * @param region_id             The ID of the region,
+ * @param cap                   Capability of the memory region
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+/*
+errval_t region_init_variable_sized(struct region** region,
+                     uint32_t region_id,
+                     struct capref* cap)
+{
+    USER_PANIC("NIY for variable sized buffers\n");
+    return SYS_ERR_OK;
+}
+*/
+/**
+ * @brief initialized a region from which only fixed size buffers are used
+ *
+ * @param region                Return pointer to the region
+ * @param region_id             The ID of the region,
+ * @param cap                   Capability of the memory region
+ * @param len                   Length of the fixed sized buffers
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+
+errval_t region_init(struct region** region,
+                     uint32_t region_id,
+                     struct capref* cap,
+                     size_t len)
+{
+    errval_t err;
+    struct frame_identity id;
+
+    struct region* tmp = malloc(sizeof(struct region));
+    if (region == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
+
+    tmp->region_id = region_id;
+    tmp->cap = cap;
+    tmp->buf_len = len;
+
+    err = invoke_frame_identify(*cap, &id);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    tmp->base_addr = id.base;
+    tmp->len = id.bytes;
+
+    // Init state for fixed buffer region
+    tmp->num_buf = id.bytes/len;
+    tmp->fixed_size = true;
+    tmp->in_use = calloc(sizeof(bool)*tmp->num_buf, 1);
+    if (tmp->in_use == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
+
+    tmp->next_buf = 0;  
+    *region = tmp;   
+    
+    DQI_DEBUG("Initialize Region size=%ld addr=%16lx num_bufs=%ld \n",
+              tmp->len, tmp->base_addr, tmp->num_buf);
+
+    return SYS_ERR_OK;
+}
+
+
+/**
+ * @brief free up a region
+ *
+ * @param region                The region to free up
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+errval_t region_destroy(struct region* region)
+{
+    for (int i = 0; i < region->num_buf; i++) {
+        if (region->in_use[i]) {
+            DQI_DEBUG("Could not destroy region, some buffers stil in use \n");
+            // TODO reasonable error;
+            return -1;      
+        }
+    }
+
+    free(region->in_use);
+    free(region);
+    return SYS_ERR_OK;
+}
+/**
+ * @brief Get a buffer from a region
+ *
+ * @param region                The region to get the buffer from
+ * @param len                   lenght of the buffer
+ * @param base_addr             Return pointer to the physical address 
+ *                              of the buffer
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+errval_t region_get_buffer(struct region* region,
+                           uint32_t* buffer_id,
+                           lpaddr_t* addr)
+{
+    if (region->fixed_size) {
+        uint32_t count = 0;
+        // Try to find empty slot, If we did not find 
+        // a slot after making a whole round, return error
+        while (count < region->num_buf+1) {
+            if (!region->in_use[region->next_buf]) {
+                *buffer_id = region->next_buf;
+                *addr = (region->base_addr + (region->next_buf* 
+                         region->buf_len));
+                region->in_use[region->next_buf] = true;
+                region->next_buf = (region->next_buf + 1) % region->num_buf;
+
+                DQI_DEBUG("Got buffer id=%d addr=%16lx \n", *buffer_id, *addr);
+                return SYS_ERR_OK;
+            } else {
+                region->next_buf = (region->next_buf + 1) % region->num_buf;
+                count++;
+            }
+        }   
+
+    } else {
+        USER_PANIC("NIY for variable sized buffers\n");
+    }
+
+    DQI_DEBUG("Failed to get buffer \n");
+    // TODO reasonable error
+    return -1;
+}
+
+
+/**
+ * @brief Return a buffer to the region
+ *
+ * @param region                The region to return the buffer to
+ * @param len                   Lenght of the buffer returned 
+ * @param buffer_id             The id of the buffer to return to the region
+ * @param addr                  The physical address of the freed buffer
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+errval_t region_free_buffer(struct region* region,
+                            uint32_t buffer_id)
+{
+    if (region->fixed_size) {
+        // Can not free buffer that is not used
+        if (region->in_use[buffer_id] != true) {
+            // TODO reasonable error
+            return -1;
+        }
+        region->in_use[buffer_id] = false;
+    } else {
+        USER_PANIC("NIY for variable sized buffers\n");
+    }
+
+    DQI_DEBUG("Returned buffer id=%d \n", buffer_id);
+    return SYS_ERR_OK;
+}
+
diff --git a/lib/device_interfaces/region.h b/lib/device_interfaces/region.h
new file mode 100644 (file)
index 0000000..10f425d
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2016 ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+#ifndef REGION_H_
+#define REGION_H_ 1
+
+
+#include <barrelfish/barrelfish.h>
+
+struct region {
+    // ID of the region
+    uint32_t region_id;
+    // Base address of the region
+    lpaddr_t base_addr;
+    // Capability of the region
+    struct capref* cap;
+    // Lenght of the memory region
+    size_t len;
+
+    // Are the buffers fixed size?
+    bool fixed_size;
+    // State for fixed sized buffers
+    size_t num_buf;
+    size_t buf_len;
+    size_t next_buf;  
+    bool* in_use;
+};
+
+/**
+ * @brief initialized a region
+ *
+ * @param region                Return pointer to the region
+ * @param region_id             The ID of the region,
+ * @param cap                   Capability of the memory region
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+errval_t region_init(struct region** region,
+                     uint32_t region_id,
+                     struct capref* cap,
+                     size_t len);
+/**
+ * @brief free up a region
+ *
+ * @param region                The region to free up
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+errval_t region_destroy(struct region* region);
+
+/**
+ * @brief initialized a region from which only fixed size buffers are used
+ *
+ * @param region                Return pointer to the region
+ * @param region_id             The ID of the region,
+ * @param cap                   Capability of the memory region
+ * @param len                   Length of the fixed sized buffers
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+/*
+errval_t region_init_variable_size(struct region** region,
+                                   uint32_t region_id,
+                                   struct capref* cap,
+                                   size_t len);
+*/
+/**
+ * @brief Get a buffer from a region
+ *
+ * @param region                The region to get the buffer from
+ * @param buffer_id             Return pointer to the buffer id of the buffer
+ * @param addr                  Return pointer to the physical address 
+ *                              of the buffer
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+errval_t region_get_buffer(struct region* region,
+                           uint32_t* buffer_id,
+                           lpaddr_t* addr);
+
+/**
+ * @brief Return a buffer to the region
+ *
+ * @param region                The region to return the buffer to
+ * @param buffer_id             The id of the buffer to return to the region
+ * @param addr                  The physical address of the freed buffer
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+errval_t region_free_buffer(struct region* region,
+                            uint32_t buffer_id);
+
+
+/**
+ * @brief Return a if a buffer to the region is in use
+ *
+ * @param region                The region to return the buffer to
+ * @param buffer_id             The id of the buffer
+ *
+ * @returns true if the buffer is in use otherwise false
+ */
+inline bool region_buffer_in_use(struct region* region,
+                                 uint32_t buffer_id)
+{
+    return region->in_use[buffer_id];
+}
+
+#endif /* REGION_H_ */
index 981bedf..db01e85 100644 (file)
@@ -9,18 +9,10 @@
 
 #include <barrelfish/barrelfish.h>
 #include "region_pool.h"
+#include "region.h"
 #include "dqi_debug.h"
 
-#define INIT_POOL_SIZE 2
-
-struct region {
-    // ID of the region
-    uint32_t region_id;
-    // Base address of the region
-    lpaddr_t base_addr;
-    // Capability of the region
-    struct capref* cap;
-};
+#define INIT_POOL_SIZE 32
 
 struct region_pool {
 
@@ -63,7 +55,7 @@ errval_t region_pool_init(struct region_pool** pool)
     (*pool)->region_offset = (rand() >> 12) ;
     (*pool)->size = INIT_POOL_SIZE;    
 
-    (*pool)->pool = calloc(sizeof(struct region)*INIT_POOL_SIZE, 1);
+    (*pool)->pool = calloc(sizeof(struct region*)*INIT_POOL_SIZE, 1);
     if (*pool == NULL) {
         DQI_DEBUG("Allocationg inital pool failed \n");
         return LIB_ERR_MALLOC_FAIL;
@@ -88,7 +80,7 @@ static errval_t region_pool_grow(struct region_pool* pool)
 
     uint16_t new_size = (pool->size)*2;
     // Allocate new pool twice the size
-    tmp = calloc(sizeof(struct region)*new_size, 1);
+    tmp = calloc(sizeof(struct region*)*new_size, 1);
     if (tmp == NULL) {
         DQI_DEBUG("Allocationg larger pool failed \n");
         return LIB_ERR_MALLOC_FAIL;
@@ -132,9 +124,7 @@ errval_t region_pool_add_region(struct region_pool* pool,
                                 uint32_t* region_id)
 {
     errval_t err;
-
-    struct region* region = malloc(sizeof(struct region));
-    region->cap = &cap;
+    struct region* region;
     
     // Check if pool size is large enough
     if (!(pool->num_regions < pool->size)) {
@@ -161,7 +151,10 @@ errval_t region_pool_add_region(struct region_pool* pool,
     }
 
     pool->last_offset = offset;
-    region->region_id = pool->region_offset + pool->num_regions + offset;
+    // TODO size 
+    err = region_init(&region,
+                      pool->region_offset + pool->num_regions + offset,
+                      &cap, 4096);
 
     // insert into pool
     pool->pool[region->region_id % pool->size] = region;
@@ -193,7 +186,7 @@ errval_t region_pool_remove_region(struct region_pool* pool,
     DQI_DEBUG("Removing slot %d \n", region_id % pool->size);
     cap = region->cap;
   
-    free(region);
+    region_destroy(region);
     pool->pool[region_id % pool->size] = NULL;
 
     pool->num_regions--;
@@ -201,3 +194,111 @@ errval_t region_pool_remove_region(struct region_pool* pool,
 }
 
 
+/**
+ * @brief get memory region from pool
+ *
+ * @param pool          The pool to get the region from
+ * @param region_id     The id of the region to get
+ * @param region        Return pointer to the region
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+static errval_t region_pool_get_region(struct region_pool* pool,
+                                uint32_t region_id,
+                                struct region** region)
+{
+    *region = pool->pool[region_id % pool->size];
+    if (region == NULL) {
+        // TODO reasonable error;
+        return -1;
+    }
+
+    return SYS_ERR_OK;
+}
+
+
+/**
+ * @brief get a page sized buffer from a region of the pool
+ *
+ * @param pool          The pool to get the region from
+ * @param region_id     The id of the region to get the buffer from
+ * @param buffer_id     Return pointer to the buffer id
+ * @param addr          Return pointer to the physical address of the buffer
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+
+errval_t region_pool_get_buffer_from_region(struct region_pool* pool,
+                                            uint32_t region_id,
+                                            uint32_t* buffer_id,
+                                            lpaddr_t* addr)
+{
+    errval_t err;
+    struct region* region;
+    err = region_pool_get_region(pool, region_id, &region);
+    if (err_is_fail(err)) {
+        return err;
+    }
+    
+    // TODO size
+    err = region_get_buffer(region, buffer_id, addr);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    return SYS_ERR_OK;
+}
+
+/**
+ * @brief return a page sized buffer to a region of the pool
+ *
+ * @param pool          The pool to get the region from
+ * @param region_id     The id of the region to get the buffer from
+ * @param buffer_id     Return pointer to the buffer id
+ * @param addr          the physical address of the buffer
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+
+errval_t region_pool_return_buffer_to_region(struct region_pool* pool,
+                                             uint32_t region_id,
+                                             uint32_t buffer_id)
+{
+    errval_t err;
+    struct region* region;
+    err = region_pool_get_region(pool, region_id, &region);
+    if (err_is_fail(err)) {
+        return err;
+    }
+    
+    // TODO size
+    err = region_free_buffer(region, buffer_id);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    return SYS_ERR_OK;
+}
+
+/**
+ * @brief return if a buffer of a region is in use
+ *
+ * @param pool          The pool to get the region from
+ * @param region_id     The id of the region
+ * @param buffer_id     The id of the buffer
+ *
+ * @returns true if the buffer is in use otherwise false
+ */
+bool region_pool_buffer_of_region_in_use(struct region_pool* pool,
+                                         uint32_t region_id,
+                                         uint32_t buffer_id)
+{
+    errval_t err;
+    struct region* region;
+    err = region_pool_get_region(pool, region_id, &region);
+    if (err_is_fail(err)) {
+        return false;
+    }
+    
+    return region_buffer_in_use(region, buffer_id);
+}
index af75071..d34e777 100644 (file)
@@ -13,6 +13,7 @@
 #include <barrelfish/barrelfish.h>
 
 struct region_pool;
+struct region;
 /**
  * @brief initialized a pool of regions
  *
@@ -51,5 +52,46 @@ errval_t region_pool_remove_region(struct region_pool* pool,
                                    uint32_t region_id,
                                    struct capref* cap);
 
+/**
+ * @brief get a page sized buffer from a region of the pool
+ *
+ * @param pool          The pool to get the region from
+ * @param region_id     The id of the region to get the buffer from
+ * @param buffer_id     Return pointer to the buffer id
+ * @param addr          Return pointer to the physical address of the buffer
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+
+errval_t region_pool_get_buffer_from_region(struct region_pool* pool,
+                                            uint32_t region_id,
+                                            uint32_t* buffer_id,
+                                            lpaddr_t* addr);
+
+/**
+ * @brief return a page sized buffer to a region of the pool
+ *
+ * @param pool          The pool to get the region from
+ * @param region_id     The id of the region to return the buffer to
+ * @param buffer_id     The id of the buffer to return to the region
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
 
+errval_t region_pool_return_buffer_to_region(struct region_pool* pool,
+                                             uint32_t region_id,
+                                             uint32_t buffer_id);
+
+/**
+ * @brief return if a buffer of a region is in use
+ *
+ * @param pool          The pool to get the region from
+ * @param region_id     The id of the region
+ * @param buffer_id     The id of the buffer
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+bool region_pool_buffer_of_region_in_use(struct region_pool* pool,
+                                         uint32_t region_id,
+                                         uint32_t buffer_id);
 #endif /* REGION_POOL_H_ */