Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


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.15 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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge