Promote surviving objects to the next generation. `survivors` must be strong references (`PyObjectRef`) to keep objects alive, since the generation read locks are released before this is called. Holds both source and destination list locks simultaneously to prevent a race where concurrent `untrack_object` reads a stale `gc_generation` and operates on the wrong list.
(&self, from_gen: usize, survivors: &[PyObjectRef])
| 743 | /// a race where concurrent `untrack_object` reads a stale `gc_generation` |
| 744 | /// and operates on the wrong list. |
| 745 | fn promote_survivors(&self, from_gen: usize, survivors: &[PyObjectRef]) { |
| 746 | if from_gen >= 2 { |
| 747 | return; // Already in oldest generation |
| 748 | } |
| 749 | |
| 750 | let next_gen = from_gen + 1; |
| 751 | |
| 752 | for obj_ref in survivors { |
| 753 | let obj = obj_ref.as_ref(); |
| 754 | let ptr = NonNull::from(obj); |
| 755 | let obj_gen = obj.gc_generation(); |
| 756 | if obj_gen as usize <= from_gen && obj_gen <= 2 { |
| 757 | let src_gen = obj_gen as usize; |
| 758 | |
| 759 | // Lock both source and destination lists simultaneously. |
| 760 | // Always ascending order (src_gen < next_gen) → no deadlock. |
| 761 | let mut src = self.generation_lists[src_gen].write(); |
| 762 | let mut dst = self.generation_lists[next_gen].write(); |
| 763 | |
| 764 | // Re-check under locks: object might have been untracked concurrently |
| 765 | if obj.gc_generation() != obj_gen || !obj.is_gc_tracked() { |
| 766 | continue; |
| 767 | } |
| 768 | |
| 769 | if unsafe { src.remove(ptr) }.is_some() { |
| 770 | self.generations[src_gen] |
| 771 | .count |
| 772 | .fetch_sub(1, Ordering::SeqCst); |
| 773 | |
| 774 | dst.push_front(ptr); |
| 775 | self.generations[next_gen] |
| 776 | .count |
| 777 | .fetch_add(1, Ordering::SeqCst); |
| 778 | |
| 779 | obj.set_gc_generation(next_gen as u8); |
| 780 | } |
| 781 | } |
| 782 | } |
| 783 | } |
| 784 | |
| 785 | /// Get count of frozen objects |
| 786 | pub fn get_freeze_count(&self) -> usize { |
no test coverage detected