#include #include #include #include #include #include #define MAX_THREADS 128 #define MAX_EVENTS 100000 #define FIRST_IRQ 62 #define MAX_VCPUS 8 static unsigned long long elapsed[MAX_THREADS]; static void bind_irq(unsigned port, unsigned cpu) { char buf[64]; FILE *f; unsigned irq = port + FIRST_IRQ; snprintf(buf, sizeof(buf), "/proc/irq/%d/smp_affinity", irq); f = fopen(buf, "w"); if (!f) return; snprintf(buf, sizeof(buf), "%x", 1 << cpu); fwrite(buf, strlen(buf), 1, f); fclose(f); } void *test_thread(void *arg) { unsigned i = (intptr_t)arg; xc_evtchn *xce; evtchn_port_t lport; evtchn_port_t rport; unsigned events = 0; struct timespec start, end; xce = xc_evtchn_open(NULL, 0); if (!xce) return NULL; lport = xc_evtchn_bind_unbound_port(xce, 0); if (lport < 0) return NULL; rport = xc_evtchn_bind_interdomain(xce, 0, lport); bind_irq(lport, lport % MAX_VCPUS); bind_irq(rport, rport % MAX_VCPUS); xc_evtchn_notify(xce, lport); clock_gettime(CLOCK_MONOTONIC, &start); while (events < MAX_EVENTS) { evtchn_port_t port; port = xc_evtchn_pending(xce); if (port == lport) xc_evtchn_notify(xce, lport); else xc_evtchn_notify(xce, rport); xc_evtchn_unmask(xce, port); events++; } clock_gettime(CLOCK_MONOTONIC, &end); xc_evtchn_close(xce); elapsed[i] = (end.tv_sec - start.tv_sec) * 1000000000ull + (end.tv_nsec - start.tv_nsec); return NULL; } static pthread_t threads[MAX_THREADS]; int start_thread(unsigned i) { return pthread_create(&threads[i], NULL, test_thread, (void *)(intptr_t)i); } void run_test(unsigned num_threads) { unsigned i; double accum = 0.0; for (i = 0; i < num_threads; i++) start_thread(i); for (i = 0; i < num_threads; i++) pthread_join(threads[i], NULL); for (i = 0; i < num_threads; i++) accum += MAX_EVENTS / (double)elapsed[i]; printf(" num_threads: %u\n", num_threads); printf(" rate: %.1f event/s\n", accum / num_threads * 1000000000.0); } int main(int argc, char *argv[]) { unsigned num_threads; unsigned num_iters; unsigned i; if (argc <=1 ) fprintf(stderr, "Usage: %s \n", argv[0]); num_iters = atoi(argv[1]); num_threads = atoi(argv[2]); for (i = 0; i < num_iters; i++) { printf("iter: %d\n", i); run_test(num_threads); } return 0; }