| 133 | } |
| 134 | |
| 135 | bool _mi_page_try_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never) { |
| 136 | mi_thread_free_t tfreex; |
| 137 | mi_delayed_t old_delay; |
| 138 | mi_thread_free_t tfree; |
| 139 | size_t yield_count = 0; |
| 140 | do { |
| 141 | tfree = mi_atomic_load_acquire(&page->xthread_free); // note: must acquire as we can break/repeat this loop and not do a CAS; |
| 142 | tfreex = mi_tf_set_delayed(tfree, delay); |
| 143 | old_delay = mi_tf_delayed(tfree); |
| 144 | if mi_unlikely(old_delay == MI_DELAYED_FREEING) { |
| 145 | if (yield_count >= 4) return false; // give up after 4 tries |
| 146 | yield_count++; |
| 147 | mi_atomic_yield(); // delay until outstanding MI_DELAYED_FREEING are done. |
| 148 | // tfree = mi_tf_set_delayed(tfree, MI_NO_DELAYED_FREE); // will cause CAS to busy fail |
| 149 | } |
| 150 | else if (delay == old_delay) { |
| 151 | break; // avoid atomic operation if already equal |
| 152 | } |
| 153 | else if (!override_never && old_delay == MI_NEVER_DELAYED_FREE) { |
| 154 | break; // leave never-delayed flag set |
| 155 | } |
| 156 | } while ((old_delay == MI_DELAYED_FREEING) || |
| 157 | !mi_atomic_cas_weak_release(&page->xthread_free, &tfree, tfreex)); |
| 158 | |
| 159 | return true; // success |
| 160 | } |
| 161 | |
| 162 | /* ----------------------------------------------------------- |
| 163 | Page collect the `local_free` and `thread_free` lists |
no test coverage detected