DeviceQueue: first try to keep track of used buffer ids
authorRoni Häcki <roni.haecki@inf.ethz.ch>
Thu, 11 Aug 2016 15:32:00 +0000 (17:32 +0200)
committerRoni Häcki <roni.haecki@inf.ethz.ch>
Thu, 11 Aug 2016 15:32:00 +0000 (17:32 +0200)
Signed-off-by: Roni Häcki <roni.haecki@inf.ethz.ch>

lib/devif/queue_interface.c
lib/devif/region.c
lib/devif/region.h

index 12b0d3a..e34fcef 100644 (file)
@@ -93,7 +93,7 @@ errval_t devq_create(struct devq **q,
 {
     errval_t err;
     struct devq* tmp = malloc(sizeof(struct devq));
-    strncpy(device_name, tmp->device_name, MAX_DEVICE_NAME);
+    strncpy(tmp->device_name, device_name, MAX_DEVICE_NAME);
 
     tmp->rx_head = 0;
     tmp->tx_head = 0;
index 6f24e9d..aebcdfa 100644 (file)
 #include "region.h"
 #include "dqi_debug.h"
 
+/*
+ * A region keeps track of the buffers that are currently allocated 
+ * i.e. If two buffer is marked as allocated and it is reused before it
+ * is freed, the region will return an allocation error
+ *
+ * The datastructure to keep track of the allocation has a bucket for each
+ * 4K page. If a buffer starts in a certain page, the buffer will be added to 
+ * the bucket of this page. Within a bucket there is a linked list. To allocated
+ * the buffer structures a slab allocator is used.
+ */
+
+
 /**
  * @brief initialized a region from which only fixed size buffers are used
  *
@@ -44,6 +56,12 @@ errval_t region_init(struct region** region,
 
     tmp->base_addr = id.base;
     tmp->len = id.bytes;
+    tmp->max_page_id = tmp->len/BASE_PAGE_SIZE;
+
+    // Datastructures for keeping track of buffers
+    slab_init(&tmp->alloc, sizeof(struct buffer), slab_default_refill);
+    slab_grow(&tmp->alloc, tmp->bufs, sizeof(tmp->bufs));
+    tmp->used_bufs = malloc(sizeof(struct buffer*)*tmp->len/BASE_PAGE_SIZE);
 
     *region = tmp;   
     
@@ -67,7 +85,7 @@ errval_t region_destroy(struct region* region)
     return SYS_ERR_OK;
 }
 /**
- * @brief Get a buffer from a region
+ * @brief Get a buffer id from a region
  *
  * @param region                The region to get the buffer from
  * @param addr                  The physical address of the buffer
@@ -79,8 +97,40 @@ errval_t region_get_buffer_id(struct region* region,
                               lpaddr_t addr,
                               bufferid_t* buffer_id)
 {
-    *buffer_id = 0;
-    DQI_DEBUG("Got buffer id=%d addr=%16lx \n", *buffer_id, *addr);
+    uint32_t page_id;
+    *buffer_id = (addr - region->base_addr);
+    page_id = *buffer_id/BASE_PAGE_SIZE;
+
+    // Test if buffer can not be in region
+    if (page_id > region->max_page_id) {
+        // TODO reasonable error
+        return -1;
+    }
+
+    // Test if buffer is already used
+    if (region_buffer_id_in_use(region, *buffer_id)) {
+        // TODO reasonable error
+        return -1;
+    }
+
+    struct buffer* tmp = slab_alloc(&region->alloc);
+    tmp->id = *buffer_id;
+    tmp->next = NULL;
+    struct buffer* ele = region->used_bufs[page_id];
+    
+    // Empty list
+    if (ele == NULL) {
+        region->used_bufs[page_id] = tmp;
+    }    
+
+    // Iterate through list
+    while (ele->next != NULL) {
+        ele = ele->next;
+    }
+
+    ele->next = tmp;
+    
+    DQI_DEBUG("buffer addr=%16lx got assigned id=%d\n", addr, *buffer_id);
     return SYS_ERR_OK;
 }
 
@@ -96,7 +146,39 @@ errval_t region_get_buffer_id(struct region* region,
 errval_t region_free_buffer_id(struct region* region,
                                bufferid_t buffer_id)
 {
-    DQI_DEBUG("Returned buffer id=%d \n", buffer_id);
+    uint32_t page_id;
+    page_id = buffer_id/BASE_PAGE_SIZE;
+    // Test if buffer can not be in region
+    if (page_id > region->max_page_id) {
+        // TODO reasonable error
+        return -1;
+    }
+
+    // Test if buffer is used
+    if (!region_buffer_id_in_use(region, buffer_id)) {
+        // TODO reasonable error
+        return -1;
+    }
+    
+    struct buffer* ele = region->used_bufs[page_id];
+    // First entry is special case
+    if (ele->id == buffer_id) {
+        region->used_bufs[page_id] = ele->next;
+        slab_free(&region->alloc, ele);
+        DQI_DEBUG("Returned buffer id=%d \n", buffer_id);
+        return SYS_ERR_OK;
+    }
+    
+    while (ele->next != NULL) {
+        if (ele->next->id == buffer_id) {
+            ele->next = ele->next->next;
+            slab_free(&region->alloc, ele);
+            DQI_DEBUG("Returned buffer id=%d \n", buffer_id);
+            return SYS_ERR_OK;
+        }
+        ele = ele->next;
+    }
+    
     return SYS_ERR_OK;
 }
 
@@ -112,7 +194,25 @@ errval_t region_free_buffer_id(struct region* region,
 bool region_buffer_id_in_use(struct region* region,
                              bufferid_t buffer_id)
 {
+    uint32_t page_id;
+    page_id = buffer_id/BASE_PAGE_SIZE;
+
+    // Empty bucket -> can not be used
+    if (region->used_bufs[page_id] == NULL) {
+        return false;
+    }
+
+    // check list
+    struct buffer* ele = region->used_bufs[page_id];
+    while (ele != NULL) {
+        if (ele->id == buffer_id) {
+            return true;
+        } 
+        ele = ele->next;
+    }
+
+    // TODO check
     DQI_DEBUG("Returned buffer id=%d \n", buffer_id);
-    return true;
+    return false;
 }
 
index 12c8a35..76d5631 100644 (file)
 
 #include <barrelfish/barrelfish.h>
 #include <devif/queue_interface.h>
+#include <barrelfish/slab.h>
+
+#define INIT_SIZE 128
+struct buffer {
+    bufferid_t id;
+    struct buffer* next;
+};
 
 struct region {
     // ID of the region
@@ -22,7 +29,16 @@ struct region {
     struct capref* cap;
     // Lenght of the memory region
     size_t len;
-    // 
+
+
+    // slab allocator for buffer structs
+    struct slab_allocator alloc;
+    // inital slab buffers
+    struct buffer bufs[INIT_SIZE];
+    // Data structure to keep track of buffers
+    struct buffer** used_bufs;
+    // Largest page id
+    uint32_t max_page_id;
 };
 
 /**