1 /* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1)
5 * Copyright (C) 2018 Julien Desfossez <jdesfossez@efficios.com>
8 #include <linux/slab.h>
9 #include <linux/percpu.h>
11 #include <lttng-tp-mempool.h>
13 struct lttng_tp_buf_entry
{
14 int cpu
; /* To make sure we return the entry to the right pool. */
15 char buf
[LTTNG_TP_MEMPOOL_BUF_SIZE
];
16 struct list_head list
;
20 * No exclusive access strategy for now, this memory pool is currently only
21 * used from a non-preemptible context, and the interrupt tracepoint probes do
22 * not use this facility.
25 struct list_head free_list
; /* Free struct lttng_tp_buf_entry. */
28 static struct per_cpu_buf __percpu
*pool
; /* Per-cpu buffer. */
30 int lttng_tp_mempool_init(void)
34 /* The pool is only supposed to be allocated once. */
41 pool
= alloc_percpu(struct per_cpu_buf
);
47 for_each_possible_cpu(cpu
) {
48 struct per_cpu_buf
*cpu_buf
= per_cpu_ptr(pool
, cpu
);
50 INIT_LIST_HEAD(&cpu_buf
->free_list
);
53 for_each_possible_cpu(cpu
) {
55 struct per_cpu_buf
*cpu_buf
= per_cpu_ptr(pool
, cpu
);
57 for (i
= 0; i
< LTTNG_TP_MEMPOOL_NR_BUF_PER_CPU
; i
++) {
58 struct lttng_tp_buf_entry
*entry
;
60 entry
= kzalloc_node(sizeof(struct lttng_tp_buf_entry
),
61 GFP_KERNEL
, cpu_to_node(cpu
));
67 list_add_tail(&entry
->list
, &cpu_buf
->free_list
);
75 lttng_tp_mempool_destroy();
80 void lttng_tp_mempool_destroy(void)
88 for_each_possible_cpu(cpu
) {
89 struct per_cpu_buf
*cpu_buf
= per_cpu_ptr(pool
, cpu
);
90 struct lttng_tp_buf_entry
*entry
, *tmp
;
93 list_for_each_entry_safe(entry
, tmp
, &cpu_buf
->free_list
, list
) {
94 list_del(&entry
->list
);
98 if (i
< LTTNG_TP_MEMPOOL_NR_BUF_PER_CPU
) {
99 printk(KERN_WARNING
"Leak detected in tp-mempool\n");
106 void *lttng_tp_mempool_alloc(size_t size
)
109 struct lttng_tp_buf_entry
*entry
;
110 struct per_cpu_buf
*cpu_buf
;
111 int cpu
= smp_processor_id();
113 if (size
> LTTNG_TP_MEMPOOL_BUF_SIZE
) {
118 cpu_buf
= per_cpu_ptr(pool
, cpu
);
119 if (list_empty(&cpu_buf
->free_list
)) {
124 entry
= list_first_entry(&cpu_buf
->free_list
, struct lttng_tp_buf_entry
, list
);
125 /* Remove the entry from the free list. */
126 list_del(&entry
->list
);
128 memset(entry
->buf
, 0, LTTNG_TP_MEMPOOL_BUF_SIZE
);
130 ret
= (void *) entry
->buf
;
136 void lttng_tp_mempool_free(void *ptr
)
138 struct lttng_tp_buf_entry
*entry
;
139 struct per_cpu_buf
*cpu_buf
;
143 entry
= container_of(ptr
, struct lttng_tp_buf_entry
, buf
);
144 cpu_buf
= per_cpu_ptr(pool
, entry
->cpu
);
147 /* Add it to the free list. */
148 list_add_tail(&entry
->list
, &cpu_buf
->free_list
);