Range<AsyncIO::Op**> AsyncIO::doWait(size_t minRequests, size_t maxRequests) { io_event events[pending_]; int count; do { // Wait forever count = io_getevents(ctx_, minRequests, maxRequests, events, nullptr); } while (count == -EINTR); checkKernelError(count, "AsyncIO: io_getevents failed"); DCHECK_GE(count, minRequests); // the man page says so DCHECK_LE(count, pending_); completed_.clear(); if (count == 0) { return folly::Range<Op**>(); } for (size_t i = 0; i < count; ++i) { DCHECK(events[i].obj); Op* op = boost::intrusive::get_parent_from_member( events[i].obj, &AsyncIOOp::iocb_); --pending_; op->complete(events[i].res); completed_.push_back(op); } return folly::Range<Op**>(&completed_.front(), count); }
void AsyncIO::initializeContext() { if (!ctxSet_.load(std::memory_order_acquire)) { std::lock_guard<std::mutex> lock(initMutex_); if (!ctxSet_.load(std::memory_order_relaxed)) { int rc = io_queue_init(capacity_, &ctx_); // returns negative errno if (rc == -EAGAIN) { long aio_nr, aio_max; std::unique_ptr<FILE, int(*)(FILE*)> fp(fopen("/proc/sys/fs/aio-nr", "r"), fclose); PCHECK(fp); CHECK_EQ(fscanf(fp.get(), "%ld", &aio_nr), 1); std::unique_ptr<FILE, int(*)(FILE*)> aio_max_fp(fopen("/proc/sys/fs/aio-max-nr", "r"), fclose); PCHECK(aio_max_fp); CHECK_EQ(fscanf(aio_max_fp.get(), "%ld", &aio_max), 1); LOG(ERROR) << "No resources for requested capacity of " << capacity_; LOG(ERROR) << "aio_nr " << aio_nr << ", aio_max_nr " << aio_max; } checkKernelError(rc, "AsyncIO: io_queue_init failed"); DCHECK(ctx_); ctxSet_.store(true, std::memory_order_release); } } }
void AsyncIO::initializeContext() { if (!ctx_) { int rc = io_queue_init(capacity_, &ctx_); // returns negative errno checkKernelError(rc, "AsyncIO: io_queue_init failed"); DCHECK(ctx_); } }
void AsyncIO::submit(Op* op) { CHECK_EQ(op->state(), Op::State::INITIALIZED); CHECK_LT(pending_, capacity_) << "too many pending requests"; initializeContext(); // on demand iocb* cb = &op->iocb_; cb->data = nullptr; // unused if (pollFd_ != -1) { io_set_eventfd(cb, pollFd_); } int rc = io_submit(ctx_, 1, &cb); checkKernelError(rc, "AsyncIO: io_submit failed"); DCHECK_EQ(rc, 1); op->start(); ++pending_; }