bin.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bin.h>
  4. enum
  5. {
  6. StructAlign = sizeof(union {vlong vl; double d; ulong p; void *v;
  7. struct{vlong v;}vs; struct{double d;}ds; struct{ulong p;}ss; struct{void *v;}xs;})
  8. };
  9. enum
  10. {
  11. BinSize = 8*1024
  12. };
  13. struct Bin
  14. {
  15. Bin *next;
  16. ulong total; /* total bytes allocated in can->next */
  17. uintptr pos;
  18. uintptr end;
  19. uintptr v; /* last value allocated */
  20. uchar body[BinSize];
  21. };
  22. /*
  23. * allocator which allows an entire set to be freed at one time
  24. */
  25. static Bin*
  26. mkbin(Bin *bin, ulong size)
  27. {
  28. Bin *b;
  29. size = ((size << 1) + (BinSize - 1)) & ~(BinSize - 1);
  30. b = malloc(sizeof(Bin) + size - BinSize);
  31. if(b == nil)
  32. return nil;
  33. b->next = bin;
  34. b->total = 0;
  35. if(bin != nil)
  36. b->total = bin->total + bin->pos - (uintptr)bin->body;
  37. b->pos = (uintptr)b->body;
  38. b->end = b->pos + size;
  39. return b;
  40. }
  41. void*
  42. binalloc(Bin **bin, ulong size, int zero)
  43. {
  44. Bin *b;
  45. uintptr p;
  46. if(size == 0)
  47. size = 1;
  48. b = *bin;
  49. if(b == nil){
  50. b = mkbin(nil, size);
  51. if(b == nil)
  52. return nil;
  53. *bin = b;
  54. }
  55. p = b->pos;
  56. p = (p + (StructAlign - 1)) & ~(StructAlign - 1);
  57. if(p + size > b->end){
  58. b = mkbin(b, size);
  59. if(b == nil)
  60. return nil;
  61. *bin = b;
  62. p = b->pos;
  63. }
  64. b->pos = p + size;
  65. b->v = p;
  66. if(zero)
  67. memset((void*)p, 0, size);
  68. return (void*)p;
  69. }
  70. void*
  71. bingrow(Bin **bin, void *op, ulong osize, ulong size, int zero)
  72. {
  73. Bin *b;
  74. void *np;
  75. uintptr p;
  76. p = (uintptr)op;
  77. b = *bin;
  78. if(b != nil && p == b->v && p + size <= b->end){
  79. b->pos = p + size;
  80. if(zero)
  81. memset((char*)p + osize, 0, size - osize);
  82. return op;
  83. }
  84. np = binalloc(bin, size, zero);
  85. if(np == nil)
  86. return nil;
  87. memmove(np, op, osize);
  88. return np;
  89. }
  90. void
  91. binfree(Bin **bin)
  92. {
  93. Bin *last;
  94. while(*bin != nil){
  95. last = *bin;
  96. *bin = (*bin)->next;
  97. last->pos = (uintptr)last->body;
  98. free(last);
  99. }
  100. }