1487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang/* 2487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang * Copyright (C) 2016 The Android Open Source Project 3487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang * 4487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang * Licensed under the Apache License, Version 2.0 (the "License"); 5487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang * you may not use this file except in compliance with the License. 6487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang * You may obtain a copy of the License at 7487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang * 8487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang * http://www.apache.org/licenses/LICENSE-2.0 9487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang * 10487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang * Unless required by applicable law or agreed to in writing, software 11487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang * distributed under the License is distributed on an "AS IS" BASIS, 12487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang * See the License for the specific language governing permissions and 14487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang * limitations under the License. 15487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang */ 16487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 17487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang#include <android-base/logging.h> 18487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang#include <condition_variable> 19487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang#include <memory> 20487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang#include <mutex> 21487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang#include <queue> 22487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 23487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang#include "AsyncIO.h" 24487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 25487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangnamespace { 26487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 27487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangvoid read_func(struct aiocb *aiocbp) { 28487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aiocbp->ret = TEMP_FAILURE_RETRY(pread(aiocbp->aio_fildes, 29487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aiocbp->aio_buf, aiocbp->aio_nbytes, aiocbp->aio_offset)); 30487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang if (aiocbp->ret == -1) aiocbp->error = errno; 31487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 32487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 33487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangvoid write_func(struct aiocb *aiocbp) { 34487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aiocbp->ret = TEMP_FAILURE_RETRY(pwrite(aiocbp->aio_fildes, 35487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aiocbp->aio_buf, aiocbp->aio_nbytes, aiocbp->aio_offset)); 36487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang if (aiocbp->ret == -1) aiocbp->error = errno; 37487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 38487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 39487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangvoid splice_read_func(struct aiocb *aiocbp) { 408e889ef487c1adb3a5a02ff41712fbca44fd449fJerry Zhang loff_t long_offset = aiocbp->aio_offset; 41487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aiocbp->ret = TEMP_FAILURE_RETRY(splice(aiocbp->aio_fildes, 428e889ef487c1adb3a5a02ff41712fbca44fd449fJerry Zhang &long_offset, aiocbp->aio_sink, 43487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang NULL, aiocbp->aio_nbytes, 0)); 44487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang if (aiocbp->ret == -1) aiocbp->error = errno; 45487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 46487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 47487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangvoid splice_write_func(struct aiocb *aiocbp) { 488e889ef487c1adb3a5a02ff41712fbca44fd449fJerry Zhang loff_t long_offset = aiocbp->aio_offset; 49487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aiocbp->ret = TEMP_FAILURE_RETRY(splice(aiocbp->aio_fildes, NULL, 508e889ef487c1adb3a5a02ff41712fbca44fd449fJerry Zhang aiocbp->aio_sink, &long_offset, 51487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aiocbp->aio_nbytes, 0)); 52487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang if (aiocbp->ret == -1) aiocbp->error = errno; 53487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 54487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 55487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangstd::queue<std::unique_ptr<struct aiocb>> queue; 56487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangstd::mutex queue_lock; 57487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangstd::condition_variable queue_cond; 58487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangstd::condition_variable write_cond; 59487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangint done = 1; 60487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangvoid splice_write_pool_func(int) { 61487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang while(1) { 62487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang std::unique_lock<std::mutex> lk(queue_lock); 63487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang queue_cond.wait(lk, []{return !queue.empty() || done;}); 64487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang if (queue.empty() && done) { 65487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang return; 66487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang } 67487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang std::unique_ptr<struct aiocb> aiocbp = std::move(queue.front()); 68487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang queue.pop(); 69487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang lk.unlock(); 70487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang write_cond.notify_one(); 71487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang splice_write_func(aiocbp.get()); 72487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang close(aiocbp->aio_fildes); 73487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang } 74487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 75487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 76487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangvoid write_pool_func(int) { 77487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang while(1) { 78487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang std::unique_lock<std::mutex> lk(queue_lock); 79487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang queue_cond.wait(lk, []{return !queue.empty() || done;}); 80487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang if (queue.empty() && done) { 81487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang return; 82487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang } 83487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang std::unique_ptr<struct aiocb> aiocbp = std::move(queue.front()); 84487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang queue.pop(); 85487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang lk.unlock(); 86487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang write_cond.notify_one(); 87487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aiocbp->ret = TEMP_FAILURE_RETRY(pwrite(aiocbp->aio_fildes, 88487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aiocbp->aio_pool_buf.get(), aiocbp->aio_nbytes, aiocbp->aio_offset)); 89487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang if (aiocbp->ret == -1) aiocbp->error = errno; 90487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang } 91487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 92487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 93487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangconstexpr int NUM_THREADS = 1; 94487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangconstexpr int MAX_QUEUE_SIZE = 10; 95487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangstd::thread pool[NUM_THREADS]; 96487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 97487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} // end anonymous namespace 98487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 997063c936e50326883e672837036381f77080c2f3Jerry Zhangaiocb::~aiocb() { 1007063c936e50326883e672837036381f77080c2f3Jerry Zhang CHECK(!thread.joinable()); 1017063c936e50326883e672837036381f77080c2f3Jerry Zhang} 1027063c936e50326883e672837036381f77080c2f3Jerry Zhang 103487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangvoid aio_pool_init(void(f)(int)) { 104487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang CHECK(done == 1); 105487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang done = 0; 106487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang for (int i = 0; i < NUM_THREADS; i++) { 107487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang pool[i] = std::thread(f, i); 108487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang } 109487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 110487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 111487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangvoid aio_pool_splice_init() { 112487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aio_pool_init(splice_write_pool_func); 113487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 114487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 115487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangvoid aio_pool_write_init() { 116487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aio_pool_init(write_pool_func); 117487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 118487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 119487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangvoid aio_pool_end() { 120487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang done = 1; 121487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang for (int i = 0; i < NUM_THREADS; i++) { 122487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang std::unique_lock<std::mutex> lk(queue_lock); 123487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang lk.unlock(); 124487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang queue_cond.notify_one(); 125487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang } 126487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 127487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang for (int i = 0; i < NUM_THREADS; i++) { 128487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang pool[i].join(); 129487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang } 130487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 131487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 132487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang// used for both writes and splices depending on which init was used before. 133487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangint aio_pool_write(struct aiocb *aiocbp) { 134487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang std::unique_lock<std::mutex> lk(queue_lock); 135487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang write_cond.wait(lk, []{return queue.size() < MAX_QUEUE_SIZE;}); 136487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang queue.push(std::unique_ptr<struct aiocb>(aiocbp)); 137487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang lk.unlock(); 138487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang queue_cond.notify_one(); 139487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang return 0; 140487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 141487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 142487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangint aio_read(struct aiocb *aiocbp) { 143487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aiocbp->thread = std::thread(read_func, aiocbp); 144487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang return 0; 145487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 146487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 147487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangint aio_write(struct aiocb *aiocbp) { 148487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aiocbp->thread = std::thread(write_func, aiocbp); 149487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang return 0; 150487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 151487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 152487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangint aio_splice_read(struct aiocb *aiocbp) { 153487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aiocbp->thread = std::thread(splice_read_func, aiocbp); 154487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang return 0; 155487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 156487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 157487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangint aio_splice_write(struct aiocb *aiocbp) { 158487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aiocbp->thread = std::thread(splice_write_func, aiocbp); 159487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang return 0; 160487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 161487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 162487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangint aio_error(const struct aiocb *aiocbp) { 163487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang return aiocbp->error; 164487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 165487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 166487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangssize_t aio_return(struct aiocb *aiocbp) { 167487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang return aiocbp->ret; 168487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 169487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 170487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangint aio_suspend(struct aiocb *aiocbp[], int n, 171487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang const struct timespec *) { 172487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang for (int i = 0; i < n; i++) { 173487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang aiocbp[i]->thread.join(); 174487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang } 175487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang return 0; 176487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 177487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 178487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhangint aio_cancel(int, struct aiocb *) { 179487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang // Not implemented 180487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang return -1; 181487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang} 182487be61fb0a38873aec1d12da92437fba5e728f2Jerry Zhang 183