1 #define _GNU_SOURCE 2 #include "main.h" 3 #include <stdlib.h> 4 #include <stdio.h> 5 #include <string.h> 6 #include <pthread.h> 7 #include <malloc.h> 8 #include <assert.h> 9 #include <errno.h> 10 #include <limits.h> 11 12 #define SMP_CACHE_BYTES 64 13 #define cache_line_size() SMP_CACHE_BYTES 14 #define ____cacheline_aligned_in_smp __attribute__ ((aligned (SMP_CACHE_BYTES))) 15 #define unlikely(x) (__builtin_expect(!!(x), 0)) 16 #define ALIGN(x, a) (((x) + (a) - 1) / (a) * (a)) 17 typedef pthread_spinlock_t spinlock_t; 18 19 typedef int gfp_t; 20 static void *kzalloc(unsigned size, gfp_t gfp) 21 { 22 void *p = memalign(64, size); 23 if (!p) 24 return p; 25 memset(p, 0, size); 26 27 return p; 28 } 29 30 static void kfree(void *p) 31 { 32 if (p) 33 free(p); 34 } 35 36 static void spin_lock_init(spinlock_t *lock) 37 { 38 int r = pthread_spin_init(lock, 0); 39 assert(!r); 40 } 41 42 static void spin_lock(spinlock_t *lock) 43 { 44 int ret = pthread_spin_lock(lock); 45 assert(!ret); 46 } 47 48 static void spin_unlock(spinlock_t *lock) 49 { 50 int ret = pthread_spin_unlock(lock); 51 assert(!ret); 52 } 53 54 static void spin_lock_bh(spinlock_t *lock) 55 { 56 spin_lock(lock); 57 } 58 59 static void spin_unlock_bh(spinlock_t *lock) 60 { 61 spin_unlock(lock); 62 } 63 64 static void spin_lock_irq(spinlock_t *lock) 65 { 66 spin_lock(lock); 67 } 68 69 static void spin_unlock_irq(spinlock_t *lock) 70 { 71 spin_unlock(lock); 72 } 73 74 static void spin_lock_irqsave(spinlock_t *lock, unsigned long f) 75 { 76 spin_lock(lock); 77 } 78 79 static void spin_unlock_irqrestore(spinlock_t *lock, unsigned long f) 80 { 81 spin_unlock(lock); 82 } 83 84 #include "../../../include/linux/ptr_ring.h" 85 86 static unsigned long long headcnt, tailcnt; 87 static struct ptr_ring array ____cacheline_aligned_in_smp; 88 89 /* implemented by ring */ 90 void alloc_ring(void) 91 { 92 int ret = ptr_ring_init(&array, ring_size, 0); 93 assert(!ret); 94 } 95 96 /* guest side */ 97 int add_inbuf(unsigned len, void *buf, void *datap) 98 { 99 int ret; 100 101 ret = __ptr_ring_produce(&array, buf); 102 if (ret >= 0) { 103 ret = 0; 104 headcnt++; 105 } 106 107 return ret; 108 } 109 110 /* 111 * ptr_ring API provides no way for producer to find out whether a given 112 * buffer was consumed. Our tests merely require that a successful get_buf 113 * implies that add_inbuf succeed in the past, and that add_inbuf will succeed, 114 * fake it accordingly. 115 */ 116 void *get_buf(unsigned *lenp, void **bufp) 117 { 118 void *datap; 119 120 if (tailcnt == headcnt || __ptr_ring_full(&array)) 121 datap = NULL; 122 else { 123 datap = "Buffer\n"; 124 ++tailcnt; 125 } 126 127 return datap; 128 } 129 130 void poll_used(void) 131 { 132 void *b; 133 134 do { 135 if (tailcnt == headcnt || __ptr_ring_full(&array)) { 136 b = NULL; 137 barrier(); 138 } else { 139 b = "Buffer\n"; 140 } 141 } while (!b); 142 } 143 144 void disable_call() 145 { 146 assert(0); 147 } 148 149 bool enable_call() 150 { 151 assert(0); 152 } 153 154 void kick_available(void) 155 { 156 assert(0); 157 } 158 159 /* host side */ 160 void disable_kick() 161 { 162 assert(0); 163 } 164 165 bool enable_kick() 166 { 167 assert(0); 168 } 169 170 void poll_avail(void) 171 { 172 void *b; 173 174 do { 175 barrier(); 176 b = __ptr_ring_peek(&array); 177 } while (!b); 178 } 179 180 bool use_buf(unsigned *lenp, void **bufp) 181 { 182 void *ptr; 183 184 ptr = __ptr_ring_consume(&array); 185 186 return ptr; 187 } 188 189 void call_used(void) 190 { 191 assert(0); 192 } 193