areas.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Part of Scheme 48 1.9. See file COPYING for notices and license.
  3. *
  4. * Authors: David Frese, Robert Ransom
  5. */
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include "utils.h"
  9. #include "areas.h"
  10. #include "page_constants.h"
  11. #include "memory_map.h"
  12. #include "area_roots.h"
  13. #include "page_alloc.h"
  14. #include "gc_config.h"
  15. #include "remset.h"
  16. static Area* make_area(s48_address start, s48_address end,
  17. s48_address frontier,
  18. unsigned char generation_index,
  19. area_type_size_t area_type_size) {
  20. Area* area = (Area*)malloc(sizeof(Area));
  21. if (area == NULL) s48_gc_error("make_area: out of memory");
  22. area->start = start;
  23. area->end = end;
  24. area->frontier = frontier;
  25. area->trace = start;
  26. area->next = NULL;
  27. area->generation_index = generation_index;
  28. area->area_type_size = area_type_size;
  29. s48_init_dirty_vector(area);
  30. #if S48_USE_REMEMBERED_SETS==TRUE
  31. area->remset = s48_make_remset();
  32. #endif
  33. return area;
  34. }
  35. inline static void free_area(Area* area) {
  36. s48_deinit_dirty_vector(area);
  37. #if S48_USE_REMEMBERED_SETS==TRUE
  38. s48_free_remset(area->remset);
  39. #endif
  40. free(area);
  41. }
  42. /* delete_area deletes AREA from the linked list starting with START,
  43. and returns the (eventually different) new start of the list. Does
  44. NOT free the memory allocated for the area structure (nor the area
  45. itself)! */
  46. Area* s48_delete_area(Area* start, Area* area) {
  47. if (start == NULL)
  48. /* no areas in the list? -> Done */
  49. return start;
  50. else if (start == area) {
  51. /* list starts with AREA? -> next is new start */
  52. Area* next = area->next;
  53. area->next = NULL;
  54. return next;
  55. } else {
  56. /* search for the area before AREA */
  57. Area* prev = start;
  58. /* if AREA is not in the list, prev->next can be NULL. But of
  59. corse this should never happen !? */
  60. while (prev->next != NULL) {
  61. if (prev->next == area) {
  62. prev->next = area->next;
  63. break;
  64. }
  65. prev = prev->next;
  66. }
  67. area->next = NULL;
  68. return start;
  69. }
  70. }
  71. /* Allocate an area of between MINIMUM and MAXIMUM pages, inclusive. */
  72. Area* s48_allocate_area_without_crashing(unsigned long minimum,
  73. unsigned long maximum,
  74. unsigned char generation_index,
  75. area_type_size_t area_type_size) {
  76. s48_address start;
  77. Area* area;
  78. unsigned long size = s48_allocate_pages(minimum, maximum, &start);
  79. if (size == 0) {
  80. return NULL;
  81. };
  82. #if (BIBOP_LOG)
  83. s48_bibop_log("s48_allocate_pages: size = %i",
  84. size);
  85. #endif
  86. /* Safe because S48_ALLOCATE_PAGES has already checked MINIMUM and
  87. MAXIMUM with PAGES_TO_BYTES_LOSES_P, and SIZE is less than
  88. MAXIMUM.
  89. This call does crash if S48_MAKE_AREA cannot allocate an Area
  90. struct, but avoiding an out-of-memory crash here is too hard to
  91. be worthwhile. */
  92. area = s48_make_area(start, ADD_PAGES_I_KNOW_THIS_CAN_OVERFLOW(start, size),
  93. start,
  94. generation_index, area_type_size);
  95. return area;
  96. }
  97. Area* s48_allocate_area(unsigned long minimum, unsigned long maximum,
  98. unsigned char generation_index,
  99. area_type_size_t area_type_size) {
  100. Area* area = s48_allocate_area_without_crashing(minimum, maximum,
  101. generation_index,
  102. area_type_size);
  103. if (area == NULL) {
  104. s48_gc_error("s48_allocate_area: out of memory");
  105. }
  106. return area;
  107. }
  108. /* Free the pages covered by AREA, and free the struct itself too. */
  109. void s48_free_area(Area* area) {
  110. unsigned long size = BYTES_TO_PAGES(area->end - area->start);
  111. s48_address start = area->start;
  112. unsigned long i;
  113. s48_free_pagesB(start, size);
  114. /* This is not really needed, I think. It's only a waste of time */
  115. for (i = 0; i < size; i++) {
  116. /* Safe because I is less than SIZE, which cannot cause an
  117. overflow here. */
  118. s48_memory_map_setB(ADD_PAGES_I_KNOW_THIS_CAN_OVERFLOW(start, i), NULL);
  119. }
  120. #ifndef NDEBUG
  121. /* Blank it out, to find errors more easily */
  122. memset(area->start, 0, area->end - area->start);
  123. #endif
  124. free_area(area);
  125. }
  126. /* Call s48_free_area on all areas in the list starting with START */
  127. void s48_free_areas(Area* start) {
  128. while (start != NULL) {
  129. Area* next = start->next;
  130. s48_free_area(start);
  131. start = next;
  132. }
  133. }
  134. /* Get the type size of this stob's area: small, large, weaks. Called
  135. from the BIBOP dumper */
  136. area_type_size_t s48_area_type_size(s48_value stob) {
  137. Area* area;
  138. area = s48_memory_map_ref(S48_ADDRESS_AT_HEADER(stob));
  139. if (area == NULL) {
  140. return AREA_TYPE_SIZE_ILLEGAL;
  141. }
  142. return area->area_type_size;
  143. }
  144. /* Allocate a block for the whole image */
  145. void s48_allocate_image_area(long bytes, s48_address* start, s48_address* end) {
  146. s48_address memory;
  147. memory = (s48_address)malloc(bytes + BYTES_PER_PAGE);
  148. if (memory == NULL) s48_gc_error("s48_allocate_image_area: out of memory\n");
  149. *start = PAGE_START_ADDRESS(memory + BYTES_PER_PAGE - 1);
  150. *end = PAGE_START_ADDRESS(*start + bytes);
  151. return;
  152. }
  153. /* Wrap the static make_area */
  154. Area* s48_make_area(s48_address start, s48_address end,
  155. s48_address frontier,
  156. unsigned char generation_index,
  157. area_type_size_t area_type_size) {
  158. Area* area = make_area(start, end, frontier, generation_index, area_type_size);
  159. /* The area is put into all memory-map cells that are covered by
  160. it. */
  161. int size = BYTES_TO_PAGES(end-start);
  162. int i;
  163. for (i = 0; i < size; i++)
  164. /* Safe because I is less than SIZE, which cannot cause an
  165. overflow here. */
  166. s48_memory_map_setB(ADD_PAGES_I_KNOW_THIS_CAN_OVERFLOW(start, i), area);
  167. return area;
  168. }