[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
new module for async-safe spin locks
From: |
Bruno Haible |
Subject: |
new module for async-safe spin locks |
Date: |
Wed, 01 Jul 2020 23:16:09 +0200 |
User-agent: |
KMail/5.1.3 (Linux/4.4.0-179-generic; KDE/5.18.0; x86_64; ; ) |
This patch series adds a module 'asyncsafe-spin', with async-safe spin locks.
What is it?
-----------
An async-safe spin lock is a spin lock that can be used to communicate between
a thread that executes normal code and a thread that executes a signal handler.
The table in section 2.4.3 of
<https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html>
lists the functions that may be called from signal handlers. Unfortunately,
POSIX spin lock functions are not among them. Therefore, a new facility is
needed.
Where is it needed?
-------------------
It is needed anytime where you want to do locking between a signal handler
and normal code.
My use-case is to make the 'clean-temp' module multithread-safe. This module
registers file names (to delete) and file descriptors (to close). The latter
is necessary because POSIX allows for unlink() to fail with error EBUSY when
attempting to delete a file that has an open file descriptor. Now, when both
a normal thread tries to do
close (fd);
and a signal handler also does
close (fd);
there is a race condition:
1. Thread A (normal code) starts to do
close (fd);
and is interrupted right when returning from the system call.
2. An unrelated thread calls open(), and receives a file descriptor
that is == fd. This is possible, since the kernel will reuse closed
file descriptors.
3. Thread A (or another thread B) gets to executes a signal handler
that also does
close (fd);
But this now closes the wrong, unrelated file descriptor!
In more abstract terms: In multithreaded applications, it is forbidden to
close the same fd twice, because you never know what unrelated open() calls
are being executed in other threads. So, the 'close (fd)' must be guarded
by a once-only guard, i.e. effectively a lock.
How is it implemented?
----------------------
Fortunately, GCC has the necessary atomic built-ins for a long time already,
and there are few compilers not based on GCC:
- AIX xlc and xlclang: are handled through a specific AIX _check_lock()
function.
- Solaris cc: are handled through inline asm, based on the code that
GCC would generate.
2020-07-01 Bruno Haible <bruno@clisp.org>
asyncsafe-spin: Add tests.
* tests/test-asyncsafe-spin1.c: New file.
* tests/test-asyncsafe-spin2.c: New file, based on tests/test-lock.c and
tests/test-pthread-spin.c.
* modules/asyncsafe-spin-tests: New file.
2020-07-01 Bruno Haible <bruno@clisp.org>
asyncsafe-spin: New module.
* lib/asyncsafe-spin.h: New file.
* lib/asyncsafe-spin.c: New file, based on lib/pthread-spin.c.
* modules/asyncsafe-spin: New file.
0001-asyncsafe-spin-New-module.patch
Description: Text Data
0002-asyncsafe-spin-Add-tests.patch
Description: Text Data
- new module for async-safe spin locks,
Bruno Haible <=