| 115 | } |
| 116 | |
| 117 | Status LockVariables(absl::Span<VariableInfo> variables) { |
| 118 | std::vector<int> lock_order(variables.size()); |
| 119 | std::iota(lock_order.begin(), lock_order.end(), 0); |
| 120 | |
| 121 | // VariableInfoComparator orders all empty VariableInfo instances as |
| 122 | // equivalent so it looks like we may want to stable sort these to maintain a |
| 123 | // deterministic order between the empty VariableInfo instances. However |
| 124 | // since we're sorting by pointer value the sort is pretty non-deterministic |
| 125 | // anyway so we don't bother using std::stable_sort for now. |
| 126 | absl::c_sort(lock_order, [&](int a, int b) { |
| 127 | if (variables[a].var() && variables[b].var()) { |
| 128 | return variables[a].var()->mu() < variables[b].var()->mu(); |
| 129 | } |
| 130 | |
| 131 | // Move all the empty VariableInfo instances to the end. |
| 132 | return variables[a].var() != nullptr; |
| 133 | }); |
| 134 | |
| 135 | mutex* prev = nullptr; |
| 136 | for (int i : lock_order) { |
| 137 | Var* variable = variables[i].var(); |
| 138 | if (variable == nullptr) { |
| 139 | // All empty VariableInfo instances are at the end of the order |
| 140 | // so we're done. |
| 141 | break; |
| 142 | } |
| 143 | mutex* mu = variable->mu(); |
| 144 | if (prev == mu) { |
| 145 | // It is an error to pass the same variable handle twice to the same XLA |
| 146 | // cluster because we would not handle variable updates correctly. Any |
| 147 | // locks we have already acquired will be released when the VariableInfo |
| 148 | // objects are destroyed. |
| 149 | // TODO(b/128495870) Add support for passing aliased resource variables. |
| 150 | return errors::Unimplemented("Duplicate variable passed to XLA cluster"); |
| 151 | } |
| 152 | VLOG(4) << "Acquiring lock for variable " |
| 153 | << reinterpret_cast<void*>(variable); |
| 154 | mu->lock(); |
| 155 | variables[i].set_lock_held(); |
| 156 | prev = mu; |
| 157 | } |
| 158 | VLOG(4) << "Finished acquiring variable locks."; |
| 159 | return Status::OK(); |
| 160 | } |
| 161 | |
| 162 | Status SnapshotResourceVariables(OpKernelContext* ctx, |
| 163 | absl::Span<const int> variable_indices, |
no test coverage detected