1 | // Copyright 2017 The Abseil Authors. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | // |
15 | |
16 | #ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_ |
17 | #define ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_ |
18 | |
19 | // A simple thread-safe memory allocator that does not depend on |
20 | // mutexes or thread-specific data. It is intended to be used |
21 | // sparingly, and only when malloc() would introduce an unwanted |
22 | // dependency, such as inside the heap-checker, or the Mutex |
23 | // implementation. |
24 | |
25 | // IWYU pragma: private, include "base/low_level_alloc.h" |
26 | |
27 | #include <sys/types.h> |
28 | |
29 | #include <cstdint> |
30 | |
31 | #include "absl/base/attributes.h" |
32 | #include "absl/base/config.h" |
33 | |
34 | // LowLevelAlloc requires that the platform support low-level |
35 | // allocation of virtual memory. Platforms lacking this cannot use |
36 | // LowLevelAlloc. |
37 | #ifdef ABSL_LOW_LEVEL_ALLOC_MISSING |
38 | #error ABSL_LOW_LEVEL_ALLOC_MISSING cannot be directly set |
39 | #elif !defined(ABSL_HAVE_MMAP) && !defined(_WIN32) |
40 | #define ABSL_LOW_LEVEL_ALLOC_MISSING 1 |
41 | #endif |
42 | |
43 | // Using LowLevelAlloc with kAsyncSignalSafe isn't supported on Windows or |
44 | // asm.js / WebAssembly. |
45 | // See https://kripken.github.io/emscripten-site/docs/porting/pthreads.html |
46 | // for more information. |
47 | #ifdef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING |
48 | #error ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING cannot be directly set |
49 | #elif defined(_WIN32) || defined(__asmjs__) || defined(__wasm__) |
50 | #define ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING 1 |
51 | #endif |
52 | |
53 | #include <cstddef> |
54 | |
55 | #include "absl/base/port.h" |
56 | |
57 | namespace absl { |
58 | namespace base_internal { |
59 | |
60 | class LowLevelAlloc { |
61 | public: |
62 | struct Arena; // an arena from which memory may be allocated |
63 | |
64 | // Returns a pointer to a block of at least "request" bytes |
65 | // that have been newly allocated from the specific arena. |
66 | // for Alloc() call the DefaultArena() is used. |
67 | // Returns 0 if passed request==0. |
68 | // Does not return 0 under other circumstances; it crashes if memory |
69 | // is not available. |
70 | static void *Alloc(size_t request) ABSL_ATTRIBUTE_SECTION(malloc_hook); |
71 | static void *AllocWithArena(size_t request, Arena *arena) |
72 | ABSL_ATTRIBUTE_SECTION(malloc_hook); |
73 | |
74 | // Deallocates a region of memory that was previously allocated with |
75 | // Alloc(). Does nothing if passed 0. "s" must be either 0, |
76 | // or must have been returned from a call to Alloc() and not yet passed to |
77 | // Free() since that call to Alloc(). The space is returned to the arena |
78 | // from which it was allocated. |
79 | static void Free(void *s) ABSL_ATTRIBUTE_SECTION(malloc_hook); |
80 | |
81 | // ABSL_ATTRIBUTE_SECTION(malloc_hook) for Alloc* and Free |
82 | // are to put all callers of MallocHook::Invoke* in this module |
83 | // into special section, |
84 | // so that MallocHook::GetCallerStackTrace can function accurately. |
85 | |
86 | // Create a new arena. |
87 | // The root metadata for the new arena is allocated in the |
88 | // meta_data_arena; the DefaultArena() can be passed for meta_data_arena. |
89 | // These values may be ored into flags: |
90 | enum { |
91 | // Report calls to Alloc() and Free() via the MallocHook interface. |
92 | // Set in the DefaultArena. |
93 | kCallMallocHook = 0x0001, |
94 | |
95 | #ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING |
96 | // Make calls to Alloc(), Free() be async-signal-safe. Not set in |
97 | // DefaultArena(). Not supported on all platforms. |
98 | kAsyncSignalSafe = 0x0002, |
99 | #endif |
100 | }; |
101 | // Construct a new arena. The allocation of the underlying metadata honors |
102 | // the provided flags. For example, the call NewArena(kAsyncSignalSafe) |
103 | // is itself async-signal-safe, as well as generatating an arena that provides |
104 | // async-signal-safe Alloc/Free. |
105 | static Arena *NewArena(int32_t flags); |
106 | |
107 | // Destroys an arena allocated by NewArena and returns true, |
108 | // provided no allocated blocks remain in the arena. |
109 | // If allocated blocks remain in the arena, does nothing and |
110 | // returns false. |
111 | // It is illegal to attempt to destroy the DefaultArena(). |
112 | static bool DeleteArena(Arena *arena); |
113 | |
114 | // The default arena that always exists. |
115 | static Arena *DefaultArena(); |
116 | |
117 | private: |
118 | LowLevelAlloc(); // no instances |
119 | }; |
120 | |
121 | } // namespace base_internal |
122 | } // namespace absl |
123 | |
124 | #endif // ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_ |
125 | |