您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

184 行
7.6 KiB

4 年前
  1. $export_common #library "ZMEMORY"
  2. $export_common #include "zcommon.acs"
  3. #include "ZMEMORY_g.acs"
  4. #include "ZMEMORY_w.acs"
  5. //Simple linked list implementation of malloc
  6. $export_option
  7. global int 63:gmemory[];
  8. $
  9. world int 255:wmemory[];
  10. $
  11. $export_common #libdefine nullptr 0
  12. $export_common //#define nullptr 0
  13. $export_common #define malloc_allocated 0
  14. $export_common #define malloc_size 1
  15. $export_common #define malloc_next_header 2
  16. $export_common #define malloc_prev_header 3
  17. $export_common #define malloc_num_header_properties 4
  18. $export_common #define p_malloc_init_flag_location 0
  19. $export_common #define p_malloc_first_header_location 1
  20. $$export_split
  21. //[Z] The reason I do it like this is because whoever made the acc is insane.
  22. #define @nullptr 0
  23. #define @malloc_allocated 0
  24. #define @malloc_size 1
  25. #define @malloc_next_header 2
  26. #define @malloc_prev_header 3
  27. #define @malloc_num_header_properties 4
  28. #define @p_malloc_init_flag_location 0
  29. #define @p_malloc_first_header_location 1
  30. $$
  31. $$export_split function int @malloc (int size) {
  32. //Do the setup on the first run of this function.
  33. if(@memory[@p_malloc_init_flag_location] == FALSE) { //Default values for global values is 0, so this is true.
  34. @memory[@p_malloc_init_flag_location] = TRUE;
  35. @memory[@p_malloc_first_header_location+@malloc_allocated] = FALSE;
  36. @memory[@p_malloc_first_header_location+@malloc_size] = -1; //"infinite"
  37. @memory[@p_malloc_first_header_location+@malloc_next_header] = @nullptr; //nullptr
  38. @memory[@p_malloc_first_header_location+@malloc_prev_header] = @nullptr; //nullptr
  39. }
  40. int p_previous_header = @nullptr;
  41. int p_current_header = @p_malloc_first_header_location;
  42. int p_retval = @nullptr;
  43. while(p_retval == @nullptr) {
  44. int memalloced = @memory[p_current_header+@malloc_allocated];
  45. int memsize = @memory[p_current_header+@malloc_size];
  46. if(memsize == -1) { //The end of the list.
  47. @memory[p_current_header+@malloc_allocated] = TRUE;
  48. @memory[p_current_header+@malloc_size] = size;
  49. @memory[p_current_header+@malloc_next_header] = p_current_header+@malloc_num_header_properties+size; //New EOL
  50. @memory[p_current_header+@malloc_prev_header] = p_previous_header;
  51. //Retrieve the return value while we are at the allocated space.
  52. p_retval = p_current_header+@malloc_num_header_properties;
  53. //Remember to initialize the new end list node.
  54. p_previous_header = p_current_header; //This is the header previous to the EOL.
  55. p_current_header = @memory[p_current_header+@malloc_next_header];
  56. //Set the tail node constants.
  57. @memory[p_current_header+@malloc_allocated] = FALSE;
  58. @memory[p_current_header+@malloc_size] = -1;
  59. @memory[p_current_header+@malloc_next_header] = @nullptr;
  60. @memory[p_current_header+@malloc_prev_header] = p_previous_header;
  61. } else if(memsize >= size && memalloced == FALSE) { //There is room here AND it isn't in use,
  62. @memory[p_current_header+@malloc_allocated] = TRUE;
  63. //The size isn't modified because we are re-using an existing space.
  64. // It would be a good idea to check just how large this space is and act accordingly rather
  65. // than using a 500 indexes large space for a 4 indexes large object.
  66. // Objects allocated in a doom mod probably won't be outside the 1-16 indexes range so it
  67. // should still be fine for most applications.
  68. //The next header isn't changed either for the same reason.
  69. if(memsize >= (size+@malloc_num_header_properties+5)) { //Assume that 5 is the smallest useful allocation size.
  70. int p_split_newheader = p_current_header+@malloc_num_header_properties+size; //Just to the end of the allocation.
  71. @memory[p_split_newheader+@malloc_allocated] = FALSE;
  72. @memory[p_split_newheader+@malloc_size] = @memory[p_current_header+@malloc_size]-@malloc_num_header_properties-size;
  73. @memory[p_split_newheader+@malloc_next_header] = @memory[p_current_header+@malloc_next_header];
  74. @memory[p_split_newheader+@malloc_prev_header] = p_current_header;
  75. @memory[p_current_header+@malloc_next_header] = p_split_newheader; //The header whose block was split should have its next pointer set to its other half.
  76. @memory[p_current_header+@malloc_size] = size; //Set the size of the allocation to reflect the split.
  77. }
  78. //Retrieve the return value while we are at the allocated space.
  79. p_retval = p_current_header+@malloc_num_header_properties;
  80. } else {
  81. //The observed node isn't useful for allocating the request. Go to the next node.
  82. p_previous_header = p_current_header;
  83. p_current_header = @memory[p_current_header+@malloc_next_header];
  84. }
  85. }
  86. //log(s:"Malloc allocated ", d:size, s:" indexes at location ", d:p_retval, s:" with header location ", d:p_current_header);
  87. return p_retval;
  88. }
  89. $$
  90. $$export_split function int @free (int p_ptr) {
  91. log(s:"Invoked free");
  92. int p_header = p_ptr - @malloc_num_header_properties;
  93. @memory[p_header+@malloc_allocated] = FALSE;
  94. int p_next = @memory[p_header+@malloc_next_header];
  95. int p_prev = @memory[p_header+@malloc_prev_header];
  96. //Below is the merging of free blocks.
  97. //It merges to the left (lower indexes) first becaue the right (larger
  98. // indexes) has a special case. (the end of the list)
  99. //the previous block is unused. Merge.
  100. if(p_prev != @nullptr //This doesn't make sense if the previous block doesn't exist.
  101. && @memory[p_prev+@malloc_allocated] == FALSE) {
  102. log(s:"Free attempting merge of header ", d:p_header, s: " to the left with header ", d:p_prev);
  103. @memory[p_prev+@malloc_size] += @memory[p_header+@malloc_size] + @malloc_num_header_properties;
  104. @memory[p_prev+@malloc_next_header] = p_next; //The prev header needs to know the new next.
  105. @memory[p_next+@malloc_prev_header] = p_prev; //The next header needs to know the new prev.
  106. //Now the two blocks are the same block. requires new initializations of the
  107. // variables for the other check to function correctly.
  108. //The header is the result of the merge, and the prev is the one before it.
  109. p_header = p_prev;
  110. p_prev = @memory[p_header+@malloc_prev_header];
  111. }
  112. //The next block is unused. Merge.
  113. //Note that p_next will never be a nullptr with correct usage.
  114. if(@memory[p_next+@malloc_allocated] == FALSE) {
  115. if(@memory[p_next+@malloc_size] == -1) { //EOL
  116. @memory[p_header+@malloc_size] = -1;
  117. @memory[p_header+@malloc_next_header] = @nullptr;
  118. } else {
  119. int p_next_next = @memory[p_next+@malloc_next_header];
  120. @memory[p_header+@malloc_size] += @memory[p_next+@malloc_size] + @malloc_num_header_properties;
  121. @memory[p_header+@malloc_next_header] = p_next_next; //The header on the other side of the next header needs to know its new prev.
  122. @memory[p_next_next+@malloc_prev_header] = p_header; //This header needs to know its new next.
  123. }
  124. }
  125. return -1;
  126. }
  127. $$
  128. //These are for debugging
  129. /*
  130. script "memory_write" (int index, int value) {
  131. memory[index] = value;
  132. }
  133. script "memory_read" (int index) {
  134. log(d:memory[index]);
  135. }
  136. script "memory_print_allocation_list" (void) {
  137. int p_current_header = p_malloc_first_header_location;
  138. while(p_current_header != nullptr) {
  139. log(s: "Header location: ", d:p_current_header,
  140. s:"\n Allocated flag: ", d:memory[p_current_header+malloc_allocated],
  141. s:"\n Allocation size: ", d:memory[p_current_header+malloc_size],
  142. s:"\n Prev header pointer: ", d:memory[p_current_header+malloc_prev_header],
  143. s:"\n Next header pointer: ", d:memory[p_current_header+malloc_next_header],
  144. s:"\n"
  145. );
  146. p_current_header = memory[p_current_header+malloc_next_header];
  147. }
  148. }
  149. */