Commit aae50806 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

always build AsyncIo and IoUring sources

Summary: Their contents may be preprocessed away if the corresponding platform headers are unavailable. But this removes some of the build-time and build-config complexity.

Differential Revision: D32629035

fbshipit-source-id: a2265ceac44b5022ed53d1c7163f591e779da651
parent cec3fcac
...@@ -201,39 +201,6 @@ list(APPEND hfiles ...@@ -201,39 +201,6 @@ list(APPEND hfiles
${FOLLY_DIR}/test/TestUtils.h ${FOLLY_DIR}/test/TestUtils.h
) )
# Exclude specific sources if we do not have third-party libraries
# required to build them.
if (NOT ${LIBAIO_FOUND})
list(REMOVE_ITEM files
${FOLLY_DIR}/experimental/io/AsyncIO.cpp
)
list(REMOVE_ITEM hfiles
${FOLLY_DIR}/experimental/io/AsyncIO.h
)
endif()
if (NOT ${LIBURING_FOUND})
list(REMOVE_ITEM files
${FOLLY_DIR}/experimental/io/IoUring.cpp
${FOLLY_DIR}/experimental/io/IoUringBackend.cpp
)
list(REMOVE_ITEM hfiles
${FOLLY_DIR}/experimental/io/IoUring.h
${FOLLY_DIR}/experimental/io/IoUringBackend.h
)
endif()
if (NOT ${LIBAIO_FOUND} AND NOT ${LIBURING_FOUND})
list(REMOVE_ITEM files
${FOLLY_DIR}/experimental/io/AsyncBase.cpp
${FOLLY_DIR}/experimental/io/PollIoBackend.cpp
${FOLLY_DIR}/experimental/io/SimpleAsyncIO.cpp
)
list(REMOVE_ITEM hfiles
${FOLLY_DIR}/experimental/io/AsyncBase.h
${FOLLY_DIR}/experimental/io/PollIoBackend.h
${FOLLY_DIR}/experimental/io/SimpleAsyncIO.h
)
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
check_cxx_compiler_flag(-fcoroutines COMPILER_HAS_F_COROUTINES) check_cxx_compiler_flag(-fcoroutines COMPILER_HAS_F_COROUTINES)
if (COMPILER_HAS_F_COROUTINES) if (COMPILER_HAS_F_COROUTINES)
......
...@@ -87,7 +87,7 @@ void AsyncBaseOp::init() { ...@@ -87,7 +87,7 @@ void AsyncBaseOp::init() {
std::string AsyncBaseOp::fd2name(int fd) { std::string AsyncBaseOp::fd2name(int fd) {
auto link = fs::path{"/proc/self/fd"} / folly::to<std::string>(fd); auto link = fs::path{"/proc/self/fd"} / folly::to<std::string>(fd);
return fs::read_symlink(link); return fs::read_symlink(link).string();
} }
AsyncBase::AsyncBase(size_t capacity, PollMode pollMode) : capacity_(capacity) { AsyncBase::AsyncBase(size_t capacity, PollMode pollMode) : capacity_(capacity) {
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <folly/experimental/io/AsyncIO.h> #include <folly/experimental/io/AsyncIO.h>
#include <sys/eventfd.h>
#include <cerrno> #include <cerrno>
#include <ostream> #include <ostream>
#include <stdexcept> #include <stdexcept>
...@@ -32,6 +31,8 @@ ...@@ -32,6 +31,8 @@
#include <folly/portability/Unistd.h> #include <folly/portability/Unistd.h>
#include <folly/small_vector.h> #include <folly/small_vector.h>
#if __has_include(<libaio.h>)
// debugging helpers // debugging helpers
namespace { namespace {
#define X(c) \ #define X(c) \
...@@ -274,3 +275,5 @@ Range<AsyncBase::Op**> AsyncIO::doWait( ...@@ -274,3 +275,5 @@ Range<AsyncBase::Op**> AsyncIO::doWait(
} }
} // namespace folly } // namespace folly
#endif
...@@ -16,10 +16,12 @@ ...@@ -16,10 +16,12 @@
#pragma once #pragma once
#include <libaio.h>
#include <folly/experimental/io/AsyncBase.h> #include <folly/experimental/io/AsyncBase.h>
#if __has_include(<libaio.h>)
#include <libaio.h>
namespace folly { namespace folly {
class AsyncIOOp : public AsyncBaseOp { class AsyncIOOp : public AsyncBaseOp {
...@@ -94,3 +96,5 @@ class AsyncIO : public AsyncBase { ...@@ -94,3 +96,5 @@ class AsyncIO : public AsyncBase {
using AsyncIOQueue = AsyncBaseQueue; using AsyncIOQueue = AsyncBaseQueue;
} // namespace folly } // namespace folly
#endif
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <folly/experimental/io/IoUring.h> #include <folly/experimental/io/IoUring.h>
#include <sys/eventfd.h>
#include <cerrno> #include <cerrno>
#include <ostream> #include <ostream>
#include <stdexcept> #include <stdexcept>
...@@ -31,6 +30,8 @@ ...@@ -31,6 +30,8 @@
#include <folly/String.h> #include <folly/String.h>
#include <folly/portability/Unistd.h> #include <folly/portability/Unistd.h>
#if __has_include(<liburing.h>)
// helpers // helpers
namespace { namespace {
// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
...@@ -338,3 +339,5 @@ Range<AsyncBase::Op**> IoUring::doWait( ...@@ -338,3 +339,5 @@ Range<AsyncBase::Op**> IoUring::doWait(
} }
} // namespace folly } // namespace folly
#endif
...@@ -16,11 +16,13 @@ ...@@ -16,11 +16,13 @@
#pragma once #pragma once
#include <liburing.h>
#include <folly/SharedMutex.h> #include <folly/SharedMutex.h>
#include <folly/experimental/io/AsyncBase.h> #include <folly/experimental/io/AsyncBase.h>
#if __has_include(<liburing.h>)
#include <liburing.h>
namespace folly { namespace folly {
/** /**
...@@ -117,3 +119,5 @@ class IoUring : public AsyncBase { ...@@ -117,3 +119,5 @@ class IoUring : public AsyncBase {
using IoUringQueue = AsyncBaseQueue; using IoUringQueue = AsyncBaseQueue;
} // namespace folly } // namespace folly
#endif
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
*/ */
#include <signal.h> #include <signal.h>
#include <sys/timerfd.h>
#include <folly/FileUtil.h> #include <folly/FileUtil.h>
#include <folly/Likely.h> #include <folly/Likely.h>
...@@ -28,6 +27,12 @@ ...@@ -28,6 +27,12 @@
#include <folly/portability/Sockets.h> #include <folly/portability/Sockets.h>
#include <folly/synchronization/CallOnce.h> #include <folly/synchronization/CallOnce.h>
#if __has_include(<sys/timerfd.h>)
#include <sys/timerfd.h>
#endif
#if __has_include(<liburing.h>)
extern "C" FOLLY_ATTR_WEAK void eb_poll_loop_pre_hook(uint64_t* call_time); extern "C" FOLLY_ATTR_WEAK void eb_poll_loop_pre_hook(uint64_t* call_time);
extern "C" FOLLY_ATTR_WEAK void eb_poll_loop_post_hook( extern "C" FOLLY_ATTR_WEAK void eb_poll_loop_post_hook(
uint64_t call_time, int ret); uint64_t call_time, int ret);
...@@ -1302,3 +1307,5 @@ void IoUringBackend::processFileOp(IoSqe* sqe, int64_t res) noexcept { ...@@ -1302,3 +1307,5 @@ void IoUringBackend::processFileOp(IoSqe* sqe, int64_t res) noexcept {
} }
} // namespace folly } // namespace folly
#endif // __has_include(<liburing.h>)
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
#pragma once #pragma once
#include <liburing.h>
#include <poll.h>
#include <sys/types.h> #include <sys/types.h>
#include <chrono> #include <chrono>
...@@ -38,6 +36,16 @@ ...@@ -38,6 +36,16 @@
#include <folly/portability/Asm.h> #include <folly/portability/Asm.h>
#include <folly/small_vector.h> #include <folly/small_vector.h>
#if __has_include(<poll.h>)
#include <poll.h>
#endif
#if __has_include(<liburing.h>)
#include <liburing.h>
#endif
#if __has_include(<liburing.h>)
namespace folly { namespace folly {
class IoUringBackend : public EventBaseBackendBase { class IoUringBackend : public EventBaseBackendBase {
...@@ -953,3 +961,5 @@ class IoUringBackend : public EventBaseBackendBase { ...@@ -953,3 +961,5 @@ class IoUringBackend : public EventBaseBackendBase {
using PollIoBackend = IoUringBackend; using PollIoBackend = IoUringBackend;
} // namespace folly } // namespace folly
#endif // __has_include(<liburing.h>)
...@@ -17,79 +17,68 @@ ...@@ -17,79 +17,68 @@
#include <folly/experimental/io/SimpleAsyncIO.h> #include <folly/experimental/io/SimpleAsyncIO.h>
#include <folly/String.h> #include <folly/String.h>
#if __has_include(<folly/experimental/io/AsyncIO.h>) && __has_include(<libaio.h>) #include <folly/experimental/coro/Baton.h>
#define AIO_SUPPORTED
#include <folly/experimental/io/AsyncIO.h> #include <folly/experimental/io/AsyncIO.h>
#endif
#if __has_include(<folly/experimental/io/IoUring.h>) && __has_include(<liburing.h>)
#define IOURING_SUPPORTED
#include <folly/experimental/io/IoUring.h> #include <folly/experimental/io/IoUring.h>
#include <folly/portability/Sockets.h>
namespace folly {
#if __has_include(<libaio.h>)
static constexpr bool has_aio = true;
using aio_type = AsyncIO;
#else
static constexpr bool has_aio = false;
using aio_type = void;
#endif #endif
#if !defined(AIO_SUPPORTED) && !defined(IOURING_SUPPORTED) #if __has_include(<liburing.h>)
#error "Cannot build without at least one of AsyncIO.h and IoUring.h" static constexpr auto has_io_uring_rt = &IoUring::isAvailable;
using io_uring_type = IoUring;
#else
static constexpr auto has_io_uring_rt = +[] { return false; };
using io_uring_type = void;
#endif #endif
#include <folly/experimental/coro/Baton.h> template <typename AsyncIOType>
#include <folly/portability/Sockets.h> void SimpleAsyncIO::init() {
asyncIO_ = std::make_unique<AsyncIOType>(maxRequests_, AsyncBase::POLLABLE);
opsFreeList_.withWLock([this](auto& freeList) {
for (size_t i = 0; i < maxRequests_; ++i) {
freeList.push(std::make_unique<typename AsyncIOType::Op>());
}
});
}
namespace folly { template <>
void SimpleAsyncIO::init<void>() {}
SimpleAsyncIO::SimpleAsyncIO(Config cfg) SimpleAsyncIO::SimpleAsyncIO(Config cfg)
: maxRequests_(cfg.maxRequests_), : maxRequests_(cfg.maxRequests_),
completionExecutor_(cfg.completionExecutor_), completionExecutor_(cfg.completionExecutor_),
terminating_(false) { terminating_(false) {
#if !defined(AIO_SUPPORTED) static bool has_io_uring = has_io_uring_rt();
if (cfg.mode_ == AIO) { if (!has_aio && !has_io_uring) {
LOG(WARNING) LOG(FATAL) << "neither aio nor io_uring is available";
<< "aio mode requested but not available at link time, falling back to io_uring.";
cfg.setMode(IOURING);
} }
#endif if (cfg.mode_ == AIO && !has_aio) {
#if !defined(IOURING_SUPPORTED) LOG(WARNING) << "aio requested but unavailable: falling back to io_uring";
if (cfg.mode_ == IOURING) { cfg.setMode(IOURING);
LOG(WARNING)
<< "io_uring mode requested but not available at link time, falling back to aio.";
cfg.setMode(AIO);
} }
#else if (cfg.mode_ == IOURING && !has_io_uring) {
if (cfg.mode_ == IOURING && !IoUring::isAvailable()) { LOG(WARNING) << "io_uring requested but unavailable: falling back to aio";
#if defined(AIO_SUPPORTED)
LOG(WARNING)
<< "io_uring requested but not available at runtime, falling back to aio mode.";
cfg.setMode(AIO); cfg.setMode(AIO);
#else
LOG(FATAL)
<< "io_uring requested but not available at runtime, aio not available at link time, cannot proceed.";
#endif
} }
#endif
switch (cfg.mode_) { switch (cfg.mode_) {
#if defined(AIO_SUPPORTED)
case AIO: case AIO:
asyncIO_ = std::make_unique<AsyncIO>(maxRequests_, AsyncBase::POLLABLE); init<aio_type>();
opsFreeList_.withWLock(
[this](std::queue<std::unique_ptr<AsyncBaseOp>>& freeList) {
for (size_t i = 0; i < maxRequests_; ++i) {
freeList.push(std::make_unique<AsyncIOOp>());
}
});
break; break;
#endif
#ifdef IOURING_SUPPORTED
case IOURING: case IOURING:
asyncIO_ = std::make_unique<IoUring>(maxRequests_, AsyncBase::POLLABLE); init<io_uring_type>();
opsFreeList_.withWLock(
[this](std::queue<std::unique_ptr<AsyncBaseOp>>& freeList) {
for (size_t i = 0; i < maxRequests_; ++i) {
freeList.push(std::make_unique<IoUringOp>());
}
});
break; break;
#endif
default: default:
// Should never happen... // Should never happen...
LOG(FATAL) << "Unavailable mode " << (int)cfg.mode_ << " requested."; LOG(FATAL) << "unrecognized mode " << (int)cfg.mode_ << " requested";
break; break;
} }
......
...@@ -164,6 +164,9 @@ class SimpleAsyncIO : public EventHandler { ...@@ -164,6 +164,9 @@ class SimpleAsyncIO : public EventHandler {
virtual void handlerReady(uint16_t events) noexcept override; virtual void handlerReady(uint16_t events) noexcept override;
template <typename AsyncIOType>
void init();
size_t maxRequests_; size_t maxRequests_;
Executor::KeepAlive<> completionExecutor_; Executor::KeepAlive<> completionExecutor_;
std::unique_ptr<AsyncBase> asyncIO_; std::unique_ptr<AsyncBase> asyncIO_;
......
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