haiku/headers/private/system
Augustin Cavalier 6f3f29c7dd user_mutex: Refactor locking and unblocking mechanism.
Suppose the following scenario:

1. Thread A holds a mutex.

2. Thread B goes to acquire the mutex, winds up in kernel waiting.

3. Thread A unlocks; first unsets the LOCKED flag.
   As WAITING is set, it calls the kernel; but instead of processing
   this immediately, the thread is suspended for any reason (locks,
   reschedule, etc.)

4. Thread B hits a timeout, or a signal. It then unblocks in the kernel,
   which causes the WAITING flag to be unset.

5. Thread C goes to acquire the lock. It sets the LOCKED flag.
   It sees the WAITING flag is not set, so it returns at once,
   having successfully acquired the lock.

6. Thread A, suspended back in step 3, resumes.

Now we encounter the problem. Under the previous code, the following
would occur.

7. Thread A sees that no threads are waiting. It thus unsets the LOCKED
   flag, and returns from the kernel. Now we have a mutex theoretically
   held by thread C but which (illegally) has no LOCKED flag set!

8. Some other thread tries to acquire the lock, and succeeds, for LOCKED
   is not set. We now have one lock owned by two separate threads.
   That's very bad!

The solution, in this commit, is to (1) switch from using "atomic_or"
to lock mutexes, to using "atomic_test_and_set", and (2) mandate that
_kern_unblock_mutex must be invoked with the mutex already unlocked.

Trying to solve the problem with (2) but without (1) produces other
complications and would overall be more complicated. For instance,
all existing userland code expected that it would set LOCKED, but then
check LOCKED|WAITING. If _kern_mutex_unlock does not unset LOCKED,
then whichever thread sets LOCKED when it was previously unset is
now the mutex's undisputed owner, and if it fails to notice this,
would deadlock.

That could have been solved with extra checks at all lock points, but
then that would mean locks would not be acquired "fairly": it would
be possible for any thread to race with an unlocking thread, and
acquire the lock before the kernel had a chance to wake anyone up.

Given how fast atomics can be, and how slow invoking the kernel is
comparatively, that would probably make our mutexes extremely "unfair."
This would not violate the POSIX specification, but it does seem like
a dangerous choice to make in implementing these APIs.

Linux's "futex" API, which our API bears some similarities to, requires
at least one atomic test-and-set for an uncontended acquisition,
and multiple atomics more for even the simplest case of contended
acquisition. If it works for them, it should work for us, too.

Fixes #18436.

Change-Id: Ib8c28acf04ce03234fe738e41aa0969ca1917540
Reviewed-on: https://review.haiku-os.org/c/haiku/+/6537
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
2023-06-08 16:49:05 +00:00
..
arch kernel/arm: don't set Accessed Flag when initially mapping a page 2023-06-06 18:49:56 +00:00
posix posix: add _POSIX_SEM_NSEMS_MAX. 2017-02-21 20:17:16 +01:00
architecture_private.h Add get_architectures() and C++ versions 2013-11-17 02:09:37 +01:00
commpage_defs.h kernel: add a compatibility commpage on x86_64. 2018-05-18 05:11:07 +00:00
computed_asm_macros.h Created new private system header computed_asm_macros.h defining the macro we 2009-11-27 14:07:05 +00:00
convertutf.h headers/private: Fix wrong filemode. 2018-08-08 23:48:37 -04:00
ddm_userland_interface_defs.h add physical_block_size field where applicable 2022-09-23 06:56:01 +00:00
device_manager_defs.h fixed listdev and device_manager syscalls 2008-06-06 22:23:25 +00:00
directories.h packagefs: Support blacklisting entries in packages 2013-11-19 15:30:34 +01:00
disk_device_types.h btrfs: make file system name consistent 2019-04-09 12:03:12 +00:00
elf_private.h kernel: support elf32 on x86_64. 2018-05-15 10:29:00 +00:00
extended_system_info_defs.h Added new private API to get more information on a team: 2010-11-16 19:42:08 +00:00
find_directory_private.h Add get_*architecture() API, extend find_path*() API 2013-11-17 02:09:36 +01:00
generic_syscall_defs.h * Introduced new header directory headers/private/system which is supposed 2008-05-14 03:55:16 +00:00
image_defs.h extended_image_info: Add text_delta field 2016-04-29 22:32:14 +02:00
node_monitor_private.h As suggested by Ingo use a B_WATCH_VOLUME flag to tell the kernel to watch 2010-10-24 00:49:20 +00:00
pe_common.h runtime_loader: Detect and trigger on PE binaries 2014-01-07 19:38:07 -06:00
real_time_data.h * More header cleanup, continuing korli's work. 2010-04-13 09:48:02 +00:00
safemode_defs.h boot/bios_ia32: basic support la57 aka 5-level paging for x86_64 kernels 2020-12-28 18:21:11 +00:00
scheduler_defs.h Scheduling analysis: Also record the number of times a thread waits on a 2008-09-04 00:07:11 +00:00
signal_defs.h Merged signals-merge branch into trunk with the following changes: 2011-06-12 00:00:23 +00:00
spinlock_contention.h * Added optional spinlock contention measurement feature. Enabled when 2008-06-02 02:04:12 +00:00
symbol_versioning.h Fixed header guard. 2009-11-27 21:10:08 +00:00
symbol_visibility.h Introduce symbol_visibility.h with macros to define hidden functions 2021-10-09 15:03:36 +02:00
syscall_load_image.h headers/kernel: Move B_WAIT_TILL_LOADED to a syscall header. 2019-02-01 19:45:56 -05:00
syscall_process_info.h * More header cleanup, continuing korli's work. 2010-04-13 09:48:02 +00:00
syscalls.h user_mutex: Refactor locking and unblocking mechanism. 2023-06-08 16:49:05 +00:00
system_info.h kernel: add frequency in cpu_info 2021-11-22 07:20:25 +00:00
system_profiler_defs.h Added support for I/O scheduling events to the system profiler interface. 2009-12-19 14:33:29 +00:00
thread_defs.h kernel: Introduce THREAD_BLOCK_TYPE_OTHER_OBJECT. 2023-04-26 15:33:53 -04:00
tls.h libs/posix: Implemented new locale functions 2022-07-11 16:30:16 +00:00
user_mutex_defs.h user_mutex: Refactor locking and unblocking mechanism. 2023-06-08 16:49:05 +00:00
user_runtime.h system/kernel: Increase MAX_PROCESS_ARGS_SIZE; fixes #17612 2022-02-23 17:36:54 +00:00
user_thread_defs.h Merged signals-merge branch into trunk with the following changes: 2011-06-12 00:00:23 +00:00
user_timer_defs.h Merged signals-merge branch into trunk with the following changes: 2011-06-12 00:00:23 +00:00
vfs_defs.h limits.h: define PIPE_BUF. 2017-04-19 17:52:28 +02:00
vm_defs.h Cleanup: Various comment and whitespace fixes. 2020-08-01 19:23:27 +00:00