| 507 | } |
| 508 | |
| 509 | static void mi_segment_perhaps_decommit(mi_segment_t* segment, uint8_t* p, size_t size, mi_stats_t* stats) { |
| 510 | if (!segment->allow_decommit) return; |
| 511 | if (mi_option_get(mi_option_decommit_delay) == 0) { |
| 512 | mi_segment_commitx(segment, false, p, size, stats); |
| 513 | } |
| 514 | else { |
| 515 | // register for future decommit in the decommit mask |
| 516 | uint8_t* start = NULL; |
| 517 | size_t full_size = 0; |
| 518 | mi_commit_mask_t mask; |
| 519 | mi_segment_commit_mask(segment, true /*conservative*/, p, size, &start, &full_size, &mask); |
| 520 | if (mi_commit_mask_is_empty(&mask) || full_size==0) return; |
| 521 | |
| 522 | // update delayed commit |
| 523 | mi_assert_internal(segment->decommit_expire > 0 || mi_commit_mask_is_empty(&segment->decommit_mask)); |
| 524 | mi_commit_mask_t cmask; |
| 525 | mi_commit_mask_create_intersect(&segment->commit_mask, &mask, &cmask); // only decommit what is committed; span_free may try to decommit more |
| 526 | mi_commit_mask_set(&segment->decommit_mask, &cmask); |
| 527 | mi_msecs_t now = _mi_clock_now(); |
| 528 | if (segment->decommit_expire == 0) { |
| 529 | // no previous decommits, initialize now |
| 530 | segment->decommit_expire = now + mi_option_get(mi_option_decommit_delay); |
| 531 | } |
| 532 | else if (segment->decommit_expire <= now) { |
| 533 | // previous decommit mask already expired |
| 534 | if (segment->decommit_expire + mi_option_get(mi_option_decommit_extend_delay) <= now) { |
| 535 | mi_segment_delayed_decommit(segment, true, stats); |
| 536 | } |
| 537 | else { |
| 538 | segment->decommit_expire = now + mi_option_get(mi_option_decommit_extend_delay); // (mi_option_get(mi_option_decommit_delay) / 8); // wait a tiny bit longer in case there is a series of free's |
| 539 | } |
| 540 | } |
| 541 | else { |
| 542 | // previous decommit mask is not yet expired, increase the expiration by a bit. |
| 543 | segment->decommit_expire += mi_option_get(mi_option_decommit_extend_delay); |
| 544 | } |
| 545 | } |
| 546 | } |
| 547 | |
| 548 | static void mi_segment_delayed_decommit(mi_segment_t* segment, bool force, mi_stats_t* stats) { |
| 549 | if (!segment->allow_decommit || mi_commit_mask_is_empty(&segment->decommit_mask)) return; |
no test coverage detected