bpf_arena_alloc.h 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
  2. /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
  3. #pragma once
  4. #include "bpf_arena_common.h"
  5. #ifndef __round_mask
  6. #define __round_mask(x, y) ((__typeof__(x))((y)-1))
  7. #endif
  8. #ifndef round_up
  9. #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
  10. #endif
  11. #ifdef __BPF__
  12. #define NR_CPUS (sizeof(struct cpumask) * 8)
  13. static void __arena * __arena page_frag_cur_page[NR_CPUS];
  14. static int __arena page_frag_cur_offset[NR_CPUS];
  15. /* Simple page_frag allocator */
  16. static inline void __arena* bpf_alloc(unsigned int size)
  17. {
  18. __u64 __arena *obj_cnt;
  19. __u32 cpu = bpf_get_smp_processor_id();
  20. void __arena *page = page_frag_cur_page[cpu];
  21. int __arena *cur_offset = &page_frag_cur_offset[cpu];
  22. int offset;
  23. size = round_up(size, 8);
  24. if (size >= PAGE_SIZE - 8)
  25. return NULL;
  26. if (!page) {
  27. refill:
  28. page = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
  29. if (!page)
  30. return NULL;
  31. cast_kern(page);
  32. page_frag_cur_page[cpu] = page;
  33. *cur_offset = PAGE_SIZE - 8;
  34. obj_cnt = page + PAGE_SIZE - 8;
  35. *obj_cnt = 0;
  36. } else {
  37. cast_kern(page);
  38. obj_cnt = page + PAGE_SIZE - 8;
  39. }
  40. offset = *cur_offset - size;
  41. if (offset < 0)
  42. goto refill;
  43. (*obj_cnt)++;
  44. *cur_offset = offset;
  45. return page + offset;
  46. }
  47. static inline void bpf_free(void __arena *addr)
  48. {
  49. __u64 __arena *obj_cnt;
  50. addr = (void __arena *)(((long)addr) & ~(PAGE_SIZE - 1));
  51. obj_cnt = addr + PAGE_SIZE - 8;
  52. if (--(*obj_cnt) == 0)
  53. bpf_arena_free_pages(&arena, addr, 1);
  54. }
  55. #else
  56. static inline void __arena* bpf_alloc(unsigned int size) { return NULL; }
  57. static inline void bpf_free(void __arena *addr) {}
  58. #endif