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