2015-01-20 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
[official-gcc.git] / libsanitizer / sanitizer_common / sanitizer_persistent_allocator.h
blobe29b7bd57aa5c379588760896bf79d050779c151
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
14 #include "sanitizer_internal_defs.h"
15 #include "sanitizer_mutex.h"
16 #include "sanitizer_atomic.h"
17 #include "sanitizer_common.h"
19 namespace __sanitizer {
21 class PersistentAllocator {
22 public:
23 void *alloc(uptr size);
25 private:
26 void *tryAlloc(uptr size);
27 StaticSpinMutex mtx; // Protects alloc of new blocks for region allocator.
28 atomic_uintptr_t region_pos; // Region allocator for Node's.
29 atomic_uintptr_t region_end;
32 inline void *PersistentAllocator::tryAlloc(uptr size) {
33 // Optimisic lock-free allocation, essentially try to bump the region ptr.
34 for (;;) {
35 uptr cmp = atomic_load(&region_pos, memory_order_acquire);
36 uptr end = atomic_load(&region_end, memory_order_acquire);
37 if (cmp == 0 || cmp + size > end) return 0;
38 if (atomic_compare_exchange_weak(&region_pos, &cmp, cmp + size,
39 memory_order_acquire))
40 return (void *)cmp;
44 inline void *PersistentAllocator::alloc(uptr size) {
45 // First, try to allocate optimisitically.
46 void *s = tryAlloc(size);
47 if (s) return s;
48 // If failed, lock, retry and alloc new superblock.
49 SpinMutexLock l(&mtx);
50 for (;;) {
51 s = tryAlloc(size);
52 if (s) return s;
53 atomic_store(&region_pos, 0, memory_order_relaxed);
54 uptr allocsz = 64 * 1024;
55 if (allocsz < size) allocsz = size;
56 uptr mem = (uptr)MmapOrDie(allocsz, "stack depot");
57 atomic_store(&region_end, mem + allocsz, memory_order_release);
58 atomic_store(&region_pos, mem, memory_order_release);
62 extern PersistentAllocator thePersistentAllocator;
63 inline void *PersistentAlloc(uptr sz) {
64 return thePersistentAllocator.alloc(sz);
67 } // namespace __sanitizer
69 #endif // SANITIZER_PERSISTENT_ALLOCATOR_H