| 253 | } |
| 254 | |
| 255 | static bool mi_segment_is_valid(mi_segment_t* segment, mi_segments_tld_t* tld) { |
| 256 | mi_assert_internal(segment != NULL); |
| 257 | mi_assert_internal(_mi_ptr_cookie(segment) == segment->cookie); |
| 258 | mi_assert_internal(segment->abandoned <= segment->used); |
| 259 | mi_assert_internal(segment->thread_id == 0 || segment->thread_id == _mi_thread_id()); |
| 260 | mi_assert_internal(mi_commit_mask_all_set(&segment->commit_mask, &segment->decommit_mask)); // can only decommit committed blocks |
| 261 | //mi_assert_internal(segment->segment_info_size % MI_SEGMENT_SLICE_SIZE == 0); |
| 262 | mi_slice_t* slice = &segment->slices[0]; |
| 263 | const mi_slice_t* end = mi_segment_slices_end(segment); |
| 264 | size_t used_count = 0; |
| 265 | mi_span_queue_t* sq; |
| 266 | while(slice < end) { |
| 267 | mi_assert_internal(slice->slice_count > 0); |
| 268 | mi_assert_internal(slice->slice_offset == 0); |
| 269 | size_t index = mi_slice_index(slice); |
| 270 | size_t maxindex = (index + slice->slice_count >= segment->slice_entries ? segment->slice_entries : index + slice->slice_count) - 1; |
| 271 | if (mi_slice_is_used(slice)) { // a page in use, we need at least MAX_SLICE_OFFSET valid back offsets |
| 272 | used_count++; |
| 273 | for (size_t i = 0; i <= MI_MAX_SLICE_OFFSET && index + i <= maxindex; i++) { |
| 274 | mi_assert_internal(segment->slices[index + i].slice_offset == i*sizeof(mi_slice_t)); |
| 275 | mi_assert_internal(i==0 || segment->slices[index + i].slice_count == 0); |
| 276 | mi_assert_internal(i==0 || segment->slices[index + i].xblock_size == 1); |
| 277 | } |
| 278 | // and the last entry as well (for coalescing) |
| 279 | const mi_slice_t* last = slice + slice->slice_count - 1; |
| 280 | if (last > slice && last < mi_segment_slices_end(segment)) { |
| 281 | mi_assert_internal(last->slice_offset == (slice->slice_count-1)*sizeof(mi_slice_t)); |
| 282 | mi_assert_internal(last->slice_count == 0); |
| 283 | mi_assert_internal(last->xblock_size == 1); |
| 284 | } |
| 285 | } |
| 286 | else { // free range of slices; only last slice needs a valid back offset |
| 287 | mi_slice_t* last = &segment->slices[maxindex]; |
| 288 | if (segment->kind != MI_SEGMENT_HUGE || slice->slice_count <= (segment->slice_entries - segment->segment_info_slices)) { |
| 289 | mi_assert_internal((uint8_t*)slice == (uint8_t*)last - last->slice_offset); |
| 290 | } |
| 291 | mi_assert_internal(slice == last || last->slice_count == 0 ); |
| 292 | mi_assert_internal(last->xblock_size == 0 || (segment->kind==MI_SEGMENT_HUGE && last->xblock_size==1)); |
| 293 | if (segment->kind != MI_SEGMENT_HUGE && segment->thread_id != 0) { // segment is not huge or abandoned |
| 294 | sq = mi_span_queue_for(slice->slice_count,tld); |
| 295 | mi_assert_internal(mi_span_queue_contains(sq,slice)); |
| 296 | } |
| 297 | } |
| 298 | slice = &segment->slices[maxindex+1]; |
| 299 | } |
| 300 | mi_assert_internal(slice == end); |
| 301 | mi_assert_internal(used_count == segment->used + 1); |
| 302 | return true; |
| 303 | } |
| 304 | #endif |
| 305 | |
| 306 | /* ----------------------------------------------------------- |
no test coverage detected