path: root/thread_sync.c
AgeCommit message (Collapse)Author
2020-02-07more on NULL versus functions.卜部昌平
Function pointers are not void*. See also ce4ea956d24eab5089a143bba38126f2b11b55b6 8427fca49bd85205f5a8766292dd893f003c0e48
2019-10-28add assertion for mutex_lock.Koichi Sasada
After do_mutex_lock(mutex), the mutex should be owned by the current thread. Adding an assertion for this assumption.
2019-09-27Adjusted spaces [ci skip]Nobuyoshi Nakada
2019-08-29fix arity of rb_mutex_synchronize_m卜部昌平
This is just a trivial mistake introduced in 6c56dae4b23c5c50e351758538141ca26b9aba40.
2019-08-27rb_ensure now free from ANYARGS卜部昌平
After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is dangerous and should be extinct. This commit deletes ANYARGS from rb_ensure, which also revealed many arity / type mismatches.
2019-06-11do_mutex_lock: release mutex before checking for interrupts (fixes issue 15360)Neeraj Bhunwal
2019-05-31Use UNALIGNED_MEMBER_PTRNobuyoshi Nakada
* internal.h (UNALIGNED_MEMBER_ACCESS, UNALIGNED_MEMBER_PTR): moved from eval_intern.h. * compile.c iseq.c, vm.c: use UNALIGNED_MEMBER_PTR for `entries` in `struct iseq_catch_table`. * vm_eval.c, vm_insnhelper.c: use UNALIGNED_MEMBER_PTR for `body` in `rb_method_definition_t`.
2018-12-22thread_sync.c (rb_mutex_t): eliminate fork_gennormal
The true bug fork_gen was hiding was rb_mutex_abandon_locking_mutex failing to unconditionally clear the waitq of mutexes it was waiting on. So we fix rb_mutex_abandon_locking_mutex, instead, and eliminate rb_mutex_cleanup_keeping_mutexes. This commit was tested heavily on a single-core Pentium-M which was my most reliable reproducer of the "crash.rb" script from [Bug #15383] [Bug #14578] [Bug #15383] Note: [Bug #15430] turned out to be an entirely different problem: RLIMIT_NPROC limit was hit on the CI VMs. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-12-21thread_sync.c (rb_mutex_cleanup_keeping_mutexes): update fork_gennormal
... when clearing waitq. Otherwise, we risk redundantly clearing valid waiters in future calls to `mutex_ptr`. Note: I am not sure if this fixes [Bug #15430], and even if it did, fork_gen is a belt-and-suspenders redundancy for [Bug #15383] which wastes one word for every Mutex object. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-12-21thread_sync.c (rb_mutex_abandon_keeping_mutexes): remove unnecessary checknormal
rb_mutex_abandon_all functions fine when passed a NULL value, so let the compiler deal with the complexity of the branch instead of the person reading the code. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-12-18thread_sync.c (mutex_ptr): only reinitalize waitqueue at forknormal
Mutexes need to remain locked after forking. This fixes "[BUG] invalid keeping_mutexes: Attempt to unlock a mutex which is locked by another thread" and should fix test_fork_while_parent_locked failures in CI [ruby-core:90581] [Bug #15424] [ruby-core:90595] [Bug #15430] Fixes: r66230 ("handle mutexes held by parent threads in children") git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-12-06Prefer rb_check_arity when 0 or 1 argumentsnobu
Especially over checking argc then calling rb_scan_args just to raise an ArgumentError. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-12-05thread_sync.c (mutex_ptr): handle mutexes held by parent threads in childrennormal
Mutexes may be held by threads which only exist in the parent process, so their waitqueues may be populated with references to other dead threads. We must reset them at fork. I am a moron for introducing this bug :< [ruby-core:90312] [Bug #15383] git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-09-16Add some missing documentation to Queue#{close|deq} [ci skip]marcandre
Patch by Lars Kanis. [Fix GH-1949] * Describe the impact of Queue#close to Queue#deq . git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-26thread_sync.c: common wakeup_{one,all} implementationnormal
This let us avoid looping in rb_szqueue_max_set, saves us some lines of code and reduces binary size slightly (numbers from 32-bit x86): text data bss dec hex filename before: 91272 392 156 91820 166ac thread.o after: 91200 392 156 91748 16664 thread.o Inspiration from this taken from the FUTEX_WAKE op of the Linux futex(2) syscall. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-25thread.c: use rb_hrtime_t scalar for high-resolution time operationsnormal
Relying on "struct timespec" was too annoying API-wise and used more stack space. "double" was a bit wacky w.r.t rounding in the past, so now we'll switch to using a 64-bit type. Unsigned 64-bit integer is able to give us over nearly 585 years of range with nanoseconds. This range is good enough for the Linux kernel internal time representation, so it ought to be good enough for us. This reduces the stack usage of functions while GVL is held (and thus subject to marking) on x86-64 Linux (with ppoll): rb_wait_for_single_fd 120 => 104 do_select 120 => 88 [ruby-core:88582] [Misc #15014] git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-21thread*.c: replace GetMutexPtr with mutex_ptrnormal
Following ko1's lead in r59192, this gets rid of non-obvious assignments which happen inside macros. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-20thread*.c: avoid unnecessary initialization for list_for_each_safenormal
According to r52446, it is only necessary for the current item (@i), not the `@nxt` parameter for list_for_each_safe. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-19thread_sync.c (rb_condvar_initialize): remove extra semicolonnormal
Oops :x git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-19thread_sync.c (rb_mutex_sleep): disable interrupt checking in ensurenormal
This is needed to reliably fix ConditionVariable#wait on Thread#kill [Bug #14999] because there is still a chance an interrupt could fire and prevent lock acquisition after an ensure statement. Arguably, rb_mutex_lock itself should be uninterruptible, but that already prevents bootstraptest/test_thread.rb from completing and probably breaks existing use cases. For reference, POSIX expressly forbids EINTR from pthread_mutex_lock. [ruby-core:88556] [Bug #14999] git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-19thread_sync.rb (rb_condvar_wait): golf out unnecessary variablesnormal
GCC is smart enough to optimize these away, but my attention span is too short :{ git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-19Revert "thread_sync.c (rb_mutex_sleep): skip interrupt check before sleep"normal
This reverts commit 2e420b8b99db4a5b81e2deda1ca386d59ad6bcba (r64464) git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-18thread_sync.c (rb_mutex_sleep): skip interrupt check before sleepnormal
We do not want to risk switching threads before going to sleep because it can cause unexpected wakeups and put us in an unexpected state when used with ConditionVariable. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-18Revert r64441eregon
* This reverts commit 647fc1227a4146ecbfeb0d59358abc8d99cd8ae6: "thread_sync.c (rb_mutex_synchronize): only unlock if we own the mutex" * Let's try to preserve the semantics of always being locked inside Mutex#synchronize, even if an exception interrupts ConditionVariable#wait. * As discussed on [Bug #14999]. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-18thread_sync.c (rb_mutex_synchronize): only unlock if we own the mutexnormal
If an exception is raised inside Mutex#sleep (via ConditionVariable#wait), we cannot guarantee we can own the mutex in the ensure callback. However, who owns the mutex at that point does not matter. What matters is the Mutex is usable after an exception occurs. * thread_sync.c (rb_mutex_synchronize): only unlock if we own the mutex * spec/ruby/library/conditionvariable/wait_spec.rb: only test lock usability after thread kill. Who owns the lock at any particular moment is an implementation detail which we cannot easily guarantee. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-18Revert "thread_sync.c (do_sleep): avoid thread-switch/interrupt check"normal
This reverts commit d7ddbff2954ba22b71bdfeba4b94e1c4fb91efb0 (r64436) Seems worthless at preventing CI failures git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-18thread_sync.c (do_sleep): avoid thread-switch/interrupt checknormal
Calling rb_mutex_sleep directly should avoid thread-switching/interrupt checking which can lead to occasional failures. Unfortunately, this means overriding Mutex#sleep is no longer supported. Will let this commit run for a bit see if CI failures from ConditionVariable specs continue... cf. [ruby-core:88524] [Bug #14999] git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-16thread_sync.c (rb_mutex_lock): acquire lock before being killednormal
We (the thread acquiring the mutex) need to acquire the mutex before being killed to work with ConditionVariable#wait. Thus we reinstate the acquire-immediately-after-sleeping logic from pre-r63711 while still retaining the acquire-after-checking-for-interrupts logic from r63711. This regression was introduced in commit 501069b8a4013f2e3fdde35c50e9527ef0061963 (r63711) ("thread_sync.c (rb_mutex_lock): fix deadlock") for [Bug #14841] [ruby-core:88503] [Bug #14999] [Bug #14841] git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-07-25[Doc] Recover example about Queuetenderlove
`trunk@42862` dropped example's last line. This brings no output. ```queue_example1.rb queue = producer = do 5.times do |i| sleep rand(i) # simulate expense queue << i puts "#{i} produced" end end consumer = do 5.times do |i| value = queue.pop sleep rand(i/2) # simulate expense puts "consumed #{value}" end end ``` ```queue_example2.rb queue = producer = do 5.times do |i| sleep rand(i) # simulate expense queue << i puts "#{i} produced" end end consumer = do 5.times do |i| value = queue.pop sleep rand(i/2) # simulate expense puts "consumed #{value}" end end consumer.join ``` $ ruby queue_example1.rb $ $ ruby queue_example2.rb 0 produced 1 produced consumed 0 consumed 1 2 produced consumed 2 3 produced consumed 3 4 produced consumed 4 $ Co-Authored-By: Sanemat <> git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* include/ruby/ruby.h (UNREACHABLE_RETURN): UNREACHABLE at the end of non-void functions. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-06-22thread_sync.c (rb_mutex_lock): fix deadlocknormal
* thread_sync.c (rb_mutex_lock): fix deadlock [ruby-core:87467] [Bug #14841] git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-04-30thread_sync.c (condvar_ptr): reset fork_gen after forkingnormal
Otherwise the condition variable waiter list will always be empty, which is wrong :x [Bug #14725] [Bug #14634] git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-04-28thread_sync.c: remove "volatile" qualifiersnormal
I may store ->ec in rb_mutex_t instead of ->th to support green thread. For now, "volatile" is useless for thread-safety anyways and we're not dealing with *jmp or signals with mutex. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-04-28thread_sync.c: remove unused list_headsnormal
I forgot to clean these up in r63215 * thread_sync.c (szqueue_list, queue_list, condvar_list): remove git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-04-20thread_sync: redo r62934 to use fork_gennormal
Instead of maintaining linked-lists to store all rb_queue/rb_szqueue/rb_condvar structs; store only a fork_gen serial number to simplify management of these items. This reduces initialization costs and avoids the up-front cost of resetting all Queue/SizedQueue/ConditionVariable objects at fork while saving 8 bytes per-structure on 64-bit. There are no savings on 32-bit. * thread.c (rb_thread_atfork_internal): remove rb_thread_sync_reset_all call * thread_sync.c (rb_thread_sync_reset_all): remove * thread_sync.c (queue_live): remove * thread_sync.c (queue_free): remove * thread_sync.c (struct rb_queue): s/live/fork_gen/ * thread_sync.c (queue_data_type): use default free * thread_sync.c (queue_alloc): remove list_add * thread_sync.c (queue_fork_check): new function * thread_sync.c (queue_ptr): call queue_fork_check * thread_sync.c (szqueue_free): remove * thread_sync.c (szqueue_data_type): use default free * thread_sync.c (szqueue_alloc): remove list_add * thread_sync.c (szqueue_ptr): check fork_gen via queue_fork_check * thread_sync.c (struct rb_condvar): s/live/fork_gen/ * thread_sync.c (condvar_free): remove * thread_sync.c (cv_data_type): use default free * thread_sync.c (condvar_ptr): check fork_gen * thread_sync.c (condvar_alloc): remove list_add [ruby-core:86316] [Bug #14634] git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-04-14thread_sync.c: [DOC] fix typostomar
git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-04-09offsetof(type, is (arguably) a GCCismshyouhei
clang -Wextended-offsetof warns this line. CF: git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-03-27thread_sync.c: avoid reaching across stacks of dead threadsnormal
rb_ensure is insufficient cleanup for fork and we must reinitialize all waitqueues in the child process. Unfortunately this increases the footprint of ConditionVariable, Queue and SizedQueue by 8 bytes on 32-bit (16 bytes on 64-bit). [ruby-core:86316] [Bug #14634] git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-03-05thread.c: reset waitq of keeping mutexes in childnormal
We must not maintain references to threads in the parent process in any mutexes held by the child process. * thread_sync.c (rb_mutex_cleanup_keeping_mutexes): new function * thread.c (rb_thread_atfork): cleanup keeping mutexes [ruby-core:85940] [Bug #14578] Fixes: r58604 (commit 3586c9e0876e784767a1c1adba9ebc2499fa0ec2) ("reduce rb_mutex_t size from 160 to 80 bytes on 64-bit") git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-23[DOC] missing docs at toplevelnobu
git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-16no ID cache in Init functionsnobu
Init functions are called only once, cache is useless. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-07thread.c: favor timespec internallynormal
This results in fewer conversion on common modern systems with support for clock_gettime, pthread_cond_timedwait and ppoll. gettimeofday is declared obsolete by POSIX.1-2008, so it is yet another reason to move away from it. This also appears to result in the reduction of compatibility code required for dealing with inconsistent implementations of "struct timeval".tv_sec In the future, this will also result in fewer conversions for kqueue and pselect if we elect to use them. [ruby-core:85416] [Feature #14452] git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-01-18raise_closed_queue_error marked as NORETURNshyouhei
git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-12-19thread_sync.c: fix rdocnobu
* thread_sync.c (define_thread_class): hide rb_define_class_under from rdoc, so that fake code to teach rdoc takes effect. * thread_sync.c (Init_thread_sync): teach rdoc Mutex. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-11-06move rb_thread_t::interrupt_flag and maskko1
to rb_execution_context_t. * vm_core.h (rb_thread_t): move `rb_thread_t::interrupt_flag` and `rb_thread_t::interrupt_mask` to rb_execution_context_t. RUBY_VM_CHECK_INTS() accepts `ec` instead of `th`. * cont.c (rb_fiber_terminate): to propagate interrupt information, add new parameter `need_interrupt`. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-10-08Remove unnecessary `require 'thread'`kazu
git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* eval_intern.h (UNALIGNED_MEMBER_ACCESS): suppress address-of-packed-member warnings by clang 4.0. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-06-23thread_sync.c: fix documentation for Queue#closenormal
When Queue#closed? is true, using push/enq/<< will raise an exception, and not return nil. * thread_sync.c: fix documentation for Queue#close Thanks to John Anderson. [ruby-core:81749] [Misc #13673] git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-05-19thread_sync.c: rewrite the rest using using ccan/listnormal
The performance improvement increases as the number of waiters increases, due to avoiding the O(n) behavior of rb_ary_delete on the waiting thread. Uncontended queues and condition variables performance is not altered significantly. Function entry cost is slightly increased for ConditionVariable, since the data pointer is separately allocated and not embedded into the RVALUE slot. [ruby-core:81235] [Feature #13552] name |trunk |built ----------------------|------:|------: vm_thread_condvar1 | 0.858| 0.858 vm_thread_condvar2 | 1.003| 0.804 vm_thread_queue | 0.131| 0.129 vm_thread_sized_queue | 0.265| 0.251 vm_thread_sized_queue2| 0.892| 0.859 vm_thread_sized_queue3| 0.879| 0.845 vm_thread_sized_queue4| 0.599| 0.486 Speedup ratio: compare with the result of `trunk' (greater is better) name |built ----------------------|------: vm_thread_condvar1 | 0.999 vm_thread_condvar2 | 1.246 vm_thread_queue | 1.020 vm_thread_sized_queue | 1.057 vm_thread_sized_queue2| 1.039 vm_thread_sized_queue3| 1.041 vm_thread_sized_queue4| 1.233 git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-05-19thread_sync.c: rename mutex_waiter struct to sync_waiternormal
We will reuse this struct for ConditionVariable, Queue, and SizedQueue, so it is no longer Mutex-specific. git-svn-id: svn+ssh:// b2dd03c8-39d4-4d8f-98ff-823fe69b080e