4 * Copyright (C) 2018 Julien Desfossez <jdesfossez@efficios.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; only
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <linux/slab.h>
22 #include <linux/percpu.h>
24 #include <lttng-tp-mempool.h>
26 struct lttng_tp_buf_entry
{
27 int cpu
; /* To make sure we return the entry to the right pool. */
28 char buf
[LTTNG_TP_MEMPOOL_BUF_SIZE
];
29 struct list_head list
;
33 * No exclusive access strategy for now, this memory pool is currently only
34 * used from a non-preemptible context, and the interrupt tracepoint probes do
35 * not use this facility.
38 struct list_head free_list
; /* Free struct lttng_tp_buf_entry. */
41 static struct per_cpu_buf __percpu
*pool
; /* Per-cpu buffer. */
43 int lttng_tp_mempool_init(void)
47 /* The pool is only supposed to be allocated once. */
54 pool
= alloc_percpu(struct per_cpu_buf
);
60 for_each_possible_cpu(cpu
) {
61 struct per_cpu_buf
*cpu_buf
= per_cpu_ptr(pool
, cpu
);
63 INIT_LIST_HEAD(&cpu_buf
->free_list
);
66 for_each_possible_cpu(cpu
) {
68 struct per_cpu_buf
*cpu_buf
= per_cpu_ptr(pool
, cpu
);
70 for (i
= 0; i
< LTTNG_TP_MEMPOOL_NR_BUF_PER_CPU
; i
++) {
71 struct lttng_tp_buf_entry
*entry
;
73 entry
= kzalloc(sizeof(struct lttng_tp_buf_entry
),
80 list_add_tail(&entry
->list
, &cpu_buf
->free_list
);
88 lttng_tp_mempool_destroy();
93 void lttng_tp_mempool_destroy(void)
101 for_each_possible_cpu(cpu
) {
102 struct per_cpu_buf
*cpu_buf
= per_cpu_ptr(pool
, cpu
);
103 struct lttng_tp_buf_entry
*entry
, *tmp
;
106 list_for_each_entry_safe(entry
, tmp
, &cpu_buf
->free_list
, list
) {
107 list_del(&entry
->list
);
111 if (i
< LTTNG_TP_MEMPOOL_NR_BUF_PER_CPU
) {
112 printk(KERN_WARNING
"Leak detected in tp-mempool\n");
119 void *lttng_tp_mempool_alloc(size_t size
)
122 struct lttng_tp_buf_entry
*entry
;
123 struct per_cpu_buf
*cpu_buf
;
124 int cpu
= smp_processor_id();
126 if (size
> LTTNG_TP_MEMPOOL_BUF_SIZE
) {
131 cpu_buf
= per_cpu_ptr(pool
, cpu
);
132 if (list_empty(&cpu_buf
->free_list
)) {
137 entry
= list_first_entry(&cpu_buf
->free_list
, struct lttng_tp_buf_entry
, list
);
138 /* Remove the entry from the free list. */
139 list_del(&entry
->list
);
141 memset(entry
->buf
, 0, LTTNG_TP_MEMPOOL_BUF_SIZE
);
143 ret
= (void *) entry
->buf
;
149 void lttng_tp_mempool_free(void *ptr
)
151 struct lttng_tp_buf_entry
*entry
;
152 struct per_cpu_buf
*cpu_buf
;
158 entry
= container_of(ptr
, struct lttng_tp_buf_entry
, buf
);
163 cpu_buf
= per_cpu_ptr(pool
, entry
->cpu
);
167 /* Add it to the free list. */
168 list_add_tail(&entry
->list
, &cpu_buf
->free_list
);