devq: stackable debugging backend for checking buffer properties
authorRoni Häcki <roni.haecki@inf.ethz.ch>
Fri, 28 Apr 2017 08:35:40 +0000 (10:35 +0200)
committerRoni Häcki <roni.haecki@inf.ethz.ch>
Fri, 28 Apr 2017 08:35:40 +0000 (10:35 +0200)
Signed-off-by: Roni Häcki <roni.haecki@inf.ethz.ch>

include/devif/backends/debug.h [new file with mode: 0644]
lib/devif/backends/debug/Hakefile [new file with mode: 0644]
lib/devif/backends/debug/debug.h [new file with mode: 0644]
lib/devif/backends/debug/devif_backend_debug.c [new file with mode: 0644]

diff --git a/include/devif/backends/debug.h b/include/devif/backends/debug.h
new file mode 100644 (file)
index 0000000..933953b
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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 DEVIF_DEBUG_H_
+#define DEVIF_DEBUG_H_ 1
+
+
+#include <barrelfish/barrelfish.h>
+
+
+struct debug_q;
+
+/**
+ */
+errval_t debug_create(struct debug_q** q,
+                      struct devq* other_q);
+
+/**
+ */
+errval_t debug_destroy(struct debug_q* q, struct devq* other_q);
+
+
+#endif /* DEVIF_DEBUG_H_ */
diff --git a/lib/devif/backends/debug/Hakefile b/lib/devif/backends/debug/Hakefile
new file mode 100644 (file)
index 0000000..583d18c
--- /dev/null
@@ -0,0 +1,22 @@
+--------------------------------------------------------------------------
+-- 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.
+--
+-- Hakefile for lib/devif/backend/debug
+-- 
+-- Debug layer for device interface.
+--
+--------------------------------------------------------------------------
+
+[
+    build library { 
+        target = "devif_backend_debug",
+        cFiles = ["devif_backend_debug.c"],
+        addCFlags = [ "-DLIBRARY" ],
+        addLibraries = libDeps ["devif_internal"]
+    }
+]
diff --git a/lib/devif/backends/debug/debug.h b/lib/devif/backends/debug/debug.h
new file mode 100644 (file)
index 0000000..c99d0fd
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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 DEBUG_DEBUG_H_
+#define DEBUG_DEBUG_H_ 1
+
+
+//#define DEBUG_ENABLED 1
+
+/*****************************************************************
+ * Debug printer:
+ *****************************************************************/
+
+#if defined(DEBUG_ENABLED) 
+#define DEBUG(x...) do { printf("DEBUG: %s.%d:%s:%d: ", \
+            disp_name(), disp_get_core_id(), __func__, __LINE__); \
+                printf(x);\
+        } while (0)
+
+#else
+#define DEBUG(x...) ((void)0)
+#endif 
+
+#endif /* DEBUG_DEBUG_H_ */
diff --git a/lib/devif/backends/debug/devif_backend_debug.c b/lib/devif/backends/debug/devif_backend_debug.c
new file mode 100644 (file)
index 0000000..d7a42ed
--- /dev/null
@@ -0,0 +1,682 @@
+/*
+ * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/waitset.h>
+#include <devif/queue_interface.h>
+#include "../../queue_interface_internal.h"
+#include <devif/backends/debug.h>
+#include "debug.h"
+
+
+struct memory_ele {
+    genoffset_t offset;
+    genoffset_t length;
+    struct memory_ele* next;
+    struct memory_ele* prev;
+};
+
+struct memory_list {
+    regionid_t rid;
+    genoffset_t length;
+    struct memory_ele* buffers;
+    struct memory_list* next; // next in list of lists
+};
+
+struct debug_q {
+    struct devq my_q;
+    struct devq* q;
+    struct memory_list* regions; // list of lists
+    struct slab_allocator alloc;
+};
+
+static void dump_list(struct memory_list* region)
+{  
+    struct memory_ele* ele = region->buffers;
+    int index = 0;
+    printf("================================================ \n");
+    while (ele != NULL) {
+        printf("Idx=%d offset=%lu length=%lu", index, ele->offset,
+               ele->length);
+        if (ele->prev != NULL) {
+
+            printf(" prev->offset=%lu prev->length=%lu", ele->prev->offset,
+                   ele->prev->length);
+        }
+        printf(" \n");
+        ele = ele->next;
+        index++;
+    }   
+    printf("================================================ \n");
+}
+
+// checks if there are elements in the list that should be merged
+static void check_consistency(struct memory_list* region)
+{
+    struct memory_ele* ele = region->buffers;
+    while (ele->next != NULL) {
+        if (ele->offset + ele->length == ele->next->offset) {
+            printf("offset=%lu length=%lu \n", ele->offset, ele->length);
+            dump_list(region);
+            USER_PANIC("Found entry that should be merged \n");
+        }
+        ele = ele->next;
+    }   
+}
+
+static errval_t debug_register(struct devq* q, struct capref cap,
+                               regionid_t rid) 
+{
+    errval_t err;
+    struct debug_q* que = (struct debug_q*) q;
+    DEBUG("Register \n");
+    struct frame_identity id;
+    
+    err = invoke_frame_identify(cap, &id);
+    if (err_is_fail(err)) {
+        return err;
+    }
+        
+    // queue of regions is empty
+    if (que->regions == NULL) {
+        // add the reigon
+        err = que->q->f.reg(que->q, cap, rid);
+        if (err_is_fail(err)) {
+            return err;
+        }
+
+        que->regions = calloc(1, sizeof(struct memory_list));
+        que->regions->rid = rid;
+        que->regions->length = id.bytes;
+        que->regions->next = NULL;
+        // add the whole regions as a buffer
+        que->regions->buffers = slab_alloc(&que->alloc);
+        que->regions->buffers->offset = 0;
+        que->regions->buffers->length = id.bytes;
+        que->regions->buffers->next = NULL;
+        DEBUG("Register rid=%"PRIu32" size=%"PRIu64" \n", rid, 
+              id.bytes);
+        return SYS_ERR_OK;
+    }
+
+    struct memory_list* ele = que->regions;
+    while (ele->next != NULL) {
+        ele = ele->next;
+    }
+
+    err = que->q->f.reg(que->q, cap, rid);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    // add the reigon
+    ele->next = calloc(1,sizeof(struct memory_list));
+    ele = ele->next;
+
+    ele->rid = rid;
+    ele->next = NULL;
+    ele->length = id.bytes;
+    // add the whole regions as a buffer
+    ele->buffers = slab_alloc(&que->alloc);
+    ele->buffers->offset = 0;
+    ele->buffers->length = id.bytes;
+    ele->buffers->next = NULL;
+    DEBUG("Register rid=%"PRIu32" size=%"PRIu64" \n", rid, 
+          id.bytes);
+
+    return SYS_ERR_OK;
+}
+
+static errval_t debug_deregister(struct devq* q, regionid_t rid) 
+{
+    DEBUG("Deregister \n");
+    struct debug_q* que = (struct debug_q*) q;
+    errval_t err;
+
+    struct memory_list* ele = que->regions;
+    if (ele == NULL) {
+        return DEVQ_ERR_INVALID_REGION_ID;
+    }    
+
+    // remove head
+    if (ele->rid == rid) {
+        // there should only be a single element in the list
+        // i.e. the whole region
+        if (ele->buffers->offset == 0 &&
+            ele->buffers->length == ele->length &&
+            ele->buffers->next == NULL) {
+
+            err = que->q->f.dereg(que->q, rid);
+            if (err_is_fail(err)) {
+                return err;
+            }
+            que->regions = ele->next;
+        
+            DEBUG("removed region rid=%"PRIu32" size=%"PRIu64" \n", rid, 
+                  ele->length);
+
+            slab_free(&que->alloc, ele->buffers);
+            free(ele);
+
+            return SYS_ERR_OK;
+        } else {
+
+            DEBUG("Destroy error rid=%d offset=%"PRIu64" length=%"PRIu64" "
+                       "should be offset=0 length=%"PRIu64"\n",
+                       ele->rid, ele->buffers->offset, 
+                       ele->buffers->length, ele->length);
+            dump_list(ele);
+            return DEVQ_ERR_REGION_DESTROY;
+        }   
+    }
+    
+    while (ele->next != NULL) {
+        if (ele->next->rid == rid) {
+            if (ele->next->buffers->offset == 0 &&
+                ele->next->buffers->length == ele->next->length &&
+                ele->next->buffers->next == NULL) {
+            
+                err = que->q->f.dereg(que->q, rid);
+                if (err_is_fail(err)) {
+                    return err;
+                }
+                // remove from queue
+                struct memory_list* next = ele->next;
+                ele->next = ele->next->next;    
+
+                DEBUG("removed region rid=%"PRIu32" size=%"PRIu64" \n", rid, 
+                      next->length);
+            
+                slab_free(&que->alloc, next->buffers);
+                free(next);
+
+                return SYS_ERR_OK;
+            } else {
+                DEBUG("Destroy error rid=%d offset=%"PRIu64" length=%"PRIu64" "
+                       "should be offset=0 length=%"PRIu64"\n",
+                       ele->next->rid, ele->next->buffers->offset, 
+                       ele->next->buffers->length, ele->next->length);
+    
+                dump_list(ele);
+                return DEVQ_ERR_REGION_DESTROY;
+            }   
+        } else {
+            ele = ele->next;
+        }
+    }
+    
+
+    return DEVQ_ERR_INVALID_REGION_ID;
+}
+
+
+static errval_t debug_control(struct devq* q, uint64_t cmd, uint64_t value,
+                              uint64_t* result)
+{
+    DEBUG("control \n");
+    struct debug_q* que = (struct debug_q*) q;
+    return que->q->f.ctrl(que->q, cmd, value, result);
+}
+
+
+static errval_t debug_notify(struct devq* q)
+{
+    DEBUG("notify \n");
+    struct debug_q* que = (struct debug_q*) q;
+    return que->q->f.notify(que->q);
+}
+
+
+// is b1 in bounds of b2?
+static bool buffer_in_bounds(genoffset_t offset_b1, genoffset_t len_b1,
+                             genoffset_t offset_b2, genoffset_t len_b2)
+{
+    return (offset_b1 >= offset_b2) && (len_b1 <= len_b2) &&
+           ((offset_b1 + len_b1) <= offset_b2 + len_b2);
+}
+
+// assumes that the buffer described by offset and length is contained
+// in the buffer that is given as a struct
+static void remove_split_buffer(struct debug_q* que,
+                                struct memory_list* region,
+                                struct memory_ele* buffer,
+                                genoffset_t offset,
+                                genoffset_t length) 
+{
+    // split the buffer 
+    // insert half before the buffer
+
+    DEBUG("enqueue offset=%"PRIu64" length=%"PRIu64" buf->offset=%lu "
+          "buf->length %lu \n",
+          offset, length, buffer->offset, buffer->length);
+
+    // check if buffer at beginning of region
+    if (buffer->offset == offset) {
+        buffer->offset += length;
+        buffer->length -= length;
+
+        if (buffer->length == 0) {
+            // remove
+            if (buffer->prev != NULL) {
+                buffer->prev->next = buffer->next;
+            }
+        
+            if (buffer->next != NULL) {
+                buffer->next->prev = buffer->prev;
+            }
+            slab_free(&que->alloc, buffer);
+        }
+
+        DEBUG("enqueue first cut off begining results in offset=%"PRIu64" "
+              "length=%"PRIu64"\n",
+              buffer->offset, buffer->length);
+        return;
+    }
+
+    // check if buffer at end of region
+    if ((buffer->offset+buffer->length) == (offset+length)) {
+        buffer->length -= length;
+
+        if (buffer->length == 0) {
+            // remove
+            if (buffer->prev != NULL) {
+                buffer->prev = buffer->next;
+            }
+        
+            if (buffer->next != NULL) {
+                buffer->next->prev = buffer->prev;
+            }
+            slab_free(&que->alloc, buffer);
+        }
+    
+        DEBUG("enqueue first cut off end results in offset=%"PRIu64" "
+              "length=%"PRIu64"\n",
+              buffer->offset, buffer->length);
+        return;
+    }
+
+    // now if this did not work need to split buffer that contains the
+    // enqueued buffer into two buffers (might also result only in one)
+
+    // inset half before buffer
+    genoffset_t old_len = buffer->length;
+
+    buffer->length = offset - buffer->offset;  
+
+    struct memory_ele* after = NULL;
+    after = slab_alloc(&que->alloc);
+    after->offset = buffer->offset + buffer->length + length;
+    after->length = old_len - buffer->length - length;
+
+    // insert after buffer
+    after->prev = buffer;
+    after->next = buffer->next;
+
+    if (buffer->next != NULL) {
+        buffer->next->prev = after;
+    }
+
+    buffer->next = after;
+    DEBUG("Split buffer length=%lu to "
+          "offset=%"PRIu64" length=%"PRIu64" and "
+          "offset=%lu length=%lu \n",
+          old_len, 
+          buffer->offset, buffer->length,
+          after->offset, after->length);
+
+}
+
+/*
+ * Inserts a buffer either before or after an existing buffer into the queue
+ * Checks for merges of prev/next buffer in the queue
+ */
+static void insert_merge_buffer(struct debug_q* que,
+                                struct memory_list* region,
+                                struct memory_ele* buffer,
+                                genoffset_t offset,
+                                genoffset_t length) 
+{
+    assert(buffer != NULL);
+    assert(region != NULL);
+    if (offset >= buffer->offset+buffer->length) {// insert after
+        // buffer is on lower boundary
+        //
+        if (buffer->offset+length == offset) {
+            buffer->length += length;
+            DEBUG("dequeue merge after "
+                  "offset=%"PRIu64" length=%"PRIu64" to offset=%"PRIu64" "
+                  "length=%"PRIu64"\n",
+                  offset, length, buffer->offset, buffer->length);
+            // check other boundary for merge
+            if (buffer->next != NULL &&
+                (buffer->offset + buffer->length == buffer->next->offset)) {
+                buffer->length += buffer->next->length;
+                struct memory_ele* next = buffer->next;
+                if (buffer->next->next != NULL) {
+                    buffer->next = buffer->next->next;
+                    buffer->next->next->prev = buffer;
+                }
+
+                DEBUG("dequeue merge after more offset=%"PRIu64" "
+                      "length=%"PRIu64" to offset=%"PRIu64" length=%"PRIu64" \n ",
+                      next->offset, next->length,
+                      buffer->offset, buffer->length);
+
+                slab_free(&que->alloc, next);
+            }
+        } else { 
+            // check higher boundary
+            if (buffer->next != NULL && 
+                buffer->next->offset == offset+length) {
+
+                buffer->next->offset = offset;
+                buffer->next->length += length;
+
+                DEBUG("dequeue merge after more offset=%"PRIu64" "
+                      "length=%"PRIu64" to offset=%"PRIu64" length=%"PRIu64" \n ",
+                      offset, length,
+                      buffer->next->offset, buffer->next->length);
+            
+            } else { 
+                // buffer->next can be null and the newly inserted buffer
+                // is the inserted at the end -> check boundary
+                if (buffer->next == NULL && 
+                    buffer->offset + buffer->length == offset) {
+
+                    buffer->length += length;
+
+                    DEBUG("dequeue insert after merged offset=%"PRIu64" "
+                          "length=%"PRIu64" "
+                          "to offset=%"PRIu64" length=%"PRIu64" \n",
+                          offset, length, buffer->offset, buffer->length);
+                } else {
+                    // insert in between
+                    struct memory_ele* ele = slab_alloc(&que->alloc);
+                    assert(ele != NULL);
+                    
+                    ele->offset = offset;
+                    ele->length = length;
+                    ele->next = buffer->next;
+                    ele->prev = buffer;            
+
+                    if (buffer->next != NULL) {
+                        buffer->next->prev = ele;
+                    }
+
+                    buffer->next = ele;
+
+                    DEBUG("dequeue insert after offset=%"PRIu64" length=%"PRIu64" "
+                          "after offset=%"PRIu64" length=%"PRIu64" \n",
+                          offset, length, buffer->offset, buffer->length);
+                }
+            }
+        }
+    } else { // insert before buffer
+        // buffer is on lower boundary
+        if (buffer->offset == offset+length) {
+            buffer->length += length;
+            buffer->offset = offset;
+
+            // check other boundary
+            if (buffer->prev != NULL &&
+                (buffer->prev->offset+ buffer->prev->length == 
+                buffer->offset)) {
+                struct memory_ele* prev = buffer->prev;
+                prev->length += buffer->length;
+                prev->next = buffer->next;
+
+                if (buffer->next != NULL) {
+                    buffer->next->prev = prev;
+                }
+
+                slab_free(&que->alloc, buffer);
+
+                DEBUG("dequeue merge before more offset=%"PRIu64" "
+                      "length=%"PRIu64" to offset=%"PRIu64" length=%"PRIu64" \n ",
+                      offset, length, prev->offset, prev->length);
+            }
+        } else {
+            // check lower boundary
+            if (buffer->prev != NULL &&
+                (buffer->prev->offset+ buffer->prev->length == 
+                offset)) {
+                buffer->prev->length += length;
+
+                DEBUG("dequeue merge before more offset=%"PRIu64" "
+                      "length=%"PRIu64" to offset=%"PRIu64" length=%"PRIu64" \n ",
+                      offset, length, buffer->prev->offset, buffer->prev->length);
+            } else { // insert in between
+
+                // insert in between
+                struct memory_ele* ele = slab_alloc(&que->alloc);
+                assert(ele != NULL);
+                
+                ele->offset = offset;
+                ele->length = length;
+                ele->next = buffer;
+                ele->prev = buffer->prev;            
+
+                if (buffer->prev != NULL) {
+                    buffer->prev->next = ele;
+                } else {
+                    region->buffers = ele;
+                }
+
+                buffer->prev = ele;
+
+                DEBUG("dequeue insert before offset=%"PRIu64" length=%"PRIu64" "
+                      "next is offset=%"PRIu64" length=%"PRIu64" \n",
+                      offset, length,
+                      buffer->offset, buffer->length);
+            }
+        }
+    }
+}
+
+static errval_t find_region(struct debug_q* que, struct memory_list** list,
+                            regionid_t rid)
+{
+    // find region
+    struct memory_list* region = que->regions;
+   
+    while (region != NULL) {
+        if (region->rid == rid) {
+            break;
+        }        
+        region = region->next;
+    }
+    
+    // check if we found the region
+    if (region == NULL) {
+        return DEVQ_ERR_INVALID_REGION_ID;
+    }
+
+    *list = region;
+    return SYS_ERR_OK;
+}
+
+static errval_t debug_enqueue(struct devq* q, regionid_t rid, 
+                              genoffset_t offset, genoffset_t length,
+                              genoffset_t valid_data, genoffset_t valid_length,
+                              uint64_t flags)
+{
+    DEBUG("enqueue offset %"PRIu64" \n", offset);
+    errval_t err;
+    struct debug_q* que = (struct debug_q*) q;
+
+    // find region
+    struct memory_list* region = NULL;
+
+    err = find_region(que, &region, rid);
+    if (err_is_fail(err)){
+        return err;
+    }
+    
+    check_consistency(region);
+
+    // find the buffer 
+    struct memory_ele* buffer = region->buffers;
+    
+    if (region->buffers == NULL) {
+        return DEVQ_ERR_BUFFER_ALREADY_IN_USE;
+    }    
+
+    // the only buffer
+    if (buffer->next == NULL) {
+        if (buffer_in_bounds(offset, length,
+                             buffer->offset, buffer->length)) {
+            err = que->q->f.enq(que->q, rid, offset, length, valid_data,
+                                valid_length, flags);
+            if (err_is_fail(err)) {
+                return err;
+            }   
+
+            remove_split_buffer(que, region, buffer, offset, length);
+            return SYS_ERR_OK;          
+        } else {
+            DEBUG("Bounds check failed only buffer offset=%lu length=%lu " 
+                  " buf->offset=%lu buf->len=%lu\n", offset, length,
+                  buffer->offset, buffer->length);
+            return DEVQ_ERR_INVALID_BUFFER_ARGS;
+        }
+    }
+
+
+    // more than one buffer
+    while (buffer != NULL) {
+        if (buffer_in_bounds(offset, length, 
+                             buffer->offset, buffer->length)){
+            err = que->q->f.enq(que->q, rid, offset, length, valid_data,
+                                valid_length, flags);
+            if (err_is_fail(err)) {
+                return err;
+            }   
+
+            remove_split_buffer(que, region, buffer, offset, length);
+            return SYS_ERR_OK;          
+        }
+        buffer = buffer->next;
+    }  
+    
+    DEBUG("Did not find region \n");
+
+    return DEVQ_ERR_INVALID_BUFFER_ARGS;
+}
+
+static errval_t debug_dequeue(struct devq* q, regionid_t* rid, genoffset_t* offset,
+                              genoffset_t* length, genoffset_t* valid_data,
+                              genoffset_t* valid_length, uint64_t* flags)
+{
+    errval_t err;
+    struct debug_q* que = (struct debug_q*) q;
+    err = que->q->f.deq(que->q, rid, offset, length, valid_data,
+                        valid_length, flags);
+
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    DEBUG("dequeued offset=%lu \n", *offset);
+
+    struct memory_list* region = NULL;
+
+    err = find_region(que, &region, *rid);
+    if (err_is_fail(err)){
+        return err;
+    }
+
+    check_consistency(region);
+
+    // find the buffer 
+    struct memory_ele* buffer = region->buffers;
+    if (buffer == NULL) {
+        region->buffers = slab_alloc(&que->alloc);
+        region->buffers->offset = *offset;
+        region->buffers->length = *length;
+        region->buffers->next = NULL;
+        region->buffers->prev = NULL;
+        return SYS_ERR_OK;
+    }
+
+    if (buffer->next == NULL) {
+        if (!buffer_in_bounds(*offset, *length, buffer->offset,
+                              buffer->length)) {
+            insert_merge_buffer(que, region, buffer, *offset, *length);
+            return SYS_ERR_OK;
+        } else {
+            return DEVQ_ERR_BUFFER_NOT_IN_USE;
+        }
+    }
+
+
+    while (buffer->next != NULL) {
+        if (*offset >= buffer->offset) {
+            buffer = buffer->next;
+        } else {
+            if (!buffer_in_bounds(*offset, *length, buffer->offset, 
+                buffer->length)) {
+                insert_merge_buffer(que, region, buffer, *offset, *length);
+                return SYS_ERR_OK;
+            } else {
+                return DEVQ_ERR_BUFFER_NOT_IN_USE;
+            }
+        }
+    }
+
+    // insert after the last buffer
+    if (!buffer_in_bounds(*offset, *length, buffer->offset, 
+        buffer->length)) {
+        insert_merge_buffer(que, region, buffer, *offset, *length);
+        return SYS_ERR_OK;
+    }
+
+    return DEVQ_ERR_BUFFER_NOT_IN_USE;
+}
+
+/**
+ * Public functions
+ *
+ */
+
+errval_t debug_create(struct debug_q** q, struct devq* other_q)
+{
+    errval_t err;
+    struct debug_q* que;
+    que = calloc(1, sizeof(struct debug_q));
+    assert(que);
+
+    slab_init(&que->alloc, sizeof(struct memory_ele),
+              slab_default_refill);
+   
+    que->q = other_q;
+    err = devq_init(&que->my_q, false);
+    if (err_is_fail(err)) {
+        return err;
+    }   
+
+    que->my_q.f.reg = debug_register;
+    que->my_q.f.dereg = debug_deregister;
+    que->my_q.f.ctrl = debug_control;
+    que->my_q.f.notify = debug_notify;
+    que->my_q.f.enq = debug_enqueue;
+    que->my_q.f.deq = debug_dequeue;
+    *q = que;
+    return SYS_ERR_OK;
+}
+
+errval_t debug_destroy(struct debug_q* q, struct devq* devq)
+{
+    devq = q->q;
+    free(q);    
+
+    return SYS_ERR_OK;
+}
+