| ... | @@ -734,7 +734,7 @@ const Serialized = struct { | ... | @@ -734,7 +734,7 @@ const Serialized = struct { |
| 734 | const Buffer = struct { | 734 | const Buffer = struct { |
| 735 | parents: [node_storage_buffer_len]Node.Parent, | 735 | parents: [node_storage_buffer_len]Node.Parent, |
| 736 | storage: [node_storage_buffer_len]Node.Storage, | 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 | parents_copy: [node_storage_buffer_len]Node.Parent, | 739 | parents_copy: [node_storage_buffer_len]Node.Parent, |
| 740 | storage_copy: [node_storage_buffer_len]Node.Storage, | 740 | storage_copy: [node_storage_buffer_len]Node.Storage, |
| ... | @@ -753,9 +753,11 @@ fn serialize(serialized_buffer: *Serialized.Buffer) Serialized { | ... | @@ -753,9 +753,11 @@ fn serialize(serialized_buffer: *Serialized.Buffer) Serialized { |
| 753 | // Iterate all of the nodes and construct a serializable copy of the state that can be examined | 753 | // Iterate all of the nodes and construct a serializable copy of the state that can be examined |
| 754 | // without atomics. | 754 | // without atomics. |
| 755 | const end_index = @atomicLoad(u32, &global_progress.node_end_index, .monotonic); | 755 | const end_index = @atomicLoad(u32, &global_progress.node_end_index, .monotonic); |
| 756 | const node_parents = global_progress.node_parents[0..end_index]; | 756 | for ( |
| 757 | const node_storage = global_progress.node_storage[0..end_index]; | 757 | global_progress.node_parents[0..end_index], |
| 758 | for (node_parents, node_storage, 0..) |*parent_ptr, *storage_ptr, i| { | 758 | global_progress.node_storage[0..end_index], |
| | 759 | serialized_buffer.map[0..end_index], |
| | 760 | ) |*parent_ptr, *storage_ptr, *map| { |
| 759 | var begin_parent = @atomicLoad(Node.Parent, parent_ptr, .acquire); | 761 | var begin_parent = @atomicLoad(Node.Parent, parent_ptr, .acquire); |
| 760 | while (begin_parent != .unused) { | 762 | while (begin_parent != .unused) { |
| 761 | const dest_storage = &serialized_buffer.storage[serialized_len]; | 763 | const dest_storage = &serialized_buffer.storage[serialized_len]; |
| ... | @@ -766,12 +768,19 @@ fn serialize(serialized_buffer: *Serialized.Buffer) Serialized { | ... | @@ -766,12 +768,19 @@ fn serialize(serialized_buffer: *Serialized.Buffer) Serialized { |
| 766 | if (begin_parent == end_parent) { | 768 | if (begin_parent == end_parent) { |
| 767 | any_ipc = any_ipc or (dest_storage.getIpcFd() != null); | 769 | any_ipc = any_ipc or (dest_storage.getIpcFd() != null); |
| 768 | serialized_buffer.parents[serialized_len] = begin_parent; | 770 | serialized_buffer.parents[serialized_len] = begin_parent; |
| 769 | serialized_buffer.map[i] = @enumFromInt(serialized_len); | 771 | map.* = @enumFromInt(serialized_len); |
| 770 | serialized_len += 1; | 772 | serialized_len += 1; |
| 771 | break; | 773 | break; |
| 772 | } | 774 | } |
| 773 | | 775 | |
| 774 | begin_parent = end_parent; | 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 | |