//===- AsyncRuntime.cpp - Async runtime reference implementation ----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements basic Async runtime API for supporting Async dialect // to LLVM dialect lowering. // //===----------------------------------------------------------------------===// #include "mlir/ExecutionEngine/AsyncRuntime.h" #include <atomic> #include <cassert> #include <condition_variable> #include <functional> #include <iostream> #include <mutex> #include <thread> #include <vector> #include "llvm/ADT/StringMap.h" #include "llvm/Support/ThreadPool.h" usingnamespacemlir::runtime; //===----------------------------------------------------------------------===// // Async runtime API. //===----------------------------------------------------------------------===// namespace mlir { namespace runtime { namespace { // Forward declare class defined below. class RefCounted; // -------------------------------------------------------------------------- // // AsyncRuntime orchestrates all async operations and Async runtime API is built // on top of the default runtime instance. // -------------------------------------------------------------------------- // class AsyncRuntime { … }; // -------------------------------------------------------------------------- // // A state of the async runtime value (token, value or group). // -------------------------------------------------------------------------- // class State { … }; // -------------------------------------------------------------------------- // // A base class for all reference counted objects created by the async runtime. // -------------------------------------------------------------------------- // class RefCounted { … }; } // namespace // Returns the default per-process instance of an async runtime. static std::unique_ptr<AsyncRuntime> &getDefaultAsyncRuntimeInstance() { … } static void resetDefaultAsyncRuntime() { … } static AsyncRuntime *getDefaultAsyncRuntime() { … } // Async token provides a mechanism to signal asynchronous operation completion. struct AsyncToken : public RefCounted { … }; // Async value provides a mechanism to access the result of asynchronous // operations. It owns the storage that is used to store/load the value of the // underlying type, and a flag to signal if the value is ready or not. struct AsyncValue : public RefCounted { … }; // Async group provides a mechanism to group together multiple async tokens or // values to await on all of them together (wait for the completion of all // tokens or values added to the group). struct AsyncGroup : public RefCounted { … }; // Adds references to reference counted runtime object. extern "C" void mlirAsyncRuntimeAddRef(RefCountedObjPtr ptr, int64_t count) { … } // Drops references from reference counted runtime object. extern "C" void mlirAsyncRuntimeDropRef(RefCountedObjPtr ptr, int64_t count) { … } // Creates a new `async.token` in not-ready state. extern "C" AsyncToken *mlirAsyncRuntimeCreateToken() { … } // Creates a new `async.value` in not-ready state. extern "C" AsyncValue *mlirAsyncRuntimeCreateValue(int64_t size) { … } // Create a new `async.group` in empty state. extern "C" AsyncGroup *mlirAsyncRuntimeCreateGroup(int64_t size) { … } extern "C" int64_t mlirAsyncRuntimeAddTokenToGroup(AsyncToken *token, AsyncGroup *group) { … } // Switches `async.token` to available or error state (terminatl state) and runs // all awaiters. static void setTokenState(AsyncToken *token, State state) { … } static void setValueState(AsyncValue *value, State state) { … } extern "C" void mlirAsyncRuntimeEmplaceToken(AsyncToken *token) { … } extern "C" void mlirAsyncRuntimeEmplaceValue(AsyncValue *value) { … } extern "C" void mlirAsyncRuntimeSetTokenError(AsyncToken *token) { … } extern "C" void mlirAsyncRuntimeSetValueError(AsyncValue *value) { … } extern "C" bool mlirAsyncRuntimeIsTokenError(AsyncToken *token) { … } extern "C" bool mlirAsyncRuntimeIsValueError(AsyncValue *value) { … } extern "C" bool mlirAsyncRuntimeIsGroupError(AsyncGroup *group) { … } extern "C" void mlirAsyncRuntimeAwaitToken(AsyncToken *token) { … } extern "C" void mlirAsyncRuntimeAwaitValue(AsyncValue *value) { … } extern "C" void mlirAsyncRuntimeAwaitAllInGroup(AsyncGroup *group) { … } // Returns a pointer to the storage owned by the async value. extern "C" ValueStorage mlirAsyncRuntimeGetValueStorage(AsyncValue *value) { … } extern "C" void mlirAsyncRuntimeExecute(CoroHandle handle, CoroResume resume) { … } extern "C" void mlirAsyncRuntimeAwaitTokenAndExecute(AsyncToken *token, CoroHandle handle, CoroResume resume) { … } extern "C" void mlirAsyncRuntimeAwaitValueAndExecute(AsyncValue *value, CoroHandle handle, CoroResume resume) { … } extern "C" void mlirAsyncRuntimeAwaitAllInGroupAndExecute(AsyncGroup *group, CoroHandle handle, CoroResume resume) { … } extern "C" int64_t mlirAsyncRuntimGetNumWorkerThreads() { … } //===----------------------------------------------------------------------===// // Small async runtime support library for testing. //===----------------------------------------------------------------------===// extern "C" void mlirAsyncRuntimePrintCurrentThreadId() { … } //===----------------------------------------------------------------------===// // MLIR ExecutionEngine dynamic library integration. //===----------------------------------------------------------------------===// // Visual Studio had a bug that fails to compile nested generic lambdas // inside an `extern "C"` function. // https://developercommunity.visualstudio.com/content/problem/475494/clexe-error-with-lambda-inside-function-templates.html // The bug is fixed in VS2019 16.1. Separating the declaration and definition is // a work around for older versions of Visual Studio. // NOLINTNEXTLINE(*-identifier-naming): externally called. extern "C" MLIR_ASYNC_RUNTIME_EXPORT void __mlir_execution_engine_init(llvm::StringMap<void *> &exportSymbols); // NOLINTNEXTLINE(*-identifier-naming): externally called. void __mlir_execution_engine_init(llvm::StringMap<void *> &exportSymbols) { … } // NOLINTNEXTLINE(*-identifier-naming): externally called. extern "C" MLIR_ASYNC_RUNTIME_EXPORT void __mlir_execution_engine_destroy() { … } } // namespace runtime } // namespace mlir