Memory.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include "Memory.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. typedef struct {
  6. u32 units;
  7. i32 next;
  8. } Slot;
  9. static Slot* memory = nullptr;
  10. static u32 maxUnits = 0;
  11. static Slot baseSlot = {.units = 0, .next = -1};
  12. static Slot* slots = &baseSlot;
  13. static constexpr i32 CANARY = (i32)0xEFBEADDE;
  14. static i32 memoryGetSlotIndex(const Slot* s) {
  15. return (i32)(s - memory);
  16. }
  17. void memoryInit(void* p, u32 n) {
  18. u32 offset = (u64)p % sizeof(Slot);
  19. if(offset > 0) {
  20. offset = (u32)sizeof(Slot) - offset;
  21. }
  22. memory = (Slot*)(void*)((char*)p + offset);
  23. maxUnits = (n - offset) / sizeof(Slot);
  24. Slot* s = memory;
  25. s->next = -1;
  26. s->units = maxUnits;
  27. slots->next = 0;
  28. }
  29. static Slot* memoryNextSlot(const Slot* s) {
  30. if(s->next == -1) {
  31. return nullptr;
  32. }
  33. return memory + s->next;
  34. }
  35. void* memoryAllocate(size_t bytes) {
  36. if(bytes == 0) {
  37. return nullptr;
  38. }
  39. u32 units = (u32)((bytes + sizeof(Slot) - 1) / sizeof(Slot) + 1);
  40. if(units > maxUnits) {
  41. return nullptr;
  42. }
  43. Slot* previous = nullptr;
  44. Slot* current = slots;
  45. while(current != nullptr) {
  46. if(current->units >= units) {
  47. break;
  48. }
  49. previous = current;
  50. current = memoryNextSlot(current);
  51. }
  52. if(current == nullptr) {
  53. return nullptr;
  54. }
  55. if(current->units == units) {
  56. previous->next = current->next;
  57. } else {
  58. Slot* newSlot = current + units;
  59. newSlot->next = current->next;
  60. newSlot->units = current->units - units;
  61. previous->next = memoryGetSlotIndex(newSlot);
  62. }
  63. current->next = CANARY;
  64. current->units = units;
  65. return current + 1;
  66. }
  67. void memoryFree(void* p) {
  68. if(p == nullptr) {
  69. return;
  70. }
  71. Slot* s = (Slot*)p - 1;
  72. if(s->next != CANARY) {
  73. fprintf(stderr, "free with corupt canary\n");
  74. abort();
  75. }
  76. Slot* previous = slots;
  77. Slot* current = memoryNextSlot(slots);
  78. while(current != nullptr && current < s) {
  79. previous = current;
  80. current = memoryNextSlot(current);
  81. }
  82. if(current == nullptr) {
  83. s->next = -1;
  84. } else if(s + s->units == current) {
  85. s->units += current->units;
  86. s->next = current->next;
  87. } else {
  88. s->next = memoryGetSlotIndex(current);
  89. }
  90. if(previous + previous->units == s) {
  91. previous->units += s->units;
  92. previous->next = s->next;
  93. } else {
  94. previous->next = memoryGetSlotIndex(s);
  95. }
  96. }
  97. void memoryDump() {
  98. // for(size_t i = 0; i < maxUnits * sizeof(Slot); i++) {
  99. // fprintf(stderr, "%02x", (unsigned)((char*)memory)[i] & 0xFF);
  100. // if((i + 1) % 30 == 0) {
  101. // fputc('\n', stderr);
  102. // }
  103. // }
  104. // fputc('\n', stderr);
  105. fputs("Free Slots ", stderr);
  106. u32 sum = 0;
  107. Slot* current = memoryNextSlot(slots);
  108. while(current != nullptr) {
  109. fprintf(stderr, "%u, ", current->units);
  110. sum += current->units;
  111. current = memoryNextSlot(current);
  112. }
  113. fprintf(stderr, " = %u\n", sum);
  114. }
  115. i32 memoryConvertToIndex(void* p) {
  116. return memoryGetSlotIndex((Slot*)p);
  117. }
  118. void* memoryConvertToPointer(i32 index) {
  119. return memory + index;
  120. }