optionally specify reentrancy when creating a System object

This allows multiple Avian VMs to share the same process space,
provided they don't try to use functionality that involves global
shared resources (e.g. signal handling).
This commit is contained in:
Joel Dice 2015-09-12 20:08:54 -06:00
parent 9b2a02e92b
commit 763aada4b0
3 changed files with 42 additions and 30 deletions

View File

@ -176,7 +176,7 @@ inline void NO_RETURN sysAbort(System* s)
// #endif // not NDEBUG // #endif // not NDEBUG
AVIAN_EXPORT System* makeSystem(); AVIAN_EXPORT System* makeSystem(bool reentrant = false);
} // namespace vm } // namespace vm

View File

@ -92,7 +92,7 @@ const int signals[] = {VisitSignal, InterruptSignal, PipeSignal};
const unsigned SignalCount = 3; const unsigned SignalCount = 3;
class MySystem; class MySystem;
MySystem* system; MySystem* globalSystem;
void handleSignal(int signal, siginfo_t* info, void* context); void handleSignal(int signal, siginfo_t* info, void* context);
@ -624,16 +624,18 @@ class MySystem : public System {
System::Library* next_; System::Library* next_;
}; };
MySystem() : threadVisitor(0), visitTarget(0) MySystem(bool reentrant) : reentrant(reentrant), threadVisitor(0), visitTarget(0)
{ {
expect(this, system == 0); if (not reentrant) {
system = this; expect(this, globalSystem == 0);
globalSystem = this;
expect(this, registerHandler(InterruptSignalIndex)); expect(this, registerHandler(InterruptSignalIndex));
expect(this, registerHandler(VisitSignalIndex)); expect(this, registerHandler(VisitSignalIndex));
expect(this, registerHandler(PipeSignalIndex)); expect(this, registerHandler(PipeSignalIndex));
expect(this, make(&visitLock) == 0); expect(this, make(&visitLock) == 0);
}
} }
// Returns true on success, false on failure // Returns true on success, false on failure
@ -708,6 +710,8 @@ class MySystem : public System {
System::Thread* sTarget, System::Thread* sTarget,
ThreadVisitor* visitor) ThreadVisitor* visitor)
{ {
expect(this, not reentrant);
assertT(this, st != sTarget); assertT(this, st != sTarget);
Thread* target = static_cast<Thread*>(sTarget); Thread* target = static_cast<Thread*>(sTarget);
@ -767,7 +771,7 @@ class MySystem : public System {
threadVisitor = 0; threadVisitor = 0;
system->visitLock->notifyAll(t); globalSystem->visitLock->notifyAll(t);
return result; return result;
#endif // not __APPLE__ #endif // not __APPLE__
@ -938,18 +942,21 @@ class MySystem : public System {
virtual void dispose() virtual void dispose()
{ {
visitLock->dispose(); if (not reentrant) {
visitLock->dispose();
expect(this, unregisterHandler(InterruptSignalIndex)); expect(this, unregisterHandler(InterruptSignalIndex));
expect(this, unregisterHandler(VisitSignalIndex)); expect(this, unregisterHandler(VisitSignalIndex));
expect(this, unregisterHandler(PipeSignalIndex)); expect(this, unregisterHandler(PipeSignalIndex));
system = 0; globalSystem = 0;
}
::free(this); ::free(this);
} }
struct sigaction oldHandlers[SignalCount]; struct sigaction oldHandlers[SignalCount];
bool reentrant;
ThreadVisitor* threadVisitor; ThreadVisitor* threadVisitor;
Thread* visitTarget; Thread* visitTarget;
System::Monitor* visitLock; System::Monitor* visitLock;
@ -965,13 +972,13 @@ void handleSignal(int signal, siginfo_t*, void* context)
switch (signal) { switch (signal) {
case VisitSignal: { case VisitSignal: {
system->threadVisitor->visit(ip, stack, link); globalSystem->threadVisitor->visit(ip, stack, link);
System::Thread* t = system->visitTarget; System::Thread* t = globalSystem->visitTarget;
system->visitTarget = 0; globalSystem->visitTarget = 0;
ACQUIRE_MONITOR(t, system->visitLock); ACQUIRE_MONITOR(t, globalSystem->visitLock);
system->visitLock->notifyAll(t); globalSystem->visitLock->notifyAll(t);
} break; } break;
case InterruptSignal: case InterruptSignal:
@ -987,9 +994,9 @@ void handleSignal(int signal, siginfo_t*, void* context)
namespace vm { namespace vm {
AVIAN_EXPORT System* makeSystem() AVIAN_EXPORT System* makeSystem(bool reentrant)
{ {
return new (malloc(sizeof(MySystem))) MySystem(); return new (malloc(sizeof(MySystem))) MySystem(reentrant);
} }
} // namespace vm } // namespace vm

View File

@ -115,7 +115,7 @@ class MutexResource {
}; };
class MySystem; class MySystem;
MySystem* system; MySystem* globalSystem;
DWORD WINAPI run(void* r) DWORD WINAPI run(void* r)
{ {
@ -655,10 +655,12 @@ class MySystem : public System {
System::Library* next_; System::Library* next_;
}; };
MySystem() MySystem(bool reentrant): reentrant(reentrant)
{ {
expect(this, system == 0); if (not reentrant) {
system = this; expect(this, globalSystem == 0);
globalSystem = this;
}
mutex = CreateMutex(0, false, 0); mutex = CreateMutex(0, false, 0);
assertT(this, mutex); assertT(this, mutex);
@ -1007,7 +1009,10 @@ class MySystem : public System {
virtual void dispose() virtual void dispose()
{ {
system = 0; if (not reentrant) {
globalSystem = 0;
}
CloseHandle(mutex); CloseHandle(mutex);
::free(this); ::free(this);
} }
@ -1019,9 +1024,9 @@ class MySystem : public System {
namespace vm { namespace vm {
AVIAN_EXPORT System* makeSystem() AVIAN_EXPORT System* makeSystem(bool reentrant)
{ {
return new (malloc(sizeof(MySystem))) MySystem(); return new (malloc(sizeof(MySystem))) MySystem(reentrant);
} }
} // namespace vm } // namespace vm