~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/virtio/ringtest/main.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * Copyright (C) 2016 Red Hat, Inc.
  4  * Author: Michael S. Tsirkin <mst@redhat.com>
  5  *
  6  * Command line processing and common functions for ring benchmarking.
  7  */
  8 #define _GNU_SOURCE
  9 #include <getopt.h>
 10 #include <pthread.h>
 11 #include <assert.h>
 12 #include <sched.h>
 13 #include "main.h"
 14 #include <sys/eventfd.h>
 15 #include <stdlib.h>
 16 #include <stdio.h>
 17 #include <unistd.h>
 18 #include <limits.h>
 19 
 20 int runcycles = 10000000;
 21 int max_outstanding = INT_MAX;
 22 int batch = 1;
 23 int param = 0;
 24 
 25 bool do_sleep = false;
 26 bool do_relax = false;
 27 bool do_exit = true;
 28 
 29 unsigned ring_size = 256;
 30 
 31 static int kickfd = -1;
 32 static int callfd = -1;
 33 
 34 void notify(int fd)
 35 {
 36         unsigned long long v = 1;
 37         int r;
 38 
 39         vmexit();
 40         r = write(fd, &v, sizeof v);
 41         assert(r == sizeof v);
 42         vmentry();
 43 }
 44 
 45 void wait_for_notify(int fd)
 46 {
 47         unsigned long long v = 1;
 48         int r;
 49 
 50         vmexit();
 51         r = read(fd, &v, sizeof v);
 52         assert(r == sizeof v);
 53         vmentry();
 54 }
 55 
 56 void kick(void)
 57 {
 58         notify(kickfd);
 59 }
 60 
 61 void wait_for_kick(void)
 62 {
 63         wait_for_notify(kickfd);
 64 }
 65 
 66 void call(void)
 67 {
 68         notify(callfd);
 69 }
 70 
 71 void wait_for_call(void)
 72 {
 73         wait_for_notify(callfd);
 74 }
 75 
 76 void set_affinity(const char *arg)
 77 {
 78         cpu_set_t cpuset;
 79         int ret;
 80         pthread_t self;
 81         long int cpu;
 82         char *endptr;
 83 
 84         if (!arg)
 85                 return;
 86 
 87         cpu = strtol(arg, &endptr, 0);
 88         assert(!*endptr);
 89 
 90         assert(cpu >= 0 && cpu < CPU_SETSIZE);
 91 
 92         self = pthread_self();
 93         CPU_ZERO(&cpuset);
 94         CPU_SET(cpu, &cpuset);
 95 
 96         ret = pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset);
 97         assert(!ret);
 98 }
 99 
100 void poll_used(void)
101 {
102         while (used_empty())
103                 busy_wait();
104 }
105 
106 static void __attribute__((__flatten__)) run_guest(void)
107 {
108         int completed_before;
109         int completed = 0;
110         int started = 0;
111         int bufs = runcycles;
112         int spurious = 0;
113         int r;
114         unsigned len;
115         void *buf;
116         int tokick = batch;
117 
118         for (;;) {
119                 if (do_sleep)
120                         disable_call();
121                 completed_before = completed;
122                 do {
123                         if (started < bufs &&
124                             started - completed < max_outstanding) {
125                                 r = add_inbuf(0, "Buffer\n", "Hello, world!");
126                                 if (__builtin_expect(r == 0, true)) {
127                                         ++started;
128                                         if (!--tokick) {
129                                                 tokick = batch;
130                                                 if (do_sleep)
131                                                         kick_available();
132                                         }
133 
134                                 }
135                         } else
136                                 r = -1;
137 
138                         /* Flush out completed bufs if any */
139                         if (get_buf(&len, &buf)) {
140                                 ++completed;
141                                 if (__builtin_expect(completed == bufs, false))
142                                         return;
143                                 r = 0;
144                         }
145                 } while (r == 0);
146                 if (completed == completed_before)
147                         ++spurious;
148                 assert(completed <= bufs);
149                 assert(started <= bufs);
150                 if (do_sleep) {
151                         if (used_empty() && enable_call())
152                                 wait_for_call();
153                 } else {
154                         poll_used();
155                 }
156         }
157 }
158 
159 void poll_avail(void)
160 {
161         while (avail_empty())
162                 busy_wait();
163 }
164 
165 static void __attribute__((__flatten__)) run_host(void)
166 {
167         int completed_before;
168         int completed = 0;
169         int spurious = 0;
170         int bufs = runcycles;
171         unsigned len;
172         void *buf;
173 
174         for (;;) {
175                 if (do_sleep) {
176                         if (avail_empty() && enable_kick())
177                                 wait_for_kick();
178                 } else {
179                         poll_avail();
180                 }
181                 if (do_sleep)
182                         disable_kick();
183                 completed_before = completed;
184                 while (__builtin_expect(use_buf(&len, &buf), true)) {
185                         if (do_sleep)
186                                 call_used();
187                         ++completed;
188                         if (__builtin_expect(completed == bufs, false))
189                                 return;
190                 }
191                 if (completed == completed_before)
192                         ++spurious;
193                 assert(completed <= bufs);
194                 if (completed == bufs)
195                         break;
196         }
197 }
198 
199 void *start_guest(void *arg)
200 {
201         set_affinity(arg);
202         run_guest();
203         pthread_exit(NULL);
204 }
205 
206 void *start_host(void *arg)
207 {
208         set_affinity(arg);
209         run_host();
210         pthread_exit(NULL);
211 }
212 
213 static const char optstring[] = "";
214 static const struct option longopts[] = {
215         {
216                 .name = "help",
217                 .has_arg = no_argument,
218                 .val = 'h',
219         },
220         {
221                 .name = "host-affinity",
222                 .has_arg = required_argument,
223                 .val = 'H',
224         },
225         {
226                 .name = "guest-affinity",
227                 .has_arg = required_argument,
228                 .val = 'G',
229         },
230         {
231                 .name = "ring-size",
232                 .has_arg = required_argument,
233                 .val = 'R',
234         },
235         {
236                 .name = "run-cycles",
237                 .has_arg = required_argument,
238                 .val = 'C',
239         },
240         {
241                 .name = "outstanding",
242                 .has_arg = required_argument,
243                 .val = 'o',
244         },
245         {
246                 .name = "batch",
247                 .has_arg = required_argument,
248                 .val = 'b',
249         },
250         {
251                 .name = "param",
252                 .has_arg = required_argument,
253                 .val = 'p',
254         },
255         {
256                 .name = "sleep",
257                 .has_arg = no_argument,
258                 .val = 's',
259         },
260         {
261                 .name = "relax",
262                 .has_arg = no_argument,
263                 .val = 'x',
264         },
265         {
266                 .name = "exit",
267                 .has_arg = no_argument,
268                 .val = 'e',
269         },
270         {
271         }
272 };
273 
274 static void help(void)
275 {
276         fprintf(stderr, "Usage: <test> [--help]"
277                 " [--host-affinity H]"
278                 " [--guest-affinity G]"
279                 " [--ring-size R (default: %d)]"
280                 " [--run-cycles C (default: %d)]"
281                 " [--batch b]"
282                 " [--outstanding o]"
283                 " [--param p]"
284                 " [--sleep]"
285                 " [--relax]"
286                 " [--exit]"
287                 "\n",
288                 ring_size,
289                 runcycles);
290 }
291 
292 int main(int argc, char **argv)
293 {
294         int ret;
295         pthread_t host, guest;
296         void *tret;
297         char *host_arg = NULL;
298         char *guest_arg = NULL;
299         char *endptr;
300         long int c;
301 
302         kickfd = eventfd(0, 0);
303         assert(kickfd >= 0);
304         callfd = eventfd(0, 0);
305         assert(callfd >= 0);
306 
307         for (;;) {
308                 int o = getopt_long(argc, argv, optstring, longopts, NULL);
309                 switch (o) {
310                 case -1:
311                         goto done;
312                 case '?':
313                         help();
314                         exit(2);
315                 case 'H':
316                         host_arg = optarg;
317                         break;
318                 case 'G':
319                         guest_arg = optarg;
320                         break;
321                 case 'R':
322                         ring_size = strtol(optarg, &endptr, 0);
323                         assert(ring_size && !(ring_size & (ring_size - 1)));
324                         assert(!*endptr);
325                         break;
326                 case 'C':
327                         c = strtol(optarg, &endptr, 0);
328                         assert(!*endptr);
329                         assert(c > 0 && c < INT_MAX);
330                         runcycles = c;
331                         break;
332                 case 'o':
333                         c = strtol(optarg, &endptr, 0);
334                         assert(!*endptr);
335                         assert(c > 0 && c < INT_MAX);
336                         max_outstanding = c;
337                         break;
338                 case 'p':
339                         c = strtol(optarg, &endptr, 0);
340                         assert(!*endptr);
341                         assert(c > 0 && c < INT_MAX);
342                         param = c;
343                         break;
344                 case 'b':
345                         c = strtol(optarg, &endptr, 0);
346                         assert(!*endptr);
347                         assert(c > 0 && c < INT_MAX);
348                         batch = c;
349                         break;
350                 case 's':
351                         do_sleep = true;
352                         break;
353                 case 'x':
354                         do_relax = true;
355                         break;
356                 case 'e':
357                         do_exit = true;
358                         break;
359                 default:
360                         help();
361                         exit(4);
362                         break;
363                 }
364         }
365 
366         /* does nothing here, used to make sure all smp APIs compile */
367         smp_acquire();
368         smp_release();
369         smp_mb();
370 done:
371 
372         if (batch > max_outstanding)
373                 batch = max_outstanding;
374 
375         if (optind < argc) {
376                 help();
377                 exit(4);
378         }
379         alloc_ring();
380 
381         ret = pthread_create(&host, NULL, start_host, host_arg);
382         assert(!ret);
383         ret = pthread_create(&guest, NULL, start_guest, guest_arg);
384         assert(!ret);
385 
386         ret = pthread_join(guest, &tret);
387         assert(!ret);
388         ret = pthread_join(host, &tret);
389         assert(!ret);
390         return 0;
391 }
392 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php