sanitizer_persistent_allocator.h 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. //===-- sanitizer_persistent_allocator.h ------------------------*- C++ -*-===//
  2. //
  3. // This file is distributed under the University of Illinois Open Source
  4. // License. See LICENSE.TXT for details.
  5. //
  6. //===----------------------------------------------------------------------===//
  7. //
  8. // A fast memory allocator that does not support free() nor realloc().
  9. // All allocations are forever.
  10. //===----------------------------------------------------------------------===//
  11. #ifndef SANITIZER_PERSISTENT_ALLOCATOR_H
  12. #define SANITIZER_PERSISTENT_ALLOCATOR_H
  13. #include "sanitizer_internal_defs.h"
  14. #include "sanitizer_mutex.h"
  15. #include "sanitizer_atomic.h"
  16. #include "sanitizer_common.h"
  17. namespace __sanitizer {
  18. class PersistentAllocator {
  19. public:
  20. void *alloc(uptr size);
  21. private:
  22. void *tryAlloc(uptr size);
  23. StaticSpinMutex mtx; // Protects alloc of new blocks for region allocator.
  24. atomic_uintptr_t region_pos; // Region allocator for Node's.
  25. atomic_uintptr_t region_end;
  26. };
  27. inline void *PersistentAllocator::tryAlloc(uptr size) {
  28. // Optimisic lock-free allocation, essentially try to bump the region ptr.
  29. for (;;) {
  30. uptr cmp = atomic_load(&region_pos, memory_order_acquire);
  31. uptr end = atomic_load(&region_end, memory_order_acquire);
  32. if (cmp == 0 || cmp + size > end) return 0;
  33. if (atomic_compare_exchange_weak(&region_pos, &cmp, cmp + size,
  34. memory_order_acquire))
  35. return (void *)cmp;
  36. }
  37. }
  38. inline void *PersistentAllocator::alloc(uptr size) {
  39. // First, try to allocate optimisitically.
  40. void *s = tryAlloc(size);
  41. if (s) return s;
  42. // If failed, lock, retry and alloc new superblock.
  43. SpinMutexLock l(&mtx);
  44. for (;;) {
  45. s = tryAlloc(size);
  46. if (s) return s;
  47. atomic_store(&region_pos, 0, memory_order_relaxed);
  48. uptr allocsz = 64 * 1024;
  49. if (allocsz < size) allocsz = size;
  50. uptr mem = (uptr)MmapOrDie(allocsz, "stack depot");
  51. atomic_store(&region_end, mem + allocsz, memory_order_release);
  52. atomic_store(&region_pos, mem, memory_order_release);
  53. }
  54. }
  55. extern PersistentAllocator thePersistentAllocator;
  56. inline void *PersistentAlloc(uptr sz) {
  57. return thePersistentAllocator.alloc(sz);
  58. }
  59. } // namespace __sanitizer
  60. #endif // SANITIZER_PERSISTENT_ALLOCATOR_H