stdlib.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. #include <alloca.h>
  2. #include <priv-vars.h>
  3. #include <stdint.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <syscall.h>
  7. #include <unistd.h>
  8. #include <string.h>
  9. #define BYTES_PER_MAX_COPY_UNIT (sizeof(uint32_t) / sizeof(uint8_t))
  10. static void* _memcpy(void* _dst, const void* _src, size_t n)
  11. {
  12. void* orig_dst = _dst;
  13. uint8_t* dst = (uint8_t*)_dst;
  14. const uint8_t* src = (const uint8_t*)_src;
  15. for (size_t i = 0; i < n / BYTES_PER_MAX_COPY_UNIT; ++i) {
  16. *(uint32_t*)dst = *(uint32_t*)src;
  17. dst += BYTES_PER_MAX_COPY_UNIT;
  18. src += BYTES_PER_MAX_COPY_UNIT;
  19. }
  20. for (size_t i = 0; i < (n % BYTES_PER_MAX_COPY_UNIT); ++i) {
  21. *((char*)dst++) = *((char*)src++);
  22. }
  23. return orig_dst;
  24. }
  25. int atoi(const char* str)
  26. {
  27. int ret = 0;
  28. while (*str) {
  29. ret *= 10;
  30. ret += *str - '0';
  31. }
  32. return ret;
  33. }
  34. void __attribute__((noreturn)) exit(int status)
  35. {
  36. syscall1(SYS_exit, status);
  37. for (;;)
  38. ;
  39. }
  40. #define MINIMUM_ALLOCATION_SIZE (8)
  41. #define MEM_ALLOCATED (1)
  42. static inline int _is_end(struct mem* p)
  43. {
  44. return p->sz == 0;
  45. }
  46. static inline int _is_allocated(struct mem* p)
  47. {
  48. return !!(p->flag & MEM_ALLOCATED);
  49. }
  50. static inline size_t _max(size_t a, size_t b)
  51. {
  52. return a > b ? a : b;
  53. }
  54. static inline size_t _size(struct mem* from)
  55. {
  56. if (!_is_end(from))
  57. return from->sz;
  58. size_t sz = curr_brk - (void*)from;
  59. if (sz < sizeof(struct mem))
  60. return 0;
  61. return sz - sizeof(struct mem);
  62. }
  63. static inline struct mem* _next(struct mem* p, size_t sz)
  64. {
  65. return (void*)p + sizeof(struct mem) + sz;
  66. }
  67. static inline void _union(struct mem* p)
  68. {
  69. if (_is_end(p))
  70. return;
  71. for (struct mem* next = _next(p, p->sz);
  72. !(next->flag & MEM_ALLOCATED);
  73. next = _next(p, p->sz)) {
  74. if (_is_end(next)) {
  75. p->sz = 0;
  76. break;
  77. }
  78. p->sz += sizeof(struct mem);
  79. p->sz += next->sz;
  80. }
  81. }
  82. static inline void _cut_block(struct mem* p, size_t mem_size, size_t block_size)
  83. {
  84. if (block_size >= mem_size + sizeof(struct mem) + MINIMUM_ALLOCATION_SIZE) {
  85. p->sz = mem_size;
  86. struct mem* next = _next(p, mem_size);
  87. next->flag = 0;
  88. next->sz = block_size - mem_size - sizeof(struct mem);
  89. }
  90. }
  91. void* malloc(size_t size)
  92. {
  93. if (size < MINIMUM_ALLOCATION_SIZE)
  94. size = MINIMUM_ALLOCATION_SIZE;
  95. struct mem* p = start_brk;
  96. size_t sz = 0;
  97. for (;; p = _next(p, p->sz)) {
  98. if (_is_allocated(p))
  99. continue;
  100. _union(p);
  101. sz = _size(p);
  102. if (_is_end(p)) {
  103. if (sz < size + sizeof(struct mem))
  104. sbrk(_max(128 * 1024, size + sizeof(struct mem)));
  105. sz = p->sz = size;
  106. struct mem* next = _next(p, size);
  107. next->flag = 0;
  108. next->sz = 0;
  109. break;
  110. }
  111. if (sz >= size)
  112. break;
  113. }
  114. p->flag |= MEM_ALLOCATED;
  115. _cut_block(p, size, sz);
  116. return _next(p, 0);
  117. }
  118. void* realloc(void* ptr, size_t newsize)
  119. {
  120. if (!ptr)
  121. return malloc(newsize);
  122. struct mem* p = ptr - sizeof(struct mem);
  123. size_t oldsize = p->sz;
  124. _union(p);
  125. if (_is_end(p)) {
  126. if (_size(p) < newsize + sizeof(struct mem))
  127. sbrk(_max(128 * 1024, newsize + sizeof(struct mem)));
  128. p->sz = newsize;
  129. struct mem* next = _next(p, newsize);
  130. next->flag = 0;
  131. next->sz = 0;
  132. return ptr;
  133. }
  134. if (p->sz >= newsize) {
  135. _cut_block(p, newsize, p->sz);
  136. return ptr;
  137. }
  138. void* newptr = malloc(newsize);
  139. if (!newptr)
  140. return NULL;
  141. _memcpy(newptr, ptr, oldsize);
  142. free(ptr);
  143. return newptr;
  144. }
  145. void free(void* ptr)
  146. {
  147. struct mem* p = ptr - sizeof(struct mem);
  148. p->flag &= ~MEM_ALLOCATED;
  149. _union(p);
  150. }
  151. static inline void _swap(void* a, void* b, size_t sz)
  152. {
  153. void* tmp = alloca(sz);
  154. _memcpy(tmp, a, sz);
  155. _memcpy(a, b, sz);
  156. _memcpy(b, tmp, sz);
  157. }
  158. void qsort(void* arr, size_t len, size_t sz, comparator_t cmp) {
  159. if (len <= 1)
  160. return;
  161. char* pivot = alloca(sz);
  162. _memcpy(pivot, arr + sz * (rand() % len), sz);
  163. int i = 0, j = 0, k = len;
  164. while (i < k) {
  165. int res = cmp(arr + sz * i, pivot);
  166. if (res < 0)
  167. _swap(arr + sz * i++, arr + sz * j++, sz);
  168. else if (res > 0)
  169. _swap(arr + sz * i, arr + sz * --k, sz);
  170. else
  171. i++;
  172. }
  173. qsort(arr, j, sz, cmp);
  174. qsort(arr + sz * k, len - k, sz, cmp);
  175. }
  176. static unsigned int __next_rand;
  177. int rand(void)
  178. {
  179. return rand_r(&__next_rand);
  180. }
  181. int rand_r(unsigned int* seedp)
  182. {
  183. *seedp = *seedp * 1103515245 + 12345;
  184. return (unsigned int) (*seedp / 65536) % 32768;
  185. }
  186. void srand(unsigned int seed)
  187. {
  188. __next_rand = seed;
  189. rand();
  190. }
  191. void* bsearch(const void* key, const void* base, size_t num, size_t size, comparator_t cmp)
  192. {
  193. if (num == 0)
  194. return NULL;
  195. size_t mid = num / 2;
  196. int result = cmp(key, base + size * mid);
  197. if (result == 0)
  198. return (void*)base + size * mid;
  199. if (result > 0) {
  200. ++mid;
  201. return bsearch(key, base + size * mid, num - mid, size, cmp);
  202. }
  203. return bsearch(key, base, mid, size, cmp);
  204. }
  205. int setenv(const char* name, const char* value, int overwrite)
  206. {
  207. size_t i = 0;
  208. for (; environ[i]; ++i) {
  209. char* eqpos = strchr(environ[i], '=');
  210. if (strncmp(name, environ[i], eqpos - environ[i]) == 0) {
  211. if (overwrite)
  212. goto fill_p;
  213. return 0;
  214. }
  215. }
  216. if (i + 2 == environ_size) {
  217. environ_size *= 2;
  218. char** newarr = malloc(environ_size * sizeof(char*));
  219. if (!newarr)
  220. return -1;
  221. _memcpy(newarr, environ, sizeof(char*) * environ_size / 2);
  222. free(environ);
  223. environ = newarr;
  224. }
  225. environ[i + 1] = NULL;
  226. fill_p:;
  227. char* newenv = NULL;
  228. if (asprintf(&newenv, "%s=%s", name, value) < 0)
  229. return -1;
  230. environ[i] = newenv;
  231. return 0;
  232. }