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