stdlib.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #include <stdlib.h>
  2. #include <sys/mman.h>
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <alloca.h>
  7. #include <assert.h>
  8. #include <errno.h>
  9. #include <AK/Assertions.h>
  10. #include <AK/Types.h>
  11. #include <Kernel/Syscall.h>
  12. extern "C" {
  13. #define MALLOC_SCRUB_BYTE 0x85
  14. #define FREE_SCRUB_BYTE 0x82
  15. struct MallocHeader {
  16. uint16_t first_chunk_index;
  17. uint16_t chunk_count;
  18. size_t size;
  19. uint32_t compute_xorcheck() const
  20. {
  21. return 0x19820413 ^ ((first_chunk_index << 16) | chunk_count) ^ size;
  22. }
  23. };
  24. struct MallocFooter {
  25. uint32_t xorcheck;
  26. };
  27. #define CHUNK_SIZE 8
  28. #define POOL_SIZE 128 * 1024
  29. static const size_t malloc_budget = POOL_SIZE;
  30. static byte s_malloc_map[POOL_SIZE / CHUNK_SIZE / 8];
  31. static byte* s_malloc_pool;
  32. static uint32_t s_malloc_sum_alloc = 0;
  33. static uint32_t s_malloc_sum_free = POOL_SIZE;
  34. void* malloc(size_t size)
  35. {
  36. if (size == 0)
  37. return nullptr;
  38. // We need space for the MallocHeader structure at the head of the block.
  39. size_t real_size = size + sizeof(MallocHeader) + sizeof(MallocFooter);
  40. if (s_malloc_sum_free < real_size) {
  41. fprintf(stderr, "malloc(): Out of memory\ns_malloc_sum_free=%u, real_size=%x\n", s_malloc_sum_free, real_size);
  42. assert(false);
  43. }
  44. size_t chunks_needed = real_size / CHUNK_SIZE;
  45. if (real_size % CHUNK_SIZE)
  46. chunks_needed++;
  47. size_t chunks_here = 0;
  48. size_t first_chunk = 0;
  49. for (unsigned i = 0; i < (POOL_SIZE / CHUNK_SIZE / 8); ++i) {
  50. if (s_malloc_map[i] == 0xff) {
  51. // Skip over completely full bucket.
  52. chunks_here = 0;
  53. continue;
  54. }
  55. // FIXME: This scan can be optimized further with TZCNT.
  56. for (unsigned j = 0; j < 8; ++j) {
  57. if ((s_malloc_map[i] & (1<<j))) {
  58. // This is in use, so restart chunks_here counter.
  59. chunks_here = 0;
  60. continue;
  61. }
  62. if (chunks_here == 0) {
  63. // Mark where potential allocation starts.
  64. first_chunk = i * 8 + j;
  65. }
  66. ++chunks_here;
  67. if (chunks_here == chunks_needed) {
  68. auto* header = (MallocHeader*)(s_malloc_pool + (first_chunk * CHUNK_SIZE));
  69. byte* ptr = ((byte*)header) + sizeof(MallocHeader);
  70. header->chunk_count = chunks_needed;
  71. header->first_chunk_index = first_chunk;
  72. header->size = size;
  73. auto* footer = (MallocFooter*)((byte*)header + (header->chunk_count * CHUNK_SIZE) - sizeof(MallocFooter));
  74. footer->xorcheck = header->compute_xorcheck();
  75. for (size_t k = first_chunk; k < (first_chunk + chunks_needed); ++k)
  76. s_malloc_map[k / 8] |= 1 << (k % 8);
  77. s_malloc_sum_alloc += header->chunk_count * CHUNK_SIZE;
  78. s_malloc_sum_free -= header->chunk_count * CHUNK_SIZE;
  79. memset(ptr, MALLOC_SCRUB_BYTE, (header->chunk_count * CHUNK_SIZE) - (sizeof(MallocHeader) + sizeof(MallocFooter)));
  80. return ptr;
  81. }
  82. }
  83. }
  84. fprintf(stderr, "malloc(): Out of memory (no consecutive chunks found for size %u)\n", size);
  85. volatile char* crashme = (char*)0xc007d00d;
  86. *crashme = 0;
  87. return nullptr;
  88. }
  89. static void validate_mallocation(void* ptr, const char* func)
  90. {
  91. auto* header = (MallocHeader*)((((byte*)ptr) - sizeof(MallocHeader)));
  92. if (header->size == 0) {
  93. fprintf(stderr, "%s called on bad pointer %p, size=0\n", func, ptr);
  94. assert(false);
  95. }
  96. auto* footer = (MallocFooter*)((byte*)header + (header->chunk_count * CHUNK_SIZE) - sizeof(MallocFooter));
  97. uint32_t expected_xorcheck = header->compute_xorcheck();
  98. if (footer->xorcheck != expected_xorcheck) {
  99. fprintf(stderr, "%s called on bad pointer %p, xorcheck=%w (expected %w)\n", func, ptr, footer->xorcheck, expected_xorcheck);
  100. assert(false);
  101. }
  102. }
  103. void free(void* ptr)
  104. {
  105. if (!ptr)
  106. return;
  107. validate_mallocation(ptr, "free()");
  108. auto* header = (MallocHeader*)((((byte*)ptr) - sizeof(MallocHeader)));
  109. for (unsigned i = header->first_chunk_index; i < (header->first_chunk_index + header->chunk_count); ++i)
  110. s_malloc_map[i / 8] &= ~(1 << (i % 8));
  111. s_malloc_sum_alloc -= header->chunk_count * CHUNK_SIZE;
  112. s_malloc_sum_free += header->chunk_count * CHUNK_SIZE;
  113. memset(header, FREE_SCRUB_BYTE, header->chunk_count * CHUNK_SIZE);
  114. }
  115. void __malloc_init()
  116. {
  117. s_malloc_pool = (byte*)mmap(nullptr, malloc_budget, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
  118. int rc = set_mmap_name(s_malloc_pool, malloc_budget, "malloc pool");
  119. if (rc < 0)
  120. perror("set_mmap_name failed");
  121. }
  122. void* calloc(size_t nmemb, size_t)
  123. {
  124. (void) nmemb;
  125. ASSERT_NOT_REACHED();
  126. return nullptr;
  127. }
  128. void* realloc(void *ptr, size_t size)
  129. {
  130. validate_mallocation(ptr, "realloc()");
  131. auto* header = (MallocHeader*)((((byte*)ptr) - sizeof(MallocHeader)));
  132. size_t old_size = header->size;
  133. auto* new_ptr = malloc(size);
  134. memcpy(new_ptr, ptr, old_size);
  135. return new_ptr;
  136. }
  137. void exit(int status)
  138. {
  139. _exit(status);
  140. assert(false);
  141. }
  142. void abort()
  143. {
  144. // FIXME: Implement proper abort().
  145. exit(253);
  146. }
  147. char* getenv(const char* name)
  148. {
  149. for (size_t i = 0; environ[i]; ++i) {
  150. const char* decl = environ[i];
  151. char* eq = strchr(decl, '=');
  152. if (!eq)
  153. continue;
  154. size_t varLength = eq - decl;
  155. char* var = (char*)alloca(varLength + 1);
  156. memcpy(var, decl, varLength);
  157. var[varLength] = '\0';
  158. if (!strcmp(var, name)) {
  159. char* value = eq + 1;
  160. return value;
  161. }
  162. }
  163. return nullptr;
  164. }
  165. int atoi(const char* str)
  166. {
  167. size_t len = strlen(str);
  168. int value = 0;
  169. bool isNegative = false;
  170. for (size_t i = 0; i < len; ++i) {
  171. if (i == 0 && str[0] == '-') {
  172. isNegative = true;
  173. continue;
  174. }
  175. if (str[i] < '0' || str[i] > '9')
  176. return value;
  177. value = value * 10;
  178. value += str[i] - '0';
  179. }
  180. return isNegative ? -value : value;
  181. }
  182. long atol(const char* str)
  183. {
  184. static_assert(sizeof(int) == sizeof(long));
  185. return atoi(str);
  186. }
  187. static char ptsname_buf[32];
  188. char* ptsname(int fd)
  189. {
  190. if (ptsname_r(fd, ptsname_buf, sizeof(ptsname_buf)) < 0)
  191. return nullptr;
  192. return ptsname_buf;
  193. }
  194. int ptsname_r(int fd, char* buffer, size_t size)
  195. {
  196. int rc = syscall(SC_ptsname_r, fd, buffer, size);
  197. __RETURN_WITH_ERRNO(rc, rc, -1);
  198. }
  199. static unsigned long s_next_rand = 1;
  200. int rand()
  201. {
  202. s_next_rand = s_next_rand * 1103515245 + 12345;
  203. return((unsigned)(s_next_rand/((RAND_MAX + 1) * 2)) % (RAND_MAX + 1));
  204. }
  205. void srand(unsigned seed)
  206. {
  207. s_next_rand = seed;
  208. }
  209. int abs(int i)
  210. {
  211. return i < 0 ? -i : i;
  212. }
  213. }