Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/tools/testing/selftests/kvm/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  irqfd_test.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <stdint.h>
#include <sys/sysinfo.h>

#include "kvm_util.h"

static struct kvm_vm *vm1;
static struct kvm_vm *vm2;
static int __eventfd;
static bool done;

/*
 * KVM de-assigns based on eventfd *and* GSI, but requires unique eventfds when
 * assigning (the API isn't symmetrical).  Abuse the oddity and use a per-task
 * GSI base to avoid false failures due to cross-task de-assign, i.e. so that
 * the secondary doesn't de-assign the primary's eventfd and cause assign to
 * unexpectedly succeed on the primary.
 */

#define GSI_BASE_PRIMARY 0x20
#define GSI_BASE_SECONDARY 0x30

static void juggle_eventfd_secondary(struct kvm_vm *vm, int eventfd)
{
 int r, i;

 /*
 * The secondary task can encounter EBADF since the primary can close
 * the eventfd at any time.  And because the primary can recreate the
 * eventfd, at the safe fd in the file table, the secondary can also
 * encounter "unexpected" success, e.g. if the close+recreate happens
 * between the first and second assignments.  The secondary's role is
 * mostly to antagonize KVM, not to detect bugs.
 */

 for (i = 0; i < 2; i++) {
  r = __kvm_irqfd(vm, GSI_BASE_SECONDARY, eventfd, 0);
  TEST_ASSERT(!r || errno == EBUSY || errno == EBADF,
       "Wanted success, EBUSY, or EBADF, r = %d, errno = %d",
       r, errno);

  /* De-assign should succeed unless the eventfd was closed. */
  r = __kvm_irqfd(vm, GSI_BASE_SECONDARY + i, eventfd, KVM_IRQFD_FLAG_DEASSIGN);
  TEST_ASSERT(!r || errno == EBADF,
       "De-assign should succeed unless the fd was closed");
 }
}

static void *secondary_irqfd_juggler(void *ign)
{
 while (!READ_ONCE(done)) {
  juggle_eventfd_secondary(vm1, READ_ONCE(__eventfd));
  juggle_eventfd_secondary(vm2, READ_ONCE(__eventfd));
 }

 return NULL;
}

static void juggle_eventfd_primary(struct kvm_vm *vm, int eventfd)
{
 int r1, r2;

 /*
 * At least one of the assigns should fail.  KVM disallows assigning a
 * single eventfd to multiple GSIs (or VMs), so it's possible that both
 * assignments can fail, too.
 */

 r1 = __kvm_irqfd(vm, GSI_BASE_PRIMARY, eventfd, 0);
 TEST_ASSERT(!r1 || errno == EBUSY,
      "Wanted success or EBUSY, r = %d, errno = %d", r1, errno);

 r2 = __kvm_irqfd(vm, GSI_BASE_PRIMARY + 1, eventfd, 0);
 TEST_ASSERT(r1 || (r2 && errno == EBUSY),
      "Wanted failure (EBUSY), r1 = %d, r2 = %d, errno = %d",
      r1, r2, errno);

 /*
 * De-assign should always succeed, even if the corresponding assign
 * failed.
 */

 kvm_irqfd(vm, GSI_BASE_PRIMARY, eventfd, KVM_IRQFD_FLAG_DEASSIGN);
 kvm_irqfd(vm, GSI_BASE_PRIMARY + 1, eventfd, KVM_IRQFD_FLAG_DEASSIGN);
}

int main(int argc, char *argv[])
{
 pthread_t racing_thread;
 int r, i;

 /* Create "full" VMs, as KVM_IRQFD requires an in-kernel IRQ chip. */
 vm1 = vm_create(1);
 vm2 = vm_create(1);

 WRITE_ONCE(__eventfd, kvm_new_eventfd());

 kvm_irqfd(vm1, 10, __eventfd, 0);

 r = __kvm_irqfd(vm1, 11, __eventfd, 0);
 TEST_ASSERT(r && errno == EBUSY,
      "Wanted EBUSY, r = %d, errno = %d", r, errno);

 r = __kvm_irqfd(vm2, 12, __eventfd, 0);
 TEST_ASSERT(r && errno == EBUSY,
      "Wanted EBUSY, r = %d, errno = %d", r, errno);

 /*
 * De-assign all eventfds, along with multiple eventfds that were never
 * assigned.  KVM's ABI is that de-assign is allowed so long as the
 * eventfd itself is valid.
 */

 kvm_irqfd(vm1, 11, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN);
 kvm_irqfd(vm1, 12, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN);
 kvm_irqfd(vm1, 13, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN);
 kvm_irqfd(vm1, 14, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN);
 kvm_irqfd(vm1, 10, READ_ONCE(__eventfd), KVM_IRQFD_FLAG_DEASSIGN);

 close(__eventfd);

 pthread_create(&racing_thread, NULL, secondary_irqfd_juggler, vm2);

 for (i = 0; i < 10000; i++) {
  WRITE_ONCE(__eventfd, kvm_new_eventfd());

  juggle_eventfd_primary(vm1, __eventfd);
  juggle_eventfd_primary(vm2, __eventfd);
  close(__eventfd);
 }

 WRITE_ONCE(done, true);
 pthread_join(racing_thread, NULL);
}

Messung V0.5
C=96 H=97 G=96

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© 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.