Commit 9c0617c3 by Antonio Maiorano

SubzeroReactor: add stubbed coroutine support

* Implement Nucleus::createCoroutine and acquireCoroutine so that they create a regular function for the Begin entry, and stubbed functions for the Await and Destroy entries. * Made Routine::getEntry const as Coroutine expects this function to be callable from multiple threads. Subzero's implementation would lazily finalize the entry and cache it. Now we finalize it eagerly in acquireRoutine, and getEntry simply returns pointers. Bug: b/130459196 Change-Id: Id9fa447ce55c7df6fb55e1c878ca021e825fecfa Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/38873 Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarBen Clayton <bclayton@google.com> Tested-by: 's avatarAntonio Maiorano <amaiorano@google.com>
parent b34b558a
...@@ -405,7 +405,7 @@ namespace ...@@ -405,7 +405,7 @@ namespace
} }
} }
const void *getEntry(int index) override const void *getEntry(int index) const override
{ {
return addresses[index]; return addresses[index];
} }
......
...@@ -25,7 +25,7 @@ namespace rr ...@@ -25,7 +25,7 @@ namespace rr
Routine() = default; Routine() = default;
virtual ~Routine() = default; virtual ~Routine() = default;
virtual const void *getEntry(int index = 0) = 0; virtual const void *getEntry(int index = 0) const = 0;
}; };
// RoutineT is a type-safe wrapper around a Routine and its callable entry, returned by FunctionT // RoutineT is a type-safe wrapper around a Routine and its callable entry, returned by FunctionT
......
...@@ -490,7 +490,7 @@ namespace rr ...@@ -490,7 +490,7 @@ namespace rr
ELFMemoryStreamer &operator=(const ELFMemoryStreamer &) = delete; ELFMemoryStreamer &operator=(const ELFMemoryStreamer &) = delete;
public: public:
ELFMemoryStreamer() : Routine(), entry(nullptr) ELFMemoryStreamer() : Routine()
{ {
position = 0; position = 0;
buffer.reserve(0x1000); buffer.reserve(0x1000);
...@@ -534,28 +534,35 @@ namespace rr ...@@ -534,28 +534,35 @@ namespace rr
void seek(uint64_t Off) override { position = Off; } void seek(uint64_t Off) override { position = Off; }
const void *getEntry(int index) override const void* finalizeEntryBegin()
{ {
ASSERT(index == 0); // Subzero does not support multiple entry points per routine yet. position = std::numeric_limits<std::size_t>::max(); // Can't stream more data after this
if(!entry)
{
position = std::numeric_limits<std::size_t>::max(); // Can't stream more data after this
size_t codeSize = 0; size_t codeSize = 0;
entry = loadImage(&buffer[0], codeSize); const void *entry = loadImage(&buffer[0], codeSize);
#if defined(_WIN32)
VirtualProtect(&buffer[0], buffer.size(), PAGE_EXECUTE_READ, &oldProtection);
FlushInstructionCache(GetCurrentProcess(), NULL, 0);
#else
mprotect(&buffer[0], buffer.size(), PROT_READ | PROT_EXEC);
__builtin___clear_cache((char*)entry, (char*)entry + codeSize);
#endif
}
#if defined(_WIN32)
VirtualProtect(&buffer[0], buffer.size(), PAGE_EXECUTE_READ, &oldProtection);
FlushInstructionCache(GetCurrentProcess(), NULL, 0);
#else
mprotect(&buffer[0], buffer.size(), PROT_READ | PROT_EXEC);
__builtin___clear_cache((char*)entry, (char*)entry + codeSize);
#endif
return entry; return entry;
} }
void setEntry(int index, const void* func)
{
ASSERT(func);
funcs[index] = func;
}
const void *getEntry(int index) const override
{
ASSERT(funcs[index]);
return funcs[index];
}
const void* addConstantData(const void* data, size_t size) const void* addConstantData(const void* data, size_t size)
{ {
auto buf = std::unique_ptr<uint8_t[]>(new uint8_t[size]); auto buf = std::unique_ptr<uint8_t[]>(new uint8_t[size]);
...@@ -566,7 +573,7 @@ namespace rr ...@@ -566,7 +573,7 @@ namespace rr
} }
private: private:
void *entry; std::array<const void*, Nucleus::CoroutineEntryCount> funcs = {};
std::vector<uint8_t, ExecutableAllocator<uint8_t>> buffer; std::vector<uint8_t, ExecutableAllocator<uint8_t>> buffer;
std::size_t position; std::size_t position;
std::vector<std::unique_ptr<uint8_t[]>> constantData; std::vector<std::unique_ptr<uint8_t[]>> constantData;
...@@ -704,6 +711,9 @@ namespace rr ...@@ -704,6 +711,9 @@ namespace rr
objectWriter->setUndefinedSyms(::context->getConstantExternSyms()); objectWriter->setUndefinedSyms(::context->getConstantExternSyms());
objectWriter->writeNonUserSections(); objectWriter->writeNonUserSections();
const void* entryBegin = ::routine->finalizeEntryBegin();
::routine->setEntry(Nucleus::CoroutineEntryBegin, entryBegin);
Routine *handoffRoutine = ::routine; Routine *handoffRoutine = ::routine;
::routine = nullptr; ::routine = nullptr;
...@@ -3609,8 +3619,28 @@ namespace rr ...@@ -3609,8 +3619,28 @@ namespace rr
void EmitDebugVariable(Value* value) {} void EmitDebugVariable(Value* value) {}
void FlushDebug() {} void FlushDebug() {}
void Nucleus::createCoroutine(Type *YieldType, std::vector<Type*> &Params) { UNIMPLEMENTED("createCoroutine"); } void Nucleus::createCoroutine(Type *YieldType, std::vector<Type*> &Params)
std::shared_ptr<Routine> Nucleus::acquireCoroutine(const char *name, const Config::Edit &cfgEdit /* = Config::Edit::None */) { UNIMPLEMENTED("acquireCoroutine"); return nullptr; } {
// Subzero currently only supports coroutines as functions (i.e. that do not yield)
createFunction(YieldType, Params);
}
static bool coroutineEntryAwaitStub(Nucleus::CoroutineHandle, void* yieldValue) { return false; }
static void coroutineEntryDestroyStub(Nucleus::CoroutineHandle) {}
std::shared_ptr<Routine> Nucleus::acquireCoroutine(const char *name, const Config::Edit &cfgEdit /* = Config::Edit::None */)
{
// acquireRoutine sets the CoroutineEntryBegin entry
auto coroutineEntry = acquireRoutine(name, cfgEdit);
// For now, set the await and destroy entries to stubs, until we add proper coroutine support to the Subzero backend
auto routine = std::static_pointer_cast<ELFMemoryStreamer>(coroutineEntry);
routine->setEntry(Nucleus::CoroutineEntryAwait, reinterpret_cast<const void*>(&coroutineEntryAwaitStub));
routine->setEntry(Nucleus::CoroutineEntryDestroy, reinterpret_cast<const void*>(&coroutineEntryDestroyStub));
return coroutineEntry;
}
void Nucleus::yield(Value* val) { UNIMPLEMENTED("Yield"); } void Nucleus::yield(Value* val) { UNIMPLEMENTED("Yield"); }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment