Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/tools/virtio/ringtest/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 6 kB image not shown  

Quelle  main.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2016 Red Hat, Inc.
 * Author: Michael S. Tsirkin <mst@redhat.com>
 *
 * Command line processing and common functions for ring benchmarking.
 */

#define _GNU_SOURCE
#include <getopt.h>
#include <pthread.h>
#include <assert.h>
#include <sched.h>
#include "main.h"
#include <sys/eventfd.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <limits.h>

int runcycles = 10000000;
int max_outstanding = INT_MAX;
int batch = 1;
int param = 0;

bool do_sleep = false;
bool do_relax = false;
bool do_exit = true;

unsigned ring_size = 256;

static int kickfd = -1;
static int callfd = -1;

void notify(int fd)
{
 unsigned long long v = 1;
 int r;

 vmexit();
 r = write(fd, &v, sizeof v);
 assert(r == sizeof v);
 vmentry();
}

void wait_for_notify(int fd)
{
 unsigned long long v = 1;
 int r;

 vmexit();
 r = read(fd, &v, sizeof v);
 assert(r == sizeof v);
 vmentry();
}

void kick(void)
{
 notify(kickfd);
}

void wait_for_kick(void)
{
 wait_for_notify(kickfd);
}

void call(void)
{
 notify(callfd);
}

void wait_for_call(void)
{
 wait_for_notify(callfd);
}

void set_affinity(const char *arg)
{
 cpu_set_t cpuset;
 int ret;
 pthread_t self;
 long int cpu;
 char *endptr;

 if (!arg)
  return;

 cpu = strtol(arg, &endptr, 0);
 assert(!*endptr);

 assert(cpu >= 0 && cpu < CPU_SETSIZE);

 self = pthread_self();
 CPU_ZERO(&cpuset);
 CPU_SET(cpu, &cpuset);

 ret = pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset);
 assert(!ret);
}

void poll_used(void)
{
 while (used_empty())
  busy_wait();
}

static void __attribute__((__flatten__)) run_guest(void)
{
 int completed_before;
 int completed = 0;
 int started = 0;
 int bufs = runcycles;
 int spurious = 0;
 int r;
 unsigned len;
 void *buf;
 int tokick = batch;

 for (;;) {
  if (do_sleep)
   disable_call();
  completed_before = completed;
  do {
   if (started < bufs &&
       started - completed < max_outstanding) {
    r = add_inbuf(0, "Buffer\n""Hello, world!");
    if (__builtin_expect(r == 0, true)) {
     ++started;
     if (!--tokick) {
      tokick = batch;
      if (do_sleep)
       kick_available();
     }

    }
   } else
    r = -1;

   /* Flush out completed bufs if any */
   if (get_buf(&len, &buf)) {
    ++completed;
    if (__builtin_expect(completed == bufs, false))
     return;
    r = 0;
   }
  } while (r == 0);
  if (completed == completed_before)
   ++spurious;
  assert(completed <= bufs);
  assert(started <= bufs);
  if (do_sleep) {
   if (used_empty() && enable_call())
    wait_for_call();
  } else {
   poll_used();
  }
 }
}

void poll_avail(void)
{
 while (avail_empty())
  busy_wait();
}

static void __attribute__((__flatten__)) run_host(void)
{
 int completed_before;
 int completed = 0;
 int spurious = 0;
 int bufs = runcycles;
 unsigned len;
 void *buf;

 for (;;) {
  if (do_sleep) {
   if (avail_empty() && enable_kick())
    wait_for_kick();
  } else {
   poll_avail();
  }
  if (do_sleep)
   disable_kick();
  completed_before = completed;
  while (__builtin_expect(use_buf(&len, &buf), true)) {
   if (do_sleep)
    call_used();
   ++completed;
   if (__builtin_expect(completed == bufs, false))
    return;
  }
  if (completed == completed_before)
   ++spurious;
  assert(completed <= bufs);
  if (completed == bufs)
   break;
 }
}

void *start_guest(void *arg)
{
 set_affinity(arg);
 run_guest();
 pthread_exit(NULL);
}

void *start_host(void *arg)
{
 set_affinity(arg);
 run_host();
 pthread_exit(NULL);
}

static const char optstring[] = "";
static const struct option longopts[] = {
 {
  .name = "help",
  .has_arg = no_argument,
  .val = 'h',
 },
 {
  .name = "host-affinity",
  .has_arg = required_argument,
  .val = 'H',
 },
 {
  .name = "guest-affinity",
  .has_arg = required_argument,
  .val = 'G',
 },
 {
  .name = "ring-size",
  .has_arg = required_argument,
  .val = 'R',
 },
 {
  .name = "run-cycles",
  .has_arg = required_argument,
  .val = 'C',
 },
 {
  .name = "outstanding",
  .has_arg = required_argument,
  .val = 'o',
 },
 {
  .name = "batch",
  .has_arg = required_argument,
  .val = 'b',
 },
 {
  .name = "param",
  .has_arg = required_argument,
  .val = 'p',
 },
 {
  .name = "sleep",
  .has_arg = no_argument,
  .val = 's',
 },
 {
  .name = "relax",
  .has_arg = no_argument,
  .val = 'x',
 },
 {
  .name = "exit",
  .has_arg = no_argument,
  .val = 'e',
 },
 {
 }
};

static void help(void)
{
 fprintf(stderr, "Usage: [--help]"
  " [--host-affinity H]"
  " [--guest-affinity G]"
  " [--ring-size R (default: %u)]"
  " [--run-cycles C (default: %d)]"
  " [--batch b]"
  " [--outstanding o]"
  " [--param p]"
  " [--sleep]"
  " [--relax]"
  " [--exit]"
  "\n",
  ring_size,
  runcycles);
}

int main(int argc, char **argv)
{
 int ret;
 pthread_t host, guest;
 void *tret;
 char *host_arg = NULL;
 char *guest_arg = NULL;
 char *endptr;
 long int c;

 kickfd = eventfd(0, 0);
 assert(kickfd >= 0);
 callfd = eventfd(0, 0);
 assert(callfd >= 0);

 for (;;) {
  int o = getopt_long(argc, argv, optstring, longopts, NULL);
  switch (o) {
  case -1:
   goto done;
  case '?':
   help();
   exit(2);
  case 'H':
   host_arg = optarg;
   break;
  case 'G':
   guest_arg = optarg;
   break;
  case 'R':
   ring_size = strtol(optarg, &endptr, 0);
   assert(ring_size && !(ring_size & (ring_size - 1)));
   assert(!*endptr);
   break;
  case 'C':
   c = strtol(optarg, &endptr, 0);
   assert(!*endptr);
   assert(c > 0 && c < INT_MAX);
   runcycles = c;
   break;
  case 'o':
   c = strtol(optarg, &endptr, 0);
   assert(!*endptr);
   assert(c > 0 && c < INT_MAX);
   max_outstanding = c;
   break;
  case 'p':
   c = strtol(optarg, &endptr, 0);
   assert(!*endptr);
   assert(c > 0 && c < INT_MAX);
   param = c;
   break;
  case 'b':
   c = strtol(optarg, &endptr, 0);
   assert(!*endptr);
   assert(c > 0 && c < INT_MAX);
   batch = c;
   break;
  case 's':
   do_sleep = true;
   break;
  case 'x':
   do_relax = true;
   break;
  case 'e':
   do_exit = true;
   break;
  default:
   help();
   exit(4);
   break;
  }
 }

 /* does nothing here, used to make sure all smp APIs compile */
 smp_acquire();
 smp_release();
 smp_mb();
done:

 if (batch > max_outstanding)
  batch = max_outstanding;

 if (optind < argc) {
  help();
  exit(4);
 }
 alloc_ring();

 ret = pthread_create(&host, NULL, start_host, host_arg);
 assert(!ret);
 ret = pthread_create(&guest, NULL, start_guest, guest_arg);
 assert(!ret);

 ret = pthread_join(guest, &tret);
 assert(!ret);
 ret = pthread_join(host, &tret);
 assert(!ret);
 return 0;
}

Messung V0.5
C=90 H=90 G=90

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.