sscanf

  1. /* Function: read_line
  2. * --------------------
  3. * Reads one line from file and stores in buf. Skips lines that are all-white or beginning with
  4. * comment char #. Increments pass-by-ref counter of number of lines read/skipped. Removes
  5. * trailing newline. Returns true if did read valid line, false otherwise.
  6. */
  7. static bool read_line(char buf[], size_t bufsz, FILE *fp, int *pnread)
  8. {
  9. while (true) {
  10. if (fgets(buf, bufsz, fp) == NULL) return false;
  11. (*pnread)++;
  12. if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] ='\0'; // remove trailing newline
  13. char ch;
  14. if (sscanf(buf, " %c", &ch) == 1 && ch != '#') // scan first non-white char, check not #
  15. return true;
  16. }
  17. }

image.png
The scanf() function reads input from the standard input stream stdin, fscanf() reads input from the stream pointer stream, and sscanf() reads its input from the character string pointed to by str.
image.png

1) Code study: test harness

  1. // struct for a single allocator request
  2. typedef struct {
  3. enum {ALLOC=1, FREE, REALLOC} op; // type of request
  4. int id; // id for free() to use later
  5. size_t size; // num bytes for alloc/realloc request
  6. int lineno; // which line in file
  7. } request_t;
  8. // struct for facts about a single malloc'ed node
  9. typedef struct {
  10. void *ptr;
  11. size_t size;
  12. } block_t;
  13. // struct for info for one script file
  14. typedef struct {
  15. char name[128]; // short name of script
  16. request_t *ops; // array of requests read from script
  17. int num_ops; // number of requests
  18. int num_ids; // number of distinct block ids
  19. block_t *blocks; // array of blocks returned by malloc when executing
  20. size_t peak, lifetime, segment_size;
  21. } script_t;
  1. /* Function: eval_correctness
  2. * --------------------------
  3. * Check the allocator for correctness on given script. Interprets the earlier parsed
  4. * script operation-by-operation and reports if it detects any "obvious"
  5. * errors (returning blocks outside the heap, unaligned, overlapping blocks, etc.)
  6. */
  7. static bool eval_correctness(script_t *script)
  8. {
  9. init_heap_segment(script->segment_size);
  10. if (!myinit(heap_segment_start(), heap_segment_size())) {
  11. allocator_error(script, 0, "myinit() returned false");
  12. return false;
  13. }
  14. if (!validate_heap()) { // check heap consistency after init
  15. allocator_error(script, 0, "validate_heap() returned false, called after myinit");
  16. return false;
  17. }
  18. memset(script->blocks, 0, script->num_ids*sizeof(script->blocks[0]));
  19. for (int req = 0; req < script->num_ops; req++) {
  20. int id = script->ops[req].id;
  21. size_t requested_size = script->ops[req].size;
  22. size_t old_size = script->blocks[id].size;
  23. void *p, *newp, *oldp = script->blocks[id].ptr;
  24. switch (script->ops[req].op) {
  25. case ALLOC:
  26. if ((p = mymalloc(requested_size)) == NULL && requested_size != 0) {
  27. allocator_error(script, script->ops[req].lineno, "heap exhausted, malloc returned NULL");
  28. return false;
  29. }
  30. // Test new block for correctness: must be properly aligned
  31. // and must not overlap any currently allocated block.
  32. if (!verify_block(p, requested_size, script, script->ops[req].lineno))
  33. return false;
  34. // Fill new block with the low-order byte of new id
  35. // can be used later to verify data copied when realloc'ing
  36. memset(p, id & 0xFF, requested_size);
  37. script->blocks[id] = (block_t){.ptr = p, .size = requested_size};
  38. break;
  39. case REALLOC:
  40. if (!verify_payload(oldp, old_size, id, script, script->ops[req].lineno, "realloc-ing"))
  41. return false;
  42. if ((newp = myrealloc(oldp, requested_size)) == NULL && requested_size != 0) {
  43. allocator_error(script, script->ops[req].lineno, "heap exhausted, realloc returned NULL");
  44. return false;
  45. }
  46. old_size = script->blocks[id].size;
  47. script->blocks[id].size = 0;
  48. if (!verify_block(newp, requested_size, script, script->ops[req].lineno))
  49. return false;
  50. // Verify new block contains the data from the old block
  51. for (size_t j = 0; j < (old_size < requested_size ? old_size : requested_size); j++) {
  52. if (*((unsigned char *)newp + j) != (id & 0xFF)) {
  53. allocator_error(script, script->ops[req].lineno, "realloc did not preserve the data from old block");
  54. return false;
  55. }
  56. }
  57. // Fill new block with the low-order byte of new id
  58. memset(newp, id & 0xFF, requested_size);
  59. script->blocks[id] = (block_t){.ptr = newp, .size = requested_size};
  60. break;
  61. case FREE:
  62. old_size = script->blocks[id].size;
  63. p = script->blocks[id].ptr;
  64. // verify payload intact before free
  65. if (!verify_payload(p, old_size, id, script, script->ops[req].lineno, "freeing"))
  66. return false;
  67. script->blocks[id] = (block_t){.ptr = NULL, .size = 0};
  68. myfree(p);
  69. break;
  70. }
  71. if (!validate_heap()) { // check heap consistency after each request
  72. allocator_error(script, script->ops[req].lineno, "validate_heap() returned false, called in-between requests");
  73. return false; // stop at first sign of error
  74. }
  75. }
  76. // verify payload is still intact for any block still allocated
  77. for (int id = 0; id < script->num_ids; id++)
  78. if (!verify_payload(script->blocks[id].ptr, script->blocks[id].size, id, script, -1, "at exit"))
  79. return false;
  80. return true;
  81. }

fprintf

C 库函数 int fprintf(FILE stream, const char format, …) 发送格式化输出到流 stream 中。
image.png

memset

image.png

2) Code study: bump allocator

  1. /*
  2. * File: bump.c
  3. * ------------
  4. * A very simple "bump" allocator.
  5. * An allocation request is serviced by tacking on the requested
  6. * space to the end of the heap thus far.
  7. * Free is a no-op: blocks are never coalesced or reused.
  8. * Realloc is implemented using malloc/memcpy/free. Operations
  9. * are fast, but utilization is terrible.
  10. *
  11. * Shows the very simplest of approaches; there are better options!
  12. */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include "allocator.h"
  17. #define ALIGNMENT 8
  18. static void *next_avail, *heap_max;
  19. // Efficient bitwise round up to nearest multiple (you saw this code in lab1)
  20. // NOTE: mult has to be power of 2 for the bitwise trick to work!
  21. size_t roundup(size_t sz, size_t mult)
  22. {
  23. return (sz + mult-1) & ~(mult-1);
  24. }
  25. // initialize global variables based on segment boundaries
  26. bool myinit(void *segment_start, size_t segment_size)
  27. {
  28. next_avail = segment_start;
  29. heap_max = (char *)segment_start + segment_size;
  30. return true;
  31. }
  32. // place block at end of heap
  33. // no search means fast but no recycle makes for terrible utilization
  34. void *mymalloc(size_t requestedsz)
  35. {
  36. size_t needed = roundup(requestedsz, ALIGNMENT);
  37. if ((char *)next_avail + needed > (char *)heap_max)
  38. return NULL;
  39. void *alloc = next_avail;
  40. next_avail = (char *)next_avail + needed;
  41. return alloc;
  42. }
  43. // free does nothing. fast!... but lame :(
  44. void myfree(void *ptr)
  45. {
  46. }
  47. // realloc built on malloc/memcpy/free is easy to write but not particularly efficient
  48. void *myrealloc(void *oldptr, size_t newsz)
  49. {
  50. void *newptr = mymalloc(newsz);
  51. if (!newptr) return NULL;
  52. memcpy(newptr, oldptr, newsz);
  53. myfree(oldptr);
  54. return newptr;
  55. }
  56. // debugging routine to detect/report inconsistencies in heap data structures
  57. bool validate_heap()
  58. {
  59. if (next_avail > heap_max) {
  60. printf("Oops! Next available spot is beyond heap end!!\n");
  61. return false;
  62. }
  63. return true;
  64. }

3) Implement implicit free list

  1. #include "allocator.h"
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdio.h>
  6. #define ALIGNMENT 8
  7. #define SIZE_T 8
  8. #define MINBLK 24
  9. #define MINBLK_NOHEADFOOT 8
  10. #define HEADFOOT_NOCONTENT 16
  11. #define ONE 0x0000000000000001
  12. #define MULT8 0xFFFFFFFFFFFFFFF8
  13. #define NOT_ONE 0xFFFFFFFFFFFFFFFE
  14. //min acceptable ptr: seg min rounded up
  15. static char *heap_min;
  16. //max acceptable ptr: (seg min + seg sz) rounded down - min blk sz
  17. static char *heap_max;
  18. /*
  19. assumptions
  20. - when given a block pointer char*ptr, it's ok to access its header and footer
  21. */
  22. size_t rounddown(size_t, size_t);
  23. inline size_t rounddown(size_t sz, size_t mult){
  24. return ~(mult-1) & sz;
  25. }
  26. size_t roundup(size_t, size_t);
  27. inline size_t roundup(size_t sz, size_t mult){
  28. return (sz + mult-1) & ~(mult-1);
  29. }
  30. char *getsizeptr1(char *);
  31. inline char *getsizeptr1(char *ptr){
  32. return ptr;
  33. }
  34. size_t ptr2size(char *);
  35. inline size_t ptr2size(char *ptr){
  36. return *(size_t*)ptr & MULT8;
  37. }
  38. size_t getsize(char *);
  39. inline size_t getsize(char *ptr){
  40. return ptr2size(getsizeptr1(ptr));
  41. }
  42. char *getsizeptr2(char *);
  43. inline char *getsizeptr2(char *ptr){
  44. ptr += getsize(ptr) - SIZE_T;
  45. return ptr;
  46. }
  47. void setsize_setfree(char *, size_t);
  48. inline void setsize_setfree(char *ptr, size_t sz){
  49. *(size_t*)ptr = sz;
  50. ptr += sz - SIZE_T;
  51. *(size_t*)ptr = sz;
  52. }
  53. void setsize_setalloc(char *, size_t);
  54. inline void setsize_setalloc(char *ptr, size_t sz){
  55. *(size_t*)ptr = sz | ONE;
  56. ptr += sz - SIZE_T;
  57. *(size_t*)ptr = sz | ONE;
  58. }
  59. bool isalloc(char *);
  60. inline bool isalloc(char *ptr){
  61. return *getsizeptr1(ptr) & 0x01;
  62. }
  63. bool setalloc(char *);
  64. inline bool setalloc(char *ptr){
  65. char *sizeptr1 = getsizeptr1(ptr);
  66. char *sizeptr2 = getsizeptr2(ptr);
  67. bool orig = *sizeptr1 & 0x01;
  68. *sizeptr1 = *sizeptr1 | 0x01;
  69. *sizeptr2 = *sizeptr1;
  70. return orig;
  71. }
  72. bool setfree(char *);
  73. inline bool setfree(char *ptr){
  74. char *sizeptr1 = getsizeptr1(ptr);
  75. char *sizeptr2 = getsizeptr2(ptr);
  76. bool orig = *sizeptr1 & 0x01;
  77. *sizeptr1 = *sizeptr1 & 0xFE;
  78. *sizeptr2 = *sizeptr1;
  79. return orig;
  80. }
  81. //sz must be getsize(ptr)
  82. char *upstairs2(char *, size_t);
  83. inline char *upstairs2(char *ptr, size_t sz){
  84. ptr += sz;
  85. if (ptr > heap_max)
  86. return NULL;
  87. return ptr;
  88. }
  89. char *upstairs1(char *);
  90. inline char *upstairs1(char *ptr){
  91. return upstairs2(ptr, getsize(ptr));
  92. }
  93. char *downstairs(char *);
  94. inline char *downstairs(char *ptr){
  95. if (ptr < heap_min + MINBLK)
  96. return NULL;
  97. return ptr - ptr2size(ptr - SIZE_T);
  98. }
  99. //how about a while loop
  100. //sz must be &(getsize(ptr))
  101. void check_up(char *, size_t *);
  102. inline void check_up(char *ptr, size_t *sz){
  103. ptr = upstairs2(ptr, *sz);
  104. if (ptr != NULL && !isalloc(ptr)){
  105. *sz += getsize(ptr);
  106. }
  107. }
  108. void check_down(char **, size_t *);
  109. inline void check_down(char **ptr, size_t *sz){
  110. char *down = downstairs(*ptr);
  111. if (down != NULL && !isalloc(down)){
  112. *sz += getsize(down);
  113. *ptr = down;
  114. }
  115. }
  116. //given ptr and sz of a blk, initialize blk to free
  117. //attach blk to front of free list
  118. void initutil(char *, size_t);
  119. inline void initutil(char *ptr, size_t sz){
  120. check_up(ptr, &sz);
  121. check_down(&ptr, &sz);
  122. setsize_setfree(ptr, sz);
  123. }
  124. //input requested size
  125. //output aligned block size
  126. size_t pumpsz(size_t);
  127. inline size_t pumpsz(size_t sz){
  128. if (sz <= MINBLK_NOHEADFOOT)
  129. return MINBLK;
  130. sz = roundup(sz, ALIGNMENT);
  131. return sz + HEADFOOT_NOCONTENT;
  132. }
  133. ////////////////////////////////////////
  134. bool myinit(void *, size_t);
  135. inline bool myinit(void *reqstart, size_t reqsz){
  136. if (reqstart == NULL)
  137. return false;
  138. char *reqend = (char *)reqstart + reqsz;
  139. // are these aligned already?
  140. char *start = (char*)roundup((size_t)reqstart, ALIGNMENT);
  141. char *end = (char*)rounddown((size_t)reqend, ALIGNMENT);
  142. size_t sz = end - start;
  143. heap_min = (char*)start;
  144. heap_max = (char*)start + sz - MINBLK;
  145. initutil(start, sz);
  146. return true;
  147. }
  148. void *mymalloc(size_t sz){
  149. sz = pumpsz(sz);
  150. char *ptr = heap_min;
  151. //first fit
  152. while (ptr <= heap_max){
  153. if (isalloc(ptr)){
  154. ptr = upstairs1(ptr);
  155. continue;
  156. }
  157. size_t blocksz = getsize(ptr);
  158. //has needed space + min free block in bytes. split
  159. if (blocksz >= sz + MINBLK){
  160. setsize_setalloc(ptr, sz);
  161. initutil(ptr + sz, blocksz - sz);
  162. return ptr + SIZE_T;//internal -> client ptr
  163. }
  164. //not enough to split. allocate whole
  165. if (blocksz >= sz){
  166. setalloc(ptr);
  167. return ptr + SIZE_T;
  168. }
  169. ptr = upstairs2(ptr, blocksz);
  170. }
  171. return NULL;
  172. }
  173. void myfree(void *);
  174. inline void myfree(void *ptrv){
  175. char *ptr = (char *)ptrv - SIZE_T;//client -> internal ptr
  176. if (ptr < heap_min ||
  177. ptr > heap_max ||
  178. !isalloc(ptr)){
  179. //printf("\ninvalid free\nheap_min %lx\nheap_max %lx\nptr %lx\n",
  180. // (size_t)heap_min, (size_t)heap_max, (size_t)ptr);
  181. //exit(1346347);
  182. }else{
  183. initutil(ptr, getsize(ptr));
  184. }
  185. }
  186. void *myrealloc(void *oldptrv, size_t newsz){
  187. char *oldptr = (char *)oldptrv - SIZE_T;//client -> internal ptr
  188. newsz = pumpsz(newsz);
  189. size_t oldsz = getsize(oldptr);
  190. if (oldsz >= newsz + MINBLK){
  191. setsize_setalloc(oldptr, newsz);
  192. initutil(oldptr + newsz, oldsz - newsz);
  193. return oldptrv;//client ptr
  194. }
  195. if (oldsz >= newsz)
  196. return oldptrv;//client ptr
  197. char *up = upstairs2(oldptr, oldsz);
  198. char *down = downstairs(oldptr);
  199. size_t szup = (up != NULL && !isalloc(up))?
  200. getsize(up):0;
  201. size_t szdown = (down != NULL && !isalloc(down))?
  202. getsize(down):0;
  203. if (oldsz + szup >= newsz + MINBLK){
  204. setsize_setalloc(oldptr, newsz);
  205. initutil(oldptr + newsz, oldsz + szup - newsz);
  206. return oldptr + SIZE_T;//internal -> client ptr
  207. }
  208. if (oldsz + szup >= newsz){
  209. setsize_setalloc(oldptr, oldsz + szup);
  210. return oldptr + SIZE_T;//internal -> client ptr
  211. }
  212. if (oldsz + szdown >= newsz + MINBLK){
  213. char *newptr = oldptr + oldsz - newsz;
  214. memmove(newptr, oldptr, oldsz);
  215. setsize_setalloc(newptr, newsz);
  216. initutil(down, oldsz + szdown - newsz);
  217. return newptr + SIZE_T;//internal -> client ptr
  218. }
  219. if (oldsz + szdown >= newsz){
  220. memmove(down, oldptr, oldsz);
  221. setsize_setalloc(down, oldsz + szdown);
  222. return down + SIZE_T;//internal -> client ptr
  223. }
  224. if (oldsz + szdown + szup >= newsz + MINBLK){
  225. char *newptr = oldptr + oldsz + szup - newsz;
  226. memmove(newptr, oldptr, oldsz);
  227. setsize_setalloc(newptr, newsz);
  228. initutil(down, oldsz + szup + szdown - newsz);
  229. return newptr + SIZE_T;//internal -> client ptr
  230. }
  231. if (oldsz + szdown + szup >= newsz){
  232. memmove(down, oldptr, oldsz);
  233. setsize_setalloc(down, oldsz + szdown + szup);
  234. return down + SIZE_T;//internal -> client ptr
  235. }
  236. char *ptr = heap_min;
  237. while (ptr <= heap_max){
  238. if (isalloc(ptr)){
  239. ptr = upstairs1(ptr);
  240. continue;
  241. }
  242. size_t ptrsz = getsize(ptr);
  243. if (ptrsz >= newsz + MINBLK){
  244. memcpy(ptr, oldptr, oldsz);
  245. //what if newsz real small? no way. newsz > oldsz here
  246. setsize_setalloc(ptr, newsz);
  247. initutil(ptr + newsz, ptrsz - newsz);
  248. initutil(oldptr, oldsz);
  249. return ptr + SIZE_T;//internal -> client ptr
  250. }
  251. if (ptrsz >= newsz){
  252. memcpy(ptr, oldptr, oldsz);
  253. setsize_setalloc(ptr, ptrsz);
  254. initutil(oldptr, oldsz);
  255. return ptr + SIZE_T;//internal -> client ptr
  256. }
  257. ptr = upstairs2(ptr, ptrsz);
  258. }
  259. return NULL;
  260. }
  261. bool validate_heap(){
  262. return true;
  263. }

4) Implement explicit free list

  1. #include "allocator.h"
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdio.h>
  6. #define ALIGNMENT 8
  7. #define SIZE_T 8
  8. #define MINBLK 32
  9. #define PTRSZ 16
  10. #define HEADFOOT_NOPTR 16
  11. #define ONE 0x0000000000000001
  12. #define MULT8 0xFFFFFFFFFFFFFFF8
  13. #define NOT_ONE 0xFFFFFFFFFFFFFFFE
  14. //head of free list
  15. static char *head;
  16. //min acceptable ptr: seg min rounded up
  17. static char *heap_min;
  18. //max acceptable ptr: (seg min + seg sz) rounded down - min blk sz
  19. static char *heap_max;
  20. /*
  21. assumptions
  22. - when given a block pointer char*ptr, it's ok to access its header and footer
  23. */
  24. size_t rounddown(size_t, size_t);
  25. inline size_t rounddown(size_t sz, size_t mult){
  26. return ~(mult-1) & sz;
  27. }
  28. size_t roundup(size_t, size_t);
  29. inline size_t roundup(size_t sz, size_t mult){
  30. return (sz + mult-1) & ~(mult-1);
  31. }
  32. char *getsizeptr1(char *);
  33. inline char *getsizeptr1(char *ptr){
  34. return ptr;
  35. }
  36. size_t ptr2size(char *);
  37. inline size_t ptr2size(char *ptr){
  38. return *(size_t*)ptr & MULT8;
  39. }
  40. size_t getsize(char *);
  41. inline size_t getsize(char *ptr){
  42. return ptr2size(getsizeptr1(ptr));
  43. }
  44. char *getsizeptr2(char *);
  45. inline char *getsizeptr2(char *ptr){
  46. ptr += getsize(ptr) - SIZE_T;
  47. return ptr;
  48. }
  49. void setsize_setfree(char *, size_t);
  50. inline void setsize_setfree(char *ptr, size_t sz){
  51. *(size_t*)ptr = sz;
  52. ptr += sz - SIZE_T;
  53. *(size_t*)ptr = sz;
  54. }
  55. void setsize_setalloc(char *, size_t);
  56. inline void setsize_setalloc(char *ptr, size_t sz){
  57. *(size_t*)ptr = sz | ONE;
  58. ptr += sz - SIZE_T;
  59. *(size_t*)ptr = sz | ONE;
  60. }
  61. bool isalloc(char *);
  62. inline bool isalloc(char *ptr){
  63. return *getsizeptr1(ptr) & 0x01;
  64. }
  65. bool setalloc(char *);
  66. inline bool setalloc(char *ptr){
  67. char *sizeptr1 = getsizeptr1(ptr);
  68. char *sizeptr2 = getsizeptr2(ptr);
  69. bool orig = *sizeptr1 & 0x01;
  70. *sizeptr1 = *sizeptr1 | 0x01;
  71. *sizeptr2 = *sizeptr1;
  72. return orig;
  73. }
  74. bool setfree(char *);
  75. inline bool setfree(char *ptr){
  76. char *sizeptr1 = getsizeptr1(ptr);
  77. char *sizeptr2 = getsizeptr2(ptr);
  78. bool orig = *sizeptr1 & 0x01;
  79. *sizeptr1 = *sizeptr1 & 0xFE;
  80. *sizeptr2 = *sizeptr1;
  81. return orig;
  82. }
  83. char *getprevptr(char *ptr);
  84. inline char *getprevptr(char *ptr){
  85. return (char *)*(size_t*)(ptr + SIZE_T);
  86. }
  87. void setprevptr(char *, char *);
  88. inline void setprevptr(char *ptr, char *prev){
  89. ptr += SIZE_T;
  90. *(size_t*)ptr = (size_t)prev;
  91. }
  92. char *getnextptr(char *ptr);
  93. inline char *getnextptr(char *ptr){
  94. return (char *)*(size_t*)(ptr + 2*SIZE_T);;
  95. }
  96. void setnextptr(char *, char *);
  97. inline void setnextptr(char *ptr, char *next){
  98. ptr += 2*SIZE_T;
  99. *(size_t*)ptr = (size_t)next;
  100. }
  101. //given ptr of a free blk, remove blk from free list
  102. void bypasslist(char *);
  103. inline void bypasslist(char *ptr){
  104. char *prev = getprevptr(ptr);
  105. char *next = getnextptr(ptr);
  106. if (prev != NULL)
  107. setnextptr(prev, next);
  108. if (next != NULL)
  109. setprevptr(next, prev);
  110. if (head == ptr)
  111. head = next;
  112. }
  113. //sz must be getsize(ptr)
  114. char *upstairs2(char *, size_t);
  115. inline char *upstairs2(char *ptr, size_t sz){
  116. ptr += sz;
  117. if (ptr > heap_max)
  118. return NULL;
  119. return ptr;
  120. }
  121. char *upstairs1(char *);
  122. inline char *upstairs1(char *ptr){
  123. return upstairs2(ptr, getsize(ptr));
  124. }
  125. char *downstairs(char *);
  126. inline char *downstairs(char *ptr){
  127. if (ptr < heap_min + MINBLK)
  128. return NULL;
  129. return ptr - ptr2size(ptr - SIZE_T);
  130. }
  131. //how about a while loop
  132. //sz must be &(getsize(ptr))
  133. void check_bypass_up(char *, size_t *);
  134. inline void check_bypass_up(char *ptr, size_t *sz){
  135. ptr = upstairs2(ptr, *sz);
  136. if (ptr != NULL && !isalloc(ptr)){
  137. *sz += getsize(ptr);
  138. bypasslist(ptr);
  139. }
  140. }
  141. void check_bypass_down(char **, size_t *);
  142. inline void check_bypass_down(char **ptr, size_t *sz){
  143. char *down = downstairs(*ptr);
  144. if (down != NULL && !isalloc(down)){
  145. *sz += getsize(down);
  146. bypasslist(down);
  147. *ptr = down;
  148. }
  149. }
  150. //given ptr and sz of a blk, initialize blk to free
  151. //attach blk to front of free list
  152. void initutil(char *, size_t);
  153. inline void initutil(char *ptr, size_t sz){
  154. check_bypass_up(ptr, &sz);
  155. check_bypass_down(&ptr, &sz);
  156. if (head != NULL){
  157. setprevptr(head, ptr);
  158. }
  159. setnextptr(ptr, head);
  160. setprevptr(ptr, NULL);
  161. setsize_setfree(ptr, sz);
  162. head = ptr;
  163. }
  164. //input requested size
  165. //output aligned block size
  166. size_t pumpsz(size_t);
  167. inline size_t pumpsz(size_t sz){
  168. if (sz < PTRSZ)
  169. return MINBLK;
  170. sz = roundup(sz, ALIGNMENT);
  171. return sz + HEADFOOT_NOPTR;
  172. }
  173. ////////////////////////////////////////
  174. bool myinit(void *, size_t);
  175. inline bool myinit(void *reqstart, size_t reqsz){
  176. if (reqstart == NULL)
  177. return false;
  178. char *reqend = (char *)reqstart + reqsz;
  179. // are these aligned already?
  180. char *start = (char*)roundup((size_t)reqstart, ALIGNMENT);
  181. char *end = (char*)rounddown((size_t)reqend, ALIGNMENT);
  182. size_t sz = end - start;
  183. heap_min = (char*)start;
  184. heap_max = (char*)start + sz - MINBLK;
  185. head = NULL;
  186. initutil(start, sz);
  187. return true;
  188. }
  189. void *mymalloc(size_t sz){
  190. sz = pumpsz(sz);
  191. char *ptr = head;
  192. //first fit
  193. while (ptr != NULL){
  194. size_t blocksz = getsize(ptr);
  195. //has needed space + min free block in bytes. split
  196. if (blocksz >= sz + MINBLK){
  197. bypasslist(ptr);
  198. setsize_setalloc(ptr, sz);
  199. initutil(ptr + sz, blocksz - sz);
  200. return ptr + SIZE_T;//internal -> client ptr
  201. }
  202. //not enough to split. allocate whole
  203. if (blocksz >= sz){
  204. bypasslist(ptr);
  205. setalloc(ptr);
  206. return ptr + SIZE_T;
  207. }
  208. ptr = getnextptr(ptr);
  209. }
  210. return NULL;
  211. }
  212. void myfree(void *);
  213. inline void myfree(void *ptrv){
  214. char *ptr = (char *)ptrv - SIZE_T;//client -> internal ptr
  215. if (ptr < heap_min ||
  216. ptr > heap_max ||
  217. !isalloc(ptr)){
  218. //printf("\ninvalid free\nheap_min %lx\nheap_max %lx\nptr %lx\n",
  219. // (size_t)heap_min, (size_t)heap_max, (size_t)ptr);
  220. //exit(1346347);
  221. }else{
  222. initutil(ptr, getsize(ptr));
  223. }
  224. }
  225. void *myrealloc(void *oldptrv, size_t newsz){
  226. char *oldptr = (char *)oldptrv - SIZE_T;//client -> internal ptr
  227. newsz = pumpsz(newsz);
  228. size_t oldsz = getsize(oldptr);
  229. if (oldsz >= newsz + MINBLK){
  230. setsize_setalloc(oldptr, newsz);
  231. initutil(oldptr + newsz, oldsz - newsz);
  232. return oldptrv;//client ptr
  233. }
  234. if (oldsz >= newsz)
  235. return oldptrv;//client ptr
  236. char *up = upstairs2(oldptr, oldsz);
  237. char *down = downstairs(oldptr);
  238. size_t szup = (up != NULL && !isalloc(up))?
  239. getsize(up):0;
  240. size_t szdown = (down != NULL && !isalloc(down))?
  241. getsize(down):0;
  242. if (oldsz + szup >= newsz + MINBLK){
  243. bypasslist(up);
  244. setsize_setalloc(oldptr, newsz);
  245. initutil(oldptr + newsz, oldsz + szup - newsz);
  246. return oldptr + SIZE_T;//internal -> client ptr
  247. }
  248. if (oldsz + szup >= newsz){
  249. bypasslist(up);
  250. setsize_setalloc(oldptr, oldsz + szup);
  251. return oldptr + SIZE_T;//internal -> client ptr
  252. }
  253. if (oldsz + szdown >= newsz + MINBLK){
  254. bypasslist(down);
  255. char *newptr = oldptr + oldsz - newsz;
  256. memmove(newptr, oldptr, oldsz);
  257. setsize_setalloc(newptr, newsz);
  258. initutil(down, oldsz + szdown - newsz);
  259. return newptr + SIZE_T;//internal -> client ptr
  260. }
  261. if (oldsz + szdown >= newsz){
  262. bypasslist(down);
  263. memmove(down, oldptr, oldsz);
  264. setsize_setalloc(down, oldsz + szdown);
  265. return down + SIZE_T;//internal -> client ptr
  266. }
  267. if (oldsz + szdown + szup >= newsz + MINBLK){
  268. bypasslist(up);
  269. bypasslist(down);
  270. char *newptr = oldptr + oldsz + szup - newsz;
  271. memmove(newptr, oldptr, oldsz);
  272. setsize_setalloc(newptr, newsz);
  273. initutil(down, oldsz + szup + szdown - newsz);
  274. return newptr + SIZE_T;//internal -> client ptr
  275. }
  276. if (oldsz + szdown + szup >= newsz){
  277. bypasslist(up);
  278. bypasslist(down);
  279. memmove(down, oldptr, oldsz);
  280. setsize_setalloc(down, oldsz + szdown + szup);
  281. return down + SIZE_T;//internal -> client ptr
  282. }
  283. char *ptr = head;
  284. while (ptr != NULL){
  285. size_t ptrsz = getsize(ptr);
  286. if (ptrsz >= newsz + MINBLK){
  287. bypasslist(ptr);
  288. memcpy(ptr, oldptr, oldsz);
  289. //what if newsz real small? no way. newsz > oldsz here
  290. setsize_setalloc(ptr, newsz);
  291. initutil(ptr + newsz, ptrsz - newsz);
  292. initutil(oldptr, oldsz);
  293. return ptr + SIZE_T;//internal -> client ptr
  294. }
  295. if (ptrsz >= newsz){
  296. bypasslist(ptr);
  297. memcpy(ptr, oldptr, oldsz);
  298. setsize_setalloc(ptr, ptrsz);
  299. initutil(oldptr, oldsz);
  300. return ptr + SIZE_T;//internal -> client ptr
  301. }
  302. ptr = getnextptr(ptr);
  303. }
  304. return NULL;
  305. }
  306. bool validate_heap(){
  307. return true;
  308. }