Hacker News new | ask | show | jobs
by rbmm 838 days ago
https://github.com/rbmm/SRW-2 - possible better repro code . where i guarantee repro this without hundreds loops. i be say that "question" in RtlReleaseSRWLockExclusive implementation. it first remove Lock bit from SRW (and after this any thread can enter to lock) and then call RtlpWakeSRWLock. but this 2 operations not atomic. if in the middle (after Lock Bit removed and before RtlpWakeSRWLock executed) another thread acquire shared access - it got exclusive. and RtlpWakeSRWLock also "fail" after this - not wake any waiters. but when shared/exlusive owner then release lock..RtlpWakeSRWLock will be called again and self job. i be of course use bit another implementation, link to which i paste in another comment here
1 comments

The lock in unfair. We are unfair because you get better performance by not allowing the lock hold time to be extended by context swap. As a result, we always unconditionally release a lock when an exclusive acquire is release or the last shared guy releases. Then we go find people to wake. In this gap the lock can be stollen. The threads that steal all look like exclusive guys. My overall rule of thumb is that in the presence of any exclusive acquires you can never assume a shared acquire is compatible with any other shared acquire. A second shared acquire might wait for the first acquire to exit. We do this for example, so a stream of readers don't starve a writer. This is another case like that but somewhat less obvious. I have no idea if the owners will attempt to fix or take the view that you're trying to assume something we don't guarantee. I'll admit that this is a kind of strange case. You could obviously queue a wait block and the in progress waker will sort this out. Could well get a performance impact from that. I tried to explain this general rule of thumb to you this morning when you contacted me. I could not understand much of what you said.
> My overall rule of thumb is that in the presence of any exclusive acquires you can never assume a shared acquire is compatible with any other shared acquire.

Contract #1: In reader writer locks in general, after I share-acquire a lock, I know that there are no active exclusive owners of that lock and won't be until I release my shared lock. I can also expect that as long as I hold this shared lock, other threads can share-acquire the same lock without waiting. ony share-exclusive threads would have to wait.

This general contract seems useful to me.

The contract you're describing, contract #2, is one in which shared-acquire is an optional optimization over exclusive-acquire (not a contractual guarantee) and that the system is free to promote shared to exclusive lock acquisitions.

This other contract seems finnicky and error-prone.

Can't we have SRWLOCK implement contract #1?

It's typical not to allow a second share acquire to proceed if we have an exclusive waiter: t1: share t2: exclusive so waits t3: share also waits

Thats how we arrive at the rule that shared acquires in anything, but a trivial system (no exclusive acquires) may not be compatible. So, contract #1 is typically not satisfied. Of course, this particular case is slightly different and so you might decide to support it.

Blocking new readers when a writer arrives is perfectly good and desirable. Blocking readers when the writer finishes, and there isn't any new queued, is definitely not.
I meant that contract #1 is that when I, thread A, already have a lock held in shared mode, I can expect shared-acquires on thread B to succeed without my first giving up my shared lock. The problem that we're discussing here is that I, A, can ask for a shared lock but actually and unknowingly get an exclusive lock. There's no exclusive-acquire involved.
"other threads can share-acquire the same lock without waiting." can but not always and mandatory. you really allow to system enter another shared requestor. but only allow,not demand. system not let shared requestor enter to lock, if before it the exclusive request will be. after first exclusive request - all next shared request will block, util this exclusive request not acquire and then release lock. can be and some another reason, in the end - this is only optimization - you only *allow* multiple shared enter at once. so i be not say that this is implementation bug
So we have to treat shared acquires as exclusive ones just in case an exclusive acquire comes along? What if I know that my program doesn't do that?