Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multithreading #8112

Merged
merged 51 commits into from Sep 2, 2019
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
8dc5c8f
LibEvent MT support
waj Aug 13, 2019
b52bfb7
Enqueue fibers in worker threads
waj May 29, 2019
de20236
Unbuffered channels can be used with MT runtime
bcardiff Jun 7, 2019
6c11306
Improve initialization of worker threads to eliminate race conditions…
bcardiff Jun 7, 2019
6223e99
Faster SpinLock
waj Jun 3, 2019
a200f4c
Use RWLock for GC
bcardiff Jun 7, 2019
9fcd530
Refactor worker selection algorithm
waj Jun 4, 2019
a2a8fc4
Fix unbuffered channel not allowing to receive value right before close
waj Jun 4, 2019
bbf8afc
Support MT in buffered channels
waj Jun 4, 2019
9b2150e
Use different IO event objects for each thread
bcardiff Jun 7, 2019
ea4ae09
Channel rebuilt and unified into a single class for buffered/unbuffer…
waj Jul 12, 2019
e0f4760
Adding names to core fibers
waj Jul 12, 2019
95eb0f6
Disable scheduling based on thread load for now (until the load calcu…
waj Jul 12, 2019
8673993
Include small stress test of select with send/receive in multiple fibers
waj Jul 15, 2019
4916b5d
Fix deadlock when the same channel is used more than once in the same…
waj Jul 15, 2019
bd5f382
Added spec to verify priority within select statement
waj Jul 15, 2019
176b886
Thread safe mutex
waj Jul 15, 2019
da6a2ea
Refactor Worker into Scheduler
waj Jul 17, 2019
8e06b98
Moved Fiber#restore logic into Scheduler.enqueue. Removed Scheduler#e…
waj Jul 17, 2019
8d2282e
Performance improvements for cross thread fiber enqueue
waj Jul 18, 2019
5ac71b6
Added flag to spawn threads within the same thread
waj Jul 19, 2019
dd845b3
Removed NullLock. Now SpinLock doesn't do anything in single thread m…
waj Jul 19, 2019
975c08f
Define UNIX_EPOCH using a protected and unsafe constructor with a har…
waj Jul 25, 2019
7011122
Run the codegen in a single thread for now (fork doesn't work with mu…
waj Jul 25, 2019
07699e9
Fix some issues with Channel.select types
waj Jul 31, 2019
3a9fa4e
Fix: channel can receive data already stored after closing
waj Aug 1, 2019
f544b22
Disable fork in multithread mode
waj Aug 1, 2019
3e45cdb
Fix race condition on Process when more than one IO is specified
waj Aug 1, 2019
573cdc7
Atomically initialize constants and class variables
waj Jul 25, 2019
946c73f
Fix IO operations not being aborted when the IO is closed from anothe…
waj Aug 2, 2019
948dd29
Do not try to get the scheduler from a non worker thread
waj Aug 2, 2019
5b1df7a
Fix UNIXServer spec failing randomly in multithread mode
waj Aug 2, 2019
3ec90a5
Fix "future" spec failing randomly in multithread mode
waj Aug 2, 2019
a9c435e
Fix formatting
waj Aug 23, 2019
9355174
Removed leftovers from an attempt to balance the load of workers
waj Aug 23, 2019
46cf74a
Fixed typo
waj Aug 26, 2019
fea9b92
Removed unused variable
waj Aug 26, 2019
c88cf4a
Give the mutex variable a more meaningful name in StackPool
waj Aug 26, 2019
fbbefd1
Renamed `eb` to `event_loop`. Simplified initialization of event loop…
waj Aug 26, 2019
f106d93
Validate value of CRYSTAL_WORKERS
waj Aug 26, 2019
717454b
Removed unused `dns_base`
waj Aug 26, 2019
9fb746d
Fix crashes on `select` specs in multithread mode
waj Aug 26, 2019
0e201f9
Removed accessor to @@workers in Scheduler
waj Aug 27, 2019
483d945
Refactored IO pipe communication between threads to a separate struct…
waj Aug 27, 2019
e53d58d
Use `class_getter` macro for `Fiber.fibers` and `Thread.threads`
waj Aug 27, 2019
480c610
Styling
waj Aug 27, 2019
f02c822
SpinLock lock/unlock executed outside begin/ensure block
waj Aug 27, 2019
b1c3997
Crystal::ThreadLocalValue can be a struct
waj Aug 27, 2019
3aa75c3
CI: run std_spec with -D preview_mt option
bcardiff Aug 26, 2019
6c6cadd
Avoid dispatch over IO in FiberChannel
waj Aug 27, 2019
e7b9252
Call PAUSE within spin-loops (for x86 architecture)
waj Aug 29, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions spec/compiler/codegen/class_spec.cr
Expand Up @@ -447,6 +447,8 @@ describe "Code gen: class" do

it "allows using self in class scope" do
run(%(
require "prelude"

class Foo
def self.foo
1
Expand Down Expand Up @@ -713,6 +715,8 @@ describe "Code gen: class" do

it "codegens singleton (#718)" do
run(%(
require "prelude"

class Singleton
@@instance = new

Expand Down
24 changes: 20 additions & 4 deletions spec/compiler/codegen/class_var_spec.cr
Expand Up @@ -106,6 +106,8 @@ describe "Codegen: class var" do

it "uses var in class var initializer" do
run(%(
require "prelude"

class Foo
@@var : Int32
@@var = begin
Expand All @@ -128,6 +130,8 @@ describe "Codegen: class var" do

it "reads simple class var before another complex one" do
run(%(
require "prelude"

class Foo
@@var2 : Int32
@@var2 = @@var &+ 1
Expand All @@ -145,6 +149,8 @@ describe "Codegen: class var" do

it "initializes class var of union with single type" do
run(%(
require "prelude"

class Foo
@@var : Int32 | String
@@var = 42
Expand Down Expand Up @@ -196,6 +202,8 @@ describe "Codegen: class var" do

it "initializes dependent constant before class var" do
run(%(
require "prelude"

def foo
a = 1
b = 2
Expand Down Expand Up @@ -233,6 +241,8 @@ describe "Codegen: class var" do

it "doesn't use nilable type for initializer" do
run(%(
require "prelude"

class Foo
@@foo : Int32?
@@foo = 42
Expand All @@ -250,7 +260,9 @@ describe "Codegen: class var" do
end

it "codegens class var with begin and vars" do
run("
run(%(
require "prelude"

class Foo
@@foo : Int32
@@foo = begin
Expand All @@ -265,11 +277,13 @@ describe "Codegen: class var" do
end

Foo.foo
").to_i.should eq(3)
)).to_i.should eq(3)
end

it "codegens class var with type declaration begin and vars" do
run("
run(%(
require "prelude"

class Foo
@@foo : Int32 = begin
a = 1
Expand All @@ -283,7 +297,7 @@ describe "Codegen: class var" do
end

Foo.foo
").to_i.should eq(3)
)).to_i.should eq(3)
end

it "codegens class var with nilable reference type" do
Expand Down Expand Up @@ -338,6 +352,8 @@ describe "Codegen: class var" do

it "gets pointerof class var complex constant" do
run(%(
require "prelude"

z = Foo.foo

class Foo
Expand Down
80 changes: 70 additions & 10 deletions spec/compiler/codegen/const_spec.cr
Expand Up @@ -87,14 +87,18 @@ describe "Codegen: const" do

it "declare constants in right order" do
run(%(
require "prelude"

CONST1 = 1 + 1
CONST2 = true ? CONST1 : 0
CONST2
)).to_i.should eq(2)
end

it "uses correct types lookup" do
run("
run(%(
require "prelude"

module Moo
class B
def foo
Expand All @@ -110,11 +114,13 @@ describe "Codegen: const" do
end

foo
").to_i.should eq(1)
)).to_i.should eq(1)
end

it "codegens variable assignment in const" do
run("
run(%(
require "prelude"

class Foo
def initialize(@x : Int32)
end
Expand All @@ -134,11 +140,13 @@ describe "Codegen: const" do
end

foo
").to_i.should eq(1)
)).to_i.should eq(1)
end

it "declaring var" do
run("
run(%(
require "prelude"

BAR = begin
a = 1
while 1 == 2
Expand All @@ -153,7 +161,7 @@ describe "Codegen: const" do
end

Foo.new.compile
").to_i.should eq(1)
)).to_i.should eq(1)
end

it "initialize const that might raise an exception" do
Expand All @@ -171,7 +179,9 @@ describe "Codegen: const" do
end

it "allows implicit self in constant, called from another class (bug)" do
run("
run(%(
require "prelude"

module Foo
def self.foo
1
Expand All @@ -187,11 +197,13 @@ describe "Codegen: const" do
end

Bar.new.bar
").to_i.should eq(1)
)).to_i.should eq(1)
end

it "codegens two consts with same variable name" do
run("
run(%(
require "prelude"

CONST1 = begin
a = 1
end
Expand All @@ -201,11 +213,13 @@ describe "Codegen: const" do
end

(CONST1 + CONST2).to_i
").to_i.should eq(3)
)).to_i.should eq(3)
end

it "works with variable declared inside if" do
run(%(
require "prelude"

FOO = begin
if 1 == 2
x = 3
Expand All @@ -220,6 +234,8 @@ describe "Codegen: const" do

it "codegens constant that refers to another constant that is a struct" do
run(%(
require "prelude"

struct Foo
X = Foo.new(1)
Y = X
Expand Down Expand Up @@ -281,6 +297,8 @@ describe "Codegen: const" do

it "uses const before declaring it (hoisting)" do
run(%(
require "prelude"

x = CONST

CONST = foo
Expand Down Expand Up @@ -342,6 +360,8 @@ describe "Codegen: const" do

it "gets pointerof constant" do
run(%(
require "prelude"

z = pointerof(FOO).value
FOO = 10
z
Expand All @@ -350,6 +370,8 @@ describe "Codegen: const" do

it "gets pointerof complex constant" do
run(%(
require "prelude"

z = pointerof(FOO).value
FOO = begin
a = 10
Expand Down Expand Up @@ -446,4 +468,42 @@ describe "Codegen: const" do

mod.to_s.should_not contain("CONST")
end

it "synchronizes initialization of constants" do
run(%(
require "prelude"

def foo
v1, v2 = 1, 1
rand(100000..10000000).times do
v1, v2 = v2, v1 + v2
end
v2
end

ch = Channel(Int32).new

10.times do
spawn do
ch.send X
end
end

X = foo

def test(ch)
expected = X

10.times do
if ch.receive != expected
return false
end
end

true
end

test(ch)
)).to_b.should be_true
end
end
2 changes: 2 additions & 0 deletions spec/compiler/codegen/debug_spec.cr
Expand Up @@ -107,6 +107,8 @@ describe "Code gen: debug" do

it "has correct debug location after constant initialization in call with block (#4719)" do
codegen(%(
require "prelude"

fun __crystal_malloc_atomic(size : UInt32) : Void*
x = uninitialized Void*
x
Expand Down
6 changes: 4 additions & 2 deletions spec/compiler/codegen/hooks_spec.cr
Expand Up @@ -115,7 +115,9 @@ describe "Code gen: hooks" do
end

it "does inherited macro before class body" do
run("
run(%(
require "prelude"

class Global
@@x = 123

Expand All @@ -142,7 +144,7 @@ describe "Code gen: hooks" do
end

Bar.y
").to_i.should eq(123)
)).to_i.should eq(123)
end

it "does finished" do
Expand Down
4 changes: 4 additions & 0 deletions spec/compiler/codegen/macro_spec.cr
Expand Up @@ -663,6 +663,8 @@ describe "Code gen: macro" do

it "transforms hooks (bug)" do
codegen(%(
require "prelude"

module GC
def self.add_finalizer(object : T)
object.responds_to?(:finalize)
Expand Down Expand Up @@ -800,6 +802,8 @@ describe "Code gen: macro" do

it "copies base macro def to sub-subtype even after it was copied to a subtype (#448)" do
run(%(
require "prelude"

class Object
def class_name : String
{{@type.name.stringify}}
Expand Down
7 changes: 5 additions & 2 deletions spec/compiler/codegen/pointer_spec.cr
Expand Up @@ -250,10 +250,11 @@ describe "Code gen: pointer" do
end

it "gets pointer to constant" do
run("
run(%(
require "prelude"
FOO = 1
pointerof(FOO).value
").to_i.should eq(1)
)).to_i.should eq(1)
end

it "passes pointer of pointer to method" do
Expand Down Expand Up @@ -324,6 +325,8 @@ describe "Code gen: pointer" do

it "does pointerof class variable with class" do
run(%(
require "prelude"

class Bar
def initialize(@x : Int32)
end
Expand Down
2 changes: 2 additions & 0 deletions spec/compiler/codegen/proc_spec.cr
Expand Up @@ -595,6 +595,8 @@ describe "Code gen: proc" do

it "codegens proc to implicit self in constant (#647)" do
run(%(
require "prelude"

module Foo
def self.blah
1
Expand Down