1/* 2 * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <stdlib.h> 11#include <stdio.h> 12#include <stdbool.h> 13#include <barrelfish/barrelfish.h> 14#include <barrelfish/waitset.h> 15#include <devif/queue_interface.h> 16#include <devif/queue_interface_backend.h> 17#include <devif/backends/debug.h> 18#include "debug.h" 19 20#define HIST_SIZE 128 21#define MAX_STR_SIZE 128 22 23/* 24 * This is a debugging interface for the device queue interface that 25 * can be used with any existing queue. It can be stacked on top 26 * to check for non valid buffer enqueues/deqeues that might happen. 27 * A not valid enqueue of a buffer is when the endpoint that enqueues 28 * the buffer does not own the buffer. 29 * 30 * We keep track of the owned buffers as a list of regions which each 31 * contains a list of memory chunks. 32 * Each chunk specifies a offset within the region and its length. 33 * 34 * When a region is registered, we add one memory chunk that describes 35 * the whole region i.e. offset=0 length= length of region 36 * 37 * If a a buffer is enqueued, it has to be contained in one of these 38 * memory chunks. The memory chunk is then altered according how 39 * the buffer is contained in the chunk. If it is at the beginning or 40 * end of the chunk, the offset/length of the chunk is changed accordingly 41 * If the buffer is in the middle of the chunk, we split the memory chunk 42 * into two new memory chunks that do not contain the buffer. 43 * 44 * If a buffer is dequeued the buffer is added to the existing memory 45 * chunks if possible, otherwise a new memory chunk is added to the 46 * list of chunks. If a buffer is dequeued that is in between two 47 * memory chunks, the memory chunks are merged to one big chunk. 48 * We might fail to find the region id in our list of regions. In this 49 * case we add the region with the deqeued offset+length as a size. 50 * We can be sure that this region exists since the devq library itself 51 * does these checks if the region is known to the endpoint. This simply 52 * means the debugging queue on top of the other queue does not have a 53 * consistant view of the registered regions (but the queue below does) 54 * 55 * When a region is deregistered, the list of chunks has to only 56 * contain a single chunk that descirbes the whole region. Otherwise 57 * the call will fail since some of the buffers are still in use. 58 * 59 */ 60 61struct memory_ele { 62 genoffset_t offset; 63 genoffset_t length; 64 struct memory_ele* next; 65 struct memory_ele* prev; 66}; 67 68struct memory_list { 69 regionid_t rid; 70 genoffset_t length; 71 // is a region that we did not register ourselves 72 bool not_consistent; 73 struct memory_ele* buffers; 74 struct memory_list* next; // next in list of lists 75}; 76 77struct operation { 78 char str[MAX_STR_SIZE]; 79 genoffset_t offset; 80 genoffset_t length; 81}; 82 83struct debug_q { 84 struct devq my_q; 85 struct devq* q; 86 struct memory_list* regions; // list of lists 87 struct slab_allocator alloc; 88 struct slab_allocator alloc_list; 89 uint16_t hist_head; 90 struct operation history[HIST_SIZE]; 91}; 92 93 94 95static void dump_list(struct memory_list* region) 96{ 97 struct memory_ele* ele = region->buffers; 98 int index = 0; 99 printf("================================================ \n"); 100 while (ele != NULL) { 101 printf("Idx=%d offset=%lu length=%lu", index, ele->offset, 102 ele->length); 103 if (ele->prev != NULL) { 104 105 printf(" prev->offset=%lu prev->length=%lu", ele->prev->offset, 106 ele->prev->length); 107 } 108 printf(" \n"); 109 ele = ele->next; 110 index++; 111 } 112 printf("================================================ \n"); 113} 114 115// checks if there are elements in the list that should be merged 116static void check_consistency(struct memory_list* region) 117{ 118 struct memory_ele* ele = region->buffers; 119 while (ele->next != NULL) { 120 if (ele->offset + ele->length == ele->next->offset) { 121 printf("offset=%lu length=%lu \n", ele->offset, ele->length); 122 dump_list(region); 123 USER_PANIC("Found entry that should be merged \n"); 124 } 125 ele = ele->next; 126 } 127} 128 129static void add_to_history(struct debug_q* q, genoffset_t offset, 130 genoffset_t length, char* s) 131{ 132 q->history[q->hist_head].offset = offset; 133 q->history[q->hist_head].length = length; 134 strncpy(q->history[q->hist_head].str, s, MAX_STR_SIZE); 135 q->hist_head = (q->hist_head + 1) % HIST_SIZE; 136 137} 138 139static void dump_history(struct debug_q* q) 140{ 141 for (int i = 0; i < HIST_SIZE; i++) { 142 printf("offset=%lu length=%lu %s\n", q->history[q->hist_head].offset, 143 q->history[q->hist_head].length, q->history[q->hist_head].str); 144 145 q->hist_head = (q->hist_head + 1) % HIST_SIZE; 146 } 147} 148 149/* 150static bool in_list(struct memory_list* region, genoffset_t offset, 151 genoffset_t length) 152{ 153 struct memory_ele* ele = region->buffers; 154 while (ele != NULL) { 155 if (offset >= ele->offset && 156 offset + length <= ele->offset+ele->length) { 157 return true; 158 } 159 ele = ele->next; 160 } 161 return false; 162} 163*/ 164 165 166 167static errval_t debug_register(struct devq* q, struct capref cap, 168 regionid_t rid) 169{ 170 errval_t err; 171 struct debug_q* que = (struct debug_q*) q; 172 DEBUG("Register \n"); 173 struct frame_identity id; 174 175 err = invoke_frame_identify(cap, &id); 176 if (err_is_fail(err)) { 177 return err; 178 } 179 180 // queue of regions is empty 181 if (que->regions == NULL) { 182 // add the reigon 183 err = que->q->f.reg(que->q, cap, rid); 184 if (err_is_fail(err)) { 185 return err; 186 } 187 188 que->regions = slab_alloc(&que->alloc_list); 189 assert(que->regions != NULL); 190 191 que->regions->rid = rid; 192 que->regions->length = id.bytes; 193 que->regions->not_consistent = false; 194 que->regions->next = NULL; 195 // add the whole regions as a buffer 196 que->regions->buffers = slab_alloc(&que->alloc); 197 assert(que->regions->buffers != NULL); 198 199 memset(que->regions->buffers, 0, sizeof(que->regions->buffers)); 200 que->regions->buffers->offset = 0; 201 que->regions->buffers->length = id.bytes; 202 que->regions->buffers->next = NULL; 203 DEBUG("Register rid=%"PRIu32" size=%"PRIu64" \n", rid, 204 id.bytes); 205 return SYS_ERR_OK; 206 } 207 208 struct memory_list* ele = que->regions; 209 while (ele->next != NULL) { 210 ele = ele->next; 211 } 212 213 err = que->q->f.reg(que->q, cap, rid); 214 if (err_is_fail(err)) { 215 return err; 216 } 217 218 // add the reigon 219 ele->next = slab_alloc(&que->alloc_list); 220 assert(ele->next != NULL); 221 222 ele = ele->next; 223 ele->rid = rid; 224 ele->next = NULL; 225 ele->length = id.bytes; 226 ele->not_consistent = false; 227 // add the whole regions as a buffer 228 ele->buffers = slab_alloc(&que->alloc); 229 assert(ele->buffers != NULL); 230 231 memset(ele->buffers, 0, sizeof(ele->buffers)); 232 ele->buffers->offset = 0; 233 ele->buffers->length = id.bytes; 234 ele->buffers->next = NULL; 235 DEBUG("Register rid=%"PRIu32" size=%"PRIu64" \n", rid, 236 id.bytes); 237 238 return SYS_ERR_OK; 239} 240 241static errval_t debug_deregister(struct devq* q, regionid_t rid) 242{ 243 DEBUG("Deregister \n"); 244 struct debug_q* que = (struct debug_q*) q; 245 errval_t err; 246 247 struct memory_list* ele = que->regions; 248 if (ele == NULL) { 249 return DEVQ_ERR_INVALID_REGION_ID; 250 } 251 252 // remove head 253 if (ele->rid == rid) { 254 // there should only be a single element in the list 255 // i.e. the whole region 256 if (ele->buffers->offset == 0 && 257 ele->buffers->length == ele->length && 258 ele->buffers->next == NULL) { 259 260 err = que->q->f.dereg(que->q, rid); 261 if (err_is_fail(err)) { 262 return err; 263 } 264 que->regions = ele->next; 265 266 DEBUG("removed region rid=%"PRIu32" size=%"PRIu64" \n", rid, 267 ele->length); 268 269 slab_free(&que->alloc, ele->buffers); 270 slab_free(&que->alloc_list, ele); 271 272 return SYS_ERR_OK; 273 } else { 274 275 DEBUG("Destroy error rid=%d offset=%"PRIu64" length=%"PRIu64" " 276 "should be offset=0 length=%"PRIu64"\n", 277 ele->rid, ele->buffers->offset, 278 ele->buffers->length, ele->length); 279 dump_list(ele); 280 return DEVQ_ERR_REGION_DESTROY; 281 } 282 } 283 284 while (ele->next != NULL) { 285 if (ele->next->rid == rid) { 286 if (ele->next->buffers->offset == 0 && 287 ele->next->buffers->length == ele->next->length && 288 ele->next->buffers->next == NULL) { 289 290 err = que->q->f.dereg(que->q, rid); 291 if (err_is_fail(err)) { 292 return err; 293 } 294 // remove from queue 295 struct memory_list* next = ele->next; 296 ele->next = ele->next->next; 297 298 DEBUG("removed region rid=%"PRIu32" size=%"PRIu64" \n", rid, 299 next->length); 300 301 slab_free(&que->alloc, next->buffers); 302 slab_free(&que->alloc_list, next); 303 304 return SYS_ERR_OK; 305 } else { 306 DEBUG("Destroy error rid=%d offset=%"PRIu64" length=%"PRIu64" " 307 "should be offset=0 length=%"PRIu64"\n", 308 ele->next->rid, ele->next->buffers->offset, 309 ele->next->buffers->length, ele->next->length); 310 311 dump_list(ele); 312 return DEVQ_ERR_REGION_DESTROY; 313 } 314 } else { 315 ele = ele->next; 316 } 317 } 318 319 320 return DEVQ_ERR_INVALID_REGION_ID; 321} 322 323 324static errval_t debug_control(struct devq* q, uint64_t cmd, uint64_t value, 325 uint64_t* result) 326{ 327 DEBUG("control \n"); 328 struct debug_q* que = (struct debug_q*) q; 329 return que->q->f.ctrl(que->q, cmd, value, result); 330} 331 332 333static errval_t debug_notify(struct devq* q) 334{ 335 DEBUG("notify \n"); 336 struct debug_q* que = (struct debug_q*) q; 337 return que->q->f.notify(que->q); 338} 339 340 341// is b1 in bounds of b2? 342static bool buffer_in_bounds(genoffset_t offset_b1, genoffset_t len_b1, 343 genoffset_t offset_b2, genoffset_t len_b2) 344{ 345 return (offset_b1 >= offset_b2) && (len_b1 <= len_b2) && 346 ((offset_b1 + len_b1) <= offset_b2 + len_b2); 347} 348 349// assumes that the buffer described by offset and length is contained 350// in the buffer that is given as a struct 351static void remove_split_buffer(struct debug_q* que, 352 struct memory_list* region, 353 struct memory_ele* buffer, 354 genoffset_t offset, 355 genoffset_t length) 356{ 357 // split the buffer 358 // insert half before the buffer 359 360 DEBUG("enqueue offset=%"PRIu64" length=%"PRIu64" buf->offset=%lu " 361 "buf->length %lu \n", 362 offset, length, buffer->offset, buffer->length); 363 364 // check if buffer at beginning of region 365 if (buffer->offset == offset) { 366 buffer->offset += length; 367 buffer->length -= length; 368 369 if (buffer->length == 0) { 370 add_to_history(que, offset, length, "enq cut of beginning remove"); 371 DEBUG("enqueue remove buffer from list\n"); 372 // remove 373 if (buffer->prev != NULL) { 374 buffer->prev->next = buffer->next; 375 } else { 376 region->buffers = buffer->next; 377 } 378 379 if (buffer->next != NULL) { 380 buffer->next->prev = buffer->prev; 381 } 382 slab_free(&que->alloc, buffer); 383 } else { 384 add_to_history(que, offset, length, "enq cut of beginning"); 385 } 386 387 DEBUG("enqueue first cut off begining results in offset=%"PRIu64" " 388 "length=%"PRIu64"\n", 389 buffer->offset, buffer->length); 390 return; 391 } 392 393 // check if buffer at end of region 394 if ((buffer->offset+buffer->length) == (offset+length)) { 395 buffer->length -= length; 396 397 if (buffer->length == 0) { 398 add_to_history(que, offset, length, "enq cut of end remove"); 399 // remove 400 if (buffer->prev != NULL) { 401 buffer->prev = buffer->next; 402 } 403 404 if (buffer->next != NULL) { 405 buffer->next->prev = buffer->prev; 406 } 407 slab_free(&que->alloc, buffer); 408 } else { 409 add_to_history(que, offset, length, "enq cut of end"); 410 } 411 412 DEBUG("enqueue first cut off end results in offset=%"PRIu64" " 413 "length=%"PRIu64"\n", 414 buffer->offset, buffer->length); 415 return; 416 } 417 418 // now if this did not work need to split buffer that contains the 419 // enqueued buffer into two buffers (might also result only in one) 420 421 // inset half before buffer 422 genoffset_t old_len = buffer->length; 423 424 buffer->length = offset - buffer->offset; 425 426 struct memory_ele* after = NULL; 427 after = slab_alloc(&que->alloc); 428 assert(after != NULL); 429 430 memset(after, 0, sizeof(after)); 431 after->offset = buffer->offset + buffer->length + length; 432 after->length = old_len - buffer->length - length; 433 434 // insert after buffer 435 after->prev = buffer; 436 after->next = buffer->next; 437 438 if (buffer->next != NULL) { 439 buffer->next->prev = after; 440 } 441 442 buffer->next = after; 443 444 add_to_history(que, offset, length, "enq split buffer"); 445 446 DEBUG("Split buffer length=%lu to " 447 "offset=%"PRIu64" length=%"PRIu64" and " 448 "offset=%lu length=%lu \n", 449 old_len, 450 buffer->offset, buffer->length, 451 after->offset, after->length); 452 453} 454 455/* 456 * Inserts a buffer either before or after an existing buffer into the queue 457 * Checks for merges of prev/next buffer in the queue 458 */ 459static void insert_merge_buffer(struct debug_q* que, 460 struct memory_list* region, 461 struct memory_ele* buffer, 462 genoffset_t offset, 463 genoffset_t length) 464{ 465 assert(buffer != NULL); 466 assert(region != NULL); 467 468 if (offset >= buffer->offset+buffer->length) {// insert after 469 // buffer is on lower boundary 470 // 471 if (buffer->offset+length == offset) { 472 buffer->length += length; 473 DEBUG("dequeue merge after " 474 "offset=%"PRIu64" length=%"PRIu64" to offset=%"PRIu64" " 475 "length=%"PRIu64"\n", 476 offset, length, buffer->offset, buffer->length); 477 // check other boundary for merge 478 if (buffer->next != NULL && 479 (buffer->offset + buffer->length == buffer->next->offset)) { 480 buffer->length += buffer->next->length; 481 struct memory_ele* next = buffer->next; 482 if (buffer->next->next != NULL) { 483 buffer->next = buffer->next->next; 484 buffer->next->next->prev = buffer; 485 } 486 487 DEBUG("dequeue merge after more offset=%"PRIu64" " 488 "length=%"PRIu64" to offset=%"PRIu64" length=%"PRIu64" \n ", 489 next->offset, next->length, 490 buffer->offset, buffer->length); 491 492 add_to_history(que, offset, length, "deq insert after" 493 " on lower boundary and merge"); 494 495 slab_free(&que->alloc, next); 496 } else { 497 add_to_history(que, offset, length, "deq insert after on lower boundary"); 498 } 499 } else { 500 // check higher boundary 501 if (buffer->next != NULL && 502 buffer->next->offset == offset+length) { 503 504 buffer->next->offset = offset; 505 buffer->next->length += length; 506 507 DEBUG("dequeue merge after more offset=%"PRIu64" " 508 "length=%"PRIu64" to offset=%"PRIu64" length=%"PRIu64" \n ", 509 offset, length, 510 buffer->next->offset, buffer->next->length); 511 add_to_history(que, offset, length, "deq insert after" 512 " on higer boundary"); 513 514 } else { 515 // buffer->next can be null and the newly inserted buffer 516 // is the inserted at the end -> check boundary 517 if (buffer->next == NULL && 518 buffer->offset + buffer->length == offset) { 519 520 buffer->length += length; 521 522 add_to_history(que, offset, length, "deq insert after" 523 " on higer boundary end"); 524 525 DEBUG("dequeue insert after merged offset=%"PRIu64" " 526 "length=%"PRIu64" " 527 "to offset=%"PRIu64" length=%"PRIu64" \n", 528 offset, length, buffer->offset, buffer->length); 529 } else { 530 // insert in between 531 struct memory_ele* ele = slab_alloc(&que->alloc); 532 assert(ele != NULL); 533 534 ele->offset = offset; 535 ele->length = length; 536 ele->next = buffer->next; 537 ele->prev = buffer; 538 539 if (buffer->next != NULL) { 540 buffer->next->prev = ele; 541 } 542 543 buffer->next = ele; 544 545 add_to_history(que, offset, length, "deq insert after" 546 " in between"); 547 DEBUG("dequeue insert after offset=%"PRIu64" length=%"PRIu64" " 548 "after offset=%"PRIu64" length=%"PRIu64" \n", 549 offset, length, buffer->offset, buffer->length); 550 } 551 } 552 } 553 } else { // insert before buffer 554 // buffer is on lower boundary 555 if (buffer->offset == offset+length) { 556 buffer->length += length; 557 buffer->offset = offset; 558 559 // check other boundary 560 if (buffer->prev != NULL && 561 (buffer->prev->offset+ buffer->prev->length == 562 buffer->offset)) { 563 struct memory_ele* prev = buffer->prev; 564 prev->length += buffer->length; 565 prev->next = buffer->next; 566 567 if (buffer->next != NULL) { 568 buffer->next->prev = prev; 569 } 570 571 slab_free(&que->alloc, buffer); 572 573 add_to_history(que, offset, length, "deq insert buffer" 574 " before lower boundary merge"); 575 DEBUG("dequeue merge before more offset=%"PRIu64" " 576 "length=%"PRIu64" to offset=%"PRIu64" length=%"PRIu64" \n ", 577 offset, length, prev->offset, prev->length); 578 } else { 579 add_to_history(que, offset, length, "deq insert buffer" 580 " before lower boundary"); 581 } 582 } else { 583 // check lower boundary 584 if (buffer->prev != NULL && 585 (buffer->prev->offset+ buffer->prev->length == 586 offset)) { 587 if (length == 0) { 588 printf("Length is 0 \n"); 589 buffer->prev->length += 2048; 590 } 591 592 buffer->prev->length += length; 593 594 add_to_history(que, offset, length, "deq insert buffer" 595 " before prev lower boundary merge"); 596 DEBUG("dequeue merge before more offset=%"PRIu64" " 597 "length=%"PRIu64" to offset=%"PRIu64" length=%"PRIu64" \n ", 598 offset, length, buffer->prev->offset, buffer->prev->length); 599 } else { // insert in between 600 601 // insert in between 602 struct memory_ele* ele = slab_alloc(&que->alloc); 603 assert(ele != NULL); 604 605 memset(ele, 0, sizeof(ele)); 606 ele->offset = offset; 607 ele->length = length; 608 ele->next = buffer; 609 ele->prev = buffer->prev; 610 611 if (buffer->prev != NULL) { 612 buffer->prev->next = ele; 613 } else { 614 region->buffers = ele; 615 } 616 617 buffer->prev = ele; 618 619 add_to_history(que, offset, length, "deq insert buffer" 620 " before in between"); 621 DEBUG("dequeue insert before offset=%"PRIu64" length=%"PRIu64" " 622 "next is offset=%"PRIu64" length=%"PRIu64" \n", 623 offset, length, 624 buffer->offset, buffer->length); 625 } 626 } 627 } 628} 629 630static errval_t find_region(struct debug_q* que, struct memory_list** list, 631 regionid_t rid) 632{ 633 // find region 634 struct memory_list* region = que->regions; 635 636 while (region != NULL) { 637 if (region->rid == rid) { 638 break; 639 } 640 region = region->next; 641 } 642 643 // check if we found the region 644 if (region == NULL) { 645 return DEVQ_ERR_INVALID_REGION_ID; 646 } 647 648 *list = region; 649 return SYS_ERR_OK; 650} 651 652static errval_t debug_enqueue(struct devq* q, regionid_t rid, 653 genoffset_t offset, genoffset_t length, 654 genoffset_t valid_data, genoffset_t valid_length, 655 uint64_t flags) 656{ 657 assert(length > 0); 658 DEBUG("enqueue offset %"PRIu64" \n", offset); 659 errval_t err; 660 struct debug_q* que = (struct debug_q*) q; 661 662 // find region 663 struct memory_list* region = NULL; 664 665 err = find_region(que, ®ion, rid); 666 if (err_is_fail(err)){ 667 return err; 668 } 669 670 check_consistency(region); 671 672 // find the buffer 673 struct memory_ele* buffer = region->buffers; 674 675 if (region->buffers == NULL) { 676 return DEVQ_ERR_BUFFER_ALREADY_IN_USE; 677 } 678 679 // the only buffer 680 if (buffer->next == NULL) { 681 if (buffer_in_bounds(offset, length, 682 buffer->offset, buffer->length)) { 683 err = que->q->f.enq(que->q, rid, offset, length, valid_data, 684 valid_length, flags); 685 if (err_is_fail(err)) { 686 return err; 687 } 688 689 remove_split_buffer(que, region, buffer, offset, length); 690 return SYS_ERR_OK; 691 } else { 692 printf("Bounds check failed only buffer offset=%lu length=%lu " 693 " buf->offset=%lu buf->len=%lu\n", offset, length, 694 buffer->offset, buffer->length); 695 dump_history(que); 696 dump_list(region); 697 return DEVQ_ERR_INVALID_BUFFER_ARGS; 698 } 699 } 700 701 702 // more than one buffer 703 while (buffer != NULL) { 704 if (buffer_in_bounds(offset, length, 705 buffer->offset, buffer->length)){ 706 err = que->q->f.enq(que->q, rid, offset, length, valid_data, 707 valid_length, flags); 708 if (err_is_fail(err)) { 709 return err; 710 } 711 712 remove_split_buffer(que, region, buffer, offset, length); 713 return SYS_ERR_OK; 714 } 715 buffer = buffer->next; 716 } 717 718 printf("Did not find region offset=%ld length=%ld \n", offset, length); 719 dump_history(que); 720 dump_list(region); 721 722 return DEVQ_ERR_INVALID_BUFFER_ARGS; 723} 724 725static errval_t debug_dequeue(struct devq* q, regionid_t* rid, genoffset_t* offset, 726 genoffset_t* length, genoffset_t* valid_data, 727 genoffset_t* valid_length, uint64_t* flags) 728{ 729 errval_t err; 730 struct debug_q* que = (struct debug_q*) q; 731 assert(que->q->f.deq != NULL); 732 err = que->q->f.deq(que->q, rid, offset, length, valid_data, 733 valid_length, flags); 734 if (err_is_fail(err)) { 735 return err; 736 } 737 DEBUG("dequeued offset=%lu \n", *offset); 738 739 struct memory_list* region = NULL; 740 741 err = find_region(que, ®ion, *rid); 742 if (err_is_fail(err)){ 743 // region ids are checked bythe devq library, if we do not find 744 // the region id when dequeueing here we do not have a consistant 745 // view of two endpoints 746 // 747 // Add region 748 if (que->regions == NULL) { 749 printf("Adding region frirst %lu len \n", *offset + *length); 750 751 que->regions = slab_alloc(&que->alloc_list); 752 assert(que->regions != NULL); 753 754 que->regions->rid = *rid; 755 que->regions->not_consistent = true; 756 // region is at least offset + length 757 que->regions->length = *offset + *length; 758 que->regions->next = NULL; 759 // add the whole regions as a buffer 760 que->regions->buffers = slab_alloc(&que->alloc); 761 assert(que->regions->buffers != NULL); 762 763 memset(que->regions->buffers, 0, sizeof(que->regions->buffers)); 764 que->regions->buffers->offset = 0; 765 que->regions->buffers->length = *offset + *length; 766 que->regions->buffers->next = NULL; 767 return SYS_ERR_OK; 768 } 769 770 struct memory_list* ele = que->regions; 771 while (ele->next != NULL) { 772 ele = ele->next; 773 } 774 775 printf("Adding region second %lu len \n", *offset + *length); 776 // add the reigon 777 ele->next = slab_alloc(&que->alloc_list); 778 assert(ele->next != NULL); 779 780 memset(que->regions->buffers, 0, sizeof(ele->next)); 781 ele = ele->next; 782 783 ele->rid = *rid; 784 ele->next = NULL; 785 ele->not_consistent = true; 786 ele->length = *offset + *length; 787 // add the whole regions as a buffer 788 ele->buffers = slab_alloc(&que->alloc); 789 assert(ele->buffers != NULL); 790 791 memset(ele->buffers, 0, sizeof(ele->buffers)); 792 ele->buffers->offset = 0; 793 ele->buffers->length = *offset + *length; 794 ele->buffers->next = NULL; 795 return SYS_ERR_OK; 796 } 797 798 if (region->not_consistent) { 799 if ((*offset + *length) > region->length) { 800 region->length = *offset + *length; 801 } 802 } 803 804 //check_consistency(region); 805 806 // find the buffer 807 struct memory_ele* buffer = region->buffers; 808 if (buffer == NULL) { 809 region->buffers = slab_alloc(&que->alloc); 810 assert(region->buffers != NULL); 811 812 region->buffers->offset = *offset; 813 region->buffers->length = *length; 814 region->buffers->next = NULL; 815 region->buffers->prev = NULL; 816 return SYS_ERR_OK; 817 } 818 819 if (buffer->next == NULL) { 820 if (!buffer_in_bounds(*offset, *length, buffer->offset, 821 buffer->length)) { 822 insert_merge_buffer(que, region, buffer, *offset, *length); 823 return SYS_ERR_OK; 824 } else { 825 return DEVQ_ERR_BUFFER_NOT_IN_USE; 826 } 827 } 828 829 830 while (buffer->next != NULL) { 831 if (*offset >= buffer->offset) { 832 buffer = buffer->next; 833 } else { 834 if (!buffer_in_bounds(*offset, *length, buffer->offset, 835 buffer->length)) { 836 insert_merge_buffer(que, region, buffer, *offset, *length); 837 return SYS_ERR_OK; 838 } else { 839 return DEVQ_ERR_BUFFER_NOT_IN_USE; 840 } 841 } 842 } 843 844 // insert after the last buffer 845 if (!buffer_in_bounds(*offset, *length, buffer->offset, 846 buffer->length)) { 847 insert_merge_buffer(que, region, buffer, *offset, *length); 848 return SYS_ERR_OK; 849 } 850 851 return DEVQ_ERR_BUFFER_NOT_IN_USE; 852} 853 854static errval_t debug_destroy(struct devq* devq) 855{ 856 // TODO cleanup 857 return SYS_ERR_OK; 858} 859 860/** 861 * Public functions 862 * 863 */ 864 865errval_t debug_create(struct debug_q** q, struct devq* other_q) 866{ 867 errval_t err; 868 struct debug_q* que; 869 que = calloc(1, sizeof(struct debug_q)); 870 assert(que); 871 872 slab_init(&que->alloc, sizeof(struct memory_ele), 873 slab_default_refill); 874 875 slab_init(&que->alloc_list, sizeof(struct memory_list), 876 slab_default_refill); 877 878 que->q = other_q; 879 err = devq_init(&que->my_q, false); 880 if (err_is_fail(err)) { 881 return err; 882 } 883 884 que->my_q.f.reg = debug_register; 885 que->my_q.f.dereg = debug_deregister; 886 que->my_q.f.ctrl = debug_control; 887 que->my_q.f.notify = debug_notify; 888 que->my_q.f.enq = debug_enqueue; 889 que->my_q.f.deq = debug_dequeue; 890 que->my_q.f.destroy = debug_destroy; 891 *q = que; 892 return SYS_ERR_OK; 893} 894 895errval_t debug_dump_region(struct debug_q* que, regionid_t rid) 896{ 897 errval_t err; 898 // find region 899 struct memory_list* region = NULL; 900 901 err = find_region(que, ®ion, rid); 902 if (err_is_fail(err)){ 903 return err; 904 } 905 906 dump_list(region); 907 return SYS_ERR_OK; 908} 909 910 911void debug_dump_history(struct debug_q* q) 912{ 913 dump_history(q); 914} 915 916errval_t debug_add_region(struct debug_q* q, struct capref cap, 917 regionid_t rid) 918{ 919 return devq_add_region((struct devq*) q, cap, rid); 920} 921 922errval_t debug_remove_region(struct debug_q* q, regionid_t rid) 923{ 924 return devq_remove_region((struct devq*) q, rid); 925} 926