@@ -215,25 +215,19 @@ Lock_acquire_impl(LockObject *self, int blocking)
215215 // `srw` only guards `locked` and the condition variable; it is held just
216216 // long enough to inspect/flip the flag, never across the user's critical
217217 // section. This is what lets a different thread call release().
218- if (!blocking ) {
219- AcquireSRWLockExclusive (& self -> srw );
220- if (!self -> locked ) {
221- self -> locked = 1 ;
222- ReleaseSRWLockExclusive (& self -> srw );
223- return 1 ;
224- }
225- ReleaseSRWLockExclusive (& self -> srw );
226- return 0 ;
227- }
228-
229- // Fast path: grab the lock without releasing the GIL if it is free.
218+ //
219+ // Fast path: grab the lock without releasing the GIL if it is free. This is
220+ // also the whole story in the non-blocking case.
230221 AcquireSRWLockExclusive (& self -> srw );
231222 if (!self -> locked ) {
232223 self -> locked = 1 ;
233224 ReleaseSRWLockExclusive (& self -> srw );
234225 return 1 ;
235226 }
236227 ReleaseSRWLockExclusive (& self -> srw );
228+ if (!blocking ) {
229+ return 0 ;
230+ }
237231
238232 // Slow path: wait for the lock to be released, with the GIL dropped so
239233 // other Python threads can run (and release the lock).
@@ -254,20 +248,10 @@ Lock_acquire_impl(LockObject *self, int blocking)
254248 // another thread consumed via sem_wait, so cross-thread release is
255249 // directly well-defined. `locked` is advisory bookkeeping for locked()
256250 // and for guarding against releasing an unheld lock.
257- if (!blocking ) {
258- int status ;
259- do {
260- status = sem_trywait (& self -> sem );
261- } while (status == -1 && errno == EINTR );
262- if (status == 0 ) {
263- self -> locked = 1 ;
264- return 1 ;
265- }
266- return 0 ; // EAGAIN: already held
267- }
268-
269- // Fast path: try non-blocking acquire first to avoid GIL release/reacquire
270- // overhead in the common uncontended case.
251+ //
252+ // Fast path: try a non-blocking acquire first to avoid GIL release/reacquire
253+ // overhead in the common uncontended case. This is also the whole story in
254+ // the non-blocking case.
271255 {
272256 int status ;
273257 do {
@@ -278,6 +262,9 @@ Lock_acquire_impl(LockObject *self, int blocking)
278262 return 1 ;
279263 }
280264 }
265+ if (!blocking ) {
266+ return 0 ; // EAGAIN: already held
267+ }
281268
282269 // Slow path: block with the GIL dropped so other Python threads can run
283270 // (and release the lock). If a signal interrupts sem_wait(), run pending
@@ -312,25 +299,19 @@ Lock_acquire_impl(LockObject *self, int blocking)
312299 // `mut` only guards `locked` and the condition variable; it is held just
313300 // long enough to inspect/flip the flag, never across the user's critical
314301 // section. This is what lets a different thread call release().
315- if (!blocking ) {
316- pthread_mutex_lock (& self -> mut );
317- if (!self -> locked ) {
318- self -> locked = 1 ;
319- pthread_mutex_unlock (& self -> mut );
320- return 1 ;
321- }
322- pthread_mutex_unlock (& self -> mut );
323- return 0 ;
324- }
325-
326- // Fast path: grab the lock without releasing the GIL if it is free.
302+ //
303+ // Fast path: grab the lock without releasing the GIL if it is free. This is
304+ // also the whole story in the non-blocking case.
327305 pthread_mutex_lock (& self -> mut );
328306 if (!self -> locked ) {
329307 self -> locked = 1 ;
330308 pthread_mutex_unlock (& self -> mut );
331309 return 1 ;
332310 }
333311 pthread_mutex_unlock (& self -> mut );
312+ if (!blocking ) {
313+ return 0 ;
314+ }
334315
335316 // Slow path: wait for the lock to be released, with the GIL dropped so
336317 // other Python threads can run (and release the lock). If we wake but do
0 commit comments