| 2369 | } |
| 2370 | |
| 2371 | JEMALLOC_EXPORT void JEMALLOC_NOTHROW |
| 2372 | je_free(void *ptr) { |
| 2373 | LOG("core.free.entry", "ptr: %p", ptr); |
| 2374 | |
| 2375 | UTRACE(ptr, 0, 0); |
| 2376 | if (likely(ptr != NULL)) { |
| 2377 | /* |
| 2378 | * We avoid setting up tsd fully (e.g. tcache, arena binding) |
| 2379 | * based on only free() calls -- other activities trigger the |
| 2380 | * minimal to full transition. This is because free() may |
| 2381 | * happen during thread shutdown after tls deallocation: if a |
| 2382 | * thread never had any malloc activities until then, a |
| 2383 | * fully-setup tsd won't be destructed properly. |
| 2384 | */ |
| 2385 | tsd_t *tsd = tsd_fetch_min(); |
| 2386 | check_entry_exit_locking(tsd_tsdn(tsd)); |
| 2387 | |
| 2388 | tcache_t *tcache; |
| 2389 | if (likely(tsd_fast(tsd))) { |
| 2390 | tsd_assert_fast(tsd); |
| 2391 | /* Unconditionally get tcache ptr on fast path. */ |
| 2392 | tcache = tsd_tcachep_get(tsd); |
| 2393 | ifree(tsd, ptr, tcache, false); |
| 2394 | } else { |
| 2395 | if (likely(tsd_reentrancy_level_get(tsd) == 0)) { |
| 2396 | tcache = tcache_get(tsd); |
| 2397 | } else { |
| 2398 | tcache = NULL; |
| 2399 | } |
| 2400 | ifree(tsd, ptr, tcache, true); |
| 2401 | } |
| 2402 | check_entry_exit_locking(tsd_tsdn(tsd)); |
| 2403 | } |
| 2404 | LOG("core.free.exit", ""); |
| 2405 | } |
| 2406 | |
| 2407 | /* |
| 2408 | * End malloc(3)-compatible functions. |