summaryrefslogtreecommitdiff
path: root/lib/librte_stack/rte_stack.h
blob: 42d042715b571c311e37fa0fe2fcfef1d82c40e8 (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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright(c) 2019 Intel Corporation
 */

/**
 * @file rte_stack.h
 * @b EXPERIMENTAL: this API may change without prior notice
 *
 * RTE Stack
 *
 * librte_stack provides an API for configuration and use of a bounded stack of
 * pointers. Push and pop operations are MT-safe, allowing concurrent access,
 * and the interface supports pushing and popping multiple pointers at a time.
 */

#ifndef _RTE_STACK_H_
#define _RTE_STACK_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <rte_compat.h>
#include <rte_debug.h>
#include <rte_errno.h>
#include <rte_memzone.h>
#include <rte_spinlock.h>

#define RTE_TAILQ_STACK_NAME "RTE_STACK"
#define RTE_STACK_MZ_PREFIX "STK_"
/** The maximum length of a stack name. */
#define RTE_STACK_NAMESIZE (RTE_MEMZONE_NAMESIZE - \
			   sizeof(RTE_STACK_MZ_PREFIX) + 1)

/* Structure containing the LIFO, its current length, and a lock for mutual
 * exclusion.
 */
struct rte_stack_std {
	rte_spinlock_t lock; /**< LIFO lock */
	uint32_t len; /**< LIFO len */
	void *objs[]; /**< LIFO pointer table */
};

/* The RTE stack structure contains the LIFO structure itself, plus metadata
 * such as its name and memzone pointer.
 */
struct rte_stack {
	/** Name of the stack. */
	char name[RTE_STACK_NAMESIZE] __rte_cache_aligned;
	/** Memzone containing the rte_stack structure. */
	const struct rte_memzone *memzone;
	uint32_t capacity; /**< Usable size of the stack. */
	uint32_t flags; /**< Flags supplied at creation. */
	struct rte_stack_std stack_std; /**< LIFO structure. */
} __rte_cache_aligned;

#include "rte_stack_std.h"

/**
 * @warning
 * @b EXPERIMENTAL: this API may change without prior notice
 *
 * Push several objects on the stack (MT-safe).
 *
 * @param s
 *   A pointer to the stack structure.
 * @param obj_table
 *   A pointer to a table of void * pointers (objects).
 * @param n
 *   The number of objects to push on the stack from the obj_table.
 * @return
 *   Actual number of objects pushed (either 0 or *n*).
 */
static __rte_always_inline unsigned int __rte_experimental
rte_stack_push(struct rte_stack *s, void * const *obj_table, unsigned int n)
{
	RTE_ASSERT(s != NULL);
	RTE_ASSERT(obj_table != NULL);

	return __rte_stack_std_push(s, obj_table, n);
}

/**
 * @warning
 * @b EXPERIMENTAL: this API may change without prior notice
 *
 * Pop several objects from the stack (MT-safe).
 *
 * @param s
 *   A pointer to the stack structure.
 * @param obj_table
 *   A pointer to a table of void * pointers (objects).
 * @param n
 *   The number of objects to pull from the stack.
 * @return
 *   Actual number of objects popped (either 0 or *n*).
 */
static __rte_always_inline unsigned int __rte_experimental
rte_stack_pop(struct rte_stack *s, void **obj_table, unsigned int n)
{
	RTE_ASSERT(s != NULL);
	RTE_ASSERT(obj_table != NULL);

	return __rte_stack_std_pop(s, obj_table, n);
}

/**
 * @warning
 * @b EXPERIMENTAL: this API may change without prior notice
 *
 * Return the number of used entries in a stack.
 *
 * @param s
 *   A pointer to the stack structure.
 * @return
 *   The number of used entries in the stack.
 */
static __rte_always_inline unsigned int __rte_experimental
rte_stack_count(struct rte_stack *s)
{
	RTE_ASSERT(s != NULL);

	return __rte_stack_std_count(s);
}

/**
 * @warning
 * @b EXPERIMENTAL: this API may change without prior notice
 *
 * Return the number of free entries in a stack.
 *
 * @param s
 *   A pointer to the stack structure.
 * @return
 *   The number of free entries in the stack.
 */
static __rte_always_inline unsigned int __rte_experimental
rte_stack_free_count(struct rte_stack *s)
{
	RTE_ASSERT(s != NULL);

	return s->capacity - rte_stack_count(s);
}

/**
 * @warning
 * @b EXPERIMENTAL: this API may change without prior notice
 *
 * Create a new stack named *name* in memory.
 *
 * This function uses ``memzone_reserve()`` to allocate memory for a stack of
 * size *count*. The behavior of the stack is controlled by the *flags*.
 *
 * @param name
 *   The name of the stack.
 * @param count
 *   The size of the stack.
 * @param socket_id
 *   The *socket_id* argument is the socket identifier in case of
 *   NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA
 *   constraint for the reserved zone.
 * @param flags
 *   Reserved for future use.
 * @return
 *   On success, the pointer to the new allocated stack. NULL on error with
 *    rte_errno set appropriately. Possible errno values include:
 *    - ENOSPC - the maximum number of memzones has already been allocated
 *    - EEXIST - a stack with the same name already exists
 *    - ENOMEM - insufficient memory to create the stack
 *    - ENAMETOOLONG - name size exceeds RTE_STACK_NAMESIZE
 */
struct rte_stack *__rte_experimental
rte_stack_create(const char *name, unsigned int count, int socket_id,
		 uint32_t flags);

/**
 * @warning
 * @b EXPERIMENTAL: this API may change without prior notice
 *
 * Free all memory used by the stack.
 *
 * @param s
 *   Stack to free
 */
void __rte_experimental
rte_stack_free(struct rte_stack *s);

/**
 * @warning
 * @b EXPERIMENTAL: this API may change without prior notice
 *
 * Lookup a stack by its name.
 *
 * @param name
 *   The name of the stack.
 * @return
 *   The pointer to the stack matching the name, or NULL if not found,
 *   with rte_errno set appropriately. Possible rte_errno values include:
 *    - ENOENT - Stack with name *name* not found.
 *    - EINVAL - *name* pointer is NULL.
 */
struct rte_stack * __rte_experimental
rte_stack_lookup(const char *name);

#ifdef __cplusplus
}
#endif

#endif /* _RTE_STACK_H_ */