123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- /*
- * Copyright (C) 2016 Red Hat, Inc.
- * Author: Michael S. Tsirkin <mst@redhat.com>
- * This work is licensed under the terms of the GNU GPL, version 2.
- *
- * Common macros and functions for ring benchmarking.
- */
- #ifndef MAIN_H
- #define MAIN_H
- #include <stdbool.h>
- extern bool do_exit;
- #if defined(__x86_64__) || defined(__i386__)
- #include "x86intrin.h"
- static inline void wait_cycles(unsigned long long cycles)
- {
- unsigned long long t;
- t = __rdtsc();
- while (__rdtsc() - t < cycles) {}
- }
- #define VMEXIT_CYCLES 500
- #define VMENTRY_CYCLES 500
- #else
- static inline void wait_cycles(unsigned long long cycles)
- {
- _Exit(5);
- }
- #define VMEXIT_CYCLES 0
- #define VMENTRY_CYCLES 0
- #endif
- static inline void vmexit(void)
- {
- if (!do_exit)
- return;
-
- wait_cycles(VMEXIT_CYCLES);
- }
- static inline void vmentry(void)
- {
- if (!do_exit)
- return;
-
- wait_cycles(VMENTRY_CYCLES);
- }
- /* implemented by ring */
- void alloc_ring(void);
- /* guest side */
- int add_inbuf(unsigned, void *, void *);
- void *get_buf(unsigned *, void **);
- void disable_call();
- bool used_empty();
- bool enable_call();
- void kick_available();
- /* host side */
- void disable_kick();
- bool avail_empty();
- bool enable_kick();
- bool use_buf(unsigned *, void **);
- void call_used();
- /* implemented by main */
- extern bool do_sleep;
- void kick(void);
- void wait_for_kick(void);
- void call(void);
- void wait_for_call(void);
- extern unsigned ring_size;
- /* Compiler barrier - similar to what Linux uses */
- #define barrier() asm volatile("" ::: "memory")
- /* Is there a portable way to do this? */
- #if defined(__x86_64__) || defined(__i386__)
- #define cpu_relax() asm ("rep; nop" ::: "memory")
- #else
- #define cpu_relax() assert(0)
- #endif
- extern bool do_relax;
- static inline void busy_wait(void)
- {
- if (do_relax)
- cpu_relax();
- else
- /* prevent compiler from removing busy loops */
- barrier();
- }
- /*
- * Not using __ATOMIC_SEQ_CST since gcc docs say they are only synchronized
- * with other __ATOMIC_SEQ_CST calls.
- */
- #define smp_mb() __sync_synchronize()
- /*
- * This abuses the atomic builtins for thread fences, and
- * adds a compiler barrier.
- */
- #define smp_release() do { \
- barrier(); \
- __atomic_thread_fence(__ATOMIC_RELEASE); \
- } while (0)
- #define smp_acquire() do { \
- __atomic_thread_fence(__ATOMIC_ACQUIRE); \
- barrier(); \
- } while (0)
- #endif
|