1c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <binder/Binder.h>
2c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <binder/IBinder.h>
3c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <binder/IPCThreadState.h>
4c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <binder/IServiceManager.h>
5c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <cstdio>
6c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <cstdlib>
7c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <cstring>
8c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <string>
9c135dbcace640473035b613bce3460048b4d94cdHoward Chen
10c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <iomanip>
11c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <iostream>
12c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <tuple>
13c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <vector>
14c135dbcace640473035b613bce3460048b4d94cdHoward Chen
15c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <pthread.h>
16c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <sys/wait.h>
17c135dbcace640473035b613bce3460048b4d94cdHoward Chen#include <unistd.h>
1825715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen#include <fstream>
19c135dbcace640473035b613bce3460048b4d94cdHoward Chen
20c135dbcace640473035b613bce3460048b4d94cdHoward Chenusing namespace std;
21c135dbcace640473035b613bce3460048b4d94cdHoward Chenusing namespace android;
22c135dbcace640473035b613bce3460048b4d94cdHoward Chen
23c135dbcace640473035b613bce3460048b4d94cdHoward Chenenum BinderWorkerServiceCode {
24c135dbcace640473035b613bce3460048b4d94cdHoward Chen  BINDER_NOP = IBinder::FIRST_CALL_TRANSACTION,
25c135dbcace640473035b613bce3460048b4d94cdHoward Chen};
26c135dbcace640473035b613bce3460048b4d94cdHoward Chen
27c135dbcace640473035b613bce3460048b4d94cdHoward Chen#define ASSERT(cond)                                                \
28c135dbcace640473035b613bce3460048b4d94cdHoward Chen  do {                                                              \
29c135dbcace640473035b613bce3460048b4d94cdHoward Chen    if (!(cond)) {                                                  \
30c135dbcace640473035b613bce3460048b4d94cdHoward Chen      cerr << __func__ << ":" << __LINE__ << " condition:" << #cond \
31c135dbcace640473035b613bce3460048b4d94cdHoward Chen           << " failed\n"                                           \
32c135dbcace640473035b613bce3460048b4d94cdHoward Chen           << endl;                                                 \
33c135dbcace640473035b613bce3460048b4d94cdHoward Chen      exit(EXIT_FAILURE);                                           \
34c135dbcace640473035b613bce3460048b4d94cdHoward Chen    }                                                               \
35c135dbcace640473035b613bce3460048b4d94cdHoward Chen  } while (0)
36c135dbcace640473035b613bce3460048b4d94cdHoward Chen
37c135dbcace640473035b613bce3460048b4d94cdHoward Chenvector<sp<IBinder> > workers;
38c135dbcace640473035b613bce3460048b4d94cdHoward Chen
39c135dbcace640473035b613bce3460048b4d94cdHoward Chen// the ratio that the service is synced on the same cpu beyond
40c135dbcace640473035b613bce3460048b4d94cdHoward Chen// GOOD_SYNC_MIN is considered as good
41c135dbcace640473035b613bce3460048b4d94cdHoward Chen#define GOOD_SYNC_MIN (0.6)
42c135dbcace640473035b613bce3460048b4d94cdHoward Chen
4360c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen#define DUMP_PRESICION 2
44c135dbcace640473035b613bce3460048b4d94cdHoward Chen
4525715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chenstring trace_path = "/sys/kernel/debug/tracing";
4625715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen
47c135dbcace640473035b613bce3460048b4d94cdHoward Chen// the default value
48c135dbcace640473035b613bce3460048b4d94cdHoward Chenint no_process = 2;
49c135dbcace640473035b613bce3460048b4d94cdHoward Chenint iterations = 100;
50c135dbcace640473035b613bce3460048b4d94cdHoward Chenint payload_size = 16;
51c135dbcace640473035b613bce3460048b4d94cdHoward Chenint no_inherent = 0;
52c135dbcace640473035b613bce3460048b4d94cdHoward Chenint no_sync = 0;
53c135dbcace640473035b613bce3460048b4d94cdHoward Chenint verbose = 0;
5425715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chenint trace;
5525715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen
5625715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chenbool traceIsOn() {
5725715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  fstream file;
5825715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  file.open(trace_path + "/tracing_on", ios::in);
5925715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  char on;
6025715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  file >> on;
6125715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  file.close();
6225715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  return on == '1';
6325715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen}
6425715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen
6525715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chenvoid traceStop() {
6625715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  ofstream file;
6725715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  file.open(trace_path + "/tracing_on", ios::out | ios::trunc);
6825715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  file << '0' << endl;
6925715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  file.close();
7025715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen}
71c135dbcace640473035b613bce3460048b4d94cdHoward Chen
72c135dbcace640473035b613bce3460048b4d94cdHoward Chen// the deadline latency that we are interested in
73c135dbcace640473035b613bce3460048b4d94cdHoward Chenuint64_t deadline_us = 2500;
74c135dbcace640473035b613bce3460048b4d94cdHoward Chen
75c135dbcace640473035b613bce3460048b4d94cdHoward Chenint thread_pri() {
76c135dbcace640473035b613bce3460048b4d94cdHoward Chen  struct sched_param param;
77c135dbcace640473035b613bce3460048b4d94cdHoward Chen  int policy;
78c135dbcace640473035b613bce3460048b4d94cdHoward Chen  ASSERT(!pthread_getschedparam(pthread_self(), &policy, &param));
79c135dbcace640473035b613bce3460048b4d94cdHoward Chen  return param.sched_priority;
80c135dbcace640473035b613bce3460048b4d94cdHoward Chen}
81c135dbcace640473035b613bce3460048b4d94cdHoward Chen
82c135dbcace640473035b613bce3460048b4d94cdHoward Chenvoid thread_dump(const char* prefix) {
83c135dbcace640473035b613bce3460048b4d94cdHoward Chen  struct sched_param param;
84c135dbcace640473035b613bce3460048b4d94cdHoward Chen  int policy;
85c135dbcace640473035b613bce3460048b4d94cdHoward Chen  if (!verbose) return;
86c135dbcace640473035b613bce3460048b4d94cdHoward Chen  cout << "--------------------------------------------------" << endl;
87c135dbcace640473035b613bce3460048b4d94cdHoward Chen  cout << setw(12) << left << prefix << " pid: " << getpid()
88c135dbcace640473035b613bce3460048b4d94cdHoward Chen       << " tid: " << gettid() << " cpu: " << sched_getcpu() << endl;
89c135dbcace640473035b613bce3460048b4d94cdHoward Chen  ASSERT(!pthread_getschedparam(pthread_self(), &policy, &param));
90c135dbcace640473035b613bce3460048b4d94cdHoward Chen  string s = (policy == SCHED_OTHER)
91c135dbcace640473035b613bce3460048b4d94cdHoward Chen                 ? "SCHED_OTHER"
92c135dbcace640473035b613bce3460048b4d94cdHoward Chen                 : (policy == SCHED_FIFO)
93c135dbcace640473035b613bce3460048b4d94cdHoward Chen                       ? "SCHED_FIFO"
94c135dbcace640473035b613bce3460048b4d94cdHoward Chen                       : (policy == SCHED_RR) ? "SCHED_RR" : "???";
95c135dbcace640473035b613bce3460048b4d94cdHoward Chen  cout << setw(12) << left << s << param.sched_priority << endl;
96c135dbcace640473035b613bce3460048b4d94cdHoward Chen  return;
97c135dbcace640473035b613bce3460048b4d94cdHoward Chen}
98c135dbcace640473035b613bce3460048b4d94cdHoward Chen
99c135dbcace640473035b613bce3460048b4d94cdHoward Chenclass BinderWorkerService : public BBinder {
100c135dbcace640473035b613bce3460048b4d94cdHoward Chen public:
101c135dbcace640473035b613bce3460048b4d94cdHoward Chen  BinderWorkerService() {
102c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
103c135dbcace640473035b613bce3460048b4d94cdHoward Chen  ~BinderWorkerService() {
104c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
105c135dbcace640473035b613bce3460048b4d94cdHoward Chen  virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
106c135dbcace640473035b613bce3460048b4d94cdHoward Chen                              uint32_t flags = 0) {
107c135dbcace640473035b613bce3460048b4d94cdHoward Chen    (void)flags;
108c135dbcace640473035b613bce3460048b4d94cdHoward Chen    (void)data;
109c135dbcace640473035b613bce3460048b4d94cdHoward Chen    (void)reply;
110c135dbcace640473035b613bce3460048b4d94cdHoward Chen    switch (code) {
111c135dbcace640473035b613bce3460048b4d94cdHoward Chen      // The transaction format is like
112c135dbcace640473035b613bce3460048b4d94cdHoward Chen      //
113c135dbcace640473035b613bce3460048b4d94cdHoward Chen      // data[in]:  int32: caller priority
114c135dbcace640473035b613bce3460048b4d94cdHoward Chen      //            int32: caller cpu
115c135dbcace640473035b613bce3460048b4d94cdHoward Chen      //
116c135dbcace640473035b613bce3460048b4d94cdHoward Chen      // reply[out]: int32: 1 if caller's priority != callee's priority
117c135dbcace640473035b613bce3460048b4d94cdHoward Chen      //             int32: 1 if caller's cpu != callee's cpu
118c135dbcace640473035b613bce3460048b4d94cdHoward Chen      //
119c135dbcace640473035b613bce3460048b4d94cdHoward Chen      // note the caller cpu read here is not always correct
120c135dbcace640473035b613bce3460048b4d94cdHoward Chen      // there're still chances that the caller got switched out
121c135dbcace640473035b613bce3460048b4d94cdHoward Chen      // right after it read the cpu number and still before the transaction.
122c135dbcace640473035b613bce3460048b4d94cdHoward Chen      case BINDER_NOP: {
123c135dbcace640473035b613bce3460048b4d94cdHoward Chen        thread_dump("binder");
124c135dbcace640473035b613bce3460048b4d94cdHoward Chen        int priority = thread_pri();
125c135dbcace640473035b613bce3460048b4d94cdHoward Chen        int priority_caller = data.readInt32();
126c135dbcace640473035b613bce3460048b4d94cdHoward Chen        int h = 0, s = 0;
127c135dbcace640473035b613bce3460048b4d94cdHoward Chen        if (priority_caller != priority) {
128c135dbcace640473035b613bce3460048b4d94cdHoward Chen          h++;
129c135dbcace640473035b613bce3460048b4d94cdHoward Chen          if (verbose) {
130c135dbcace640473035b613bce3460048b4d94cdHoward Chen            cout << "err priority_caller:" << priority_caller
131c135dbcace640473035b613bce3460048b4d94cdHoward Chen                 << ", priority:" << priority << endl;
132c135dbcace640473035b613bce3460048b4d94cdHoward Chen          }
133c135dbcace640473035b613bce3460048b4d94cdHoward Chen        }
134c135dbcace640473035b613bce3460048b4d94cdHoward Chen        if (priority == sched_get_priority_max(SCHED_FIFO)) {
135c135dbcace640473035b613bce3460048b4d94cdHoward Chen          int cpu = sched_getcpu();
136c135dbcace640473035b613bce3460048b4d94cdHoward Chen          int cpu_caller = data.readInt32();
137c135dbcace640473035b613bce3460048b4d94cdHoward Chen          if (cpu != cpu_caller) {
138c135dbcace640473035b613bce3460048b4d94cdHoward Chen            s++;
139c135dbcace640473035b613bce3460048b4d94cdHoward Chen          }
140c135dbcace640473035b613bce3460048b4d94cdHoward Chen        }
141c135dbcace640473035b613bce3460048b4d94cdHoward Chen        reply->writeInt32(h);
142c135dbcace640473035b613bce3460048b4d94cdHoward Chen        reply->writeInt32(s);
143c135dbcace640473035b613bce3460048b4d94cdHoward Chen        return NO_ERROR;
144c135dbcace640473035b613bce3460048b4d94cdHoward Chen      }
145c135dbcace640473035b613bce3460048b4d94cdHoward Chen      default:
146c135dbcace640473035b613bce3460048b4d94cdHoward Chen        return UNKNOWN_TRANSACTION;
147c135dbcace640473035b613bce3460048b4d94cdHoward Chen    };
148c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
149c135dbcace640473035b613bce3460048b4d94cdHoward Chen};
150c135dbcace640473035b613bce3460048b4d94cdHoward Chen
151c135dbcace640473035b613bce3460048b4d94cdHoward Chenclass Pipe {
152c135dbcace640473035b613bce3460048b4d94cdHoward Chen  int m_readFd;
153c135dbcace640473035b613bce3460048b4d94cdHoward Chen  int m_writeFd;
154c135dbcace640473035b613bce3460048b4d94cdHoward Chen  Pipe(int readFd, int writeFd) : m_readFd{readFd}, m_writeFd{writeFd} {
155c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
156c135dbcace640473035b613bce3460048b4d94cdHoward Chen  Pipe(const Pipe&) = delete;
157c135dbcace640473035b613bce3460048b4d94cdHoward Chen  Pipe& operator=(const Pipe&) = delete;
158c135dbcace640473035b613bce3460048b4d94cdHoward Chen  Pipe& operator=(const Pipe&&) = delete;
159c135dbcace640473035b613bce3460048b4d94cdHoward Chen
160c135dbcace640473035b613bce3460048b4d94cdHoward Chen public:
161c135dbcace640473035b613bce3460048b4d94cdHoward Chen  Pipe(Pipe&& rval) noexcept {
162c135dbcace640473035b613bce3460048b4d94cdHoward Chen    m_readFd = rval.m_readFd;
163c135dbcace640473035b613bce3460048b4d94cdHoward Chen    m_writeFd = rval.m_writeFd;
164c135dbcace640473035b613bce3460048b4d94cdHoward Chen    rval.m_readFd = 0;
165c135dbcace640473035b613bce3460048b4d94cdHoward Chen    rval.m_writeFd = 0;
166c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
167c135dbcace640473035b613bce3460048b4d94cdHoward Chen  ~Pipe() {
168c135dbcace640473035b613bce3460048b4d94cdHoward Chen    if (m_readFd) close(m_readFd);
169c135dbcace640473035b613bce3460048b4d94cdHoward Chen    if (m_writeFd) close(m_writeFd);
170c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
171c135dbcace640473035b613bce3460048b4d94cdHoward Chen  void signal() {
172c135dbcace640473035b613bce3460048b4d94cdHoward Chen    bool val = true;
173c135dbcace640473035b613bce3460048b4d94cdHoward Chen    int error = write(m_writeFd, &val, sizeof(val));
174c135dbcace640473035b613bce3460048b4d94cdHoward Chen    ASSERT(error >= 0);
175c135dbcace640473035b613bce3460048b4d94cdHoward Chen  };
176c135dbcace640473035b613bce3460048b4d94cdHoward Chen  void wait() {
177c135dbcace640473035b613bce3460048b4d94cdHoward Chen    bool val = false;
178c135dbcace640473035b613bce3460048b4d94cdHoward Chen    int error = read(m_readFd, &val, sizeof(val));
179c135dbcace640473035b613bce3460048b4d94cdHoward Chen    ASSERT(error >= 0);
180c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
181c135dbcace640473035b613bce3460048b4d94cdHoward Chen  template <typename T>
182c135dbcace640473035b613bce3460048b4d94cdHoward Chen  void send(const T& v) {
183c135dbcace640473035b613bce3460048b4d94cdHoward Chen    int error = write(m_writeFd, &v, sizeof(T));
184c135dbcace640473035b613bce3460048b4d94cdHoward Chen    ASSERT(error >= 0);
185c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
186c135dbcace640473035b613bce3460048b4d94cdHoward Chen  template <typename T>
187c135dbcace640473035b613bce3460048b4d94cdHoward Chen  void recv(T& v) {
188c135dbcace640473035b613bce3460048b4d94cdHoward Chen    int error = read(m_readFd, &v, sizeof(T));
189c135dbcace640473035b613bce3460048b4d94cdHoward Chen    ASSERT(error >= 0);
190c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
191c135dbcace640473035b613bce3460048b4d94cdHoward Chen  static tuple<Pipe, Pipe> createPipePair() {
192c135dbcace640473035b613bce3460048b4d94cdHoward Chen    int a[2];
193c135dbcace640473035b613bce3460048b4d94cdHoward Chen    int b[2];
194c135dbcace640473035b613bce3460048b4d94cdHoward Chen
195c135dbcace640473035b613bce3460048b4d94cdHoward Chen    int error1 = pipe(a);
196c135dbcace640473035b613bce3460048b4d94cdHoward Chen    int error2 = pipe(b);
197c135dbcace640473035b613bce3460048b4d94cdHoward Chen    ASSERT(error1 >= 0);
198c135dbcace640473035b613bce3460048b4d94cdHoward Chen    ASSERT(error2 >= 0);
199c135dbcace640473035b613bce3460048b4d94cdHoward Chen
200c135dbcace640473035b613bce3460048b4d94cdHoward Chen    return make_tuple(Pipe(a[0], b[1]), Pipe(b[0], a[1]));
201c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
202c135dbcace640473035b613bce3460048b4d94cdHoward Chen};
203c135dbcace640473035b613bce3460048b4d94cdHoward Chen
204c135dbcace640473035b613bce3460048b4d94cdHoward Chentypedef chrono::time_point<chrono::high_resolution_clock> Tick;
205c135dbcace640473035b613bce3460048b4d94cdHoward Chen
206c135dbcace640473035b613bce3460048b4d94cdHoward Chenstatic inline Tick tickNow() {
207c135dbcace640473035b613bce3460048b4d94cdHoward Chen  return chrono::high_resolution_clock::now();
208c135dbcace640473035b613bce3460048b4d94cdHoward Chen}
209c135dbcace640473035b613bce3460048b4d94cdHoward Chen
210c135dbcace640473035b613bce3460048b4d94cdHoward Chenstatic inline uint64_t tickNano(Tick& sta, Tick& end) {
211c135dbcace640473035b613bce3460048b4d94cdHoward Chen  return uint64_t(chrono::duration_cast<chrono::nanoseconds>(end - sta).count());
212c135dbcace640473035b613bce3460048b4d94cdHoward Chen}
213c135dbcace640473035b613bce3460048b4d94cdHoward Chen
214c135dbcace640473035b613bce3460048b4d94cdHoward Chenstruct Results {
215c135dbcace640473035b613bce3460048b4d94cdHoward Chen  uint64_t m_best = 0xffffffffffffffffULL;
216c135dbcace640473035b613bce3460048b4d94cdHoward Chen  uint64_t m_worst = 0;
217c135dbcace640473035b613bce3460048b4d94cdHoward Chen  uint64_t m_transactions = 0;
218c135dbcace640473035b613bce3460048b4d94cdHoward Chen  uint64_t m_total_time = 0;
219c135dbcace640473035b613bce3460048b4d94cdHoward Chen  uint64_t m_miss = 0;
22025715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  bool tracing;
22125715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  Results(bool _tracing) : tracing(_tracing) {
22225715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  }
22325715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  inline bool miss_deadline(uint64_t nano) {
22425715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    return nano > deadline_us * 1000;
22525715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  }
226c135dbcace640473035b613bce3460048b4d94cdHoward Chen  void add_time(uint64_t nano) {
227c135dbcace640473035b613bce3460048b4d94cdHoward Chen    m_best = min(nano, m_best);
228c135dbcace640473035b613bce3460048b4d94cdHoward Chen    m_worst = max(nano, m_worst);
229c135dbcace640473035b613bce3460048b4d94cdHoward Chen    m_transactions += 1;
230c135dbcace640473035b613bce3460048b4d94cdHoward Chen    m_total_time += nano;
23125715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    if (miss_deadline(nano)) m_miss++;
23225715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    if (miss_deadline(nano) && tracing) {
23325715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen      // There might be multiple process pair running the test concurrently
23425715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen      // each may execute following statements and only the first one actually
23525715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen      // stop the trace and any traceStop() afterthen has no effect.
23625715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen      traceStop();
23725715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen      cout << endl;
23825715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen      cout << "deadline triggered: halt & stop trace" << endl;
23925715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen      cout << "log:" + trace_path + "/trace" << endl;
24025715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen      cout << endl;
24125715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen      exit(1);
24225715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    }
243c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
244c135dbcace640473035b613bce3460048b4d94cdHoward Chen  void dump() {
245c135dbcace640473035b613bce3460048b4d94cdHoward Chen    double best = (double)m_best / 1.0E6;
246c135dbcace640473035b613bce3460048b4d94cdHoward Chen    double worst = (double)m_worst / 1.0E6;
247c135dbcace640473035b613bce3460048b4d94cdHoward Chen    double average = (double)m_total_time / m_transactions / 1.0E6;
248c135dbcace640473035b613bce3460048b4d94cdHoward Chen    // FIXME: libjson?
24960c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen    int W = DUMP_PRESICION + 2;
25060c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen    cout << setprecision(DUMP_PRESICION) << "{ \"avg\":" << setw(W) << left
25160c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen         << average << ",\"wst\":" << setw(W) << left << worst
25260c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen         << ",\"bst\":" << setw(W) << left << best << ",\"miss\":" << left
25360c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen         << m_miss << ",\"meetR\":" << left << setprecision(DUMP_PRESICION + 3)
25425715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen         << (1.0 - (double)m_miss / m_transactions) << "}";
255c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
256c135dbcace640473035b613bce3460048b4d94cdHoward Chen};
257c135dbcace640473035b613bce3460048b4d94cdHoward Chen
258c135dbcace640473035b613bce3460048b4d94cdHoward ChenString16 generateServiceName(int num) {
259c135dbcace640473035b613bce3460048b4d94cdHoward Chen  char num_str[32];
260c135dbcace640473035b613bce3460048b4d94cdHoward Chen  snprintf(num_str, sizeof(num_str), "%d", num);
261c135dbcace640473035b613bce3460048b4d94cdHoward Chen  String16 serviceName = String16("binderWorker") + String16(num_str);
262c135dbcace640473035b613bce3460048b4d94cdHoward Chen  return serviceName;
263c135dbcace640473035b613bce3460048b4d94cdHoward Chen}
264c135dbcace640473035b613bce3460048b4d94cdHoward Chen
265c135dbcace640473035b613bce3460048b4d94cdHoward Chenstatic void parcel_fill(Parcel& data, int sz, int priority, int cpu) {
266c135dbcace640473035b613bce3460048b4d94cdHoward Chen  ASSERT(sz >= (int)sizeof(uint32_t) * 2);
267c135dbcace640473035b613bce3460048b4d94cdHoward Chen  data.writeInt32(priority);
268c135dbcace640473035b613bce3460048b4d94cdHoward Chen  data.writeInt32(cpu);
269c135dbcace640473035b613bce3460048b4d94cdHoward Chen  sz -= sizeof(uint32_t);
270c135dbcace640473035b613bce3460048b4d94cdHoward Chen  while (sz > (int)sizeof(uint32_t)) {
271c135dbcace640473035b613bce3460048b4d94cdHoward Chen    data.writeInt32(0);
272c135dbcace640473035b613bce3460048b4d94cdHoward Chen    sz -= sizeof(uint32_t);
273c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
274c135dbcace640473035b613bce3460048b4d94cdHoward Chen}
275c135dbcace640473035b613bce3460048b4d94cdHoward Chen
27660c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chentypedef struct {
27760c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  void* result;
27860c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  int target;
27960c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen} thread_priv_t;
28060c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen
281c135dbcace640473035b613bce3460048b4d94cdHoward Chenstatic void* thread_start(void* p) {
28260c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  thread_priv_t* priv = (thread_priv_t*)p;
28360c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  int target = priv->target;
28460c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  Results* results_fifo = (Results*)priv->result;
285c135dbcace640473035b613bce3460048b4d94cdHoward Chen  Parcel data, reply;
286c135dbcace640473035b613bce3460048b4d94cdHoward Chen  Tick sta, end;
287c135dbcace640473035b613bce3460048b4d94cdHoward Chen
288c135dbcace640473035b613bce3460048b4d94cdHoward Chen  parcel_fill(data, payload_size, thread_pri(), sched_getcpu());
289c135dbcace640473035b613bce3460048b4d94cdHoward Chen  thread_dump("fifo-caller");
290c135dbcace640473035b613bce3460048b4d94cdHoward Chen
291c135dbcace640473035b613bce3460048b4d94cdHoward Chen  sta = tickNow();
29260c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  status_t ret = workers[target]->transact(BINDER_NOP, data, &reply);
293c135dbcace640473035b613bce3460048b4d94cdHoward Chen  end = tickNow();
294c135dbcace640473035b613bce3460048b4d94cdHoward Chen  results_fifo->add_time(tickNano(sta, end));
295c135dbcace640473035b613bce3460048b4d94cdHoward Chen
296c135dbcace640473035b613bce3460048b4d94cdHoward Chen  no_inherent += reply.readInt32();
297c135dbcace640473035b613bce3460048b4d94cdHoward Chen  no_sync += reply.readInt32();
298c135dbcace640473035b613bce3460048b4d94cdHoward Chen  return 0;
299c135dbcace640473035b613bce3460048b4d94cdHoward Chen}
300c135dbcace640473035b613bce3460048b4d94cdHoward Chen
301c135dbcace640473035b613bce3460048b4d94cdHoward Chen// create a fifo thread to transact and wait it to finished
30260c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chenstatic void thread_transaction(int target, Results* results_fifo) {
30360c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  thread_priv_t thread_priv;
304c135dbcace640473035b613bce3460048b4d94cdHoward Chen  void* dummy;
305c135dbcace640473035b613bce3460048b4d94cdHoward Chen  pthread_t thread;
306c135dbcace640473035b613bce3460048b4d94cdHoward Chen  pthread_attr_t attr;
307c135dbcace640473035b613bce3460048b4d94cdHoward Chen  struct sched_param param;
30860c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  thread_priv.target = target;
30960c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  thread_priv.result = results_fifo;
310c135dbcace640473035b613bce3460048b4d94cdHoward Chen  ASSERT(!pthread_attr_init(&attr));
311c135dbcace640473035b613bce3460048b4d94cdHoward Chen  ASSERT(!pthread_attr_setschedpolicy(&attr, SCHED_FIFO));
312c135dbcace640473035b613bce3460048b4d94cdHoward Chen  param.sched_priority = sched_get_priority_max(SCHED_FIFO);
313c135dbcace640473035b613bce3460048b4d94cdHoward Chen  ASSERT(!pthread_attr_setschedparam(&attr, &param));
31460c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  ASSERT(!pthread_create(&thread, &attr, &thread_start, &thread_priv));
315c135dbcace640473035b613bce3460048b4d94cdHoward Chen  ASSERT(!pthread_join(thread, &dummy));
316c135dbcace640473035b613bce3460048b4d94cdHoward Chen}
317c135dbcace640473035b613bce3460048b4d94cdHoward Chen
318c135dbcace640473035b613bce3460048b4d94cdHoward Chen#define is_client(_num) ((_num) >= (no_process / 2))
319c135dbcace640473035b613bce3460048b4d94cdHoward Chen
320c135dbcace640473035b613bce3460048b4d94cdHoward Chenvoid worker_fx(int num, int no_process, int iterations, int payload_size,
321c135dbcace640473035b613bce3460048b4d94cdHoward Chen               Pipe p) {
322c135dbcace640473035b613bce3460048b4d94cdHoward Chen  int dummy;
32325715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  Results results_other(false), results_fifo(trace);
324c135dbcace640473035b613bce3460048b4d94cdHoward Chen
325c135dbcace640473035b613bce3460048b4d94cdHoward Chen  // Create BinderWorkerService and for go.
326c135dbcace640473035b613bce3460048b4d94cdHoward Chen  ProcessState::self()->startThreadPool();
327c135dbcace640473035b613bce3460048b4d94cdHoward Chen  sp<IServiceManager> serviceMgr = defaultServiceManager();
328c135dbcace640473035b613bce3460048b4d94cdHoward Chen  sp<BinderWorkerService> service = new BinderWorkerService;
329c135dbcace640473035b613bce3460048b4d94cdHoward Chen  serviceMgr->addService(generateServiceName(num), service);
33060c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  // init done
331c135dbcace640473035b613bce3460048b4d94cdHoward Chen  p.signal();
33260c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  // wait for kick-off
333c135dbcace640473035b613bce3460048b4d94cdHoward Chen  p.wait();
334c135dbcace640473035b613bce3460048b4d94cdHoward Chen
335c135dbcace640473035b613bce3460048b4d94cdHoward Chen  // If client/server pairs, then half the workers are
336c135dbcace640473035b613bce3460048b4d94cdHoward Chen  // servers and half are clients
337c135dbcace640473035b613bce3460048b4d94cdHoward Chen  int server_count = no_process / 2;
338c135dbcace640473035b613bce3460048b4d94cdHoward Chen
339c135dbcace640473035b613bce3460048b4d94cdHoward Chen  for (int i = 0; i < server_count; i++) {
340c135dbcace640473035b613bce3460048b4d94cdHoward Chen    // self service is in-process so just skip
341c135dbcace640473035b613bce3460048b4d94cdHoward Chen    if (num == i) continue;
342c135dbcace640473035b613bce3460048b4d94cdHoward Chen    workers.push_back(serviceMgr->getService(generateServiceName(i)));
343c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
344c135dbcace640473035b613bce3460048b4d94cdHoward Chen
345c135dbcace640473035b613bce3460048b4d94cdHoward Chen  // Client for each pair iterates here
346c135dbcace640473035b613bce3460048b4d94cdHoward Chen  // each iterations contains exatcly 2 transactions
347c135dbcace640473035b613bce3460048b4d94cdHoward Chen  for (int i = 0; is_client(num) && i < iterations; i++) {
348c135dbcace640473035b613bce3460048b4d94cdHoward Chen    Parcel data, reply;
349c135dbcace640473035b613bce3460048b4d94cdHoward Chen    Tick sta, end;
350c135dbcace640473035b613bce3460048b4d94cdHoward Chen    // the target is paired to make it easier to diagnose
351c135dbcace640473035b613bce3460048b4d94cdHoward Chen    int target = num % server_count;
352c135dbcace640473035b613bce3460048b4d94cdHoward Chen
353c135dbcace640473035b613bce3460048b4d94cdHoward Chen    // 1. transaction by fifo thread
35460c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen    thread_transaction(target, &results_fifo);
355c135dbcace640473035b613bce3460048b4d94cdHoward Chen    parcel_fill(data, payload_size, thread_pri(), sched_getcpu());
356c135dbcace640473035b613bce3460048b4d94cdHoward Chen    thread_dump("other-caller");
357c135dbcace640473035b613bce3460048b4d94cdHoward Chen
358c135dbcace640473035b613bce3460048b4d94cdHoward Chen    // 2. transaction by other thread
359c135dbcace640473035b613bce3460048b4d94cdHoward Chen    sta = tickNow();
360c135dbcace640473035b613bce3460048b4d94cdHoward Chen    ASSERT(NO_ERROR == workers[target]->transact(BINDER_NOP, data, &reply));
361c135dbcace640473035b613bce3460048b4d94cdHoward Chen    end = tickNow();
362c135dbcace640473035b613bce3460048b4d94cdHoward Chen    results_other.add_time(tickNano(sta, end));
363c135dbcace640473035b613bce3460048b4d94cdHoward Chen
364c135dbcace640473035b613bce3460048b4d94cdHoward Chen    no_inherent += reply.readInt32();
365c135dbcace640473035b613bce3460048b4d94cdHoward Chen    no_sync += reply.readInt32();
366c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
367c135dbcace640473035b613bce3460048b4d94cdHoward Chen  // Signal completion to master and wait.
368c135dbcace640473035b613bce3460048b4d94cdHoward Chen  p.signal();
369c135dbcace640473035b613bce3460048b4d94cdHoward Chen  p.wait();
370c135dbcace640473035b613bce3460048b4d94cdHoward Chen
371c135dbcace640473035b613bce3460048b4d94cdHoward Chen  p.send(&dummy);
37260c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  // wait for kill
373c135dbcace640473035b613bce3460048b4d94cdHoward Chen  p.wait();
374c135dbcace640473035b613bce3460048b4d94cdHoward Chen  // Client for each pair dump here
375c135dbcace640473035b613bce3460048b4d94cdHoward Chen  if (is_client(num)) {
376c135dbcace640473035b613bce3460048b4d94cdHoward Chen    int no_trans = iterations * 2;
377c135dbcace640473035b613bce3460048b4d94cdHoward Chen    double sync_ratio = (1.0 - (double)no_sync / no_trans);
378c135dbcace640473035b613bce3460048b4d94cdHoward Chen    // FIXME: libjson?
379c135dbcace640473035b613bce3460048b4d94cdHoward Chen    cout << "\"P" << (num - server_count) << "\":{\"SYNC\":\""
380c135dbcace640473035b613bce3460048b4d94cdHoward Chen         << ((sync_ratio > GOOD_SYNC_MIN) ? "GOOD" : "POOR") << "\","
381c135dbcace640473035b613bce3460048b4d94cdHoward Chen         << "\"S\":" << (no_trans - no_sync) << ",\"I\":" << no_trans << ","
382c135dbcace640473035b613bce3460048b4d94cdHoward Chen         << "\"R\":" << sync_ratio << "," << endl;
383c135dbcace640473035b613bce3460048b4d94cdHoward Chen
38460c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen    cout << "  \"other_ms\":";
385c135dbcace640473035b613bce3460048b4d94cdHoward Chen    results_other.dump();
386c135dbcace640473035b613bce3460048b4d94cdHoward Chen    cout << "," << endl;
38760c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen    cout << "  \"fifo_ms\": ";
388c135dbcace640473035b613bce3460048b4d94cdHoward Chen    results_fifo.dump();
389c135dbcace640473035b613bce3460048b4d94cdHoward Chen    cout << endl;
390c135dbcace640473035b613bce3460048b4d94cdHoward Chen    cout << "}," << endl;
391c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
392c135dbcace640473035b613bce3460048b4d94cdHoward Chen  exit(no_inherent);
393c135dbcace640473035b613bce3460048b4d94cdHoward Chen}
394c135dbcace640473035b613bce3460048b4d94cdHoward Chen
395c135dbcace640473035b613bce3460048b4d94cdHoward ChenPipe make_process(int num, int iterations, int no_process, int payload_size) {
396c135dbcace640473035b613bce3460048b4d94cdHoward Chen  auto pipe_pair = Pipe::createPipePair();
397c135dbcace640473035b613bce3460048b4d94cdHoward Chen  pid_t pid = fork();
398c135dbcace640473035b613bce3460048b4d94cdHoward Chen  if (pid) {
399c135dbcace640473035b613bce3460048b4d94cdHoward Chen    // parent
400c135dbcace640473035b613bce3460048b4d94cdHoward Chen    return move(get<0>(pipe_pair));
401c135dbcace640473035b613bce3460048b4d94cdHoward Chen  } else {
402c135dbcace640473035b613bce3460048b4d94cdHoward Chen    // child
403c135dbcace640473035b613bce3460048b4d94cdHoward Chen    thread_dump(is_client(num) ? "client" : "server");
404c135dbcace640473035b613bce3460048b4d94cdHoward Chen    worker_fx(num, no_process, iterations, payload_size,
405c135dbcace640473035b613bce3460048b4d94cdHoward Chen              move(get<1>(pipe_pair)));
406c135dbcace640473035b613bce3460048b4d94cdHoward Chen    // never get here
407c135dbcace640473035b613bce3460048b4d94cdHoward Chen    return move(get<0>(pipe_pair));
408c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
409c135dbcace640473035b613bce3460048b4d94cdHoward Chen}
410c135dbcace640473035b613bce3460048b4d94cdHoward Chen
411c135dbcace640473035b613bce3460048b4d94cdHoward Chenvoid wait_all(vector<Pipe>& v) {
412c135dbcace640473035b613bce3460048b4d94cdHoward Chen  for (size_t i = 0; i < v.size(); i++) {
413c135dbcace640473035b613bce3460048b4d94cdHoward Chen    v[i].wait();
414c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
415c135dbcace640473035b613bce3460048b4d94cdHoward Chen}
416c135dbcace640473035b613bce3460048b4d94cdHoward Chen
417c135dbcace640473035b613bce3460048b4d94cdHoward Chenvoid signal_all(vector<Pipe>& v) {
418c135dbcace640473035b613bce3460048b4d94cdHoward Chen  for (size_t i = 0; i < v.size(); i++) {
419c135dbcace640473035b613bce3460048b4d94cdHoward Chen    v[i].signal();
420c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
421c135dbcace640473035b613bce3460048b4d94cdHoward Chen}
422c135dbcace640473035b613bce3460048b4d94cdHoward Chen
423c135dbcace640473035b613bce3460048b4d94cdHoward Chen// This test is modified from binderThroughputTest.cpp
424c135dbcace640473035b613bce3460048b4d94cdHoward Chenint main(int argc, char** argv) {
425c135dbcace640473035b613bce3460048b4d94cdHoward Chen  for (int i = 1; i < argc; i++) {
426c135dbcace640473035b613bce3460048b4d94cdHoward Chen    if (string(argv[i]) == "-i") {
427c135dbcace640473035b613bce3460048b4d94cdHoward Chen      iterations = atoi(argv[i + 1]);
428c135dbcace640473035b613bce3460048b4d94cdHoward Chen      i++;
429c135dbcace640473035b613bce3460048b4d94cdHoward Chen      continue;
430c135dbcace640473035b613bce3460048b4d94cdHoward Chen    }
431c135dbcace640473035b613bce3460048b4d94cdHoward Chen    if (string(argv[i]) == "-pair") {
432c135dbcace640473035b613bce3460048b4d94cdHoward Chen      no_process = 2 * atoi(argv[i + 1]);
433c135dbcace640473035b613bce3460048b4d94cdHoward Chen      i++;
434c135dbcace640473035b613bce3460048b4d94cdHoward Chen      continue;
435c135dbcace640473035b613bce3460048b4d94cdHoward Chen    }
436c135dbcace640473035b613bce3460048b4d94cdHoward Chen    if (string(argv[i]) == "-deadline_us") {
437c135dbcace640473035b613bce3460048b4d94cdHoward Chen      deadline_us = atoi(argv[i + 1]);
438c135dbcace640473035b613bce3460048b4d94cdHoward Chen      i++;
439c135dbcace640473035b613bce3460048b4d94cdHoward Chen      continue;
440c135dbcace640473035b613bce3460048b4d94cdHoward Chen    }
441c135dbcace640473035b613bce3460048b4d94cdHoward Chen    if (string(argv[i]) == "-v") {
442c135dbcace640473035b613bce3460048b4d94cdHoward Chen      verbose = 1;
443c135dbcace640473035b613bce3460048b4d94cdHoward Chen    }
44425715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    // The -trace argument is used like that:
44525715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    //
44625715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    // First start trace with atrace command as usual
44725715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    // >atrace --async_start sched freq
44825715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    //
44925715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    // then use schd-dbg with -trace arguments
45025715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    //./schd-dbg -trace -deadline_us 2500
45125715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    //
45225715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    // This makes schd-dbg to stop trace once it detects a transaction
45325715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    // duration over the deadline. By writing '0' to
45425715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    // /sys/kernel/debug/tracing and halt the process. The tracelog is
45525715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    // then available on /sys/kernel/debug/trace
45625715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    if (string(argv[i]) == "-trace") {
45725715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen      trace = 1;
45825715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    }
45925715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  }
46025715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen  if (trace && !traceIsOn()) {
46125715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    cout << "trace is not running" << endl;
46225715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    cout << "check " << trace_path + "/tracing_on" << endl;
46325715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    cout << "use atrace --async_start first" << endl;
46425715517db7e056c0ebd71ecc0debf37c7d2b271Howard Chen    exit(-1);
465c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
466c135dbcace640473035b613bce3460048b4d94cdHoward Chen  vector<Pipe> pipes;
467c135dbcace640473035b613bce3460048b4d94cdHoward Chen  thread_dump("main");
468c135dbcace640473035b613bce3460048b4d94cdHoward Chen  // FIXME: libjson?
469c135dbcace640473035b613bce3460048b4d94cdHoward Chen  cout << "{" << endl;
470c135dbcace640473035b613bce3460048b4d94cdHoward Chen  cout << "\"cfg\":{\"pair\":" << (no_process / 2)
471c135dbcace640473035b613bce3460048b4d94cdHoward Chen       << ",\"iterations\":" << iterations << ",\"deadline_us\":" << deadline_us
472c135dbcace640473035b613bce3460048b4d94cdHoward Chen       << "}," << endl;
473c135dbcace640473035b613bce3460048b4d94cdHoward Chen
474c135dbcace640473035b613bce3460048b4d94cdHoward Chen  // the main process fork 2 processes for each pairs
475c135dbcace640473035b613bce3460048b4d94cdHoward Chen  // 1 server + 1 client
476c135dbcace640473035b613bce3460048b4d94cdHoward Chen  // each has a pipe to communicate with
477c135dbcace640473035b613bce3460048b4d94cdHoward Chen  for (int i = 0; i < no_process; i++) {
478c135dbcace640473035b613bce3460048b4d94cdHoward Chen    pipes.push_back(make_process(i, iterations, no_process, payload_size));
479c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
48060c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  // wait for init done
481c135dbcace640473035b613bce3460048b4d94cdHoward Chen  wait_all(pipes);
48260c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  // kick-off iterations
483c135dbcace640473035b613bce3460048b4d94cdHoward Chen  signal_all(pipes);
48460c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  // wait for completion
485c135dbcace640473035b613bce3460048b4d94cdHoward Chen  wait_all(pipes);
48660c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen  // start to send result
487c135dbcace640473035b613bce3460048b4d94cdHoward Chen  signal_all(pipes);
488c135dbcace640473035b613bce3460048b4d94cdHoward Chen  for (int i = 0; i < no_process; i++) {
489c135dbcace640473035b613bce3460048b4d94cdHoward Chen    int status;
49060c513c5e1ef92fadf851f56ecff6b289fc93a2cHoward Chen    // kill
491c135dbcace640473035b613bce3460048b4d94cdHoward Chen    pipes[i].signal();
492c135dbcace640473035b613bce3460048b4d94cdHoward Chen    wait(&status);
493c135dbcace640473035b613bce3460048b4d94cdHoward Chen    // the exit status is number of transactions without priority inheritance
494c135dbcace640473035b613bce3460048b4d94cdHoward Chen    // detected in the child process
495c135dbcace640473035b613bce3460048b4d94cdHoward Chen    no_inherent += status;
496c135dbcace640473035b613bce3460048b4d94cdHoward Chen  }
497c135dbcace640473035b613bce3460048b4d94cdHoward Chen  // FIXME: libjson?
498c135dbcace640473035b613bce3460048b4d94cdHoward Chen  cout << "\"inheritance\": " << (no_inherent == 0 ? "\"PASS\"" : "\"FAIL\"")
499c135dbcace640473035b613bce3460048b4d94cdHoward Chen       << endl;
500c135dbcace640473035b613bce3460048b4d94cdHoward Chen  cout << "}" << endl;
501c135dbcace640473035b613bce3460048b4d94cdHoward Chen  return -no_inherent;
502c135dbcace640473035b613bce3460048b4d94cdHoward Chen}
503