Skip to content

Commit 172f082

Browse files
committed
count started python threads ourselves
1 parent 07d748e commit 172f082

File tree

1 file changed

+43
-10
lines changed

1 file changed

+43
-10
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ThreadModuleBuiltins.java

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,13 @@
4949
import com.oracle.graal.python.PythonLanguage;
5050
import com.oracle.graal.python.builtins.Builtin;
5151
import com.oracle.graal.python.builtins.CoreFunctions;
52+
import com.oracle.graal.python.builtins.Python3Core;
5253
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
5354
import com.oracle.graal.python.builtins.PythonBuiltins;
5455
import com.oracle.graal.python.builtins.objects.PNone;
5556
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
5657
import com.oracle.graal.python.builtins.objects.function.PKeyword;
58+
import com.oracle.graal.python.builtins.objects.module.PythonModule;
5759
import com.oracle.graal.python.builtins.objects.thread.PLock;
5860
import com.oracle.graal.python.builtins.objects.thread.PRLock;
5961
import com.oracle.graal.python.builtins.objects.thread.PThread;
@@ -67,21 +69,26 @@
6769
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
6870
import com.oracle.graal.python.runtime.GilNode;
6971
import com.oracle.graal.python.runtime.PythonContext;
70-
import com.oracle.graal.python.builtins.Python3Core;
7172
import com.oracle.graal.python.runtime.exception.PException;
7273
import com.oracle.graal.python.runtime.exception.PythonThreadKillException;
7374
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
75+
import com.oracle.truffle.api.CompilerDirectives;
7476
import com.oracle.truffle.api.TruffleLanguage;
7577
import com.oracle.truffle.api.dsl.Cached;
7678
import com.oracle.truffle.api.dsl.CachedContext;
7779
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
7880
import com.oracle.truffle.api.dsl.NodeFactory;
7981
import com.oracle.truffle.api.dsl.Specialization;
8082
import com.oracle.truffle.api.frame.VirtualFrame;
83+
import com.oracle.truffle.api.nodes.UnexpectedResultException;
84+
import com.oracle.truffle.api.object.DynamicObjectLibrary;
85+
import com.oracle.truffle.api.object.HiddenKey;
8186
import com.oracle.truffle.api.profiles.ConditionProfile;
8287

8388
@CoreFunctions(defineModule = "_thread")
8489
public class ThreadModuleBuiltins extends PythonBuiltins {
90+
private static final HiddenKey THREAD_COUNT = new HiddenKey("thread_count");
91+
8592
@Override
8693
protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() {
8794
return ThreadModuleBuiltinsFactory.getFactories();
@@ -91,6 +98,7 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
9198
public void initialize(Python3Core core) {
9299
builtinConstants.put("error", core.lookupType(PythonBuiltinClassType.RuntimeError));
93100
builtinConstants.put("TIMEOUT_MAX", TIMEOUT_MAX);
101+
builtinConstants.put(THREAD_COUNT, 0);
94102
super.initialize(core);
95103
}
96104

@@ -140,13 +148,17 @@ public static long getId() {
140148
}
141149
}
142150

143-
@Builtin(name = "_count", minNumOfPositionalArgs = 0)
151+
@Builtin(name = "_count", minNumOfPositionalArgs = 1, declaresExplicitSelf = true)
144152
@GenerateNodeFactory
145-
abstract static class GetThreadCountNode extends PythonBuiltinNode {
153+
abstract static class GetThreadCountNode extends PythonUnaryBuiltinNode {
146154
@Specialization
147155
@TruffleBoundary
148-
long getCount() {
149-
return getContext().getThreadGroup().activeCount();
156+
long getCount(PythonModule self) {
157+
try {
158+
return DynamicObjectLibrary.getUncached().getIntOrDefault(self, THREAD_COUNT, 0);
159+
} catch (UnexpectedResultException e) {
160+
throw CompilerDirectives.shouldNotReachHere();
161+
}
150162
}
151163
}
152164

@@ -189,6 +201,7 @@ long start(VirtualFrame frame, Object cls, Object callable, Object args, Object
189201
@Cached ExpandKeywordStarargsNode getKwArgsNode) {
190202
PythonContext context = getContext();
191203
TruffleLanguage.Env env = context.getEnv();
204+
PythonModule threadModule = context.getCore().lookupBuiltinModule("_thread");
192205

193206
// TODO: python thread stack size != java thread stack size
194207
// ignore setting the stack size for the moment
@@ -197,11 +210,31 @@ long start(VirtualFrame frame, Object cls, Object callable, Object args, Object
197210
PKeyword[] keywords = getKwArgsNode.execute(kwargs);
198211

199212
try (GilNode.UncachedAcquire gil = GilNode.uncachedAcquire()) {
200-
// n.b.: It is important to pass 'null' frame here because each thread has it's
201-
// own stack and if we would pass the current frame, this would be connected as
202-
// a caller which is incorrect. However, the thread-local 'topframeref' is
203-
// initialized with EMPTY which will be picked up.
204-
callNode.execute(null, callable, arguments, keywords);
213+
// the increment is protected by the gil
214+
DynamicObjectLibrary lib = DynamicObjectLibrary.getUncached();
215+
int curCount = 0;
216+
try {
217+
curCount = lib.getIntOrDefault(threadModule, THREAD_COUNT, 0);
218+
} catch (UnexpectedResultException ure) {
219+
throw CompilerDirectives.shouldNotReachHere();
220+
}
221+
lib.putInt(threadModule, THREAD_COUNT, curCount + 1);
222+
try {
223+
// n.b.: It is important to pass 'null' frame here because each thread has
224+
// it's own stack and if we would pass the current frame, this would be
225+
// connected as a caller which is incorrect. However, the thread-local
226+
// 'topframeref' is initialized with EMPTY which will be picked up.
227+
callNode.execute(null, callable, arguments, keywords);
228+
} finally {
229+
// the catch blocks run ofter the gil is released, so we decrement the
230+
// threadcount here while still protected by the gil
231+
try {
232+
curCount = lib.getIntOrDefault(threadModule, THREAD_COUNT, 1);
233+
} catch (UnexpectedResultException ure) {
234+
throw CompilerDirectives.shouldNotReachHere();
235+
}
236+
lib.putInt(threadModule, THREAD_COUNT, curCount - 1);
237+
}
205238
} catch (PythonThreadKillException e) {
206239
return;
207240
} catch (PException e) {

0 commit comments

Comments
 (0)