malloc.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #include <stdlib.h>
  2. #include <string.h>
  3. typedef unsigned int uint;
  4. enum
  5. {
  6. MAGIC = 0xbada110c,
  7. MAX2SIZE = 32,
  8. CUTOFF = 12,
  9. };
  10. typedef struct Bucket Bucket;
  11. struct Bucket
  12. {
  13. int size;
  14. int magic;
  15. Bucket *next;
  16. int pad;
  17. char data[1];
  18. };
  19. typedef struct Arena Arena;
  20. struct Arena
  21. {
  22. Bucket *btab[MAX2SIZE];
  23. };
  24. static Arena arena;
  25. #define datoff ((int)((Bucket*)0)->data)
  26. #define nil ((void*)0)
  27. extern void *sbrk(unsigned long);
  28. void*
  29. malloc(size_t size)
  30. {
  31. uint next;
  32. int pow, n;
  33. Bucket *bp, *nbp;
  34. for(pow = 1; pow < MAX2SIZE; pow++) {
  35. if(size <= (1<<pow))
  36. goto good;
  37. }
  38. return nil;
  39. good:
  40. /* Allocate off this list */
  41. bp = arena.btab[pow];
  42. if(bp) {
  43. arena.btab[pow] = bp->next;
  44. if(bp->magic != 0)
  45. abort();
  46. bp->magic = MAGIC;
  47. return bp->data;
  48. }
  49. size = sizeof(Bucket)+(1<<pow);
  50. size += 7;
  51. size &= ~7;
  52. if(pow < CUTOFF) {
  53. n = (CUTOFF-pow)+2;
  54. bp = sbrk(size*n);
  55. if((int)bp < 0)
  56. return nil;
  57. next = (uint)bp+size;
  58. nbp = (Bucket*)next;
  59. arena.btab[pow] = nbp;
  60. for(n -= 2; n; n--) {
  61. next = (uint)nbp+size;
  62. nbp->next = (Bucket*)next;
  63. nbp->size = pow;
  64. nbp = nbp->next;
  65. }
  66. nbp->size = pow;
  67. }
  68. else {
  69. bp = sbrk(size);
  70. if((int)bp < 0)
  71. return nil;
  72. }
  73. bp->size = pow;
  74. bp->magic = MAGIC;
  75. return bp->data;
  76. }
  77. void
  78. free(void *ptr)
  79. {
  80. Bucket *bp, **l;
  81. if(ptr == nil)
  82. return;
  83. /* Find the start of the structure */
  84. bp = (Bucket*)((uint)ptr - datoff);
  85. if(bp->magic != MAGIC)
  86. abort();
  87. bp->magic = 0;
  88. l = &arena.btab[bp->size];
  89. bp->next = *l;
  90. *l = bp;
  91. }
  92. void*
  93. realloc(void *ptr, size_t n)
  94. {
  95. void *new;
  96. uint osize;
  97. Bucket *bp;
  98. if(ptr == nil)
  99. return malloc(n);
  100. /* Find the start of the structure */
  101. bp = (Bucket*)((uint)ptr - datoff);
  102. if(bp->magic != MAGIC)
  103. abort();
  104. /* enough space in this bucket */
  105. osize = 1<<bp->size;
  106. if(osize >= n)
  107. return ptr;
  108. new = malloc(n);
  109. if(new == nil)
  110. return nil;
  111. memmove(new, ptr, osize);
  112. free(ptr);
  113. return new;
  114. }