memory_map.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * Part of Scheme 48 1.9. See file COPYING for notices and license.
  3. *
  4. * Authors: David Frese, Marcus Crestani
  5. */
  6. #ifndef __S48_MEMORY_MAP_H
  7. #define __S48_MEMORY_MAP_H
  8. #include "scheme48arch.h"
  9. #ifdef HAVE_STDINT_H
  10. #include <stdint.h>
  11. #endif
  12. #include "memory.h"
  13. #include "areas.h"
  14. #include "page_constants.h"
  15. /* When a new page is allocated: */
  16. extern void s48_memory_map_setB(s48_address address, Area* value);
  17. /* When the Area structure of a page is needed: */
  18. /* extern Area* s48_memory_map_ref(s48_address address);
  19. - defined inline below */
  20. /* The following is only defined here to allow the inlining of
  21. s48_memory_map_ref, and not used elsewhere: */
  22. #include <assert.h>
  23. /* We need an integer type of the same size as pointers, and the bit
  24. length of addresses: */
  25. #ifdef _WIN32
  26. #define ADDRESS_LENGTH 32
  27. #elif _WIN64
  28. #define ADDRESS_LENGTH 64
  29. #else
  30. #include <limits.h>
  31. #define ADDRESS_LENGTH WORDSIZE
  32. #endif
  33. /*** CONFIGURATION ***/
  34. /* The memory_map provides a way to store and find an Area structure
  35. for every memory page we have allocated for the heap. It must be
  36. very fast, without consuming too much memory at the same time.
  37. For 32bit systems, this is quite easy, but to achieve this for
  38. 64bit systems, a sort of hashing is implemented. It is
  39. automatically activated if the defined page size and a given size
  40. for a statically allocated array are too small to cover all
  41. potential addresses.
  42. The first relevant size is defined in page_constants.h:
  43. LOG_BYTES_PER_PAGE
  44. The next one defines the size of a statically allocated global
  45. array, which stores pointers to Metapage structures; it's
  46. logarithmic size is:
  47. */
  48. #define LOG_TABLE_SIZE 10
  49. /* Metapage structures are allocated by need, and each consists of
  50. another array of pointers to Area structures. It's logarithmic size
  51. is:
  52. */
  53. #define LOG_PAGES_PER_METAPAGE 10
  54. /*** END OF CONFIGURATION ***/
  55. /* Now with the usual sizes on a 32bit system these sizes sum up to 32
  56. bits and we don't need the hashing algorithm. Let's see if we do
  57. need it:
  58. */
  59. #define USED_ADDRESS_BITS \
  60. (LOG_BYTES_PER_PAGE + LOG_TABLE_SIZE + LOG_PAGES_PER_METAPAGE)
  61. #define REMAINING_ADDRESS_BITS \
  62. (ADDRESS_LENGTH - USED_ADDRESS_BITS)
  63. #if REMAINING_ADDRESS_BITS > 0
  64. #define NEED_METAPAGE_HASHING
  65. #elif REMAINING_ADDRESS_BITS == 0
  66. #undef NEED_METAPAGE_HASHING
  67. #else
  68. #error "Misconfigured memory map."##REMAINING_ADDRESS_BITS
  69. #endif
  70. /* For both direct access and hashed access, we split an address into
  71. the following fields:
  72. high low
  73. | Rest | Metapage in Table | Page in Metapage | Byte in Page |
  74. If the Rest has 0-length we don't need hashing.
  75. */
  76. /* Some sizes: */
  77. #define METAPAGES (((uintptr_t)1) << LOG_TABLE_SIZE)
  78. #define PAGES_PER_METAPAGE (((uintptr_t)1) << LOG_PAGES_PER_METAPAGE)
  79. /* Some accessors for the fields : */
  80. #define ADDR_METAPAGE_INDEX(address) \
  81. ( ( ((uintptr_t)address) >> (LOG_BYTES_PER_PAGE + LOG_PAGES_PER_METAPAGE) ) \
  82. & (METAPAGES - 1) )
  83. #define ADDR_PAGE_INDEX(address) \
  84. ( ( ((uintptr_t)address) >> LOG_BYTES_PER_PAGE ) \
  85. & (PAGES_PER_METAPAGE - 1) )
  86. #ifdef NEED_METAPAGE_HASHING
  87. #define ADDR_REST(address) \
  88. ( ((uintptr_t)address) >> USED_ADDRESS_BITS )
  89. /* To identify the correct hash bucket, we need store the start
  90. address of all pages of a metapage. We use this macro to compare
  91. them: */
  92. #define ADDR_REST_MASK \
  93. ( ((uintptr_t)-1) << USED_ADDRESS_BITS )
  94. #define ADDR_REST_MASKED(address) ((void*)(ADDR_REST_MASK & ((uintptr_t)address)))
  95. #define IS_CORRECT_METAPAGE(metapage, address) \
  96. ( ADDR_REST_MASKED(metapage->start_address) == ADDR_REST_MASKED(address) )
  97. #endif
  98. /* And now the structure we use; for hashing, we use a linked list of
  99. Metapages for pages which have the same ADDR_METAPAGE_INDEX, but
  100. different ADDR_REST parts:
  101. */
  102. typedef struct _Metapage {
  103. #ifdef NEED_METAPAGE_HASHING
  104. s48_address start_address;
  105. struct _Metapage* next;
  106. #endif
  107. Area* contents[PAGES_PER_METAPAGE];
  108. } Metapage;
  109. #define TABLE_SIZE (1L << LOG_TABLE_SIZE)
  110. S48_EXTERN Metapage* s48_memory_table[];
  111. #ifdef NEED_METAPAGE_HASHING
  112. /* returns the place of the found pointer to the metapage, resp. the
  113. place where a newly allocated metepage should be stored: */
  114. inline static Metapage** find_metapagep(s48_address address) {
  115. Metapage** bucketp = &s48_memory_table[ADDR_METAPAGE_INDEX(address)];
  116. while ((*bucketp != NULL) && (!IS_CORRECT_METAPAGE((*bucketp), address))) {
  117. bucketp = &(*bucketp)->next;
  118. }
  119. assert(bucketp != NULL);
  120. return bucketp;
  121. }
  122. #else
  123. #define find_metapagep(address) (&s48_memory_table[ADDR_METAPAGE_INDEX(address)])
  124. #endif
  125. inline static Area* s48_memory_map_ref(s48_address address) {
  126. Metapage* metapage = *find_metapagep(address);
  127. if (metapage == NULL)
  128. return NULL;
  129. else
  130. return metapage->contents[ADDR_PAGE_INDEX(address)];
  131. };
  132. #endif