aboutsummaryrefslogtreecommitdiff
path: root/platform/linux-generic/include/odp_ring_st_internal.h
blob: 5fb37d4ef840704e1e8d23ebed180c018ddefd92 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/* Copyright (c) 2018, Linaro Limited
 * All rights reserved.
 *
 * SPDX-License-Identifier:     BSD-3-Clause
 */

#ifndef ODP_RING_ST_INTERNAL_H_
#define ODP_RING_ST_INTERNAL_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <odp/api/hints.h>
#include <odp_align_internal.h>

/* Basic ring for single thread usage. Operations must be synchronized by using
 * locks (or other means), when multiple threads use the same ring. */
typedef struct {
	uint32_t head;
	uint32_t tail;
	uint32_t mask;
	uint32_t *data;

} ring_st_t;

/* Initialize ring. Ring size must be a power of two. */
static inline void ring_st_init(ring_st_t *ring, uint32_t *data, uint32_t size)
{
	ring->head = 0;
	ring->tail = 0;
	ring->mask = size - 1;
	ring->data = data;
}

/* Dequeue data from the ring head. Max_num is smaller than ring size.*/
static inline uint32_t ring_st_deq_multi(ring_st_t *ring, uint32_t data[],
					 uint32_t max_num)
{
	uint32_t head, tail, mask, idx;
	uint32_t num, i;

	head = ring->head;
	tail = ring->tail;
	mask = ring->mask;
	num  = tail - head;

	/* Empty */
	if (num == 0)
		return 0;

	if (num > max_num)
		num = max_num;

	idx = head & mask;

	for (i = 0; i < num; i++) {
		data[i] = ring->data[idx];
		idx     = (idx + 1) & mask;
	}

	ring->head = head + num;

	return num;
}

/* Enqueue data into the ring tail. Num_data is smaller than ring size. */
static inline uint32_t ring_st_enq_multi(ring_st_t *ring, const uint32_t data[],
					 uint32_t num_data)
{
	uint32_t head, tail, mask, size, idx;
	uint32_t num, i;

	head = ring->head;
	tail = ring->tail;
	mask = ring->mask;
	size = mask + 1;
	num  = size - (tail - head);

	/* Full */
	if (num == 0)
		return 0;

	if (num > num_data)
		num = num_data;

	idx = tail & mask;

	for (i = 0; i < num; i++) {
		ring->data[idx] = data[i];
		idx     = (idx + 1) & mask;
	}

	ring->tail = tail + num;

	return num;
}

/* Check if ring is empty */
static inline int ring_st_is_empty(ring_st_t *ring)
{
	return ring->head == ring->tail;
}

#ifdef __cplusplus
}
#endif

#endif