fork.patch 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. --- contrib/libs/tcmalloc/tcmalloc/central_freelist.h (index)
  2. +++ contrib/libs/tcmalloc/tcmalloc/central_freelist.h (working tree)
  3. @@ -70,6 +70,14 @@ class CentralFreeList {
  4. SpanStats GetSpanStats() const;
  5. + void AcquireInternalLocks() {
  6. + lock_.Lock();
  7. + }
  8. +
  9. + void ReleaseInternalLocks() {
  10. + lock_.Unlock();
  11. + }
  12. +
  13. private:
  14. // Release an object to spans.
  15. // Returns object's span if it become completely free.
  16. --- contrib/libs/tcmalloc/tcmalloc/cpu_cache.cc (index)
  17. +++ contrib/libs/tcmalloc/tcmalloc/cpu_cache.cc (working tree)
  18. @@ -1031,6 +1031,20 @@ void CPUCache::PrintInPbtxt(PbtxtRegion *region) const {
  19. }
  20. }
  21. +void CPUCache::AcquireInternalLocks() {
  22. + for (int cpu = 0, num_cpus = absl::base_internal::NumCPUs(); cpu < num_cpus;
  23. + ++cpu) {
  24. + resize_[cpu].lock.Lock();
  25. + }
  26. +}
  27. +
  28. +void CPUCache::ReleaseInternalLocks() {
  29. + for (int cpu = 0, num_cpus = absl::base_internal::NumCPUs(); cpu < num_cpus;
  30. + ++cpu) {
  31. + resize_[cpu].lock.Unlock();
  32. + }
  33. +}
  34. +
  35. void CPUCache::PerClassResizeInfo::Init() {
  36. state_.store(0, std::memory_order_relaxed);
  37. }
  38. --- contrib/libs/tcmalloc/tcmalloc/cpu_cache.h (index)
  39. +++ contrib/libs/tcmalloc/tcmalloc/cpu_cache.h (working tree)
  40. @@ -164,6 +164,9 @@ class CPUCache {
  41. void Print(Printer* out) const;
  42. void PrintInPbtxt(PbtxtRegion* region) const;
  43. + void AcquireInternalLocks();
  44. + void ReleaseInternalLocks();
  45. +
  46. private:
  47. // Per-size-class freelist resizing info.
  48. class PerClassResizeInfo {
  49. --- contrib/libs/tcmalloc/tcmalloc/internal_malloc_extension.h (index)
  50. +++ contrib/libs/tcmalloc/tcmalloc/internal_malloc_extension.h (working tree)
  51. @@ -116,6 +116,10 @@ ABSL_ATTRIBUTE_WEAK int64_t
  52. MallocExtension_Internal_GetMaxTotalThreadCacheBytes();
  53. ABSL_ATTRIBUTE_WEAK void MallocExtension_Internal_SetMaxTotalThreadCacheBytes(
  54. int64_t value);
  55. +
  56. +ABSL_ATTRIBUTE_WEAK void
  57. +MallocExtension_EnableForkSupport();
  58. +
  59. }
  60. #endif
  61. --- contrib/libs/tcmalloc/tcmalloc/malloc_extension.cc (index)
  62. +++ contrib/libs/tcmalloc/tcmalloc/malloc_extension.cc (working tree)
  63. @@ -460,6 +460,14 @@ void MallocExtension::SetBackgroundReleaseRate(BytesPerSecond rate) {
  64. #endif
  65. }
  66. +void MallocExtension::EnableForkSupport() {
  67. +#if ABSL_INTERNAL_HAVE_WEAK_MALLOCEXTENSION_STUBS
  68. + if (&MallocExtension_EnableForkSupport != nullptr) {
  69. + MallocExtension_EnableForkSupport();
  70. + }
  71. +#endif
  72. +}
  73. +
  74. } // namespace tcmalloc
  75. // Default implementation just returns size. The expectation is that
  76. --- contrib/libs/tcmalloc/tcmalloc/malloc_extension.h (index)
  77. +++ contrib/libs/tcmalloc/tcmalloc/malloc_extension.h (working tree)
  78. @@ -468,6 +468,10 @@ class MallocExtension final {
  79. // Specifies the release rate from the page heap. ProcessBackgroundActions
  80. // must be called for this to be operative.
  81. static void SetBackgroundReleaseRate(BytesPerSecond rate);
  82. +
  83. + // Enables fork support.
  84. + // Allocator will continue to function correctly in the child, after calling fork().
  85. + static void EnableForkSupport();
  86. };
  87. } // namespace tcmalloc
  88. --- contrib/libs/tcmalloc/tcmalloc/static_vars.cc (index)
  89. +++ contrib/libs/tcmalloc/tcmalloc/static_vars.cc (working tree)
  90. @@ -59,6 +59,7 @@ ABSL_CONST_INIT PageHeapAllocator<StackTraceTable::Bucket>
  91. Static::bucket_allocator_;
  92. ABSL_CONST_INIT std::atomic<bool> Static::inited_{false};
  93. ABSL_CONST_INIT bool Static::cpu_cache_active_ = false;
  94. +ABSL_CONST_INIT bool Static::fork_support_enabled_ = false;
  95. ABSL_CONST_INIT Static::PageAllocatorStorage Static::page_allocator_;
  96. ABSL_CONST_INIT PageMap Static::pagemap_;
  97. ABSL_CONST_INIT absl::base_internal::SpinLock guarded_page_lock(
  98. @@ -116,6 +117,13 @@ ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE void Static::SlowInitIfNecessary() {
  99. pagemap_.MapRootWithSmallPages();
  100. guardedpage_allocator_.Init(/*max_alloced_pages=*/64, /*total_pages=*/128);
  101. inited_.store(true, std::memory_order_release);
  102. +
  103. + pageheap_lock.Unlock();
  104. + pthread_atfork(
  105. + TCMallocPreFork,
  106. + TCMallocPostFork,
  107. + TCMallocPostFork);
  108. + pageheap_lock.Lock();
  109. }
  110. }
  111. --- contrib/libs/tcmalloc/tcmalloc/static_vars.h (index)
  112. +++ contrib/libs/tcmalloc/tcmalloc/static_vars.h (working tree)
  113. @@ -50,6 +50,9 @@ class CPUCache;
  114. class PageMap;
  115. class ThreadCache;
  116. +void TCMallocPreFork();
  117. +void TCMallocPostFork();
  118. +
  119. class Static {
  120. public:
  121. // True if InitIfNecessary() has run to completion.
  122. @@ -124,6 +127,9 @@ class Static {
  123. static void ActivateCPUCache() { cpu_cache_active_ = true; }
  124. static void DeactivateCPUCache() { cpu_cache_active_ = false; }
  125. + static bool ForkSupportEnabled() { return fork_support_enabled_; }
  126. + static void EnableForkSupport() { fork_support_enabled_ = true; }
  127. +
  128. static bool ABSL_ATTRIBUTE_ALWAYS_INLINE IsOnFastPath() {
  129. return
  130. #ifndef TCMALLOC_DEPRECATED_PERTHREAD
  131. @@ -169,6 +175,7 @@ class Static {
  132. static PageHeapAllocator<StackTraceTable::Bucket> bucket_allocator_;
  133. ABSL_CONST_INIT static std::atomic<bool> inited_;
  134. static bool cpu_cache_active_;
  135. + static bool fork_support_enabled_;
  136. ABSL_CONST_INIT static PeakHeapTracker peak_heap_tracker_;
  137. ABSL_CONST_INIT static NumaTopology<kNumaPartitions, kNumBaseClasses>
  138. numa_topology_;
  139. --- contrib/libs/tcmalloc/tcmalloc/system-alloc.cc (index)
  140. +++ contrib/libs/tcmalloc/tcmalloc/system-alloc.cc (working tree)
  141. @@ -354,6 +354,14 @@ ABSL_CONST_INIT std::atomic<int> system_release_errors = ATOMIC_VAR_INIT(0);
  142. } // namespace
  143. +void AcquireSystemAllocLock() {
  144. + spinlock.Lock();
  145. +}
  146. +
  147. +void ReleaseSystemAllocLock() {
  148. + spinlock.Unlock();
  149. +}
  150. +
  151. void* SystemAlloc(size_t bytes, size_t* actual_bytes, size_t alignment,
  152. const MemoryTag tag) {
  153. // If default alignment is set request the minimum alignment provided by
  154. --- contrib/libs/tcmalloc/tcmalloc/system-alloc.h (index)
  155. +++ contrib/libs/tcmalloc/tcmalloc/system-alloc.h (working tree)
  156. @@ -50,6 +50,9 @@ void *SystemAlloc(size_t bytes, size_t *actual_bytes, size_t alignment,
  157. // call to SystemRelease.
  158. int SystemReleaseErrors();
  159. +void AcquireSystemAllocLock();
  160. +void ReleaseSystemAllocLock();
  161. +
  162. // This call is a hint to the operating system that the pages
  163. // contained in the specified range of memory will not be used for a
  164. // while, and can be released for use by other processes or the OS.
  165. --- contrib/libs/tcmalloc/tcmalloc/tcmalloc.cc (index)
  166. +++ contrib/libs/tcmalloc/tcmalloc/tcmalloc.cc (working tree)
  167. @@ -1117,6 +1117,40 @@ extern "C" void MallocExtension_Internal_ReleaseMemoryToSystem(
  168. }
  169. }
  170. +extern "C" void MallocExtension_EnableForkSupport() {
  171. + Static::EnableForkSupport();
  172. +}
  173. +
  174. +void TCMallocPreFork() {
  175. + if (!Static::ForkSupportEnabled()) {
  176. + return;
  177. + }
  178. +
  179. + if (Static::CPUCacheActive()) {
  180. + Static::cpu_cache().AcquireInternalLocks();
  181. + }
  182. + Static::transfer_cache().AcquireInternalLocks();
  183. + guarded_page_lock.Lock();
  184. + release_lock.Lock();
  185. + pageheap_lock.Lock();
  186. + AcquireSystemAllocLock();
  187. +}
  188. +
  189. +void TCMallocPostFork() {
  190. + if (!Static::ForkSupportEnabled()) {
  191. + return;
  192. + }
  193. +
  194. + ReleaseSystemAllocLock();
  195. + pageheap_lock.Unlock();
  196. + guarded_page_lock.Unlock();
  197. + release_lock.Unlock();
  198. + Static::transfer_cache().ReleaseInternalLocks();
  199. + if (Static::CPUCacheActive()) {
  200. + Static::cpu_cache().ReleaseInternalLocks();
  201. + }
  202. +}
  203. +
  204. // nallocx slow path.
  205. // Moved to a separate function because size_class_with_alignment is not inlined
  206. // which would cause nallocx to become non-leaf function with stack frame and
  207. --- contrib/libs/tcmalloc/tcmalloc/tcmalloc.h (index)
  208. +++ contrib/libs/tcmalloc/tcmalloc/tcmalloc.h (working tree)
  209. @@ -120,4 +120,7 @@ void TCMallocInternalDeleteArrayNothrow(void* p, const std::nothrow_t&) __THROW
  210. }
  211. #endif
  212. +void TCMallocInternalAcquireLocks();
  213. +void TCMallocInternalReleaseLocks();
  214. +
  215. #endif // TCMALLOC_TCMALLOC_H_
  216. --- contrib/libs/tcmalloc/tcmalloc/transfer_cache.h (index)
  217. +++ contrib/libs/tcmalloc/tcmalloc/transfer_cache.h (working tree)
  218. @@ -176,6 +176,26 @@ class TransferCacheManager : public StaticForwarder {
  219. }
  220. }
  221. + void AcquireInternalLocks() {
  222. + for (int i = 0; i < kNumClasses; ++i) {
  223. + if (implementation_ == TransferCacheImplementation::Ring) {
  224. + cache_[i].rbtc.AcquireInternalLocks();
  225. + } else {
  226. + cache_[i].tc.AcquireInternalLocks();
  227. + }
  228. + }
  229. + }
  230. +
  231. + void ReleaseInternalLocks() {
  232. + for (int i = 0; i < kNumClasses; ++i) {
  233. + if (implementation_ == TransferCacheImplementation::Ring) {
  234. + cache_[i].rbtc.ReleaseInternalLocks();
  235. + } else {
  236. + cache_[i].tc.ReleaseInternalLocks();
  237. + }
  238. + }
  239. + }
  240. +
  241. void InsertRange(int size_class, absl::Span<void *> batch) {
  242. if (implementation_ == TransferCacheImplementation::Ring) {
  243. cache_[size_class].rbtc.InsertRange(size_class, batch);
  244. @@ -295,6 +315,9 @@ class TransferCacheManager {
  245. return TransferCacheImplementation::None;
  246. }
  247. + void AcquireInternalLocks() {}
  248. + void ReleaseInternalLocks() {}
  249. +
  250. private:
  251. CentralFreeList freelist_[kNumClasses];
  252. } ABSL_CACHELINE_ALIGNED;
  253. --- contrib/libs/tcmalloc/tcmalloc/transfer_cache_internals.h (index)
  254. +++ contrib/libs/tcmalloc/tcmalloc/transfer_cache_internals.h (working tree)
  255. @@ -366,6 +366,18 @@ class TransferCache {
  256. return freelist_do_not_access_directly_;
  257. }
  258. + void AcquireInternalLocks()
  259. + {
  260. + freelist().AcquireInternalLocks();
  261. + lock_.Lock();
  262. + }
  263. +
  264. + void ReleaseInternalLocks()
  265. + {
  266. + lock_.Unlock();
  267. + freelist().ReleaseInternalLocks();
  268. + }
  269. +
  270. private:
  271. // Returns first object of the i-th slot.
  272. void **GetSlot(size_t i) ABSL_EXCLUSIVE_LOCKS_REQUIRED(lock_) {
  273. @@ -468,6 +480,18 @@ class RingBufferTransferCache {
  274. // These methods all do internal locking.
  275. + void AcquireInternalLocks()
  276. + {
  277. + freelist().AcquireInternalLocks();
  278. + lock_.Lock();
  279. + }
  280. +
  281. + void ReleaseInternalLocks()
  282. + {
  283. + lock_.Unlock();
  284. + freelist().ReleaseInternalLocks();
  285. + }
  286. +
  287. // Insert the specified batch into the transfer cache. N is the number of
  288. // elements in the range. RemoveRange() is the opposite operation.
  289. void InsertRange(int size_class, absl::Span<void *> batch)