summaryrefslogtreecommitdiff
path: root/ractor.c
Commit message (Collapse)AuthorAgeFilesLines
* Implement Hash AR tables on VWAPeter Zhu2023-05-171-5/+0
|
* add new debug log line on `rb_ractor_terminate_all`Koichi Sasada2023-04-261-0/+2
| | | | to leave the trace.
* show debug log for `ractor_terminal_interrupt_all`Koichi Sasada2023-03-301-1/+4
|
* `rb_ractor_thread_list()` only for current ractorKoichi Sasada2023-03-301-23/+12
| | | | so that no need to lock the ractor.
* `rb_current_ractor_raw(b)`Koichi Sasada2023-03-301-4/+5
| | | | | | `rb_current_ractor()` expects it has valid `ec` and `r`. `rb_current_ractor_raw()` with a parameter `false` allows to return NULL if `ec` is not available.
* Use an st table for "too complex" objectsAaron Patterson2023-03-201-21/+22
| | | | | | | | | | st tables will maintain insertion order so we can marshal dump / load objects with instance variables in the same order they were set on that particular instance [ruby-core:112926] [Bug #19535] Co-Authored-By: Jemma Issroff <jemmaissroff@gmail.com>
* Fix -Wclobbered warning from gcc 12Nobuyoshi Nakada2023-03-191-2/+2
| | | | | | | | | | | A variable modified in `EXEC_TAG` block should be `volatile`. ``` ractor.c: In function 'ractor_try_yield': ractor.c:1251:97: warning: argument 'obj' might be clobbered by 'longjmp' or 'vfork' [-Wclobbered] 1251 | ractor_try_yield(rb_execution_context_t *ec, rb_ractor_t *cr, struct rb_ractor_queue *ts, VALUE obj, VALUE move, bool exc, bool is_will) | ~~~~~~^~~ ```
* Fix indirect counter incrementNobuyoshi Nakada2023-03-151-1/+1
| | | | | `*pcnt++` just dereferences `pcnt` then increments the local variable, but has no side effect.
* s/mjit/rjit/Takashi Kokubun2023-03-061-2/+2
|
* s/MJIT/RJIT/Takashi Kokubun2023-03-061-3/+3
|
* Stop exporting symbols for MJITTakashi Kokubun2023-03-061-3/+3
|
* fix timing bugKoichi Sasada2023-03-031-7/+16
| | | | | | | | | | | | | | | | | | | passing will and closing notification can conflict and `Ractor::Selector#empty?` can return wrong answer. This patch fix it. ``` s = Ractor::Selector.new s.add Ractor.new{10} s.add Ractor.new{20} r, v = s.wait vs = [] vs << v r, v = s.wait vs << v [*vs.sort, s.empty?] #=> "[10, 20, false]" (expected "[10, 20, true]") ```
* `Ractor::Selector#empty?`Koichi Sasada2023-03-031-1/+14
| | | | | | It returns the waiting set is empty or not. Also add Ractor::Selector's tests.
* Rewrite Ractor synchronization mechanismKoichi Sasada2023-03-021-609/+985
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch rewrites Ractor synchronization mechanism, send/receive and take/yield. * API * Ractor::Selector is introduced for lightweight waiting for many ractors. * Data structure * remove `struct rb_ractor_waiting_list` and use `struct rb_ractor_queue takers_queue` to manage takers. * remove `rb_ractor_t::yield_atexit` and use `rb_ractor_t::sync::will_basket::type` to check the will. * add `rb_ractor_basket::p.take` to represent a taking ractor. * Synchronization protocol * For the Ractor local GC, `take` can not make a copy object directly so ask to generate the copy from the yielding ractor. * The following steps shows what `r1.take` does on `r0`. * step1: (r0) register `r0` into `r1`'s takers. * step2: (r0) check `r1`'s status and wakeup r0 if `r1` is waiting for yielding a value. * step3: (r0) sleep until `r1` wakes up `r0`. * The following steps shows what `Ractor.yield(v)` on `r1`. * step1: (r1) check first takers of `r1` and if there is (`r0`), make a copy object of `v` and pass it to `r0` and wakes up `r0`. * step2: (r1) if there is no taker ractors, sleep until another ractor try to take.
* `ractor_queue_enq/deq` doesn't need `rq` paramKoichi Sasada2023-02-151-6/+7
| | | | `rq` is always `r`'s queue.
* Merge gc.h and internal/gc.hMatt Valentine-House2023-02-091-1/+1
| | | | [Feature #19425]
* Remove rb_hash_st_tablePeter Zhu2023-01-311-2/+2
| | | | It's a duplicate of RHASH_ST_TABLE.
* MJIT: Cancel all on disastrous situations (#7019)Takashi Kokubun2022-12-241-0/+2
| | | | | | | | | | I noticed this while running test_yjit with --mjit-call-threshold=1, which redefines `Integer#<`. When Ruby is monkey-patched, MJIT itself could be broken. Similarly, Ruby scripts could break MJIT in many different ways. I prepared the same set of hooks as YJIT so that we could possibly override it and disable it on those moments. Every constant under RubyVM::MJIT is private and thus it's an unsupported behavior though.
* Transition complex objects to "too complex" shapeJemma Issroff2022-12-151-11/+72
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When an object becomes "too complex" (in other words it has too many variations in the shape tree), we transition it to use a "too complex" shape and use a hash for storing instance variables. Without this patch, there were rare cases where shape tree growth could "explode" and cause performance degradation on what would otherwise have been cached fast paths. This patch puts a limit on shape tree growth, and gracefully degrades in the rare case where there could be a factorial growth in the shape tree. For example: ```ruby class NG; end HUGE_NUMBER.times do NG.new.instance_variable_set(:"@unique_ivar_#{_1}", 1) end ``` We consider objects to be "too complex" when the object's class has more than SHAPE_MAX_VARIATIONS (currently 8) leaf nodes in the shape tree and the object introduces a new variation (a new leaf node) associated with that class. For example, new variations on instances of the following class would be considered "too complex" because those instances create more than 8 leaves in the shape tree: ```ruby class Foo; end 9.times { Foo.new.instance_variable_set(":@uniq_#{_1}", 1) } ``` However, the following class is *not* too complex because it only has one leaf in the shape tree: ```ruby class Foo def initialize @a = @b = @c = @d = @e = @f = @g = @h = @i = nil end end 9.times { Foo.new } `` This case is rare, so we don't expect this change to impact performance of most applications, but it needs to be handled. Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org>
* Using UNDEF_P macroS-H-GAMELINKS2022-11-161-14/+14
|
* [Bug #19081] Show the caller location in warning for RactorNobuyoshi Nakada2022-10-261-6/+0
| | | | | | | The internal location in ractor.rb is not usefull at all. ``` $ ruby -e 'Ractor.new {}' <internal:ractor>:267: warning: Ractor is experimental, ... ```
* More precisely iterate over Object instance variablesAaron Patterson2022-10-151-2/+2
| | | | | | Shapes provides us with an (almost) exact count of instance variables. We only need to check for Qundef when an IV has been "undefined" Prefer to use ROBJECT_IV_COUNT when iterating IVs
* obj_refer_only_sharables_p_i: need derefernce卜部昌平2022-09-211-1/+1
| | | | | | Clang says "warning: variable 'pcnt' set but not used" here. In fact it doesn't. The intention is clear that we want to increment cnt, not pcnt. Adding a * mark solves everything.
* Disable Ractor check on 32bit architecturesAaron Patterson2022-08-241-0/+4
| | | | | | | | | | | | | Ractor verification requires storing the ractor id in the top 32 bits of the object header. Unfortunately 32 bit machines only have 32 bits in the object header. The verification code has a 32 bit left shift which doesn't work on i686 and will clobber existing flags. This commit disables the verification code on i686 since i686 will crash if it's enabled. Co-Authored-By: John Hawthorn <john@hawthorn.email> Co-Authored-By: Jemma Issroff <jemmaissroff@gmail.com>
* Add "rb_" prefixes to toplevel enum definitionsYusuke Endoh2022-07-221-7/+7
| | | | ... as per ko1's request.
* Expand tabs [ci skip]Takashi Kokubun2022-07-211-2/+2
| | | | [Misc #18891]
* rename thread internal namingKoichi Sasada2022-04-221-8/+2
| | | | | | | | | | | | | | | | | | | | | | | | Now GVL is not process *Global* so this patch try to use another words. * `rb_global_vm_lock_t` -> `struct rb_thread_sched` * `gvl->owner` -> `sched->running` * `gvl->waitq` -> `sched->readyq` * `rb_gvl_init` -> `rb_thread_sched_init` * `gvl_destroy` -> `rb_thread_sched_destroy` * `gvl_acquire` -> `thread_sched_to_running` # waiting -> ready -> running * `gvl_release` -> `thread_sched_to_waiting` # running -> waiting * `gvl_yield` -> `thread_sched_yield` * `GVL_UNLOCK_BEGIN` -> `THREAD_BLOCKING_BEGIN` * `GVL_UNLOCK_END` -> `THREAD_BLOCKING_END` * removed * `rb_ractor_gvl` * `rb_vm_gvl_destroy` (not used) There are GVL functions such as `rb_thread_call_without_gvl()` yet but I don't have good name to replace them. Maybe GVL stands for "Greate Valuable Lock" or something like that.
* Get rid of type-punning pointer castsNobuyoshi Nakada2022-04-071-12/+12
|
* ractor.c: Add a helper function to ensure the context is a main ractorYusuke Endoh2022-03-301-0/+8
|
* Prefix ccan headers (#4568)Nobuyoshi Nakada2022-03-301-9/+9
| | | | | | | | | | | | | * Prefixed ccan headers * Remove unprefixed names in ccan/build_assert * Remove unprefixed names in ccan/check_type * Remove unprefixed names in ccan/container_of * Remove unprefixed names in ccan/list Co-authored-by: Samuel Williams <samuel.williams@oriontransfer.co.nz>
* Fix Ractor.receive_if + rb_vm_barrier() deadlockAlan Wu2022-03-281-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I have this scripts that deadlocks after about 5 minutes if I repeatedly run it with a shell loop: ```ruby $VERBOSE = nil lamb = ->(main, gc) do gc.verify_internal_consistency gc.verify_internal_consistency main << 1 gc.verify_internal_consistency gc.verify_internal_consistency main << 2 gc.verify_internal_consistency gc.verify_internal_consistency main << 3 gc.verify_internal_consistency gc.verify_internal_consistency end lamb[[], GC] lamb[[], GC] r = Ractor.new Ractor.current, GC, &lamb a = [] a << Ractor.receive_if{|msg| msg == 2} a << Ractor.receive_if{|msg| msg == 3} a << Ractor.receive_if{|msg| msg == 1} ``` Shell loop: ```shell while ./miniruby deadlock.rb; do date; done ``` Once it locks up, CTRL-C doesn't interrupt the process which led me to infer `receive_if` is looping in `ractor_receive_if()` without checking for interrupts. This can be confirmed by attaching a debugger to the deadlocked miniruby. The deadlock has one thread looping in `receive_if` and another waiting in `rb_vm_barrier()`. The barrier relies on interrupt checking to finish. Theoretically speaking the `rb_vm_barrier()` could come from one thread naturally starting GC. We found this while developing YJIT but it dead locks running with YJIT disabled. YJIT currently relies on `rb_vm_barrier()` to synchronize before changing memory protection. This diff adds an interrupt check in the loop in `Ractor#receive_if` which seems to fix the deadlock. In addition, this commit allows interrupting the following single ractor script with CTRL-C. ```shell ruby -e 'Ractor.current.send(3); Ractor.receive_if { false }' ```
* `USE_RUBY_DEBUG_LOG` doesn't check `RUBY_DEVEL`Koichi Sasada2021-12-291-1/+1
| | | | | | | | `USE_RUBY_DEBUG_LOG` was only defined when `RUBY_DEVEL` is defined. This patch removes this dependency (`USE_RUBY_DEBUG_LOG` is defined independently from `RUBY_DEVEL`). Do not commit a patch which enables `USE_RUBY_DEBUG_LOG`.
* Suppress undef warnings for USE_RUBY_DEBUG_LOGNobuyoshi Nakada2021-12-251-1/+1
|
* Yet Another Ruby JIT!Jose Narvaez2021-10-201-2/+2
| | | | Renaming uJIT to YJIT. AKA s/ujit/yjit/g.
* uJIT: Implement opt_getinlinecacheAlan Wu2021-10-201-0/+2
| | | | | | | | | | | | | | | | | * ujit: implement opt_getinlinecache Aggressively bet that writes to constants don't happen and invalidate all opt_getinlinecache blocks on any and all constant writes. Use alignment padding on block_t to track this assumption. No change to sizeof(block_t). * Fix compile warnings when not RUBY_DEBUG * Fix reversed condition * Switch to st_table to keep track of assumptions Co-authored-by: Aaron Patterson <aaron.patterson@gmail.com> Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
* Use `RUBY_FUNCTION_NAME_STRING` for old Visual C++Nobuyoshi Nakada2021-10-201-3/+3
| | | | | Probably `__func__` is supported since Visual C++ 2015 (= 14.0, `_MSC_VER` = 1900).
* Cast to void pointer for `%p` in commented out code [ci skip]Nobuyoshi Nakada2021-10-201-4/+5
|
* Supress `warning: data argument not used by format string [-Wformat-extra-args]`Kazuhiro NISHIYAMA2021-10-201-4/+4
|
* Cast to void pointer to suppress -Wformat-pedantic in RUBY_DEBUG_LOGNobuyoshi Nakada2021-10-031-1/+1
|
* [Bug #18117] Fix Ractor race condition with GCPeter Zhu2021-08-241-2/+10
| | | | | | | | | | | | | | rb_objspace_reachable_objects_from requires that the GC not be active. Since the Ractor barrier is not executed for incremental sweeping, Ractor may call rb_objspace_reachable_objects_from after sweeping has started to share objects. This causes a crash that looks like the following: ``` <internal:ractor>:627: [BUG] rb_objspace_reachable_objects_from() is not supported while during_gc == true ``` Co-authored-by: Vinicius Stock <vinicius.stock@shopify.com>
* [Bug #18014] Fix memory leak in GC when using RactorsPeter Zhu2021-07-151-0/+3
| | | | | | | When a Ractor is removed, the freelist in the Ractor cache is not returned to the GC, leaving the freelist permanently lost. This commit recycles the freelist when the Ractor is destroyed, preventing a memory leak from occurring.
* Evacuate transient heap when enabling ractorseileencodes2021-06-231-0/+6
| | | | | | | | | | | If the GC has been disabled we need to re-enable it so we can evacuate the transient heap. Fixes https://bugs.ruby-lang.org/issues/17985 [Bug #17985] [ruby-core:104260] Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
* Enable VM_ASSERT in --jit CIs (#4543)Takashi Kokubun2021-06-011-3/+3
|
* Fix some typos by spell checkerRyuta Kamizono2021-04-261-2/+2
|
* Moved locking VM to an atomic operationNobuyoshi Nakada2021-03-131-6/+2
|
* Make Ractor stdio belonging to the Ractor [Bug #17672]Nobuyoshi Nakada2021-03-071-9/+0
| | | | | Defer making ractor stdio until ractor started. Before ractor started, created objects belong to the caller ractor instead of the created ractor.
* Ractor.allocate should not be allowedKoichi Sasada2021-02-181-0/+2
| | | | | Ractor.allocate and Ractor#dup should not be allowed like Thread. [Bug #17642]
* fix Ractor.yield(obj, move: true)Koichi Sasada2021-01-221-15/+58
| | | | | | | | | | | | | | | | Ractor.yield(obj, move: true) and Ractor.select(..., yield_value: obj, move: true) tried to yield a value with move semantices, but if the trial is faild, the obj should not become a moved object. To keep this rule, `wait_moving` wait status is introduced. New yield/take process: (1) If a ractor tried to yield (move:true), make taking racotr's wait status `wait_moving` and make a moved object by `ractor_move(obj)` and wakeup taking ractor. (2) If a ractor tried to take a message from a ractor waiting fo yielding (move:true), wakeup the ractor and wait for (1).
* alen should be actions number on ractor_select()Koichi Sasada2021-01-221-7/+6
| | | | | alen was number of rs, but it should be actions number (taking ractors + receiving + yielding).
* use ractor_wakeup()Koichi Sasada2021-01-221-28/+27
| | | | Use ractor_wakeup() for same code.