Skip to content

Commit 20df533

Browse files
committed
Merge branch 'master' into update/GR-21590/190321
2 parents a5ed189 + b750ee4 commit 20df533

File tree

166 files changed

+6824
-3605
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

166 files changed

+6824
-3605
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ language runtime. The main focus is on user-observable behavior of the engine.
55

66
## Version 21.1.0
77

8+
* Support multi-threading with a global interpreter lock by default.
89
* Added SSL/TLS support (the `ssl` module)
910
* Added subclassing of Java classes in JVM mode
1011
* Use native posix functions in the GraalPython Launcher

docs/contributor/IMPLEMENTATION_DETAILS.md

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,4 +198,53 @@ this order:
198198
* `P.patch`
199199

200200
The same applies to `*.dir` files, and the search is independent of the search
201-
for the `*.patch` file, i.e., multiple versions of `*.patch` may share one `*.dir`.
201+
for the `*.patch` file, i.e., multiple versions of `*.patch` may share one `*.dir`.
202+
203+
## The GIL
204+
205+
We always run with a GIL, because C extensions in CPython expect to do so and
206+
are usually not written to be reentrant. The reason to always have the GIL
207+
enabled is that when using Python, at least Sulong/LLVM is always available in
208+
the same context and we cannot know if someone may be using that (or another
209+
polyglot language or the Java host interop) to start additional threads that
210+
could call back into Python. This could legitimately happen in C extensions when
211+
the C extension authors use knowledge of how CPython works to do something
212+
GIL-less in a C thread that is fine to do on CPython's data structures, but not
213+
for ours.
214+
215+
Suppose we were running GIL-less until a second thread appears. There is now two
216+
options: the second thread immediately takes the GIL, but both threads might be
217+
executing in parallel for a little while before the first thread gets to the
218+
next safepoint where they try to release and re-acquire the GIL. Option two is
219+
that we block the second thread on some other semaphore until the first thread
220+
has acquired the GIL. This scenario may deadlock if the first thread is
221+
suspended in a blocking syscall. This could be a legitimate use case when
222+
e.g. one thread is supposed to block on a `select` call that the other thread
223+
would unblock by operating on the selected resource. Now the second thread
224+
cannot start to run because it is waiting for the first thread to acquire the
225+
GIL. To get around this potential deadlock, we would have to "remember" around
226+
blocking calls that the first thread would have released the GIL before and
227+
re-acquired it after that point. Since this is equivalent to just releasing and
228+
re-acquiring the GIL, we might as well always do that.
229+
230+
The implication of this is that we may have to acquire and release the GIL
231+
around all library messages that may be invoked without already holding the
232+
GIL. The pattern here is, around every one of those messages:
233+
234+
```
235+
@ExportMessage xxx(..., @Cached GilNode gil) {
236+
boolean mustRelease = gil.acquire();
237+
try {
238+
...
239+
} finally {
240+
gil.release(mustRelease);
241+
}
242+
}
243+
```
244+
245+
The `GilNode` when used in this pattern ensures that we only release the GIL if
246+
we acquired it before. The `GilNode` internally uses profiles to ensure that if
247+
we are always running single threaded or always own the GIL already when we get
248+
to a specific message we never emit a boundary call to lock and unlock the
249+
GIL. This implies that we may deopt in some places if, after compiling some
250+
code, we later start a second thread.

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/module/ThreadPoolTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
import java.io.ByteArrayOutputStream;
4646
import java.io.PrintStream;
47-
import java.util.Collections;
47+
import java.util.HashMap;
4848

4949
import org.junit.Test;
5050

@@ -70,7 +70,7 @@ public void threadPool() {
7070
"print(res)\n";
7171
final ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
7272
final PrintStream printStream = new PrintStream(byteArray);
73-
PythonTests.runScript(Collections.singletonMap("python.WithThread", "true"), new String[0], source, printStream, System.err, () -> PythonTests.closeContext());
73+
PythonTests.runScript(new HashMap<>(), new String[0], source, printStream, System.err, () -> PythonTests.closeContext());
7474
String result = byteArray.toString().replaceAll("\r\n", "\n");
7575
assertEquals("[True, True, True, True, True, True, True, True, True, True]\n", result);
7676
}

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_memoryview.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@
3737
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3838
# SOFTWARE.
3939

40-
import sys
41-
import time
42-
import gc
4340
import itertools
41+
import sys
42+
4443
from . import CPyExtTestCase, CPyExtFunction, CPyExtType, unhandled_error_compare_with_message, unhandled_error_compare
44+
4545
__dir__ = __file__.rpartition("/")[0]
4646

4747
indices = (-2, 2, 10)
@@ -407,11 +407,6 @@ def test_memoryview_acquire_release(self):
407407
assert mv2[3] == 126
408408
mv2.release()
409409
assert mv3[2] == 126
410-
del mv1
411-
del mv3
412-
for i in range(120):
413-
gc.collect()
414-
if obj.get_bufcount() == 0:
415-
break
416-
time.sleep(1)
410+
mv1.release()
411+
mv3.release()
417412
assert obj.get_bufcount() == 0

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_support.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
*graalpython.lib-python.3.test.test_support.TestSupport.test_check_syntax_error
1313
*graalpython.lib-python.3.test.test_support.TestSupport.test_detect_api_mismatch
1414
*graalpython.lib-python.3.test.test_support.TestSupport.test_detect_api_mismatch__ignore
15-
*graalpython.lib-python.3.test.test_support.TestSupport.test_find_unused_port
1615
*graalpython.lib-python.3.test.test_support.TestSupport.test_forget
1716
*graalpython.lib-python.3.test.test_support.TestSupport.test_gc_collect
1817
*graalpython.lib-python.3.test.test_support.TestSupport.test_get_attribute
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
11
*graalpython.lib-python.3.test.test_thread.BarrierTest.test_barrier
2+
*graalpython.lib-python.3.test.test_thread.LockTests.test_acquire_contended
3+
*graalpython.lib-python.3.test.test_thread.LockTests.test_acquire_destroy
4+
*graalpython.lib-python.3.test.test_thread.LockTests.test_acquire_release
5+
*graalpython.lib-python.3.test.test_thread.LockTests.test_constructor
6+
*graalpython.lib-python.3.test.test_thread.LockTests.test_different_thread
7+
*graalpython.lib-python.3.test.test_thread.LockTests.test_locked_repr
8+
*graalpython.lib-python.3.test.test_thread.LockTests.test_reacquire
9+
*graalpython.lib-python.3.test.test_thread.LockTests.test_repr
10+
*graalpython.lib-python.3.test.test_thread.LockTests.test_state_after_timeout
11+
*graalpython.lib-python.3.test.test_thread.LockTests.test_thread_leak
12+
*graalpython.lib-python.3.test.test_thread.LockTests.test_timeout
13+
*graalpython.lib-python.3.test.test_thread.LockTests.test_try_acquire
14+
*graalpython.lib-python.3.test.test_thread.LockTests.test_try_acquire_contended
15+
*graalpython.lib-python.3.test.test_thread.LockTests.test_weakref_deleted
16+
*graalpython.lib-python.3.test.test_thread.LockTests.test_weakref_exists
17+
*graalpython.lib-python.3.test.test_thread.LockTests.test_with
218
*graalpython.lib-python.3.test.test_thread.TestForkInThread.test_forkinthread
19+
*graalpython.lib-python.3.test.test_thread.ThreadRunningTests.test__count
320
*graalpython.lib-python.3.test.test_thread.ThreadRunningTests.test_nt_and_posix_stack_size
21+
*graalpython.lib-python.3.test.test_thread.ThreadRunningTests.test_stack_size
22+
*graalpython.lib-python.3.test.test_thread.ThreadRunningTests.test_starting_threads
23+
*graalpython.lib-python.3.test.test_thread.ThreadRunningTests.test_unraisable_exception

0 commit comments

Comments
 (0)