这是一个本人学习 csapp 的 learning 库

336 lines
8.8 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. /*
  2. * mm-naive.c - The fastest, least memory-efficient malloc package.
  3. *
  4. * In this naive approach, a block is allocated by simply incrementing
  5. * the brk pointer. A block is pure payload. There are no headers or
  6. * footers. Blocks are never coalesced or reused. Realloc is
  7. * implemented directly using mm_malloc and mm_free.
  8. *
  9. * NOTE TO STUDENTS: Replace this header comment with your own header
  10. * comment that gives a high level description of your solution.
  11. */
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <assert.h>
  15. #include <unistd.h>
  16. #include <string.h>
  17. #include "mm.h"
  18. #include "memlib.h"
  19. /*********************************************************
  20. * NOTE TO STUDENTS: Before you do anything else, please
  21. * provide your team information in the following struct.
  22. ********************************************************/
  23. team_t team = {
  24. /* Team name */
  25. "team",
  26. /* First member's full name */
  27. "GentleCold",
  28. /* First member's email address */
  29. "1952173800@qq.com",
  30. /* Second member's full name (leave blank if none) */
  31. "",
  32. /* Second member's email address (leave blank if none) */
  33. ""
  34. };
  35. /* single word (4) or double word (8) alignment */
  36. #define ALIGNMENT 8
  37. /* rounds up to the nearest multiple of ALIGNMENT */
  38. #define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~0x7)
  39. // My define
  40. #define WSIZE 4
  41. #define DSIZE 8
  42. #define FSIZE 16
  43. #define CHUNK 1 << 10
  44. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  45. #define PARSE(v) ((v) & ~0x7)
  46. #define PACK(v, a) ((v) | (a))
  47. #define HEAD(bp) ((byte *)(bp) - WSIZE)
  48. #define FOOT(bp) ((byte *)(bp) + SIZE(bp))
  49. #define SIZE(bp) (PARSE(GET(HEAD(bp))))
  50. #define ALLOC(bp) (GET(HEAD(bp)) & 0x1)
  51. #define GET(p) (*(word *)(p))
  52. #define SET(p, v) (*(word *)(p) = (v))
  53. #define NEXT(bp) (FOOT(bp) + DSIZE)
  54. #define PREV(bp) ((byte *)(bp) - PARSE(GET((bp) - DSIZE)) - DSIZE)
  55. typedef unsigned int word;
  56. typedef char byte;
  57. // mark the front and tail pos
  58. void *front_p = NULL;
  59. void *tail_p = NULL;
  60. // used for next fit, updated by mm_init, mm_malloc, _coalesce
  61. void *fitted_p = NULL;
  62. // My func
  63. /**
  64. * add a blank chunk and coalesce
  65. * will update tail_p
  66. * @param size align by 8, excluding head and foot
  67. * @return new bp
  68. */
  69. static void *_extend(size_t size);
  70. /**
  71. * coalesce blank chunk before and after bp
  72. * @param bp loaded point
  73. * @return bp after coalesce
  74. */
  75. static void *_coalesce(void *bp);
  76. static void *__coalesce_prev(void *bp);
  77. static void *__coalesce_next(void *bp);
  78. static void *__coalesce_all(void *bp);
  79. /**
  80. * traverse and find first fit, then place in
  81. * @deprecated too slow
  82. * @param size align by 8, excluding head and foot
  83. * @return
  84. */
  85. static void *_first_fit(size_t size);
  86. /**
  87. * find next fit, then place in
  88. * @param size align by 8, excluding head and foot
  89. * @return
  90. */
  91. static void *_next_fit(size_t size);
  92. /**
  93. * find next fit, then place in, if from beginning, use best fit
  94. * @deprecated thru loss
  95. * @param size align by 8, excluding head and foot
  96. * @return
  97. */
  98. static void *_next_best_fit(size_t size);
  99. /**
  100. * allocate the block and cut sometimes
  101. * @param size align by 8, excluding head and foot
  102. */
  103. static void _place(void *ptr, size_t size);
  104. // end
  105. /**
  106. * initialize the malloc package.
  107. * get a new chunk, set front_p and tail_p
  108. */
  109. int mm_init(void) {
  110. if ((front_p = mem_sbrk(WSIZE)) == (void *) - 1) return -1; // blank
  111. front_p += DSIZE; // first chunk
  112. fitted_p = front_p; // init fitted_p
  113. if (!_extend(CHUNK)) return -1;
  114. return 0;
  115. }
  116. /**
  117. * find first fit or extend
  118. */
  119. void *mm_malloc(size_t size) {
  120. size_t adjust_size = ALIGN(size);
  121. size_t extend_size;
  122. void *bp;
  123. if ((bp = _next_fit(adjust_size)) != NULL) {
  124. fitted_p = bp;
  125. return bp;
  126. } else {
  127. extend_size = adjust_size;
  128. if (!ALLOC(tail_p)) {
  129. extend_size -= (SIZE(tail_p) + DSIZE);
  130. }
  131. bp = _extend(MAX(extend_size, CHUNK));
  132. if (bp == NULL) return bp;
  133. _place(bp, adjust_size);
  134. fitted_p = bp;
  135. return bp;
  136. }
  137. }
  138. /**
  139. * free a block and coalesce immediately
  140. */
  141. void mm_free(void *ptr) {
  142. size_t size = SIZE(ptr);
  143. SET(HEAD(ptr), PACK(size, 0));
  144. SET(FOOT(ptr), PACK(size, 0));
  145. _coalesce(ptr);
  146. }
  147. /**
  148. * implemented simply in terms of mm_malloc and mm_free
  149. * compare adjust_size and total_size step by step
  150. */
  151. void *mm_realloc(void *ptr, size_t size) {
  152. if (ptr == NULL) return mm_malloc(size);
  153. if (size == 0) return NULL;
  154. void *new_ptr;
  155. size_t adjust_size = ALIGN(size);
  156. size_t old_size = SIZE(ptr);
  157. if (adjust_size <= old_size) {
  158. // just return, for the memory lost is little
  159. return ptr;
  160. }
  161. size_t next_size = (ptr != tail_p && !ALLOC(NEXT(ptr))) ? SIZE(NEXT(ptr)) + DSIZE : 0;
  162. size_t total_size = old_size + next_size;
  163. if (adjust_size <= total_size) {
  164. __coalesce_next(ptr);
  165. _place(ptr, adjust_size); // just cut
  166. return ptr;
  167. }
  168. size_t prev_size = (ptr != front_p && !ALLOC(PREV(ptr))) ? SIZE(PREV(ptr)) + DSIZE : 0;
  169. total_size += prev_size;
  170. if (adjust_size <= total_size) { // coalesce prev or all
  171. new_ptr = _coalesce(ptr);
  172. memmove(new_ptr, ptr, old_size);
  173. _place(new_ptr, adjust_size);
  174. } else {
  175. if ((new_ptr = mm_malloc(size)) == NULL) return NULL;
  176. memmove(new_ptr, ptr, old_size);
  177. mm_free(ptr);
  178. }
  179. return new_ptr;
  180. }
  181. // my func
  182. static void *_extend(size_t size) {
  183. void *bp;
  184. if ((bp = mem_sbrk(size + DSIZE)) == (void *) - 1) return NULL;
  185. // init chunk
  186. SET(bp, PACK(size, 0));
  187. bp += WSIZE;
  188. SET(FOOT(bp), PACK(size, 0));
  189. // init mark point
  190. tail_p = bp;
  191. return _coalesce(bp);
  192. }
  193. static void *_coalesce(void *bp) {
  194. // one chunk
  195. if (bp == front_p && bp == tail_p) return bp;
  196. if (bp == front_p || ALLOC(PREV(bp))) {
  197. if (bp == tail_p || ALLOC(NEXT(bp))) return bp;
  198. return __coalesce_next(bp);
  199. } else if (bp == tail_p || ALLOC(NEXT(bp))) {
  200. return __coalesce_prev(bp);
  201. } else {
  202. return __coalesce_all(bp);
  203. }
  204. }
  205. static void *__coalesce_prev(void *bp) {
  206. void *prev = PREV(bp);
  207. size_t new_size = SIZE(prev) + SIZE(bp) + DSIZE;
  208. SET(HEAD(prev), PACK(new_size, 0));
  209. SET(FOOT(bp), PACK(new_size, 0));
  210. if (bp == tail_p) tail_p = prev;
  211. if (bp == fitted_p) fitted_p = prev;
  212. return prev;
  213. }
  214. static void *__coalesce_next(void *bp) {
  215. void *next = NEXT(bp);
  216. size_t new_size = SIZE(next) + SIZE(bp) + DSIZE;
  217. SET(HEAD(bp), PACK(new_size, 0));
  218. SET(FOOT(next), PACK(new_size, 0));
  219. if (next == tail_p) tail_p = bp; // should also change
  220. if (next == fitted_p) fitted_p = bp;
  221. return bp;
  222. }
  223. static void *__coalesce_all(void *bp) {
  224. void *prev = PREV(bp);
  225. void *next = NEXT(bp);
  226. size_t new_size = SIZE(prev) + SIZE(bp) + SIZE(next) + FSIZE;
  227. SET(HEAD(prev), PACK(new_size, 0));
  228. SET(FOOT(next), PACK(new_size, 0));
  229. if (next == tail_p) tail_p = prev;
  230. if (next == fitted_p || bp == fitted_p) fitted_p = prev;
  231. return prev;
  232. }
  233. static void *_first_fit(size_t size) {
  234. void *bp = front_p;
  235. void *after_p = NEXT(tail_p);
  236. while (bp != after_p) {
  237. if (!ALLOC(bp) && SIZE(bp) >= size) {
  238. _place(bp, size);
  239. return bp;
  240. }
  241. bp = NEXT(bp);
  242. }
  243. return NULL;
  244. }
  245. static void *_next_fit(size_t size) {
  246. void *bp = fitted_p;
  247. void *after_p = NEXT(tail_p);
  248. while (bp != after_p) {
  249. if (!ALLOC(bp) && SIZE(bp) >= size) {
  250. _place(bp, size);
  251. return bp;
  252. }
  253. bp = NEXT(bp);
  254. }
  255. bp = front_p;
  256. while (bp != fitted_p) {
  257. if (!ALLOC(bp) && SIZE(bp) >= size) {
  258. _place(bp, size);
  259. return bp;
  260. }
  261. bp = NEXT(bp);
  262. }
  263. return NULL;
  264. }
  265. static void *_next_best_fit(size_t size) {
  266. void *bp = fitted_p;
  267. void *after_p = NEXT(tail_p);
  268. while (bp != after_p) {
  269. if (!ALLOC(bp) && SIZE(bp) >= size) {
  270. _place(bp, size);
  271. return bp;
  272. }
  273. bp = NEXT(bp);
  274. }
  275. bp = front_p;
  276. size_t min = 0;
  277. void *min_p = NULL;
  278. while (bp != fitted_p) {
  279. if (!ALLOC(bp) && SIZE(bp) >= size) {
  280. if (min_p == NULL || SIZE(bp) < min) {
  281. min = SIZE(bp);
  282. min_p = bp;
  283. }
  284. }
  285. bp = NEXT(bp);
  286. }
  287. if (min_p == NULL) return NULL;
  288. _place(min_p, size);
  289. return min_p;
  290. }
  291. static void _place(void *ptr, size_t size) {
  292. size_t p_size = SIZE(ptr);
  293. if (p_size - size >= FSIZE) {
  294. SET(HEAD(ptr), PACK(size, 1));
  295. SET(FOOT(ptr), PACK(size, 1));
  296. // DSIZE adjust
  297. size_t adjust_size = p_size - size - DSIZE;
  298. SET(HEAD(NEXT(ptr)), PACK(adjust_size, 0));
  299. SET(FOOT(NEXT(ptr)), PACK(adjust_size, 0));
  300. if (ptr == tail_p) tail_p = NEXT(ptr);
  301. } else {
  302. SET(HEAD(ptr), PACK(p_size, 1));
  303. SET(FOOT(ptr), PACK(p_size, 1));
  304. }
  305. }