//===- 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" #ifdef MLIR_ASYNCRUNTIME_DEFINE_FUNCTIONS #include #include #include #include #include #include //===----------------------------------------------------------------------===// // Async runtime API. //===----------------------------------------------------------------------===// struct AsyncToken { bool ready = false; std::mutex mu; std::condition_variable cv; std::vector> awaiters; }; // Create a new `async.token` in not-ready state. extern "C" MLIR_ASYNCRUNTIME_EXPORT AsyncToken *mlirAsyncRuntimeCreateToken() { AsyncToken *token = new AsyncToken; return token; } // Switches `async.token` to ready state and runs all awaiters. extern "C" MLIR_ASYNCRUNTIME_EXPORT void mlirAsyncRuntimeEmplaceToken(AsyncToken *token) { std::unique_lock lock(token->mu); token->ready = true; token->cv.notify_all(); for (auto &awaiter : token->awaiters) awaiter(); } extern "C" MLIR_ASYNCRUNTIME_EXPORT void mlirAsyncRuntimeAwaitToken(AsyncToken *token) { std::unique_lock lock(token->mu); if (!token->ready) token->cv.wait(lock, [token] { return token->ready; }); delete token; } extern "C" MLIR_ASYNCRUNTIME_EXPORT void mlirAsyncRuntimeExecute(CoroHandle handle, CoroResume resume) { #if LLVM_ENABLE_THREADS std::thread thread([handle, resume]() { (*resume)(handle); }); thread.detach(); #else (*resume)(handle); #endif } extern "C" MLIR_ASYNCRUNTIME_EXPORT void mlirAsyncRuntimeAwaitTokenAndExecute(AsyncToken *token, CoroHandle handle, CoroResume resume) { std::unique_lock lock(token->mu); auto execute = [token, handle, resume]() { mlirAsyncRuntimeExecute(handle, resume); delete token; }; if (token->ready) execute(); else token->awaiters.push_back([execute]() { execute(); }); } //===----------------------------------------------------------------------===// // Small async runtime support library for testing. //===----------------------------------------------------------------------===// extern "C" MLIR_ASYNCRUNTIME_EXPORT void mlirAsyncRuntimePrintCurrentThreadId() { static thread_local std::thread::id thisId = std::this_thread::get_id(); std::cout << "Current thread id: " << thisId << "\n"; } #endif // MLIR_ASYNCRUNTIME_DEFINE_FUNCTIONS