这是一个本人学习 csapp 的 learning 库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

486 lines
12 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
2 years ago
  1. /*
  2. * mm-naive.c - The clear list, first fit malloc package.
  3. */
  4. #include <string.h>
  5. #include "mm.h"
  6. #include "memlib.h"
  7. team_t team = {
  8. /* Team name */
  9. "team",
  10. /* First member's full name */
  11. "GentleCold",
  12. /* First member's email address */
  13. "1952173800@qq.com",
  14. /* Second member's full name (leave blank if none) */
  15. "",
  16. /* Second member's email address (leave blank if none) */
  17. ""
  18. };
  19. /* single word (4) or double word (8) alignment */
  20. #define ALIGNMENT 8
  21. /* rounds up to the nearest multiple of ALIGNMENT */
  22. #define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~0x7)
  23. // My define
  24. #define WSIZE 4
  25. #define DSIZE 8
  26. #define FSIZE 16
  27. #define ADDRESS (sizeof(unsigned long))
  28. #define CHUNK 1 << 12
  29. #define MIN_BLOCK (2 * ADDRESS + DSIZE)
  30. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  31. #define PARSE(v) ((v) & ~0x7)
  32. #define PACK(v, a) ((v) | (a))
  33. #define HEAD(bp) ((byte *)(bp) - WSIZE)
  34. #define FOOT(bp) ((byte *)(bp) + SIZE(bp))
  35. #define SIZE(bp) (PARSE(GET(HEAD(bp))))
  36. #define ALLOC(bp) (GET(HEAD(bp)) & 0x1)
  37. #define GET(p) (*(word *)(p))
  38. #define SET(p, v) (*(word *)(p) = (v))
  39. #define NEXT(bp) (FOOT(bp) + DSIZE)
  40. #define PREV(bp) ((byte *)(bp) - PARSE(GET((bp) - DSIZE)) - DSIZE)
  41. #define POS_PRED(bp) ((byte *)(bp))
  42. #define POS_SUCC(bp) (((byte *)(bp) + ADDRESS))
  43. #define GET_PRED(bp) (*(word *)POS_PRED(bp))
  44. #define GET_SUCC(bp) (*(word *)POS_SUCC(bp))
  45. typedef unsigned long word;
  46. typedef char byte;
  47. // mark the front and tail pos
  48. void *front_p = NULL;
  49. void *tail_p = NULL;
  50. /**
  51. * used for next fit, updated by mm_init, mm_malloc, _coalesce
  52. * @deprecated useless for clear list
  53. */
  54. void *fitted_p = NULL;
  55. void *list_p = NULL;
  56. // My func
  57. /**
  58. * add a blank chunk and coalesce
  59. * will update tail_p
  60. * @param size align by 8, excluding head and foot
  61. * @return new bp
  62. */
  63. static void *_extend(size_t size);
  64. /**
  65. * coalesce blank chunk before and after bp
  66. * @param bp loaded point
  67. * @return bp after coalesce
  68. */
  69. static void *_coalesce(void *bp);
  70. static void *__coalesce_prev(void *bp);
  71. static void *__coalesce_next(void *bp);
  72. static void *__coalesce_all(void *bp);
  73. static void *__coalesce_none(void *bp);
  74. /**
  75. * traverse and find first fit, then place in
  76. * @deprecated too slow
  77. * @param size align by 8, excluding head and foot
  78. * @return
  79. */
  80. static void *_first_fit(size_t size);
  81. /**
  82. * find next fit, then place in
  83. * @deprecated I'll use clear list
  84. * @param size align by 8, excluding head and foot
  85. * @return
  86. */
  87. static void *_next_fit(size_t size);
  88. /**
  89. * find next fit, then place in, if from beginning, use best fit
  90. * @deprecated thru loss
  91. * @param size align by 8, excluding head and foot
  92. * @return
  93. */
  94. static void *_next_best_fit(size_t size);
  95. /**
  96. * traverse blank block only and find first fit, then place in
  97. * @param size align by 8, excluding head and foot
  98. * @return
  99. */
  100. static void *_first_fit_of_clear(size_t size);
  101. /**
  102. * allocate the block and cut sometimes
  103. * @param size align by 8, excluding head and foot
  104. */
  105. static void _place(void *ptr, size_t size);
  106. /**
  107. * just replace in of out in list
  108. * @param in the block that in the list
  109. * @param out the block that out the list
  110. */
  111. static void _fix_list(void *in, void *out);
  112. /**
  113. * check the number of blank list nums and real blank nums and print
  114. * @deprecated
  115. */
  116. static void _check();
  117. // end
  118. /**
  119. * initialize the malloc package.
  120. * get a new chunk, set front_p and tail_p
  121. */
  122. int mm_init(void) {
  123. if ((front_p = mem_sbrk(WSIZE)) == (void *) - 1) return -1; // blank
  124. front_p += DSIZE; // first chunk
  125. // fitted_p = front_p; // init fitted_p
  126. if (!_extend(CHUNK)) return -1;
  127. return 0;
  128. }
  129. /**
  130. * find first fit or extend
  131. */
  132. void *mm_malloc(size_t size) {
  133. size_t adjust_size = ALIGN(size);
  134. size_t extend_size;
  135. void *bp;
  136. if ((bp = _first_fit_of_clear(adjust_size)) != NULL) {
  137. // fitted_p = bp;
  138. return bp;
  139. } else {
  140. extend_size = adjust_size;
  141. if (!ALLOC(tail_p)) {
  142. extend_size -= (SIZE(tail_p) + DSIZE);
  143. }
  144. bp = _extend(MAX(extend_size, CHUNK));
  145. if (bp == NULL) return bp;
  146. _place(bp, adjust_size);
  147. // fitted_p = bp;
  148. return bp;
  149. }
  150. }
  151. /**
  152. * free a block and coalesce immediately
  153. */
  154. void mm_free(void *ptr) {
  155. #ifdef DEBUG
  156. printf("---free---\n");
  157. _check();
  158. printf("----------\n");
  159. #endif
  160. size_t size = SIZE(ptr);
  161. SET(HEAD(ptr), PACK(size, 0));
  162. SET(FOOT(ptr), PACK(size, 0));
  163. _coalesce(ptr);
  164. }
  165. /**
  166. * implemented simply in terms of mm_malloc and mm_free
  167. * compare adjust_size and total_size step by step
  168. */
  169. void *mm_realloc(void *ptr, size_t size) {
  170. if (ptr == NULL) return mm_malloc(size);
  171. if (size == 0) return NULL;
  172. void *new_ptr;
  173. size_t adjust_size = ALIGN(size);
  174. size_t old_size = SIZE(ptr);
  175. if (adjust_size <= old_size) {
  176. // just return, for the memory lost is little
  177. return ptr;
  178. }
  179. size_t next_size = (ptr != tail_p && !ALLOC(NEXT(ptr))) ? SIZE(NEXT(ptr)) + DSIZE : 0;
  180. size_t total_size = old_size + next_size;
  181. if (adjust_size <= total_size) {
  182. void *next = NEXT(ptr);
  183. // remove
  184. SET(POS_SUCC(GET_PRED(next)), GET_SUCC(next));
  185. SET(POS_PRED(GET_SUCC(next)), GET_PRED(next));
  186. if (next == list_p) {
  187. if (GET_SUCC(next) == (word)next) list_p = NULL;
  188. else list_p = (void *)GET_SUCC(next);
  189. }
  190. SET(HEAD(ptr), PACK(total_size, 1));
  191. SET(FOOT(ptr), PACK(total_size, 1));
  192. if (next == tail_p) tail_p = ptr;
  193. return ptr;
  194. } else {
  195. if ((new_ptr = mm_malloc(size)) == NULL) return NULL;
  196. memmove(new_ptr, ptr, old_size);
  197. mm_free(ptr);
  198. return new_ptr;
  199. }
  200. }
  201. // my func
  202. static void *_extend(size_t size) {
  203. void *bp;
  204. if ((bp = mem_sbrk(size + DSIZE)) == (void *) - 1) return NULL;
  205. // init chunk
  206. SET(bp, PACK(size, 0));
  207. bp += WSIZE;
  208. SET(FOOT(bp), PACK(size, 0));
  209. #ifdef DEBUG
  210. if (tail_p) {
  211. printf("----extend----\n");
  212. _check();
  213. printf("--------------\n");
  214. }
  215. #endif
  216. // init mark point
  217. tail_p = bp;
  218. return _coalesce(bp);
  219. }
  220. static void *_coalesce(void *bp) {
  221. // one chunk
  222. if (bp == front_p && bp == tail_p) return __coalesce_none(bp);
  223. if (bp == front_p || ALLOC(PREV(bp))) {
  224. if (bp == tail_p || ALLOC(NEXT(bp))) return __coalesce_none(bp);
  225. return __coalesce_next(bp);
  226. } else if (bp == tail_p || ALLOC(NEXT(bp))) {
  227. return __coalesce_prev(bp);
  228. } else {
  229. return __coalesce_all(bp);
  230. }
  231. }
  232. static void *__coalesce_prev(void *bp) {
  233. void *prev = PREV(bp);
  234. size_t new_size = SIZE(prev) + SIZE(bp) + DSIZE;
  235. SET(HEAD(prev), PACK(new_size, 0));
  236. SET(FOOT(bp), PACK(new_size, 0));
  237. if (bp == tail_p) tail_p = prev;
  238. // if (bp == fitted_p) fitted_p = prev;
  239. list_p = prev;
  240. return prev;
  241. }
  242. static void *__coalesce_next(void *bp) {
  243. void *next = NEXT(bp);
  244. // tweak list
  245. _fix_list(next, bp);
  246. // coalesce
  247. size_t new_size = SIZE(next) + SIZE(bp) + DSIZE;
  248. SET(HEAD(bp), PACK(new_size, 0));
  249. SET(FOOT(next), PACK(new_size, 0));
  250. if (next == tail_p) tail_p = bp; // should also change
  251. // if (next == fitted_p) fitted_p = bp;
  252. list_p = bp;
  253. #ifdef DEBUG
  254. printf("----coalesce next----\n");
  255. _check();
  256. printf("---------------------\n");
  257. #endif
  258. return bp;
  259. }
  260. static void *__coalesce_all(void *bp) {
  261. void *prev = PREV(bp);
  262. void *next = NEXT(bp);
  263. // tweak list
  264. SET(POS_SUCC(GET_PRED(next)), GET_SUCC(next));
  265. SET(POS_PRED(GET_SUCC(next)), GET_PRED(next));
  266. // coalesce
  267. size_t new_size = SIZE(prev) + SIZE(bp) + SIZE(next) + FSIZE;
  268. SET(HEAD(prev), PACK(new_size, 0));
  269. SET(FOOT(next), PACK(new_size, 0));
  270. if (next == tail_p) tail_p = prev;
  271. // if (next == fitted_p || bp == fitted_p) fitted_p = prev;
  272. list_p = prev;
  273. #ifdef DEBUG
  274. printf("---coalesce all---\n");
  275. _check();
  276. printf("-------------------\n");
  277. #endif
  278. return prev;
  279. }
  280. static void *__coalesce_none(void *bp) {
  281. // tweak list
  282. if (list_p == NULL) {
  283. list_p = bp;
  284. SET(POS_SUCC(list_p), (word)list_p);
  285. SET(POS_PRED(list_p), (word)list_p);
  286. } else {
  287. // add to list
  288. SET(POS_SUCC(bp), GET_SUCC(list_p));
  289. SET(POS_PRED(bp), (word)list_p);
  290. SET(POS_PRED(GET_SUCC(list_p)), (word)bp);
  291. SET(POS_SUCC(list_p), (word)bp);
  292. list_p = bp;
  293. }
  294. #ifdef DEBUG
  295. printf("---coalesce none---\n");
  296. _check();
  297. printf("-------------------\n");
  298. #endif
  299. return bp;
  300. }
  301. static void *_first_fit(size_t size) {
  302. void *bp = front_p;
  303. void *after_p = NEXT(tail_p);
  304. while (bp != after_p) {
  305. if (!ALLOC(bp) && SIZE(bp) >= size) {
  306. _place(bp, size);
  307. return bp;
  308. }
  309. bp = NEXT(bp);
  310. }
  311. return NULL;
  312. }
  313. static void *_next_fit(size_t size) {
  314. void *bp = fitted_p;
  315. void *after_p = NEXT(tail_p);
  316. while (bp != after_p) {
  317. if (!ALLOC(bp) && SIZE(bp) >= size) {
  318. _place(bp, size);
  319. return bp;
  320. }
  321. bp = NEXT(bp);
  322. }
  323. bp = front_p;
  324. while (bp != fitted_p) {
  325. if (!ALLOC(bp) && SIZE(bp) >= size) {
  326. _place(bp, size);
  327. return bp;
  328. }
  329. bp = NEXT(bp);
  330. }
  331. return NULL;
  332. }
  333. static void *_next_best_fit(size_t size) {
  334. void *bp = fitted_p;
  335. void *after_p = NEXT(tail_p);
  336. while (bp != after_p) {
  337. if (!ALLOC(bp) && SIZE(bp) >= size) {
  338. _place(bp, size);
  339. return bp;
  340. }
  341. bp = NEXT(bp);
  342. }
  343. bp = front_p;
  344. size_t min = 0;
  345. void *min_p = NULL;
  346. while (bp != fitted_p) {
  347. if (!ALLOC(bp) && SIZE(bp) >= size) {
  348. if (min_p == NULL || SIZE(bp) < min) {
  349. min = SIZE(bp);
  350. min_p = bp;
  351. }
  352. }
  353. bp = NEXT(bp);
  354. }
  355. if (min_p == NULL) return NULL;
  356. _place(min_p, size);
  357. return min_p;
  358. }
  359. static void *_first_fit_of_clear(size_t size) {
  360. void *bp = list_p;
  361. if (bp == NULL) return NULL;
  362. do {
  363. if (SIZE(bp) >= size) {
  364. _place(bp, size);
  365. return bp;
  366. }
  367. bp = (void *)GET_SUCC(bp);
  368. } while (bp != list_p);
  369. return NULL;
  370. }
  371. static void _place(void *ptr, size_t size) {
  372. size_t p_size = SIZE(ptr);
  373. if (p_size - size >= MIN_BLOCK) {
  374. SET(HEAD(ptr), PACK(size, 1));
  375. SET(FOOT(ptr), PACK(size, 1));
  376. // DSIZE adjust
  377. size_t adjust_size = p_size - size - DSIZE;
  378. void *new_ptr = NEXT(ptr);
  379. SET(HEAD(new_ptr), PACK(adjust_size, 0));
  380. SET(FOOT(new_ptr), PACK(adjust_size, 0));
  381. if (ptr == tail_p) tail_p = new_ptr;
  382. // tweak list
  383. _fix_list(ptr, new_ptr);
  384. if (ptr == list_p) list_p = new_ptr;
  385. } else {
  386. SET(HEAD(ptr), PACK(p_size, 1));
  387. SET(FOOT(ptr), PACK(p_size, 1));
  388. // tweak list
  389. // remove
  390. SET(POS_SUCC(GET_PRED(ptr)), GET_SUCC(ptr));
  391. SET(POS_PRED(GET_SUCC(ptr)), GET_PRED(ptr));
  392. if (ptr == list_p) {
  393. if (GET_SUCC(ptr) == (word)ptr) list_p = NULL;
  394. else list_p = (void *)GET_SUCC(ptr);
  395. }
  396. }
  397. //#ifdef DEBUG
  398. // printf("----place----\n");
  399. // _check();
  400. // printf("-------------\n");
  401. //#endif
  402. }
  403. static void _fix_list(void *in, void *out) {
  404. if (GET_SUCC(in) == (word)in) {
  405. SET(POS_SUCC(out), (word)out);
  406. SET(POS_PRED(out), (word)out);
  407. } else {
  408. SET(POS_SUCC(out), GET_SUCC(in));
  409. SET(POS_PRED(out), GET_PRED(in));
  410. SET(POS_SUCC(GET_PRED(in)), (word)out);
  411. SET(POS_PRED(GET_SUCC(in)), (word)out);
  412. }
  413. }
  414. static void _check() {
  415. int num1 = 0;
  416. int num2 = 0;
  417. int num3 = 0;
  418. void *bp = front_p;
  419. void *after_p = NEXT(tail_p);
  420. void *blank_p = NULL;
  421. while (bp != after_p) {
  422. if (!ALLOC(bp)) {
  423. if (blank_p == NULL) blank_p = bp;
  424. num1++;
  425. }
  426. bp = NEXT(bp);
  427. }
  428. bp = blank_p;
  429. do {
  430. if (bp != NULL) {
  431. bp = (void *)GET_SUCC(bp);
  432. num2++;
  433. }
  434. } while (bp != blank_p);
  435. bp = list_p;
  436. do {
  437. if (bp != NULL) {
  438. bp = (void *)GET_SUCC(bp);
  439. num3++;
  440. }
  441. } while (bp != list_p);
  442. printf("expect: %d, actual: %d, list_p: %d\n", num1, num2, num3);
  443. }