Plan 9 from Bell Labs’s /usr/web/sources/contrib/mospak/libc-canlock-wakeup/README

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


libc-canlock-wakeup: a failed canlock lets two processes hold one Lock

sys/src/libc/port/lock.c builds Lock from a counter, key, and a
kernel semaphore, sem.  lock adds one to key and sleeps on sem if
the lock was taken; unlock subtracts one and releases sem if anyone
is waiting.

canlock adds one to key and, when the lock is taken, undoes the
increment.  If the lock is still taken it then releases sem.  No
process is waiting for that release; the semaphore keeps the extra
count, and the next lock that has to wait takes it and enters
while the holder is still inside.  Every failed canlock on a held
lock leaves one such count behind.

Programs that call canlock on a lock they already hold, as a check,
leak a count on every call.  ndb/dns does this on its cache lock;
two workers then changed the cache at once and one of them aborted.

The fix undoes the increment and, in the one case where the lock
was released meanwhile, takes back the wakeup that unlock released
because of the increment.  canlock now leaves sem as it found it.
In that case canlock waits until the releasing process has finished
unlock; it never waits for the lock itself.  lock(2) calls canlock
non-blocking; this brief wait is the one exception.

The APE copies in sys/src/ape/lib/ap/*/lock.c have the same code
and get the same change.

Apply
	cd /
	ape/patch -p0 < /path/to/libc-canlock-wakeup/libc-canlock-wakeup.diff

Rebuild
	cd /sys/src/libc && mk install
	cd /sys/src/ape/lib/ap && mk install

	Programs are linked statically: each one that uses Lock,
	directly or through QLock, RWLock or libthread, keeps the old
	code until it is rebuilt.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.