1515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <binder/Binder.h> 2515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <binder/IBinder.h> 3515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <binder/IPCThreadState.h> 4515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <binder/IServiceManager.h> 5515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <string> 6515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <cstring> 7515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <cstdlib> 8515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <cstdio> 9515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 10515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <iostream> 11515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <vector> 12515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <tuple> 13515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 14515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <unistd.h> 15515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <sys/wait.h> 16515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 17515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsusing namespace std; 18515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsusing namespace android; 19515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 20515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsenum BinderWorkerServiceCode { 21515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews BINDER_NOP = IBinder::FIRST_CALL_TRANSACTION, 22515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews}; 23515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 24515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#define ASSERT_TRUE(cond) \ 25515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsdo { \ 26515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (!(cond)) {\ 27515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cerr << __func__ << ":" << __LINE__ << " condition:" << #cond << " failed\n" << endl; \ 28515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews exit(EXIT_FAILURE); \ 29515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } \ 30515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews} while (0) 31515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 32515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsclass BinderWorkerService : public BBinder 33515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews{ 34515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewspublic: 35515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews BinderWorkerService() {} 36515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ~BinderWorkerService() {} 37515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews virtual status_t onTransact(uint32_t code, 38515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews const Parcel& data, Parcel* reply, 39515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint32_t flags = 0) { 40515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews (void)flags; 41515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews (void)data; 42515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews (void)reply; 43515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews switch (code) { 44515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews case BINDER_NOP: 45515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return NO_ERROR; 46515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews default: 47515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return UNKNOWN_TRANSACTION; 48515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews }; 49515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 50515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews}; 51515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 52515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsclass Pipe { 53515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int m_readFd; 54515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int m_writeFd; 55515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews Pipe(int readFd, int writeFd) : m_readFd{readFd}, m_writeFd{writeFd} {} 56515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews Pipe(const Pipe &) = delete; 57515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews Pipe& operator=(const Pipe &) = delete; 58515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews Pipe& operator=(const Pipe &&) = delete; 59515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewspublic: 60515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews Pipe(Pipe&& rval) noexcept { 61515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews m_readFd = rval.m_readFd; 62515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews m_writeFd = rval.m_writeFd; 63515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews rval.m_readFd = 0; 64515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews rval.m_writeFd = 0; 65515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 66515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ~Pipe() { 67515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (m_readFd) 68515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews close(m_readFd); 69515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (m_writeFd) 70515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews close(m_writeFd); 71515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 72515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews void signal() { 73515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews bool val = true; 74515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int error = write(m_writeFd, &val, sizeof(val)); 75515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ASSERT_TRUE(error >= 0); 76515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews }; 77515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews void wait() { 78515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews bool val = false; 79515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int error = read(m_readFd, &val, sizeof(val)); 80515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ASSERT_TRUE(error >= 0); 81515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 82515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews template <typename T> void send(const T& v) { 83515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int error = write(m_writeFd, &v, sizeof(T)); 84515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ASSERT_TRUE(error >= 0); 85515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 86515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews template <typename T> void recv(T& v) { 87515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int error = read(m_readFd, &v, sizeof(T)); 88515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ASSERT_TRUE(error >= 0); 89515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 90515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews static tuple<Pipe, Pipe> createPipePair() { 91515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int a[2]; 92515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int b[2]; 93515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 94515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int error1 = pipe(a); 95515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int error2 = pipe(b); 96515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ASSERT_TRUE(error1 >= 0); 97515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ASSERT_TRUE(error2 >= 0); 98515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 99515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return make_tuple(Pipe(a[0], b[1]), Pipe(b[0], a[1])); 100515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 101515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews}; 102515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 103515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsstatic const uint32_t num_buckets = 128; 104515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsstatic const uint64_t max_time_bucket = 50ull * 1000000; 105515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsstatic const uint64_t time_per_bucket = max_time_bucket / num_buckets; 106515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsstatic constexpr float time_per_bucket_ms = time_per_bucket / 1.0E6; 107515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 108515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsstruct ProcResults { 109515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint64_t m_best = max_time_bucket; 110515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint64_t m_worst = 0; 111515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint32_t m_buckets[num_buckets] = {0}; 112515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint64_t m_transactions = 0; 113515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint64_t m_total_time = 0; 114515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 115515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews void add_time(uint64_t time) { 116515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews m_buckets[min(time, max_time_bucket-1) / time_per_bucket] += 1; 117515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews m_best = min(time, m_best); 118515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews m_worst = max(time, m_worst); 119515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews m_transactions += 1; 120515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews m_total_time += time; 121515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 122515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews static ProcResults combine(const ProcResults& a, const ProcResults& b) { 123515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ProcResults ret; 124515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < num_buckets; i++) { 125515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ret.m_buckets[i] = a.m_buckets[i] + b.m_buckets[i]; 126515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 127515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ret.m_worst = max(a.m_worst, b.m_worst); 128515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ret.m_best = min(a.m_best, b.m_best); 129515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ret.m_transactions = a.m_transactions + b.m_transactions; 130515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ret.m_total_time = a.m_total_time + b.m_total_time; 131515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return ret; 132515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 133515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews void dump() { 134515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews double best = (double)m_best / 1.0E6; 135515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews double worst = (double)m_worst / 1.0E6; 136515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews double average = (double)m_total_time / m_transactions / 1.0E6; 137515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "average:" << average << "ms worst:" << worst << "ms best:" << best << "ms" << endl; 138515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 139515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint64_t cur_total = 0; 140515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < num_buckets; i++) { 141515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews float cur_time = time_per_bucket_ms * i + 0.5f * time_per_bucket_ms; 142515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if ((cur_total < 0.5f * m_transactions) && (cur_total + m_buckets[i] >= 0.5f * m_transactions)) { 143515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "50%: " << cur_time << " "; 144515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 145515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if ((cur_total < 0.9f * m_transactions) && (cur_total + m_buckets[i] >= 0.9f * m_transactions)) { 146515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "90%: " << cur_time << " "; 147515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 148515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if ((cur_total < 0.95f * m_transactions) && (cur_total + m_buckets[i] >= 0.95f * m_transactions)) { 149515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "95%: " << cur_time << " "; 150515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 151515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if ((cur_total < 0.99f * m_transactions) && (cur_total + m_buckets[i] >= 0.99f * m_transactions)) { 152515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "99%: " << cur_time << " "; 153515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 154515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cur_total += m_buckets[i]; 155515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 156515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << endl; 157515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 158515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 159515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews}; 160515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 161515aa0b911aebb0bd4665bc0b61a693d6951e994Riley AndrewsString16 generateServiceName(int num) 162515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews{ 163515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews char num_str[32]; 164515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews snprintf(num_str, sizeof(num_str), "%d", num); 165515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews String16 serviceName = String16("binderWorker") + String16(num_str); 166515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return serviceName; 167515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews} 168515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 169515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsvoid worker_fx( 170515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int num, 171515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int worker_count, 172515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int iterations, 173515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews Pipe p) 174515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews{ 175515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Create BinderWorkerService and for go. 176515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ProcessState::self()->startThreadPool(); 177515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews sp<IServiceManager> serviceMgr = defaultServiceManager(); 178515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews sp<BinderWorkerService> service = new BinderWorkerService; 179515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews serviceMgr->addService(generateServiceName(num), service); 180515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 181515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews srand(num); 182515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews p.signal(); 183515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews p.wait(); 184515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 185515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Get references to other binder services. 186515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "Created BinderWorker" << num << endl; 187515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews (void)worker_count; 188515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews vector<sp<IBinder> > workers; 189515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < worker_count; i++) { 190515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (num == i) 191515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews continue; 192515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews workers.push_back(serviceMgr->getService(generateServiceName(i))); 193515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 194515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 195515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Run the benchmark. 196515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ProcResults results; 197515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews chrono::time_point<chrono::high_resolution_clock> start, end; 198515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < iterations; i++) { 199515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int target = rand() % workers.size(); 200515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews Parcel data, reply; 201515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews start = chrono::high_resolution_clock::now(); 202515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews status_t ret = workers[target]->transact(BINDER_NOP, data, &reply); 203515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews end = chrono::high_resolution_clock::now(); 204515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 205515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint64_t cur_time = uint64_t(chrono::duration_cast<chrono::nanoseconds>(end - start).count()); 206515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews results.add_time(cur_time); 207515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 208515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (ret != NO_ERROR) { 209515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "thread " << num << " failed " << ret << "i : " << i << endl; 210515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews exit(EXIT_FAILURE); 211515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 212515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 213515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Signal completion to master and wait. 214515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews p.signal(); 215515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews p.wait(); 216515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 217515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Send results to master and wait for go to exit. 218515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews p.send(results); 219515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews p.wait(); 220515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 221515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews exit(EXIT_SUCCESS); 222515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews} 223515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 224515aa0b911aebb0bd4665bc0b61a693d6951e994Riley AndrewsPipe make_worker(int num, int iterations, int worker_count) 225515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews{ 226515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews auto pipe_pair = Pipe::createPipePair(); 227515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews pid_t pid = fork(); 228515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (pid) { 229515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews /* parent */ 230515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return move(get<0>(pipe_pair)); 231515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } else { 232515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews /* child */ 233515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews worker_fx(num, worker_count, iterations, move(get<1>(pipe_pair))); 234515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews /* never get here */ 235515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return move(get<0>(pipe_pair)); 236515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 237515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 238515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews} 239515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 240515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsvoid wait_all(vector<Pipe>& v) 241515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews{ 242515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < v.size(); i++) { 243515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews v[i].wait(); 244515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 245515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews} 246515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 247515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsvoid signal_all(vector<Pipe>& v) 248515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews{ 249515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < v.size(); i++) { 250515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews v[i].signal(); 251515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 252515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews} 253515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 254515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsint main(int argc, char *argv[]) 255515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews{ 256515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int workers = 2; 257515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int iterations = 10000; 258515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews (void)argc; 259515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews (void)argv; 260515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews vector<Pipe> pipes; 261515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 262515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Parse arguments. 263515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 1; i < argc; i++) { 264515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (string(argv[i]) == "-w") { 265515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews workers = atoi(argv[i+1]); 266515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews i++; 267515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews continue; 268515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 269515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (string(argv[i]) == "-i") { 270515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews iterations = atoi(argv[i+1]); 271515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews i++; 272515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews continue; 273515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 274515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 275515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 276515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Create all the workers and wait for them to spawn. 277515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < workers; i++) { 278515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews pipes.push_back(make_worker(i, iterations, workers)); 279515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 280515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews wait_all(pipes); 281515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 282515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 283515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Run the workers and wait for completion. 284515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews chrono::time_point<chrono::high_resolution_clock> start, end; 285515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "waiting for workers to complete" << endl; 286515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews start = chrono::high_resolution_clock::now(); 287515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews signal_all(pipes); 288515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews wait_all(pipes); 289515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews end = chrono::high_resolution_clock::now(); 290515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 291515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Calculate overall throughput. 292515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews double iterations_per_sec = double(iterations * workers) / (chrono::duration_cast<chrono::nanoseconds>(end - start).count() / 1.0E9); 293515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "iterations per sec: " << iterations_per_sec << endl; 294515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 295515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Collect all results from the workers. 296515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "collecting results" << endl; 297515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews signal_all(pipes); 298515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ProcResults tot_results; 299515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < workers; i++) { 300515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ProcResults tmp_results; 301515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews pipes[i].recv(tmp_results); 302515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews tot_results = ProcResults::combine(tot_results, tmp_results); 303515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 304515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews tot_results.dump(); 305515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 306515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Kill all the workers. 307515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "killing workers" << endl; 308515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews signal_all(pipes); 309515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < workers; i++) { 310515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int status; 311515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews wait(&status); 312515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (status != 0) { 313515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "nonzero child status" << status << endl; 314515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 315515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 316515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return 0; 317515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews} 318