32
32
import org .truffleruby .core .klass .RubyClass ;
33
33
import org .truffleruby .core .string .StringUtils ;
34
34
import org .truffleruby .core .support .PRNGRandomizerNodes ;
35
- import org .truffleruby .extra .ffi .Pointer ;
36
35
import org .truffleruby .language .Nil ;
37
36
import org .truffleruby .language .SafepointManager ;
38
37
import org .truffleruby .language .control .DynamicReturnException ;
39
38
import org .truffleruby .language .control .ExitException ;
40
39
import org .truffleruby .language .control .KillException ;
41
40
import org .truffleruby .language .control .RaiseException ;
42
41
import org .truffleruby .language .objects .shared .SharedObjects ;
43
- import org .truffleruby .platform .NativeConfiguration ;
44
- import org .truffleruby .platform .TruffleNFIPlatform ;
45
- import org .truffleruby .platform .TruffleNFIPlatform .NativeFunction ;
46
42
47
43
import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
48
44
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
49
45
import com .oracle .truffle .api .TruffleStackTrace ;
50
46
import com .oracle .truffle .api .nodes .Node ;
51
47
import com .oracle .truffle .api .object .Shape ;
48
+ import org .truffleruby .signal .LibRubySignal ;
52
49
53
50
public class ThreadManager {
54
51
@@ -104,13 +101,10 @@ void restore(UnblockingAction action) {
104
101
public static final UnblockingAction EMPTY_UNBLOCKING_ACTION = () -> {
105
102
};
106
103
104
+ private boolean nativeInterrupt ;
107
105
private final ThreadLocal <UnblockingAction > blockingNativeCallUnblockingAction = ThreadLocal
108
106
.withInitial (() -> EMPTY_UNBLOCKING_ACTION );
109
107
110
- private int SIGVTALRM ;
111
- private NativeFunction pthread_self ;
112
- private NativeFunction pthread_kill ;
113
-
114
108
private final ExecutorService fiberPool ;
115
109
116
110
public ThreadManager (RubyContext context , RubyLanguage language ) {
@@ -120,10 +114,11 @@ public ThreadManager(RubyContext context, RubyLanguage language) {
120
114
this .fiberPool = Executors .newCachedThreadPool (this ::createFiberJavaThread );
121
115
}
122
116
123
- public void initialize (TruffleNFIPlatform nfi , NativeConfiguration nativeConfiguration ) {
124
- if (context .getOptions ().NATIVE_INTERRUPT && nfi != null ) {
125
- setupSignalHandler (nfi , nativeConfiguration );
126
- setupNativeThreadSupport (nfi , nativeConfiguration );
117
+ public void initialize () {
118
+ nativeInterrupt = context .getOptions ().NATIVE_INTERRUPT && context .getRubyHome () != null ;
119
+ if (nativeInterrupt ) {
120
+ LibRubySignal .loadLibrary (context .getRubyHome ());
121
+ LibRubySignal .setupSIGVTALRMEmptySignalHandler ();
127
122
}
128
123
}
129
124
@@ -251,37 +246,6 @@ private boolean getGlobalAbortOnException() {
251
246
return (boolean ) DynamicObjectLibrary .getUncached ().getOrDefault (threadClass , "@abort_on_exception" , null );
252
247
}
253
248
254
- private void setupSignalHandler (TruffleNFIPlatform nfi , NativeConfiguration config ) {
255
- SIGVTALRM = (int ) config .get ("platform.signal.SIGVTALRM" );
256
-
257
- final Object libC = nfi .getDefaultLibrary ();
258
-
259
- // We use abs() as a function taking a int and having no side effects
260
- final Object abs = nfi .lookup (libC , "abs" );
261
- final NativeFunction sigaction = nfi .getFunction ("sigaction" , "(sint32,pointer,pointer):sint32" );
262
-
263
- final int sizeOfSigAction = (int ) config .get ("platform.sigaction.sizeof" );
264
- final int handlerOffset = (int ) config .get ("platform.sigaction.sa_handler.offset" );
265
-
266
- try (Pointer structSigAction = Pointer .calloc (sizeOfSigAction )) {
267
- structSigAction .writeLong (handlerOffset , nfi .asPointer (abs ));
268
-
269
- // flags = 0 is OK as we want no SA_RESTART so we can interrupt blocking syscalls.
270
- final int result = (int ) sigaction .call (SIGVTALRM , structSigAction .getAddress (), 0L );
271
- if (result != 0 ) {
272
- // TODO (eregon, 24 Nov. 2017): we should show the NFI errno here.
273
- throw new UnsupportedOperationException ("sigaction() failed" );
274
- }
275
- }
276
- }
277
-
278
- private void setupNativeThreadSupport (TruffleNFIPlatform nfi , NativeConfiguration nativeConfiguration ) {
279
- final String pthread_t = nfi .resolveType (nativeConfiguration , "pthread_t" );
280
-
281
- pthread_self = nfi .getFunction ("pthread_self" , "():" + pthread_t );
282
- pthread_kill = nfi .getFunction ("pthread_kill" , "(" + pthread_t + ",sint32):sint32" );
283
- }
284
-
285
249
public void initialize (RubyThread rubyThread , Node currentNode , String info , String sharingReason ,
286
250
Supplier <Object > task ) {
287
251
startSharing (rubyThread , sharingReason );
@@ -541,10 +505,9 @@ public void initializeValuesForJavaThread(RubyThread rubyThread, Thread thread)
541
505
foreignThreadMap .put (thread , rubyThread );
542
506
}
543
507
544
- if (pthread_self != null && isRubyManagedThread (thread )) {
545
- final Object pThreadID = pthread_self .call ();
546
-
547
- blockingNativeCallUnblockingAction .set (() -> pthread_kill .call (pThreadID , SIGVTALRM ));
508
+ if (nativeInterrupt && isRubyManagedThread (thread )) {
509
+ final long threadID = LibRubySignal .threadID ();
510
+ blockingNativeCallUnblockingAction .set (() -> LibRubySignal .sendSIGVTALRMToThread (threadID ));
548
511
}
549
512
550
513
unblockingActions .put (thread , new UnblockingActionHolder (thread , () -> thread .interrupt ()));
@@ -556,7 +519,7 @@ public void cleanupValuesForJavaThread(Thread thread) {
556
519
}
557
520
foreignThreadMap .remove (thread );
558
521
559
- if (pthread_self != null ) {
522
+ if (nativeInterrupt ) {
560
523
blockingNativeCallUnblockingAction .remove ();
561
524
}
562
525
0 commit comments