| 47 | void* mem_pool::sub_header(void* a) { return (void*)((char*)a - header_size); } |
| 48 | |
| 49 | void* mem_pool::alloc(size_t s) { |
| 50 | size_t log_size = log2_up((size_t)s + header_size); |
| 51 | if (log_size < 20) { |
| 52 | void* a = (void*)aligned_alloc(header_size, s + header_size); |
| 53 | *((size_t*)a) = small_size_tag; |
| 54 | return add_header(a); |
| 55 | } |
| 56 | size_t bucket = log_size - log_base; |
| 57 | std::optional<void*> r = buckets[bucket].pop(); |
| 58 | size_t n = ((size_t)1) << log_size; |
| 59 | used += n; |
| 60 | if (r.has_value()) { |
| 61 | // if (n > 10000000) std::cout << "alloc: " << add_header(*r) << ", " << n << |
| 62 | // std::endl; |
| 63 | return add_header(*r); |
| 64 | } else { |
| 65 | void* a = (void*)aligned_alloc(header_size, n); |
| 66 | // if (n > 10000000) std::cout << "alloc: " << add_header(a) << ", " << n << |
| 67 | // std::endl; |
| 68 | allocated += n; |
| 69 | if (a == NULL) std::cout << "alloc failed" << std::endl; |
| 70 | // a hack to make sure pages are touched in parallel |
| 71 | // not the right choice if you want processor local allocations |
| 72 | size_t stride = (1 << 21); // 2 Mbytes in a huge page |
| 73 | auto touch_f = [&](size_t i) { ((bool*)a)[i * stride] = 0; }; |
| 74 | parallel_for(0, n / stride, touch_f, 1); |
| 75 | *((size_t*)a) = bucket; |
| 76 | return add_header(a); |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | void mem_pool::afree(void* a) { |
| 81 | // std::cout << "free: " << a << std::endl; |
no test coverage detected