1d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller/*
2d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller * Copyright (C) 2010 The Android Open Source Project
3d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller *
4d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller * Licensed under the Apache License, Version 2.0 (the "License");
5d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller * you may not use this file except in compliance with the License.
6d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller * You may obtain a copy of the License at
7d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller *
8d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller *      http://www.apache.org/licenses/LICENSE-2.0
9d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller *
10d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller * Unless required by applicable law or agreed to in writing, software
11d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller * distributed under the License is distributed on an "AS IS" BASIS,
12d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller * See the License for the specific language governing permissions and
14d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller * limitations under the License.
15d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller *
16d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller */
17d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
18d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller/*
19b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez * Binder add integers benchmark (Using google-benchmark library)
20d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller *
21d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller */
22d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
23d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <cerrno>
24d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <grp.h>
25d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <iostream>
26f9a1c15c7430c009c522a06b93c8530a0611a6ceJohn Reck#include <iomanip>
27d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <libgen.h>
28d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <time.h>
29d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <unistd.h>
30d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
31d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <sys/syscall.h>
32d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <sys/time.h>
33d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <sys/types.h>
34d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <sys/wait.h>
35d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
36d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <binder/IPCThreadState.h>
37d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <binder/ProcessState.h>
38d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <binder/IServiceManager.h>
39b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez
40b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez#include <benchmark/benchmark.h>
41b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez
42d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <utils/Log.h>
43d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller#include <testUtil.h>
44d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
45d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemillerusing namespace android;
46d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemillerusing namespace std;
47d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
48d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemillerconst int unbound = -1; // Indicator for a thread not bound to a specific CPU
49d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
50d2447fd2505466a8c30cdca247325f79ba95be34Louis HuemillerString16 serviceName("test.binderAddInts");
51d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
52d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemillerstruct options {
53d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    int serverCPU;
54d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    int clientCPU;
55d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    float        iterDelay; // End of iteration delay in seconds
56d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller} options = { // Set defaults
57d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    unbound, // Server CPU
58d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    unbound, // Client CPU
59b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    0.0,    // End of iteration delay
60d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller};
61d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
62d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemillerclass AddIntsService : public BBinder
63d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller{
64d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller  public:
6511b95b9c3a946089d52f205838c05373c954b16eChih-Hung Hsieh    explicit AddIntsService(int cpu = unbound);
66920f089dc6c15a3be3f68ead68ef1d439d5d7c93Bernhard Rosenkränzer    virtual ~AddIntsService() {}
67d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
68d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    enum command {
69d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        ADD_INTS = 0x120,
70d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    };
71d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
72d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    virtual status_t onTransact(uint32_t code,
73d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller                                const Parcel& data, Parcel* reply,
74d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller                                uint32_t flags = 0);
75d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
76d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller  private:
77d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    int cpu_;
78d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller};
79d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
80d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller// File scope function prototypes
81f9a1c15c7430c009c522a06b93c8530a0611a6ceJohn Reckstatic bool server(void);
82187816e5793ad177f6f70fe6270baf1475d74149John Reckstatic void BM_addInts(benchmark::State& state);
83d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemillerstatic void bindCPU(unsigned int cpu);
84d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemillerstatic ostream &operator<<(ostream &stream, const String16& str);
85d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemillerstatic ostream &operator<<(ostream &stream, const cpu_set_t& set);
86d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
87f9a1c15c7430c009c522a06b93c8530a0611a6ceJohn Reckstatic bool server(void)
88d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller{
89d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    int rv;
90d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
91d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    // Add the service
92d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    sp<ProcessState> proc(ProcessState::self());
93d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    sp<IServiceManager> sm = defaultServiceManager();
94d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    if ((rv = sm->addService(serviceName,
95d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        new AddIntsService(options.serverCPU))) != 0) {
96d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        cerr << "addService " << serviceName << " failed, rv: " << rv
97d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller            << " errno: " << errno << endl;
98f9a1c15c7430c009c522a06b93c8530a0611a6ceJohn Reck        return false;
99d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    }
100d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
101d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    // Start threads to handle server work
102d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    proc->startThreadPool();
103f9a1c15c7430c009c522a06b93c8530a0611a6ceJohn Reck    return true;
104d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller}
105d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
106187816e5793ad177f6f70fe6270baf1475d74149John Reckstatic void BM_addInts(benchmark::State& state)
107d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller{
108d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    int rv;
109d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    sp<IServiceManager> sm = defaultServiceManager();
110d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
111d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    // If needed bind to client CPU
112d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    if (options.clientCPU != unbound) { bindCPU(options.clientCPU); }
113d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
114d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    // Attach to service
115d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    sp<IBinder> binder;
116f9a1c15c7430c009c522a06b93c8530a0611a6ceJohn Reck    for (int i = 0; i < 3; i++) {
117d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        binder = sm->getService(serviceName);
118d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        if (binder != 0) break;
119d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        cout << serviceName << " not published, waiting..." << endl;
120d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        usleep(500000); // 0.5 s
121f9a1c15c7430c009c522a06b93c8530a0611a6ceJohn Reck    }
122f9a1c15c7430c009c522a06b93c8530a0611a6ceJohn Reck
123f9a1c15c7430c009c522a06b93c8530a0611a6ceJohn Reck    if (binder == 0) {
124f9a1c15c7430c009c522a06b93c8530a0611a6ceJohn Reck        cout << serviceName << " failed to publish, aborting" << endl;
125f9a1c15c7430c009c522a06b93c8530a0611a6ceJohn Reck        return;
126f9a1c15c7430c009c522a06b93c8530a0611a6ceJohn Reck    }
127d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
128b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    unsigned int iter = 0;
129b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    // Perform the IPC operations in the benchmark
130b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    while (state.KeepRunning()) {
131d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        Parcel send, reply;
132d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
133d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        // Create parcel to be sent.  Will use the iteration cound
134d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        // and the iteration count + 3 as the two integer values
135d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        // to be sent.
136b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        state.PauseTiming();
137d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        int val1 = iter;
138d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        int val2 = iter + 3;
139d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        int expected = val1 + val2;  // Expect to get the sum back
140d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        send.writeInt32(val1);
141d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        send.writeInt32(val2);
142b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        state.ResumeTiming();
143d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        // Send the parcel, while timing how long it takes for
144d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        // the answer to return.
145d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        if ((rv = binder->transact(AddIntsService::ADD_INTS,
146d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller            send, &reply)) != 0) {
147d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller            cerr << "binder->transact failed, rv: " << rv
148d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller                << " errno: " << errno << endl;
149d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller            exit(10);
150d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        }
151b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez
152b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        state.PauseTiming();
153d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        int result = reply.readInt32();
154d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        if (result != (int) (iter + iter + 3)) {
155d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller            cerr << "Unexpected result for iteration " << iter << endl;
156d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller            cerr << "  result: " << result << endl;
157d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller            cerr << "expected: " << expected << endl;
158d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        }
159d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
160f3df372c18c3baf9c0c9c93bce7622818ae6a8a1Louis Huemiller        if (options.iterDelay > 0.0) { testDelaySpin(options.iterDelay); }
161b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        state.ResumeTiming();
162d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    }
163d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller}
164187816e5793ad177f6f70fe6270baf1475d74149John ReckBENCHMARK(BM_addInts);
165b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez
166d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
167d2447fd2505466a8c30cdca247325f79ba95be34Louis HuemillerAddIntsService::AddIntsService(int cpu): cpu_(cpu) {
168d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    if (cpu != unbound) { bindCPU(cpu); }
169920f089dc6c15a3be3f68ead68ef1d439d5d7c93Bernhard Rosenkränzer}
170d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
171d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller// Server function that handles parcels received from the client
172d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemillerstatus_t AddIntsService::onTransact(uint32_t code, const Parcel &data,
1731281503d76c3ce0599dbfba329ba044036b17c16Andreas Gampe                                    Parcel* reply, uint32_t /* flags */) {
174d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    int val1, val2;
175d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    status_t rv(0);
176d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    int cpu;
177d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
178d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    // If server bound to a particular CPU, check that
179d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    // were executing on that CPU.
180d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    if (cpu_ != unbound) {
181e337f25c84b2dfbeca6cb50abe35f6c2956b08c7David 'Digit' Turner        cpu = sched_getcpu();
182d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        if (cpu != cpu_) {
183d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller            cerr << "server onTransact on CPU " << cpu << " expected CPU "
184d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller                  << cpu_ << endl;
185d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller            exit(20);
186d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        }
187d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    }
188d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
189d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    // Perform the requested operation
190d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    switch (code) {
191d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    case ADD_INTS:
192d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        val1 = data.readInt32();
193d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        val2 = data.readInt32();
194d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        reply->writeInt32(val1 + val2);
195d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        break;
196d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
197d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    default:
198d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller      cerr << "server onTransact unknown code, code: " << code << endl;
199d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller      exit(21);
200d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    }
201d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
202d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    return rv;
203d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller}
204d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
205d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemillerstatic void bindCPU(unsigned int cpu)
206d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller{
207d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    int rv;
208d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    cpu_set_t cpuset;
209d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
210d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    CPU_ZERO(&cpuset);
211d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    CPU_SET(cpu, &cpuset);
212d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    rv = sched_setaffinity(0, sizeof(cpuset), &cpuset);
213d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
214d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    if (rv != 0) {
215d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        cerr << "bindCPU failed, rv: " << rv << " errno: " << errno << endl;
216d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        perror(NULL);
217d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        exit(30);
218d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    }
219d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller}
220d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
221d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemillerstatic ostream &operator<<(ostream &stream, const String16& str)
222d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller{
223d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    for (unsigned int n1 = 0; n1 < str.size(); n1++) {
224d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        if ((str[n1] > 0x20) && (str[n1] < 0x80)) {
225d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller            stream << (char) str[n1];
226d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        } else {
227d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller            stream << '~';
228d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        }
229d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    }
230d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
231d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    return stream;
232d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller}
233d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
234d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemillerstatic ostream &operator<<(ostream &stream, const cpu_set_t& set)
235d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller{
236d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    for (unsigned int n1 = 0; n1 < CPU_SETSIZE; n1++) {
237d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        if (CPU_ISSET(n1, &set)) {
238d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller            if (n1 != 0) { stream << ' '; }
239d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller            stream << n1;
240d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller        }
241d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    }
242d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller
243d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller    return stream;
244d2447fd2505466a8c30cdca247325f79ba95be34Louis Huemiller}
245b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez
246b529b0634351d6e175dd011754095b8e567c21cfJulien Desprezint main(int argc, char *argv[])
247b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez{
248b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    int rv;
249b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    ::benchmark::Initialize(&argc, argv);
250b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    // Determine CPUs available for use.
251b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    // This testcase limits its self to using CPUs that were
252b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    // available at the start of the benchmark.
253b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    cpu_set_t availCPUs;
254b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    if ((rv = sched_getaffinity(0, sizeof(availCPUs), &availCPUs)) != 0) {
255b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        cerr << "sched_getaffinity failure, rv: " << rv
256b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            << " errno: " << errno << endl;
257b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        exit(1);
258b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    }
259b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez
260b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    // Parse command line arguments
261b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    int opt;
262b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    while ((opt = getopt(argc, argv, "s:c:d:?")) != -1) {
263b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        char *chptr; // character pointer for command-line parsing
264b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez
265b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        switch (opt) {
266b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        case 'c': // client CPU
267b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        case 's': { // server CPU
268b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            // Parse the CPU number
269b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            int cpu = strtoul(optarg, &chptr, 10);
270b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            if (*chptr != '\0') {
271b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez                cerr << "Invalid cpu specified for -" << (char) opt
272b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez                    << " option of: " << optarg << endl;
273b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez                exit(2);
274b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            }
275b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez
276b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            // Is the CPU available?
277b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            if (!CPU_ISSET(cpu, &availCPUs)) {
278b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez                cerr << "CPU " << optarg << " not currently available" << endl;
279b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez                cerr << "  Available CPUs: " << availCPUs << endl;
280b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez                exit(3);
281b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            }
282b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez
283b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            // Record the choice
284b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            *((opt == 'c') ? &options.clientCPU : &options.serverCPU) = cpu;
285b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            break;
286b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        }
287b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez
288b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        case 'd': // delay between each iteration
289b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            options.iterDelay = strtod(optarg, &chptr);
290b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            if ((*chptr != '\0') || (options.iterDelay < 0.0)) {
291b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez                cerr << "Invalid delay specified of: " << optarg << endl;
292b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez                exit(6);
293b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            }
294b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            break;
295b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez
296b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        case '?':
297b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        default:
298b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            cerr << basename(argv[0]) << " [options]" << endl;
299b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            cerr << "  options:" << endl;
300b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            cerr << "    -s cpu - server CPU number" << endl;
301b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            cerr << "    -c cpu - client CPU number" << endl;
302b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            cerr << "    -d time - delay after operation in seconds" << endl;
303b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez            exit(((optopt == 0) || (optopt == '?')) ? 0 : 7);
304b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez        }
305b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez    }
306b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez
307187816e5793ad177f6f70fe6270baf1475d74149John Reck    fflush(stdout);
308187816e5793ad177f6f70fe6270baf1475d74149John Reck    switch (pid_t pid = fork()) {
309187816e5793ad177f6f70fe6270baf1475d74149John Reck    case 0: // Child
310187816e5793ad177f6f70fe6270baf1475d74149John Reck        ::benchmark::RunSpecifiedBenchmarks();
311187816e5793ad177f6f70fe6270baf1475d74149John Reck        return 0;
312187816e5793ad177f6f70fe6270baf1475d74149John Reck
313187816e5793ad177f6f70fe6270baf1475d74149John Reck    default: // Parent
314187816e5793ad177f6f70fe6270baf1475d74149John Reck        if (!server()) { break; }
315187816e5793ad177f6f70fe6270baf1475d74149John Reck
316187816e5793ad177f6f70fe6270baf1475d74149John Reck        // Wait for all children to end
317187816e5793ad177f6f70fe6270baf1475d74149John Reck        do {
318187816e5793ad177f6f70fe6270baf1475d74149John Reck            int stat;
319187816e5793ad177f6f70fe6270baf1475d74149John Reck            rv = wait(&stat);
320187816e5793ad177f6f70fe6270baf1475d74149John Reck            if ((rv == -1) && (errno == ECHILD)) { break; }
321187816e5793ad177f6f70fe6270baf1475d74149John Reck            if (rv == -1) {
322187816e5793ad177f6f70fe6270baf1475d74149John Reck                cerr << "wait failed, rv: " << rv << " errno: "
323187816e5793ad177f6f70fe6270baf1475d74149John Reck                    << errno << endl;
324187816e5793ad177f6f70fe6270baf1475d74149John Reck                perror(NULL);
325187816e5793ad177f6f70fe6270baf1475d74149John Reck                exit(8);
326187816e5793ad177f6f70fe6270baf1475d74149John Reck            }
327187816e5793ad177f6f70fe6270baf1475d74149John Reck        } while (1);
328187816e5793ad177f6f70fe6270baf1475d74149John Reck        return 0;
329b529b0634351d6e175dd011754095b8e567c21cfJulien Desprez
330187816e5793ad177f6f70fe6270baf1475d74149John Reck    case -1: // Error
331187816e5793ad177f6f70fe6270baf1475d74149John Reck        exit(9);
332187816e5793ad177f6f70fe6270baf1475d74149John Reck    }
333187816e5793ad177f6f70fe6270baf1475d74149John Reck}
334