ptr_ring.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define _GNU_SOURCE
  3. #include "main.h"
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <pthread.h>
  8. #include <malloc.h>
  9. #include <assert.h>
  10. #include <errno.h>
  11. #include <limits.h>
  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. #define KMALLOC_MAX_SIZE SIZE_MAX
  20. typedef pthread_spinlock_t spinlock_t;
  21. typedef int gfp_t;
  22. #define __GFP_ZERO 0x1
  23. static void *kmalloc(unsigned size, gfp_t gfp)
  24. {
  25. void *p = memalign(64, size);
  26. if (!p)
  27. return p;
  28. if (gfp & __GFP_ZERO)
  29. memset(p, 0, size);
  30. return p;
  31. }
  32. static inline void *kzalloc(unsigned size, gfp_t flags)
  33. {
  34. return kmalloc(size, flags | __GFP_ZERO);
  35. }
  36. static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags)
  37. {
  38. if (size != 0 && n > SIZE_MAX / size)
  39. return NULL;
  40. return kmalloc(n * size, flags);
  41. }
  42. static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
  43. {
  44. return kmalloc_array(n, size, flags | __GFP_ZERO);
  45. }
  46. static void kfree(void *p)
  47. {
  48. if (p)
  49. free(p);
  50. }
  51. #define kvmalloc_array kmalloc_array
  52. #define kvfree kfree
  53. static void spin_lock_init(spinlock_t *lock)
  54. {
  55. int r = pthread_spin_init(lock, 0);
  56. assert(!r);
  57. }
  58. static void spin_lock(spinlock_t *lock)
  59. {
  60. int ret = pthread_spin_lock(lock);
  61. assert(!ret);
  62. }
  63. static void spin_unlock(spinlock_t *lock)
  64. {
  65. int ret = pthread_spin_unlock(lock);
  66. assert(!ret);
  67. }
  68. static void spin_lock_bh(spinlock_t *lock)
  69. {
  70. spin_lock(lock);
  71. }
  72. static void spin_unlock_bh(spinlock_t *lock)
  73. {
  74. spin_unlock(lock);
  75. }
  76. static void spin_lock_irq(spinlock_t *lock)
  77. {
  78. spin_lock(lock);
  79. }
  80. static void spin_unlock_irq(spinlock_t *lock)
  81. {
  82. spin_unlock(lock);
  83. }
  84. static void spin_lock_irqsave(spinlock_t *lock, unsigned long f)
  85. {
  86. spin_lock(lock);
  87. }
  88. static void spin_unlock_irqrestore(spinlock_t *lock, unsigned long f)
  89. {
  90. spin_unlock(lock);
  91. }
  92. #include "../../../include/linux/ptr_ring.h"
  93. static unsigned long long headcnt, tailcnt;
  94. static struct ptr_ring array ____cacheline_aligned_in_smp;
  95. /* implemented by ring */
  96. void alloc_ring(void)
  97. {
  98. int ret = ptr_ring_init(&array, ring_size, 0);
  99. assert(!ret);
  100. /* Hacky way to poke at ring internals. Useful for testing though. */
  101. if (param)
  102. array.batch = param;
  103. }
  104. /* guest side */
  105. int add_inbuf(unsigned len, void *buf, void *datap)
  106. {
  107. int ret;
  108. ret = __ptr_ring_produce(&array, buf);
  109. if (ret >= 0) {
  110. ret = 0;
  111. headcnt++;
  112. }
  113. return ret;
  114. }
  115. /*
  116. * ptr_ring API provides no way for producer to find out whether a given
  117. * buffer was consumed. Our tests merely require that a successful get_buf
  118. * implies that add_inbuf succeed in the past, and that add_inbuf will succeed,
  119. * fake it accordingly.
  120. */
  121. void *get_buf(unsigned *lenp, void **bufp)
  122. {
  123. void *datap;
  124. if (tailcnt == headcnt || __ptr_ring_full(&array))
  125. datap = NULL;
  126. else {
  127. datap = "Buffer\n";
  128. ++tailcnt;
  129. }
  130. return datap;
  131. }
  132. bool used_empty()
  133. {
  134. return (tailcnt == headcnt || __ptr_ring_full(&array));
  135. }
  136. void disable_call()
  137. {
  138. assert(0);
  139. }
  140. bool enable_call()
  141. {
  142. assert(0);
  143. }
  144. void kick_available(void)
  145. {
  146. assert(0);
  147. }
  148. /* host side */
  149. void disable_kick()
  150. {
  151. assert(0);
  152. }
  153. bool enable_kick()
  154. {
  155. assert(0);
  156. }
  157. bool avail_empty()
  158. {
  159. return __ptr_ring_empty(&array);
  160. }
  161. bool use_buf(unsigned *lenp, void **bufp)
  162. {
  163. void *ptr;
  164. ptr = __ptr_ring_consume(&array);
  165. return ptr;
  166. }
  167. void call_used(void)
  168. {
  169. assert(0);
  170. }