MCPcopy Create free account
hub / github.com/beefytech/Beef / prof_recent_alloc

Function prof_recent_alloc

BeefRT/JEMalloc/src/prof_recent.c:278–403  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

276}
277
278void
279prof_recent_alloc(tsd_t *tsd, edata_t *edata, size_t size, size_t usize) {
280 cassert(config_prof);
281 assert(edata != NULL);
282 prof_tctx_t *tctx = edata_prof_tctx_get(edata);
283
284 malloc_mutex_assert_not_owner(tsd_tsdn(tsd), tctx->tdata->lock);
285 malloc_mutex_lock(tsd_tsdn(tsd), &prof_recent_alloc_mtx);
286 prof_recent_alloc_assert_count(tsd);
287
288 /*
289 * Reserve a new prof_recent_t node if needed. If needed, we release
290 * the prof_recent_alloc_mtx lock and allocate. Then, rather than
291 * immediately checking for OOM, we regain the lock and try to make use
292 * of the reserve node if needed. There are six scenarios:
293 *
294 * \ now | no need | need but OOMed | need and allocated
295 * later \ | | |
296 * ------------------------------------------------------------
297 * no need | (1) | (2) | (3)
298 * ------------------------------------------------------------
299 * need | (4) | (5) | (6)
300 *
301 * First, "(4)" never happens, because we don't release the lock in the
302 * middle if there's no need for a new node; in such cases "(1)" always
303 * takes place, which is trivial.
304 *
305 * Out of the remaining four scenarios, "(6)" is the common case and is
306 * trivial. "(5)" is also trivial, in which case we'll rollback the
307 * effect of prof_recent_alloc_prepare() as expected.
308 *
309 * "(2)" / "(3)" occurs when the need for a new node is gone after we
310 * regain the lock. If the new node is successfully allocated, i.e. in
311 * the case of "(3)", we'll release it in the end; otherwise, i.e. in
312 * the case of "(2)", we do nothing - we're lucky that the OOM ends up
313 * doing no harm at all.
314 *
315 * Therefore, the only performance cost of the "release lock" ->
316 * "allocate" -> "regain lock" design is the "(3)" case, but it happens
317 * very rarely, so the cost is relatively small compared to the gain of
318 * not having to have the lock order of prof_recent_alloc_mtx above all
319 * the allocation locks.
320 */
321 prof_recent_t *reserve = NULL;
322 if (prof_recent_alloc_max_get(tsd) == -1 ||
323 prof_recent_alloc_count < prof_recent_alloc_max_get(tsd)) {
324 assert(prof_recent_alloc_max_get(tsd) != 0);
325 malloc_mutex_unlock(tsd_tsdn(tsd), &prof_recent_alloc_mtx);
326 reserve = prof_recent_allocate_node(tsd_tsdn(tsd));
327 malloc_mutex_lock(tsd_tsdn(tsd), &prof_recent_alloc_mtx);
328 prof_recent_alloc_assert_count(tsd);
329 }
330
331 if (prof_recent_alloc_max_get(tsd) == 0) {
332 assert(prof_recent_alloc_is_empty(tsd));
333 goto label_rollback;
334 }
335

Callers 1

Calls 15

edata_prof_tctx_getFunction · 0.85
tsd_tsdnFunction · 0.85
malloc_mutex_lockFunction · 0.85
malloc_mutex_unlockFunction · 0.85
nstime_copyFunction · 0.85

Tested by

no test coverage detected