Unmap and unlink any mmapped segments that don't contain used chunks */
| 4241 | |
| 4242 | /* Unmap and unlink any mmapped segments that don't contain used chunks */ |
| 4243 | static size_t release_unused_segments(mstate m) { |
| 4244 | size_t released = 0; |
| 4245 | int nsegs = 0; |
| 4246 | msegmentptr pred = &m->seg; |
| 4247 | msegmentptr sp = pred->next; |
| 4248 | while (sp != 0) { |
| 4249 | char* base = sp->base; |
| 4250 | size_t size = sp->size; |
| 4251 | msegmentptr next = sp->next; |
| 4252 | ++nsegs; |
| 4253 | if (is_mmapped_segment(sp) && !is_extern_segment(sp)) { |
| 4254 | mchunkptr p = align_as_chunk(base); |
| 4255 | size_t psize = chunksize(p); |
| 4256 | /* Can unmap if first chunk holds entire segment and not pinned */ |
| 4257 | if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) { |
| 4258 | tchunkptr tp = (tchunkptr)p; |
| 4259 | assert(segment_holds(sp, (char*)sp)); |
| 4260 | if (p == m->dv) { |
| 4261 | m->dv = 0; |
| 4262 | m->dvsize = 0; |
| 4263 | } |
| 4264 | else { |
| 4265 | unlink_large_chunk(m, tp); |
| 4266 | } |
| 4267 | if (CALL_MUNMAP(base, size) == 0) { |
| 4268 | released += size; |
| 4269 | m->footprint -= size; |
| 4270 | /* unlink obsoleted record */ |
| 4271 | sp = pred; |
| 4272 | sp->next = next; |
| 4273 | } |
| 4274 | else { /* back out if cannot unmap */ |
| 4275 | insert_large_chunk(m, tp, psize); |
| 4276 | } |
| 4277 | } |
| 4278 | } |
| 4279 | if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */ |
| 4280 | break; |
| 4281 | pred = sp; |
| 4282 | sp = next; |
| 4283 | } |
| 4284 | /* Reset check counter */ |
| 4285 | m->release_checks = (((size_t) nsegs > (size_t) MAX_RELEASE_CHECK_RATE)? |
| 4286 | (size_t) nsegs : (size_t) MAX_RELEASE_CHECK_RATE); |
| 4287 | return released; |
| 4288 | } |
| 4289 | |
| 4290 | static int sys_trim(mstate m, size_t pad) { |
| 4291 | size_t released = 0; |
no outgoing calls
no test coverage detected