80 const void* owner = currentCallbackOwner();
87 auto compactGuard = m_CompactWaiters.acquire();
88 if (m_bCompacting.compareAndSwap(
false,
true)) {
89 __atomic_store_n(&m_pCompactOwner, owner, __ATOMIC_RELEASE);
93 if (__atomic_load_n(&m_pCompactOwner, __ATOMIC_ACQUIRE) == owner) {
97 const WaitQueue::WakeReason compactWake = compactGuard.waitForCompletion(
102 if (!m_bCompacting.compareAndSwap(
false,
true)) {
105 __atomic_store_n(&m_pCompactOwner, owner, __ATOMIC_RELEASE);
109 Metrics::increment(Metrics::MemoryPressurePass);
112 size_t registrationLimit = 0;
115 registrationLimit = m_NextRegistrationSequence;
118 bool releasedPages =
false;
120 size_t registrationCursor = 0;
121 while (priority < MAX_MEMPRESSURE_PRIORITY) {
126 candidate = candidate->m_pNext) {
127 if (candidate->m_RegistrationSequence > registrationCursor &&
128 candidate->m_RegistrationSequence <= registrationLimit) {
130 registrationCursor = candidate->m_RegistrationSequence;
137 auto callbackGuard = handler->m_CallbackWaiters.acquire();
140 handler->m_pCallbackOwner = currentCallbackOwner();
147 registrationCursor = 0;
152 NOTICE(
"Compact: " << (description ? description :
"<unnamed memory-pressure handler>"));
153 releasedPages = handler->
compact();
155 NOTICE(
" -> pages released!");
157 NOTICE(
" -> no pages released.");
162 auto callbackGuard = handler->m_CallbackWaiters.acquire();
165 handler->m_pCallbackOwner =
nullptr;
177 auto compactGuard = m_CompactWaiters.acquire();
178 __atomic_store_n(&m_pCompactOwner,
nullptr, __ATOMIC_RELEASE);
179 const bool cleared = m_bCompacting.compareAndSwap(
true,
false);
184 __atomic_store_n(&m_pCompactOwner,
nullptr, __ATOMIC_RELEASE);
185 const bool cleared = m_bCompacting.compareAndSwap(
true,
false);
189 Metrics::increment(Metrics::MemoryPressurePassSuccess);
191 return releasedPages;
217 FATAL(
"Cannot register a null memory-pressure handler.");
220 if (prio >= MAX_MEMPRESSURE_PRIORITY) {
221 prio = MAX_MEMPRESSURE_PRIORITY - 1;
226 auto callbackGuard = pHandler->m_CallbackWaiters.acquire();
228 if (pHandler->m_bRegistered || pHandler->m_bRemoving) {
229 FATAL(
"Memory-pressure handler registered more than once.");
234 FATAL(
"Memory-pressure handler registered during callback removal.");
238 pHandler->m_Priority = prio;
239 pHandler->m_RegistrationSequence = ++m_NextRegistrationSequence;
240 pHandler->m_pPrevious = m_HandlerTails[prio];
241 pHandler->m_pNext =
nullptr;
242 pHandler->m_bRegistered =
true;
244 if (m_HandlerTails[prio]) {
245 m_HandlerTails[prio]->m_pNext = pHandler;
247 m_Handlers[prio] = pHandler;
249 m_HandlerTails[prio] = pHandler;
257 bool needsDrain =
false;
262 auto callbackGuard = pHandler->m_CallbackWaiters.acquire();
263 if (pHandler->
m_CallbacksInFlight && pHandler->m_pCallbackOwner == currentCallbackOwner()) {
265 "A memory-pressure callback cannot synchronously remove "
270 if (pHandler->m_bRegistered) {
271 const size_t priority = pHandler->m_Priority;
272 if (pHandler->m_pPrevious) {
273 pHandler->m_pPrevious->m_pNext = pHandler->m_pNext;
275 m_Handlers[priority] = pHandler->m_pNext;
277 if (pHandler->m_pNext) {
278 pHandler->m_pNext->m_pPrevious = pHandler->m_pPrevious;
280 m_HandlerTails[priority] = pHandler->m_pPrevious;
283 pHandler->m_pPrevious =
nullptr;
284 pHandler->m_pNext =
nullptr;
285 pHandler->m_bRegistered =
false;
286 pHandler->m_bRemoving =
true;
289 if (pHandler->m_bRemoving) {
291 "Concurrent removal of one memory-pressure handler is "
304 auto callbackGuard = pHandler->m_CallbackWaiters.acquire();
306 if (!callbacksInFlight) {
312 "Cannot drain a live memory-pressure callback from atomic "
316 const WaitQueue::WakeReason callbackWake = callbackGuard.waitForCompletion(
317 WaitQueue::Channel(pHandler), Thread::CallbackDrain,
reinterpret_cast<uintptr_t
>(pHandler));
323 assert(pHandler->m_bRemoving);
324 assert(!pHandler->m_bRegistered);
325 pHandler->m_bRemoving =
false;
330 if (!pHandler->m_bRegistered) {
331 pHandler->m_bRemoving =
false;