MCPcopy Create free account
hub / github.com/emscripten-core/emscripten / try_lock

Method try_lock

system/lib/llvm-libc/shared/rpc.h:171–207  ·  view source on GitHub ↗

Attempt to claim the lock at index. Return true on lock taken. lane_mask is a bitmap of the threads in the warp that would hold the single lock on success, e.g. the result of rpc::get_lane_mask() The lock is held when the n-th bit of the lock bitfield is set.

Source from the content-addressed store, hash-verified

169 /// single lock on success, e.g. the result of rpc::get_lane_mask()
170 /// The lock is held when the n-th bit of the lock bitfield is set.
171 RPC_ATTRS bool try_lock(uint64_t lane_mask, uint32_t index) {
172 // On amdgpu, test and set to the nth lock bit and a sync_lane would suffice
173 // On volta, need to handle differences between the threads running and
174 // the threads that were detected in the previous call to get_lane_mask()
175 //
176 // All threads in lane_mask try to claim the lock. At most one can succeed.
177 // There may be threads active which are not in lane mask which must not
178 // succeed in taking the lock, as otherwise it will leak. This is handled
179 // by making threads which are not in lane_mask or with 0, a no-op.
180 uint32_t id = rpc::get_lane_id();
181 bool id_in_lane_mask = lane_mask & (1ul << id);
182
183 // All threads in the warp call fetch_or. Possibly at the same time.
184 bool before = set_nth(lock, index, id_in_lane_mask);
185 uint64_t packed = rpc::ballot(lane_mask, before);
186
187 // If every bit set in lane_mask is also set in packed, every single thread
188 // in the warp failed to get the lock. Ballot returns unset for threads not
189 // in the lane mask.
190 //
191 // Cases, per thread:
192 // mask==0 -> unspecified before, discarded by ballot -> 0
193 // mask==1 and before==0 (success), set zero by ballot -> 0
194 // mask==1 and before==1 (failure), set one by ballot -> 1
195 //
196 // mask != packed implies at least one of the threads got the lock
197 // atomic semantics of fetch_or mean at most one of the threads for the lock
198
199 // If holding the lock then the caller can load values knowing said loads
200 // won't move past the lock. No such guarantee is needed if the lock acquire
201 // failed. This conditional branch is expected to fold in the caller after
202 // inlining the current function.
203 bool holding_lock = lane_mask != packed;
204 if (holding_lock)
205 __scoped_atomic_thread_fence(__ATOMIC_ACQUIRE, __MEMORY_SCOPE_DEVICE);
206 return holding_lock;
207 }
208
209 /// Unlock the lock at index. We need a lane sync to keep this function
210 /// convergent, otherwise the compiler will sink the store and deadlock.

Callers 2

openMethod · 0.45
try_openMethod · 0.45

Calls 2

get_lane_idFunction · 0.70
ballotFunction · 0.70

Tested by

no test coverage detected