2018-07-12 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libsanitizer / sanitizer_common / sanitizer_persistent_allocator.h
blob71185033eff4e8d59e838d9e9190943dda963fb1
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 //===----------------------------------------------------------------------===//
12 #ifndef SANITIZER_PERSISTENT_ALLOCATOR_H
13 #define SANITIZER_PERSISTENT_ALLOCATOR_H
15 #include "sanitizer_internal_defs.h"
16 #include "sanitizer_mutex.h"
17 #include "sanitizer_atomic.h"
18 #include "sanitizer_common.h"
20 namespace __sanitizer {
22 class PersistentAllocator {
23 public:
24 void *alloc(uptr size);
26 private:
27 void *tryAlloc(uptr size);
28 StaticSpinMutex mtx; // Protects alloc of new blocks for region allocator.
29 atomic_uintptr_t region_pos; // Region allocator for Node's.
30 atomic_uintptr_t region_end;
33 inline void *PersistentAllocator::tryAlloc(uptr size) {
34 // Optimisic lock-free allocation, essentially try to bump the region ptr.
35 for (;;) {
36 uptr cmp = atomic_load(&region_pos, memory_order_acquire);
37 uptr end = atomic_load(&region_end, memory_order_acquire);
38 if (cmp == 0 || cmp + size > end) return nullptr;
39 if (atomic_compare_exchange_weak(&region_pos, &cmp, cmp + size,
40 memory_order_acquire))
41 return (void *)cmp;
45 inline void *PersistentAllocator::alloc(uptr size) {
46 // First, try to allocate optimisitically.
47 void *s = tryAlloc(size);
48 if (s) return s;
49 // If failed, lock, retry and alloc new superblock.
50 SpinMutexLock l(&mtx);
51 for (;;) {
52 s = tryAlloc(size);
53 if (s) return s;
54 atomic_store(&region_pos, 0, memory_order_relaxed);
55 uptr allocsz = 64 * 1024;
56 if (allocsz < size) allocsz = size;
57 uptr mem = (uptr)MmapOrDie(allocsz, "stack depot");
58 atomic_store(&region_end, mem + allocsz, memory_order_release);
59 atomic_store(&region_pos, mem, memory_order_release);
63 extern PersistentAllocator thePersistentAllocator;
64 inline void *PersistentAlloc(uptr sz) {
65 return thePersistentAllocator.alloc(sz);
68 } // namespace __sanitizer
70 #endif // SANITIZER_PERSISTENT_ALLOCATOR_H