xref: /unit/src/test/nxt_cq_test.c (revision 1554:8f22edff911d)
1*1554Smax.romanov@nginx.com 
2*1554Smax.romanov@nginx.com /*
3*1554Smax.romanov@nginx.com  * Copyright (C) NGINX, Inc.
4*1554Smax.romanov@nginx.com  */
5*1554Smax.romanov@nginx.com 
6*1554Smax.romanov@nginx.com #include <nxt_main.h>
7*1554Smax.romanov@nginx.com #include <math.h>
8*1554Smax.romanov@nginx.com #include <inttypes.h>
9*1554Smax.romanov@nginx.com 
10*1554Smax.romanov@nginx.com #ifndef NXT_NCQ_TEST
11*1554Smax.romanov@nginx.com #define NXT_NCQ_TEST          1
12*1554Smax.romanov@nginx.com #endif
13*1554Smax.romanov@nginx.com 
14*1554Smax.romanov@nginx.com #define NXT_QTEST_USE_THREAD  0
15*1554Smax.romanov@nginx.com 
16*1554Smax.romanov@nginx.com #if NXT_NCQ_TEST
17*1554Smax.romanov@nginx.com #include <nxt_nncq.h>
18*1554Smax.romanov@nginx.com #else
19*1554Smax.romanov@nginx.com #include <nxt_nvbcq.h>
20*1554Smax.romanov@nginx.com #endif
21*1554Smax.romanov@nginx.com 
22*1554Smax.romanov@nginx.com 
23*1554Smax.romanov@nginx.com #define MAX_ITER   20
24*1554Smax.romanov@nginx.com #define STAT_ITER  5
25*1554Smax.romanov@nginx.com #define MIN_COV    0.02
26*1554Smax.romanov@nginx.com 
27*1554Smax.romanov@nginx.com extern char  **environ;
28*1554Smax.romanov@nginx.com static uintptr_t nops = 10000000;
29*1554Smax.romanov@nginx.com 
30*1554Smax.romanov@nginx.com static uintptr_t nprocs_enq     = 0;
31*1554Smax.romanov@nginx.com static uintptr_t nprocs_deq     = 0;
32*1554Smax.romanov@nginx.com static uintptr_t nprocs_wenq    = 0;
33*1554Smax.romanov@nginx.com static uintptr_t nprocs_wdeq    = 0;
34*1554Smax.romanov@nginx.com static uintptr_t nprocs_enq_deq = 0;
35*1554Smax.romanov@nginx.com static uintptr_t nprocs_cas     = 0;
36*1554Smax.romanov@nginx.com static uintptr_t nprocs_faa     = 0;
37*1554Smax.romanov@nginx.com 
38*1554Smax.romanov@nginx.com static uintptr_t nprocs = 1;
39*1554Smax.romanov@nginx.com 
40*1554Smax.romanov@nginx.com 
41*1554Smax.romanov@nginx.com static size_t
elapsed_time(size_t us)42*1554Smax.romanov@nginx.com elapsed_time(size_t us)
43*1554Smax.romanov@nginx.com {
44*1554Smax.romanov@nginx.com   struct timeval t;
45*1554Smax.romanov@nginx.com 
46*1554Smax.romanov@nginx.com   gettimeofday(&t, NULL);
47*1554Smax.romanov@nginx.com 
48*1554Smax.romanov@nginx.com   return t.tv_sec * 1000000 + t.tv_usec - us;
49*1554Smax.romanov@nginx.com }
50*1554Smax.romanov@nginx.com 
51*1554Smax.romanov@nginx.com 
52*1554Smax.romanov@nginx.com static double
mean(const double * times,int n)53*1554Smax.romanov@nginx.com mean(const double *times, int n)
54*1554Smax.romanov@nginx.com {
55*1554Smax.romanov@nginx.com     int     i;
56*1554Smax.romanov@nginx.com     double  sum;
57*1554Smax.romanov@nginx.com 
58*1554Smax.romanov@nginx.com     sum = 0;
59*1554Smax.romanov@nginx.com 
60*1554Smax.romanov@nginx.com     for (i = 0; i < n; i++) {
61*1554Smax.romanov@nginx.com         sum += times[i];
62*1554Smax.romanov@nginx.com     }
63*1554Smax.romanov@nginx.com 
64*1554Smax.romanov@nginx.com     return sum / n;
65*1554Smax.romanov@nginx.com }
66*1554Smax.romanov@nginx.com 
67*1554Smax.romanov@nginx.com 
68*1554Smax.romanov@nginx.com static double
cov(const double * times,double mean,int n)69*1554Smax.romanov@nginx.com cov(const double *times, double mean, int n)
70*1554Smax.romanov@nginx.com {
71*1554Smax.romanov@nginx.com     int     i;
72*1554Smax.romanov@nginx.com     double  variance;
73*1554Smax.romanov@nginx.com 
74*1554Smax.romanov@nginx.com     variance = 0;
75*1554Smax.romanov@nginx.com 
76*1554Smax.romanov@nginx.com     for (i = 0; i < n; i++) {
77*1554Smax.romanov@nginx.com         variance += (times[i] - mean) * (times[i] - mean);
78*1554Smax.romanov@nginx.com     }
79*1554Smax.romanov@nginx.com 
80*1554Smax.romanov@nginx.com     variance /= n;
81*1554Smax.romanov@nginx.com 
82*1554Smax.romanov@nginx.com     return sqrt(variance) / mean;
83*1554Smax.romanov@nginx.com }
84*1554Smax.romanov@nginx.com 
85*1554Smax.romanov@nginx.com typedef struct {
86*1554Smax.romanov@nginx.com #if NXT_NCQ_TEST
87*1554Smax.romanov@nginx.com     nxt_nncq_t   free_queue;
88*1554Smax.romanov@nginx.com     nxt_nncq_t   active_queue;
89*1554Smax.romanov@nginx.com #else
90*1554Smax.romanov@nginx.com     nxt_nvbcq_t  free_queue;
91*1554Smax.romanov@nginx.com     nxt_nvbcq_t  active_queue;
92*1554Smax.romanov@nginx.com #endif
93*1554Smax.romanov@nginx.com     uint32_t     counter;
94*1554Smax.romanov@nginx.com } nxt_cq_t;
95*1554Smax.romanov@nginx.com 
96*1554Smax.romanov@nginx.com 
97*1554Smax.romanov@nginx.com static nxt_cq_t  *pgq;
98*1554Smax.romanov@nginx.com 
99*1554Smax.romanov@nginx.com 
100*1554Smax.romanov@nginx.com #if NXT_NCQ_TEST
101*1554Smax.romanov@nginx.com #define nxt_cq_enqueue  nxt_nncq_enqueue
102*1554Smax.romanov@nginx.com #define nxt_cq_dequeue  nxt_nncq_dequeue
103*1554Smax.romanov@nginx.com #define nxt_cq_empty    nxt_nncq_empty
104*1554Smax.romanov@nginx.com #define nxt_cq_init     nxt_nncq_init
105*1554Smax.romanov@nginx.com #define NXT_CQ_SIZE     NXT_NNCQ_SIZE
106*1554Smax.romanov@nginx.com #else
107*1554Smax.romanov@nginx.com #define nxt_cq_enqueue  nxt_nvbcq_enqueue
108*1554Smax.romanov@nginx.com #define nxt_cq_dequeue  nxt_nvbcq_dequeue
109*1554Smax.romanov@nginx.com #define nxt_cq_empty    nxt_nvbcq_empty
110*1554Smax.romanov@nginx.com #define nxt_cq_init     nxt_nvbcq_init
111*1554Smax.romanov@nginx.com #define NXT_CQ_SIZE     NXT_NVBCQ_SIZE
112*1554Smax.romanov@nginx.com #endif
113*1554Smax.romanov@nginx.com 
114*1554Smax.romanov@nginx.com typedef struct {
115*1554Smax.romanov@nginx.com     int                  id;
116*1554Smax.romanov@nginx.com     uint64_t             enq;
117*1554Smax.romanov@nginx.com     uint64_t             deq;
118*1554Smax.romanov@nginx.com     uint64_t             wait_enq;
119*1554Smax.romanov@nginx.com     uint64_t             wait_deq;
120*1554Smax.romanov@nginx.com     uint64_t             own_res;
121*1554Smax.romanov@nginx.com     uint64_t             cas;
122*1554Smax.romanov@nginx.com     uint64_t             faa;
123*1554Smax.romanov@nginx.com 
124*1554Smax.romanov@nginx.com #if NXT_QTEST_USE_THREAD
125*1554Smax.romanov@nginx.com     nxt_thread_handle_t  handle;
126*1554Smax.romanov@nginx.com #else
127*1554Smax.romanov@nginx.com     nxt_pid_t            pid;
128*1554Smax.romanov@nginx.com     int status;
129*1554Smax.romanov@nginx.com #endif
130*1554Smax.romanov@nginx.com } nxt_worker_info_t;
131*1554Smax.romanov@nginx.com 
132*1554Smax.romanov@nginx.com 
133*1554Smax.romanov@nginx.com static void
cas_worker(void * p)134*1554Smax.romanov@nginx.com cas_worker(void *p)
135*1554Smax.romanov@nginx.com {
136*1554Smax.romanov@nginx.com     nxt_cq_t           *q;
137*1554Smax.romanov@nginx.com     uint32_t           c;
138*1554Smax.romanov@nginx.com     uintptr_t          i;
139*1554Smax.romanov@nginx.com     nxt_worker_info_t  *wi;
140*1554Smax.romanov@nginx.com 
141*1554Smax.romanov@nginx.com     q = pgq;
142*1554Smax.romanov@nginx.com     wi = p;
143*1554Smax.romanov@nginx.com 
144*1554Smax.romanov@nginx.com     for (i = 0; i < nops / nprocs_cas; i++) {
145*1554Smax.romanov@nginx.com         c = q->counter;
146*1554Smax.romanov@nginx.com 
147*1554Smax.romanov@nginx.com         if (nxt_atomic_cmp_set(&q->counter, c, c + 1)) {
148*1554Smax.romanov@nginx.com             ++wi->cas;
149*1554Smax.romanov@nginx.com         }
150*1554Smax.romanov@nginx.com     }
151*1554Smax.romanov@nginx.com }
152*1554Smax.romanov@nginx.com 
153*1554Smax.romanov@nginx.com 
154*1554Smax.romanov@nginx.com static void
faa_worker(void * p)155*1554Smax.romanov@nginx.com faa_worker(void *p)
156*1554Smax.romanov@nginx.com {
157*1554Smax.romanov@nginx.com     nxt_cq_t           *q;
158*1554Smax.romanov@nginx.com     uintptr_t          i;
159*1554Smax.romanov@nginx.com     nxt_worker_info_t  *wi;
160*1554Smax.romanov@nginx.com 
161*1554Smax.romanov@nginx.com     q = pgq;
162*1554Smax.romanov@nginx.com     wi = p;
163*1554Smax.romanov@nginx.com 
164*1554Smax.romanov@nginx.com     for (i = 0; i < nops / nprocs_faa; i++) {
165*1554Smax.romanov@nginx.com         nxt_atomic_fetch_add(&q->counter, 1);
166*1554Smax.romanov@nginx.com         wi->faa++;
167*1554Smax.romanov@nginx.com     }
168*1554Smax.romanov@nginx.com }
169*1554Smax.romanov@nginx.com 
170*1554Smax.romanov@nginx.com 
171*1554Smax.romanov@nginx.com static void
enq_deq_worker(void * p)172*1554Smax.romanov@nginx.com enq_deq_worker(void *p)
173*1554Smax.romanov@nginx.com {
174*1554Smax.romanov@nginx.com     nxt_cq_t           *q;
175*1554Smax.romanov@nginx.com     uintptr_t          i, v;
176*1554Smax.romanov@nginx.com     nxt_worker_info_t  *wi;
177*1554Smax.romanov@nginx.com 
178*1554Smax.romanov@nginx.com     q = pgq;
179*1554Smax.romanov@nginx.com     wi = p;
180*1554Smax.romanov@nginx.com 
181*1554Smax.romanov@nginx.com     for (i = 0; i < nops / nprocs_enq_deq; i++) {
182*1554Smax.romanov@nginx.com         v = nxt_cq_dequeue(&q->free_queue);
183*1554Smax.romanov@nginx.com 
184*1554Smax.romanov@nginx.com         if (v != nxt_cq_empty(&q->free_queue)) {
185*1554Smax.romanov@nginx.com             nxt_cq_enqueue(&q->active_queue, wi->id);
186*1554Smax.romanov@nginx.com             wi->enq++;
187*1554Smax.romanov@nginx.com         }
188*1554Smax.romanov@nginx.com 
189*1554Smax.romanov@nginx.com         v = nxt_cq_dequeue(&q->active_queue);
190*1554Smax.romanov@nginx.com 
191*1554Smax.romanov@nginx.com         if (v != nxt_cq_empty(&q->active_queue)) {
192*1554Smax.romanov@nginx.com             nxt_cq_enqueue(&q->free_queue, v);
193*1554Smax.romanov@nginx.com             wi->deq++;
194*1554Smax.romanov@nginx.com 
195*1554Smax.romanov@nginx.com             if ((int) v == wi->id) {
196*1554Smax.romanov@nginx.com                 wi->own_res++;
197*1554Smax.romanov@nginx.com             }
198*1554Smax.romanov@nginx.com         }
199*1554Smax.romanov@nginx.com     }
200*1554Smax.romanov@nginx.com }
201*1554Smax.romanov@nginx.com 
202*1554Smax.romanov@nginx.com 
203*1554Smax.romanov@nginx.com static void
enq_worker(void * p)204*1554Smax.romanov@nginx.com enq_worker(void *p)
205*1554Smax.romanov@nginx.com {
206*1554Smax.romanov@nginx.com     nxt_cq_t           *q;
207*1554Smax.romanov@nginx.com     uintptr_t          i, v;
208*1554Smax.romanov@nginx.com     nxt_worker_info_t  *wi;
209*1554Smax.romanov@nginx.com 
210*1554Smax.romanov@nginx.com     q = pgq;
211*1554Smax.romanov@nginx.com     wi = p;
212*1554Smax.romanov@nginx.com 
213*1554Smax.romanov@nginx.com     for (i = 0; i < nops / nprocs_enq; i++) {
214*1554Smax.romanov@nginx.com         v = nxt_cq_dequeue(&q->free_queue);
215*1554Smax.romanov@nginx.com 
216*1554Smax.romanov@nginx.com         if (v != nxt_cq_empty(&q->free_queue)) {
217*1554Smax.romanov@nginx.com             nxt_cq_enqueue(&q->active_queue, v);
218*1554Smax.romanov@nginx.com             wi->enq++;
219*1554Smax.romanov@nginx.com         }
220*1554Smax.romanov@nginx.com     }
221*1554Smax.romanov@nginx.com }
222*1554Smax.romanov@nginx.com 
223*1554Smax.romanov@nginx.com 
224*1554Smax.romanov@nginx.com static void
deq_worker(void * p)225*1554Smax.romanov@nginx.com deq_worker(void *p)
226*1554Smax.romanov@nginx.com {
227*1554Smax.romanov@nginx.com     nxt_cq_t           *q;
228*1554Smax.romanov@nginx.com     uintptr_t          i, v;
229*1554Smax.romanov@nginx.com     nxt_worker_info_t  *wi;
230*1554Smax.romanov@nginx.com 
231*1554Smax.romanov@nginx.com     q = pgq;
232*1554Smax.romanov@nginx.com     wi = p;
233*1554Smax.romanov@nginx.com 
234*1554Smax.romanov@nginx.com     for (i = 0; i < nops / nprocs_deq; i++) {
235*1554Smax.romanov@nginx.com         v = nxt_cq_dequeue(&q->active_queue);
236*1554Smax.romanov@nginx.com 
237*1554Smax.romanov@nginx.com         if (v != nxt_cq_empty(&q->active_queue)) {
238*1554Smax.romanov@nginx.com             nxt_cq_enqueue(&q->free_queue, v);
239*1554Smax.romanov@nginx.com             ++wi->deq;
240*1554Smax.romanov@nginx.com         }
241*1554Smax.romanov@nginx.com     }
242*1554Smax.romanov@nginx.com }
243*1554Smax.romanov@nginx.com 
244*1554Smax.romanov@nginx.com 
245*1554Smax.romanov@nginx.com static void
wenq_worker(void * p)246*1554Smax.romanov@nginx.com wenq_worker(void *p)
247*1554Smax.romanov@nginx.com {
248*1554Smax.romanov@nginx.com     nxt_cq_t           *q;
249*1554Smax.romanov@nginx.com     uintptr_t          i, v;
250*1554Smax.romanov@nginx.com     nxt_worker_info_t  *wi;
251*1554Smax.romanov@nginx.com 
252*1554Smax.romanov@nginx.com     q = pgq;
253*1554Smax.romanov@nginx.com     wi = p;
254*1554Smax.romanov@nginx.com 
255*1554Smax.romanov@nginx.com     for (i = 0; i < nops / nprocs_wenq; i++) {
256*1554Smax.romanov@nginx.com 
257*1554Smax.romanov@nginx.com         do {
258*1554Smax.romanov@nginx.com             wi->wait_enq++;
259*1554Smax.romanov@nginx.com             v = nxt_cq_dequeue(&q->free_queue);
260*1554Smax.romanov@nginx.com         } while (v == nxt_cq_empty(&q->free_queue));
261*1554Smax.romanov@nginx.com 
262*1554Smax.romanov@nginx.com         nxt_cq_enqueue(&q->active_queue, v);
263*1554Smax.romanov@nginx.com 
264*1554Smax.romanov@nginx.com         wi->enq++;
265*1554Smax.romanov@nginx.com         wi->wait_enq--;
266*1554Smax.romanov@nginx.com     }
267*1554Smax.romanov@nginx.com }
268*1554Smax.romanov@nginx.com 
269*1554Smax.romanov@nginx.com 
270*1554Smax.romanov@nginx.com static void
wdeq_worker(void * p)271*1554Smax.romanov@nginx.com wdeq_worker(void *p)
272*1554Smax.romanov@nginx.com {
273*1554Smax.romanov@nginx.com     nxt_cq_t           *q;
274*1554Smax.romanov@nginx.com     uintptr_t          i, v;
275*1554Smax.romanov@nginx.com     nxt_worker_info_t  *wi;
276*1554Smax.romanov@nginx.com 
277*1554Smax.romanov@nginx.com     q = pgq;
278*1554Smax.romanov@nginx.com     wi = p;
279*1554Smax.romanov@nginx.com 
280*1554Smax.romanov@nginx.com     for (i = 0; i < nops / nprocs_wdeq; i++) {
281*1554Smax.romanov@nginx.com 
282*1554Smax.romanov@nginx.com         do {
283*1554Smax.romanov@nginx.com             wi->wait_deq++;
284*1554Smax.romanov@nginx.com             v = nxt_cq_dequeue(&q->active_queue);
285*1554Smax.romanov@nginx.com         } while (v == nxt_cq_empty(&q->active_queue));
286*1554Smax.romanov@nginx.com 
287*1554Smax.romanov@nginx.com         nxt_cq_enqueue(&q->free_queue, v);
288*1554Smax.romanov@nginx.com 
289*1554Smax.romanov@nginx.com         wi->deq++;
290*1554Smax.romanov@nginx.com         wi->wait_deq--;
291*1554Smax.romanov@nginx.com     }
292*1554Smax.romanov@nginx.com }
293*1554Smax.romanov@nginx.com 
294*1554Smax.romanov@nginx.com 
295*1554Smax.romanov@nginx.com static nxt_int_t
worker_create(nxt_worker_info_t * wi,int id,nxt_thread_start_t start)296*1554Smax.romanov@nginx.com worker_create(nxt_worker_info_t *wi, int id, nxt_thread_start_t start)
297*1554Smax.romanov@nginx.com {
298*1554Smax.romanov@nginx.com     wi->id = id;
299*1554Smax.romanov@nginx.com 
300*1554Smax.romanov@nginx.com #if NXT_QTEST_USE_THREAD
301*1554Smax.romanov@nginx.com     nxt_thread_link_t  *link;
302*1554Smax.romanov@nginx.com 
303*1554Smax.romanov@nginx.com     link = nxt_zalloc(sizeof(nxt_thread_link_t));
304*1554Smax.romanov@nginx.com 
305*1554Smax.romanov@nginx.com     link->start = start;
306*1554Smax.romanov@nginx.com     link->work.data = wi;
307*1554Smax.romanov@nginx.com 
308*1554Smax.romanov@nginx.com     return nxt_thread_create(&wi->handle, link);
309*1554Smax.romanov@nginx.com 
310*1554Smax.romanov@nginx.com #else
311*1554Smax.romanov@nginx.com     pid_t pid = fork();
312*1554Smax.romanov@nginx.com 
313*1554Smax.romanov@nginx.com     if (pid == 0) {
314*1554Smax.romanov@nginx.com         start(wi);
315*1554Smax.romanov@nginx.com         exit(0);
316*1554Smax.romanov@nginx.com 
317*1554Smax.romanov@nginx.com     } else {
318*1554Smax.romanov@nginx.com         wi->pid = pid;
319*1554Smax.romanov@nginx.com     }
320*1554Smax.romanov@nginx.com 
321*1554Smax.romanov@nginx.com     return NXT_OK;
322*1554Smax.romanov@nginx.com #endif
323*1554Smax.romanov@nginx.com }
324*1554Smax.romanov@nginx.com 
325*1554Smax.romanov@nginx.com 
326*1554Smax.romanov@nginx.com static void
worker_wait(nxt_worker_info_t * wi)327*1554Smax.romanov@nginx.com worker_wait(nxt_worker_info_t *wi)
328*1554Smax.romanov@nginx.com {
329*1554Smax.romanov@nginx.com #if NXT_QTEST_USE_THREAD
330*1554Smax.romanov@nginx.com     pthread_join(wi->handle, NULL);
331*1554Smax.romanov@nginx.com 
332*1554Smax.romanov@nginx.com #else
333*1554Smax.romanov@nginx.com     waitpid(wi->pid, &wi->status, 0);
334*1554Smax.romanov@nginx.com #endif
335*1554Smax.romanov@nginx.com }
336*1554Smax.romanov@nginx.com 
337*1554Smax.romanov@nginx.com 
338*1554Smax.romanov@nginx.com int nxt_cdecl
main(int argc,char ** argv)339*1554Smax.romanov@nginx.com main(int argc, char **argv)
340*1554Smax.romanov@nginx.com {
341*1554Smax.romanov@nginx.com     int                i, k, id, verbose, objective, rk;
342*1554Smax.romanov@nginx.com     char               *a;
343*1554Smax.romanov@nginx.com     size_t             start, elapsed;
344*1554Smax.romanov@nginx.com     double             *stats, m, c;
345*1554Smax.romanov@nginx.com     uint64_t           total_ops;
346*1554Smax.romanov@nginx.com     uintptr_t          j;
347*1554Smax.romanov@nginx.com     nxt_task_t         task;
348*1554Smax.romanov@nginx.com     nxt_thread_t       *thr;
349*1554Smax.romanov@nginx.com     nxt_worker_info_t  *wi;
350*1554Smax.romanov@nginx.com     double             times[MAX_ITER], mopsec[MAX_ITER];
351*1554Smax.romanov@nginx.com 
352*1554Smax.romanov@nginx.com     verbose = 0;
353*1554Smax.romanov@nginx.com     objective = 0;
354*1554Smax.romanov@nginx.com 
355*1554Smax.romanov@nginx.com     for (i = 1; i < argc; i++) {
356*1554Smax.romanov@nginx.com         a = argv[i];
357*1554Smax.romanov@nginx.com 
358*1554Smax.romanov@nginx.com         if (strcmp(a, "-v") == 0) {
359*1554Smax.romanov@nginx.com             verbose++;
360*1554Smax.romanov@nginx.com             continue;
361*1554Smax.romanov@nginx.com         }
362*1554Smax.romanov@nginx.com 
363*1554Smax.romanov@nginx.com         if (strcmp(a, "-n") == 0 && (i + 1) < argc) {
364*1554Smax.romanov@nginx.com             nops = atoi(argv[++i]);
365*1554Smax.romanov@nginx.com             continue;
366*1554Smax.romanov@nginx.com         }
367*1554Smax.romanov@nginx.com 
368*1554Smax.romanov@nginx.com         if (strcmp(a, "--enq") == 0 && (i + 1) < argc) {
369*1554Smax.romanov@nginx.com             nprocs_enq = atoi(argv[++i]);
370*1554Smax.romanov@nginx.com             continue;
371*1554Smax.romanov@nginx.com         }
372*1554Smax.romanov@nginx.com 
373*1554Smax.romanov@nginx.com         if (strcmp(a, "--deq") == 0 && (i + 1) < argc) {
374*1554Smax.romanov@nginx.com             nprocs_deq = atoi(argv[++i]);
375*1554Smax.romanov@nginx.com             continue;
376*1554Smax.romanov@nginx.com         }
377*1554Smax.romanov@nginx.com 
378*1554Smax.romanov@nginx.com         if (strcmp(a, "--wenq") == 0 && (i + 1) < argc) {
379*1554Smax.romanov@nginx.com             nprocs_wenq = atoi(argv[++i]);
380*1554Smax.romanov@nginx.com             continue;
381*1554Smax.romanov@nginx.com         }
382*1554Smax.romanov@nginx.com 
383*1554Smax.romanov@nginx.com         if (strcmp(a, "--wdeq") == 0 && (i + 1) < argc) {
384*1554Smax.romanov@nginx.com             nprocs_wdeq = atoi(argv[++i]);
385*1554Smax.romanov@nginx.com             continue;
386*1554Smax.romanov@nginx.com         }
387*1554Smax.romanov@nginx.com 
388*1554Smax.romanov@nginx.com         if (strcmp(a, "--ed") == 0 && (i + 1) < argc) {
389*1554Smax.romanov@nginx.com             nprocs_enq_deq = atoi(argv[++i]);
390*1554Smax.romanov@nginx.com             continue;
391*1554Smax.romanov@nginx.com         }
392*1554Smax.romanov@nginx.com 
393*1554Smax.romanov@nginx.com         if (strcmp(a, "--cas") == 0 && (i + 1) < argc) {
394*1554Smax.romanov@nginx.com             nprocs_cas = atoi(argv[++i]);
395*1554Smax.romanov@nginx.com             continue;
396*1554Smax.romanov@nginx.com         }
397*1554Smax.romanov@nginx.com 
398*1554Smax.romanov@nginx.com         if (strcmp(a, "--faa") == 0 && (i + 1) < argc) {
399*1554Smax.romanov@nginx.com             nprocs_faa = atoi(argv[++i]);
400*1554Smax.romanov@nginx.com             continue;
401*1554Smax.romanov@nginx.com         }
402*1554Smax.romanov@nginx.com 
403*1554Smax.romanov@nginx.com         if (strcmp(a, "--obj") == 0 && (i + 1) < argc) {
404*1554Smax.romanov@nginx.com             objective = atoi(argv[++i]);
405*1554Smax.romanov@nginx.com             continue;
406*1554Smax.romanov@nginx.com         }
407*1554Smax.romanov@nginx.com 
408*1554Smax.romanov@nginx.com         printf("unknown option %s", a);
409*1554Smax.romanov@nginx.com 
410*1554Smax.romanov@nginx.com         return 1;
411*1554Smax.romanov@nginx.com     }
412*1554Smax.romanov@nginx.com 
413*1554Smax.romanov@nginx.com     if (nxt_lib_start("ncq_test", argv, &environ) != NXT_OK) {
414*1554Smax.romanov@nginx.com         return 1;
415*1554Smax.romanov@nginx.com     }
416*1554Smax.romanov@nginx.com 
417*1554Smax.romanov@nginx.com     nprocs = nprocs_enq + nprocs_deq + nprocs_wenq + nprocs_wdeq
418*1554Smax.romanov@nginx.com              + nprocs_enq_deq + nprocs_cas + nprocs_faa;
419*1554Smax.romanov@nginx.com 
420*1554Smax.romanov@nginx.com     if (nprocs == 0) {
421*1554Smax.romanov@nginx.com         return 0;
422*1554Smax.romanov@nginx.com     }
423*1554Smax.romanov@nginx.com 
424*1554Smax.romanov@nginx.com     nxt_main_log.level = NXT_LOG_INFO;
425*1554Smax.romanov@nginx.com     task.log  = &nxt_main_log;
426*1554Smax.romanov@nginx.com 
427*1554Smax.romanov@nginx.com     thr = nxt_thread();
428*1554Smax.romanov@nginx.com     thr->task = &task;
429*1554Smax.romanov@nginx.com 
430*1554Smax.romanov@nginx.com     pgq = mmap(NULL, sizeof(nxt_cq_t), PROT_READ | PROT_WRITE,
431*1554Smax.romanov@nginx.com                MAP_ANON | MAP_SHARED, -1, 0);
432*1554Smax.romanov@nginx.com     if (pgq == MAP_FAILED) {
433*1554Smax.romanov@nginx.com         return 2;
434*1554Smax.romanov@nginx.com     }
435*1554Smax.romanov@nginx.com 
436*1554Smax.romanov@nginx.com     nxt_cq_init(&pgq->free_queue);
437*1554Smax.romanov@nginx.com     nxt_cq_init(&pgq->active_queue);
438*1554Smax.romanov@nginx.com 
439*1554Smax.romanov@nginx.com     for(i = 0; i < NXT_CQ_SIZE; i++) {
440*1554Smax.romanov@nginx.com         nxt_cq_enqueue(&pgq->free_queue, i);
441*1554Smax.romanov@nginx.com     }
442*1554Smax.romanov@nginx.com 
443*1554Smax.romanov@nginx.com     if (verbose >= 1) {
444*1554Smax.romanov@nginx.com         printf("number of workers: %d\n", (int) nprocs);
445*1554Smax.romanov@nginx.com         printf("number of ops:     %d\n", (int) nops);
446*1554Smax.romanov@nginx.com     }
447*1554Smax.romanov@nginx.com 
448*1554Smax.romanov@nginx.com     wi = mmap(NULL, nprocs * sizeof(nxt_worker_info_t), PROT_READ | PROT_WRITE,
449*1554Smax.romanov@nginx.com               MAP_ANON | MAP_SHARED, -1, 0);
450*1554Smax.romanov@nginx.com     if (wi == MAP_FAILED) {
451*1554Smax.romanov@nginx.com         return 3;
452*1554Smax.romanov@nginx.com     }
453*1554Smax.romanov@nginx.com 
454*1554Smax.romanov@nginx.com     for (k = 0; k < MAX_ITER; k++) {
455*1554Smax.romanov@nginx.com         nxt_memzero(wi, nprocs * sizeof(nxt_worker_info_t));
456*1554Smax.romanov@nginx.com 
457*1554Smax.romanov@nginx.com         nxt_cq_init(&pgq->free_queue);
458*1554Smax.romanov@nginx.com         nxt_cq_init(&pgq->active_queue);
459*1554Smax.romanov@nginx.com 
460*1554Smax.romanov@nginx.com         for(i = 0; i < NXT_CQ_SIZE; i++) {
461*1554Smax.romanov@nginx.com             nxt_cq_enqueue(&pgq->free_queue, i);
462*1554Smax.romanov@nginx.com         }
463*1554Smax.romanov@nginx.com 
464*1554Smax.romanov@nginx.com         start = elapsed_time(0);
465*1554Smax.romanov@nginx.com 
466*1554Smax.romanov@nginx.com         id = 0;
467*1554Smax.romanov@nginx.com 
468*1554Smax.romanov@nginx.com         for (j = 0; j < nprocs_enq; j++, id++) {
469*1554Smax.romanov@nginx.com             worker_create(wi + id, id, enq_worker);
470*1554Smax.romanov@nginx.com         }
471*1554Smax.romanov@nginx.com 
472*1554Smax.romanov@nginx.com         for (j = 0; j < nprocs_deq; j++, id++) {
473*1554Smax.romanov@nginx.com             worker_create(wi + id, id, deq_worker);
474*1554Smax.romanov@nginx.com         }
475*1554Smax.romanov@nginx.com 
476*1554Smax.romanov@nginx.com         for (j = 0; j < nprocs_wenq; j++, id++) {
477*1554Smax.romanov@nginx.com             worker_create(wi + id, id, wenq_worker);
478*1554Smax.romanov@nginx.com         }
479*1554Smax.romanov@nginx.com 
480*1554Smax.romanov@nginx.com         for (j = 0; j < nprocs_wdeq; j++, id++) {
481*1554Smax.romanov@nginx.com             worker_create(wi + id, id, wdeq_worker);
482*1554Smax.romanov@nginx.com         }
483*1554Smax.romanov@nginx.com 
484*1554Smax.romanov@nginx.com         for (j = 0; j < nprocs_enq_deq; j++, id++) {
485*1554Smax.romanov@nginx.com             worker_create(wi + id, id, enq_deq_worker);
486*1554Smax.romanov@nginx.com         }
487*1554Smax.romanov@nginx.com 
488*1554Smax.romanov@nginx.com         for (j = 0; j < nprocs_cas; j++, id++) {
489*1554Smax.romanov@nginx.com             worker_create(wi + id, id, cas_worker);
490*1554Smax.romanov@nginx.com         }
491*1554Smax.romanov@nginx.com 
492*1554Smax.romanov@nginx.com         for (j = 0; j < nprocs_faa; j++, id++) {
493*1554Smax.romanov@nginx.com             worker_create(wi + id, id, faa_worker);
494*1554Smax.romanov@nginx.com         }
495*1554Smax.romanov@nginx.com 
496*1554Smax.romanov@nginx.com         for (j = 0; j < nprocs; j++) {
497*1554Smax.romanov@nginx.com             worker_wait(wi + j);
498*1554Smax.romanov@nginx.com         }
499*1554Smax.romanov@nginx.com 
500*1554Smax.romanov@nginx.com         elapsed = elapsed_time(start);
501*1554Smax.romanov@nginx.com 
502*1554Smax.romanov@nginx.com         for (j = 1; j < nprocs; j++) {
503*1554Smax.romanov@nginx.com             wi[0].enq += wi[j].enq;
504*1554Smax.romanov@nginx.com             wi[0].deq += wi[j].deq;
505*1554Smax.romanov@nginx.com             wi[0].wait_enq += wi[j].wait_enq;
506*1554Smax.romanov@nginx.com             wi[0].wait_deq += wi[j].wait_deq;
507*1554Smax.romanov@nginx.com             wi[0].own_res += wi[j].own_res;
508*1554Smax.romanov@nginx.com             wi[0].cas += wi[j].cas;
509*1554Smax.romanov@nginx.com             wi[0].faa += wi[j].faa;
510*1554Smax.romanov@nginx.com         }
511*1554Smax.romanov@nginx.com 
512*1554Smax.romanov@nginx.com         total_ops = wi[0].enq + wi[0].deq + wi[0].cas + wi[0].faa;
513*1554Smax.romanov@nginx.com 
514*1554Smax.romanov@nginx.com         if (total_ops == 0) {
515*1554Smax.romanov@nginx.com             total_ops = nops;
516*1554Smax.romanov@nginx.com         }
517*1554Smax.romanov@nginx.com 
518*1554Smax.romanov@nginx.com         times[k] = elapsed / 1000.0;
519*1554Smax.romanov@nginx.com         mopsec[k] = (double) total_ops / elapsed;
520*1554Smax.romanov@nginx.com 
521*1554Smax.romanov@nginx.com         if (verbose >= 2) {
522*1554Smax.romanov@nginx.com             printf("enq        %10"PRIu64"\n", wi[0].enq);
523*1554Smax.romanov@nginx.com             printf("deq        %10"PRIu64"\n", wi[0].deq);
524*1554Smax.romanov@nginx.com             printf("wait_enq   %10"PRIu64"\n", wi[0].wait_enq);
525*1554Smax.romanov@nginx.com             printf("wait_deq   %10"PRIu64"\n", wi[0].wait_deq);
526*1554Smax.romanov@nginx.com             printf("own_res    %10"PRIu64"\n", wi[0].own_res);
527*1554Smax.romanov@nginx.com             printf("cas        %10"PRIu64"\n", wi[0].cas);
528*1554Smax.romanov@nginx.com             printf("faa        %10"PRIu64"\n", wi[0].faa);
529*1554Smax.romanov@nginx.com             printf("total ops  %10"PRIu64"\n", total_ops);
530*1554Smax.romanov@nginx.com             printf("Mops/sec   %13.2f\n", mopsec[k]);
531*1554Smax.romanov@nginx.com 
532*1554Smax.romanov@nginx.com             printf("elapsed    %10d us\n", (int) elapsed);
533*1554Smax.romanov@nginx.com             printf("per op     %10d ns\n", (int) ((1000 * elapsed) / total_ops));
534*1554Smax.romanov@nginx.com         }
535*1554Smax.romanov@nginx.com 
536*1554Smax.romanov@nginx.com         if (k >= STAT_ITER) {
537*1554Smax.romanov@nginx.com             stats = (objective == 0) ? times : mopsec;
538*1554Smax.romanov@nginx.com 
539*1554Smax.romanov@nginx.com             m = mean(stats + k - STAT_ITER, STAT_ITER);
540*1554Smax.romanov@nginx.com             c = cov(stats + k - STAT_ITER, m, STAT_ITER);
541*1554Smax.romanov@nginx.com 
542*1554Smax.romanov@nginx.com             if (verbose >= 1) {
543*1554Smax.romanov@nginx.com                 if (objective == 0) {
544*1554Smax.romanov@nginx.com                     printf("  #%02d elapsed time: %.2f ms; Mops/sec %.2f; "
545*1554Smax.romanov@nginx.com                            "mean time %.2f ms; cov %.4f\n",
546*1554Smax.romanov@nginx.com                            (int) k + 1, times[k], mopsec[k], m, c);
547*1554Smax.romanov@nginx.com 
548*1554Smax.romanov@nginx.com                 } else {
549*1554Smax.romanov@nginx.com                     printf("  #%02d elapsed time: %.2f ms; Mops/sec %.2f; "
550*1554Smax.romanov@nginx.com                            "mean Mop/sec %.2f; cov %.4f\n",
551*1554Smax.romanov@nginx.com                            (int) k + 1, times[k], mopsec[k], m, c);
552*1554Smax.romanov@nginx.com                 }
553*1554Smax.romanov@nginx.com             }
554*1554Smax.romanov@nginx.com 
555*1554Smax.romanov@nginx.com             if (c < MIN_COV) {
556*1554Smax.romanov@nginx.com                 rk = k - STAT_ITER;
557*1554Smax.romanov@nginx.com 
558*1554Smax.romanov@nginx.com                 for (i = rk + 1; i <= k; i++) {
559*1554Smax.romanov@nginx.com                     if (fabs(stats[i] - m) < fabs(stats[rk] - m)) {
560*1554Smax.romanov@nginx.com                         rk = i;
561*1554Smax.romanov@nginx.com                     }
562*1554Smax.romanov@nginx.com                 }
563*1554Smax.romanov@nginx.com 
564*1554Smax.romanov@nginx.com                 printf("#%d %.2f ms; %.2f\n", rk, times[rk], mopsec[rk]);
565*1554Smax.romanov@nginx.com 
566*1554Smax.romanov@nginx.com                 return 0;
567*1554Smax.romanov@nginx.com             }
568*1554Smax.romanov@nginx.com 
569*1554Smax.romanov@nginx.com         } else {
570*1554Smax.romanov@nginx.com             if (verbose >= 1) {
571*1554Smax.romanov@nginx.com                 printf("  #%02d elapsed time: %.2f ms; Mops/sec %.2f\n",
572*1554Smax.romanov@nginx.com                        (int) k + 1, times[k], mopsec[k]);
573*1554Smax.romanov@nginx.com             }
574*1554Smax.romanov@nginx.com         }
575*1554Smax.romanov@nginx.com     }
576*1554Smax.romanov@nginx.com 
577*1554Smax.romanov@nginx.com     return 0;
578*1554Smax.romanov@nginx.com }
579