aboutsummaryrefslogtreecommitdiffstats
path: root/examples/performance-thread/common/lthread_objcache.h
blob: 777a1945b486e2b59df7e536a842a3b7900f446b (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
/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright(c) 2015 Intel Corporation
 */
#ifndef LTHREAD_OBJCACHE_H_
#define LTHREAD_OBJCACHE_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <string.h>

#include <rte_per_lcore.h>
#include <rte_malloc.h>
#include <rte_memory.h>

#include "lthread_int.h"
#include "lthread_diag.h"
#include "lthread_queue.h"


RTE_DECLARE_PER_LCORE(struct lthread_sched *, this_sched);

struct lthread_objcache {
	struct lthread_queue *q;
	size_t obj_size;
	int prealloc_size;
	char name[LT_MAX_NAME_SIZE];

	DIAG_COUNT_DEFINE(rd);
	DIAG_COUNT_DEFINE(wr);
	DIAG_COUNT_DEFINE(prealloc);
	DIAG_COUNT_DEFINE(capacity);
	DIAG_COUNT_DEFINE(available);
};

/*
 * Create a cache
 */
static inline struct
lthread_objcache *_lthread_objcache_create(const char *name,
					size_t obj_size,
					int prealloc_size)
{
	struct lthread_objcache *c =
	    rte_malloc_socket(NULL, sizeof(struct lthread_objcache),
				RTE_CACHE_LINE_SIZE,
				rte_socket_id());
	if (c == NULL)
		return NULL;

	c->q = _lthread_queue_create("cache queue");
	if (c->q == NULL) {
		rte_free(c);
		return NULL;
	}
	c->obj_size = obj_size;
	c->prealloc_size = prealloc_size;

	if (name != NULL)
		strncpy(c->name, name, LT_MAX_NAME_SIZE);
	c->name[sizeof(c->name)-1] = 0;

	DIAG_COUNT_INIT(c, rd);
	DIAG_COUNT_INIT(c, wr);
	DIAG_COUNT_INIT(c, prealloc);
	DIAG_COUNT_INIT(c, capacity);
	DIAG_COUNT_INIT(c, available);
	return c;
}

/*
 * Destroy an objcache
 */
static inline int
_lthread_objcache_destroy(struct lthread_objcache *c)
{
	if (_lthread_queue_destroy(c->q) == 0) {
		rte_free(c);
		return 0;
	}
	return -1;
}

/*
 * Allocate an object from an object cache
 */
static inline void *
_lthread_objcache_alloc(struct lthread_objcache *c)
{
	int i;
	void *data;
	struct lthread_queue *q = c->q;
	size_t obj_size = c->obj_size;
	int prealloc_size = c->prealloc_size;

	data = _lthread_queue_remove(q);

	if (data == NULL) {
		DIAG_COUNT_INC(c, prealloc);
		for (i = 0; i < prealloc_size; i++) {
			data =
			    rte_zmalloc_socket(NULL, obj_size,
					RTE_CACHE_LINE_SIZE,
					rte_socket_id());
			if (data == NULL)
				return NULL;

			DIAG_COUNT_INC(c, available);
			DIAG_COUNT_INC(c, capacity);
			_lthread_queue_insert_mp(q, data);
		}
		data = _lthread_queue_remove(q);
	}
	DIAG_COUNT_INC(c, rd);
	DIAG_COUNT_DEC(c, available);
	return data;
}

/*
 * free an object to a cache
 */
static inline void
_lthread_objcache_free(struct lthread_objcache *c, void *obj)
{
	DIAG_COUNT_INC(c, wr);
	DIAG_COUNT_INC(c, available);
	_lthread_queue_insert_mp(c->q, obj);
}


#ifdef __cplusplus
}
#endif

#endif				/* LTHREAD_OBJCACHE_H_ */