1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2016-2017 Intel Corporation
3 */
4
5 /*
6 * Generic ring structure for passing events from one core to another.
7 *
8 * Used by the software scheduler for the producer and consumer rings for
9 * each port, i.e. for passing events from worker cores to scheduler and
10 * vice-versa. Designed for single-producer, single-consumer use with two
11 * cores working on each ring.
12 */
13
14 #ifndef _EVENT_RING_
15 #define _EVENT_RING_
16
17 #include <stdint.h>
18
19 #include <rte_common.h>
20 #include <rte_memory.h>
21 #include <rte_malloc.h>
22
23 /* Custom single threaded ring implementation used for ROB */
24 struct rob_ring {
25 uint32_t ring_size;
26 uint32_t mask;
27 uint32_t size;
28 uint32_t write_idx;
29 uint32_t read_idx;
30 void *ring[0] __rte_cache_aligned;
31 };
32
33 static inline struct rob_ring *
rob_ring_create(unsigned int size,unsigned int socket_id)34 rob_ring_create(unsigned int size, unsigned int socket_id)
35 {
36 struct rob_ring *retval;
37 const uint32_t ring_size = rte_align32pow2(size + 1);
38 size_t memsize = sizeof(*retval) +
39 (ring_size * sizeof(retval->ring[0]));
40
41 retval = rte_zmalloc_socket(NULL, memsize, 0, socket_id);
42 if (retval == NULL)
43 goto end;
44 retval->ring_size = ring_size;
45 retval->mask = ring_size - 1;
46 retval->size = size;
47 end:
48 return retval;
49 }
50
51 static inline void
rob_ring_free(struct rob_ring * r)52 rob_ring_free(struct rob_ring *r)
53 {
54 rte_free(r);
55 }
56
57 static __rte_always_inline unsigned int
rob_ring_count(const struct rob_ring * r)58 rob_ring_count(const struct rob_ring *r)
59 {
60 return r->write_idx - r->read_idx;
61 }
62
63 static __rte_always_inline unsigned int
rob_ring_free_count(const struct rob_ring * r)64 rob_ring_free_count(const struct rob_ring *r)
65 {
66 return r->size - rob_ring_count(r);
67 }
68
69 static __rte_always_inline unsigned int
rob_ring_enqueue(struct rob_ring * r,void * re)70 rob_ring_enqueue(struct rob_ring *r, void *re)
71 {
72 const uint32_t size = r->size;
73 const uint32_t mask = r->mask;
74 const uint32_t read = r->read_idx;
75 uint32_t write = r->write_idx;
76 const uint32_t space = read + size - write;
77 if (space < 1)
78 return 0;
79 r->ring[write & mask] = re;
80 r->write_idx++;
81 return 1;
82 }
83
84 static __rte_always_inline unsigned int
rob_ring_dequeue(struct rob_ring * r,void ** re)85 rob_ring_dequeue(struct rob_ring *r, void **re)
86 {
87 const uint32_t mask = r->mask;
88 uint32_t read = r->read_idx;
89 const uint32_t write = r->write_idx;
90 const uint32_t items = write - read;
91 if (items < 1)
92 return 0;
93 *re = r->ring[read & mask];
94 r->read_idx++;
95 return 1;
96 }
97
98 #endif
99