| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
| |
for an MJIT worker thread. We can't do it because its GET_EC() returns
NULL.
|
|
|
|
|
|
| |
Same as 8247b8edde, should not use rb_str_modify() here.
https://bugs.ruby-lang.org/issues/17343#change-88858
|
|
|
|
|
|
|
|
|
|
|
| |
C extensions can violate the ractor-safety, so only ractor-safe
C extensions (C methods) can run on non-main ractors.
rb_ext_ractor_safe(true) declares that the successive
defined methods are ractor-safe. Otherwiwze, defined methods
checked they are invoked in main ractor and raise an error
if invoked at non-main ractors.
[Feature #17307]
|
|
|
|
|
|
|
|
|
|
|
| |
ractor_copy() used rb_ary_modify() to make sure this array is not
sharing anything, but it also checks frozen flag. So frozen arrays
raises an error. To solve this issue, this patch introduces new
function rb_ary_cancel_sharing() which makes sure the array does not
share another array and it doesn't check frozen flag.
[Bug #17343]
A test is quoted from https://github.com/ruby/ruby/pull/3817
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
To manage ractor-local data for C extension, the following APIs
are defined.
* rb_ractor_local_storage_value_newkey
* rb_ractor_local_storage_value
* rb_ractor_local_storage_value_set
* rb_ractor_local_storage_ptr_newkey
* rb_ractor_local_storage_ptr
* rb_ractor_local_storage_ptr_set
At first, you need to create a key of storage by
rb_ractor_local_(value|ptr)_newkey().
For ptr storage, it accepts the type of storage,
how to mark and how to free with ractor's lifetime.
rb_ractor_local_storage_value/set are used to access a VALUE
and rb_ractor_local_storage_ptr/set are used to access a pointer.
random.c uses this API.
|
|
|
|
| |
Followup to #3823
|
| |
|
| |
|
|
|
|
| |
default_rand can points a Bignum seed, so it should be marked.
|
|
|
|
|
|
|
|
|
|
| |
Random generators are not Ractor-safe, so we need to prepare
per-ractor default random genearators. This patch set
`Random::DEFAULT = Randm` (not a Random instance, but the Random
class) and singleton methods like `Random.rand()` use a per-ractor
random generator.
[Feature #17322]
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
To make some kind of Ractor related extensions, some functions
should be exposed.
* include/ruby/thread_native.h
* rb_native_mutex_*
* rb_native_cond_*
* include/ruby/ractor.h
* RB_OBJ_SHAREABLE_P(obj)
* rb_ractor_shareable_p(obj)
* rb_ractor_std*()
* rb_cRactor
and rm ractor_pub.h
and rename srcdir/ractor.h to srcdir/ractor_core.h
(to avoid conflict with include/ruby/ractor.h)
|
|
|
|
|
| |
If outgoing_port is closed, Ractor.yield never successes.
[Bug #17310]
|
|
|
|
|
| |
If a terminating ractor has child threads, then kill all child
threads.
|
|
|
|
|
|
|
|
|
| |
T_DATA objects can refer unshareable objects and they should be
copied recursively, however there is no way to replace with copied
unshareable objects. However, if a T_DATA object refers only
shareable objects, there is no need to replace. So this kind of
T_DATA object (such as Time, Dir, File::Status and so on) can be
sent by Ractor.send.
|
| |
|
|
|
|
| |
Now copying objects do not need marshal protocol.
|
|
|
|
| |
This patch allows to move more data types.
|
|
|
|
|
|
|
|
|
|
| |
`r = Ractor.new{ expr }` generates the block return value from `expr`
and we can get this value by `r.take`. Ractor.yield and Ractor#take
passing values by copying on default. However, the block return value
(we named it "will" in the code) is not referred from the Ractor
because the Ractor is already dead. So we can pass the reference
of "will" to another ractor without copying. We can apply same story
for the propagated exception.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Ractor.make_shareable() supports Proc object if
(1) a Proc only read outer local variables (no assignments)
(2) read outer local variables are shareable.
Read local variables are stored in a snapshot, so after making
shareable Proc, any assignments are not affeect like that:
```ruby
a = 1
pr = Ractor.make_shareable(Proc.new{p a})
pr.call #=> 1
a = 2
pr.call #=> 1 # `a = 2` doesn't affect
```
[Feature #17284]
|
| |
|
| |
|
|
|
|
|
|
| |
* create rec check hash lazily
* do not pass *data pointer for enter/leave function because
it is not used.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Introduce new method Ractor.make_shareable(obj) which tries to make
obj shareable object. Protocol is here.
(1) If obj is shareable, it is shareable.
(2) If obj is not a shareable object and if obj can be shareable
object if it is frozen, then freeze obj. If obj has reachable
objects (rs), do rs.each{|o| Ractor.make_shareable(o)}
recursively (recursion is not Ruby-level, but C-level).
(3) Otherwise, raise Ractor::Error. Now T_DATA is not a shareable
object even if the object is frozen.
If the method finished without error, given obj is marked as
a sharable object.
To allow makng a shareable frozen T_DATA object, then set
`RUBY_TYPED_FROZEN_SHAREABLE` as type->flags. On default,
this flag is not set. It means user defined T_DATA objects are
not allowed to become shareable objects when it is frozen.
You can make any object shareable by setting FL_SHAREABLE flag,
so if you know that the T_DATA object is shareable (== thread-safe),
set this flag, at creation time for example. `Ractor` object is one
example, which is not a frozen, but a shareable object.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Some global variables should be used from non-main Ractors.
[Bug #17268]
```ruby
# ractor-local (derived from created ractor): debug
'$DEBUG' => $DEBUG,
'$-d' => $-d,
# ractor-local (derived from created ractor): verbose
'$VERBOSE' => $VERBOSE,
'$-w' => $-w,
'$-W' => $-W,
'$-v' => $-v,
# process-local (readonly): other commandline parameters
'$-p' => $-p,
'$-l' => $-l,
'$-a' => $-a,
# process-local (readonly): getpid
'$$' => $$,
# thread local: process result
'$?' => $?,
# scope local: match
'$~' => $~.inspect,
'$&' => $&,
'$`' => $`,
'$\'' => $',
'$+' => $+,
'$1' => $1,
# scope local: last line
'$_' => $_,
# scope local: last backtrace
'$@' => $@,
'$!' => $!,
# ractor local: stdin, out, err
'$stdin' => $stdin.inspect,
'$stdout' => $stdout.inspect,
'$stderr' => $stderr.inspect,
```
|
| |
|
|
|
|
| |
* Keep Ractor#recv/Ractor.recv as an alias for now.
|
| |
|
|
|
|
|
| |
A frozen Struct object which refers to shareable objects should be
shareable.
|
|
|
|
|
| |
Ractor.yield should raise Ractor::ClosedError if current Ractor's
outgoing-port is closed.
|
|
|
|
|
| |
If an T_OBJECT object is frozen and all ivars are shareable,
the object should be shareable.
|
|
|
|
|
|
| |
Ractor#close_outgoing should cancel waiting Ractor.yield. However,
yield a value by the Ractor's block should not cancel (to recognize
terminating Ractor, introduce rb_ractor_t::yield_atexit flag).
|
|
|
|
|
| |
We observed mark miss on this point so we add RB_GC_GUARD() to
avoid wrong free.
|
| |
|
| |
|
| |
|
|
|
|
|
| |
signal can interrupt Ractor.select, but if there is no exception,
Ractor.select should restart automatically.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
| |
rb_ractor_main_p() need to access to the ractor pointer in TLS.
However it is slow operation so that we need to skip this check
if it is not multi-ractor mode (!ruby_multi_ractor).
This performance regression is pointed at
https://bugs.ruby-lang.org/issues/17100#note-27
|
| |
|
|
This commit introduces Ractor mechanism to run Ruby program in
parallel. See doc/ractor.md for more details about Ractor.
See ticket [Feature #17100] to see the implementation details
and discussions.
[Feature #17100]
This commit does not complete the implementation. You can find
many bugs on using Ractor. Also the specification will be changed
so that this feature is experimental. You will see a warning when
you make the first Ractor with `Ractor.new`.
I hope this feature can help programmers from thread-safety issues.
|