| ... | ... | @@ -734,7 +734,7 @@ const Serialized = struct { |
| 734 | 734 | const Buffer = struct { |
| 735 | 735 | parents: [node_storage_buffer_len]Node.Parent, |
| 736 | 736 | storage: [node_storage_buffer_len]Node.Storage, |
| 737 | | map: [node_storage_buffer_len]Node.Index, |
| 737 | map: [node_storage_buffer_len]Node.OptionalIndex, |
| 738 | 738 | |
| 739 | 739 | parents_copy: [node_storage_buffer_len]Node.Parent, |
| 740 | 740 | storage_copy: [node_storage_buffer_len]Node.Storage, |
| ... | ... | @@ -753,9 +753,11 @@ fn serialize(serialized_buffer: *Serialized.Buffer) Serialized { |
| 753 | 753 | // Iterate all of the nodes and construct a serializable copy of the state that can be examined |
| 754 | 754 | // without atomics. |
| 755 | 755 | const end_index = @atomicLoad(u32, &global_progress.node_end_index, .monotonic); |
| 756 | | const node_parents = global_progress.node_parents[0..end_index]; |
| 757 | | const node_storage = global_progress.node_storage[0..end_index]; |
| 758 | | for (node_parents, node_storage, 0..) |*parent_ptr, *storage_ptr, i| { |
| 756 | for ( |
| 757 | global_progress.node_parents[0..end_index], |
| 758 | global_progress.node_storage[0..end_index], |
| 759 | serialized_buffer.map[0..end_index], |
| 760 | ) |*parent_ptr, *storage_ptr, *map| { |
| 759 | 761 | var begin_parent = @atomicLoad(Node.Parent, parent_ptr, .acquire); |
| 760 | 762 | while (begin_parent != .unused) { |
| 761 | 763 | const dest_storage = &serialized_buffer.storage[serialized_len]; |
| ... | ... | @@ -766,12 +768,19 @@ fn serialize(serialized_buffer: *Serialized.Buffer) Serialized { |
| 766 | 768 | if (begin_parent == end_parent) { |
| 767 | 769 | any_ipc = any_ipc or (dest_storage.getIpcFd() != null); |
| 768 | 770 | serialized_buffer.parents[serialized_len] = begin_parent; |
| 769 | | serialized_buffer.map[i] = @enumFromInt(serialized_len); |
| 771 | map.* = @enumFromInt(serialized_len); |
| 770 | 772 | serialized_len += 1; |
| 771 | 773 | break; |
| 772 | 774 | } |
| 773 | 775 | |
| 774 | 776 | begin_parent = end_parent; |
| 777 | } else { |
| 778 | // A node may be freed during the execution of this loop, causing |
| 779 | // there to be a parent reference to a nonexistent node. Without |
| 780 | // this assignment, this would lead to the map entry containing |
| 781 | // stale data. By assigning none, the child node with the bad |
| 782 | // parent pointer will be harmlessly omitted from the tree. |
| 783 | map.* = .none; |
| 775 | 784 | } |
| 776 | 785 | } |
| 777 | 786 | |