blob: 036f78607d9404489816cde4b0958d218b1e8df6 [file] [log] [blame]
Willy Tarreau50e608d2007-05-13 18:26:08 +02001/*
2 * Memory management functions.
3 *
4 * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Willy Tarreau12833bb2014-01-28 16:49:56 +010013#include <types/global.h>
Willy Tarreau50e608d2007-05-13 18:26:08 +020014#include <common/config.h>
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +020015#include <common/debug.h>
Willy Tarreau50e608d2007-05-13 18:26:08 +020016#include <common/memory.h>
17#include <common/mini-clist.h>
18#include <common/standard.h>
19
20#include <proto/log.h>
21
22static struct list pools = LIST_HEAD_INIT(pools);
Willy Tarreau067ac9f2015-10-08 14:12:13 +020023int mem_poison_byte = -1;
Willy Tarreau50e608d2007-05-13 18:26:08 +020024
25/* Try to find an existing shared pool with the same characteristics and
26 * returns it, otherwise creates this one. NULL is returned if no memory
27 * is available for a new creation.
28 */
29struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags)
30{
31 struct pool_head *pool;
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020032 struct pool_head *entry;
33 struct list *start;
Willy Tarreau50e608d2007-05-13 18:26:08 +020034 unsigned int align;
35
Willy Tarreauac421112015-10-28 15:09:29 +010036 /* We need to store a (void *) at the end of the chunks. Since we know
Willy Tarreau50e608d2007-05-13 18:26:08 +020037 * that the malloc() function will never return such a small size,
38 * let's round the size up to something slightly bigger, in order to
39 * ease merging of entries. Note that the rounding is a power of two.
Willy Tarreauac421112015-10-28 15:09:29 +010040 * This extra (void *) is not accounted for in the size computation
41 * so that the visible parts outside are not affected.
Willy Tarreau50e608d2007-05-13 18:26:08 +020042 */
43
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020044 align = 16;
Willy Tarreauac421112015-10-28 15:09:29 +010045 size = ((size + POOL_EXTRA + align - 1) & -align) - POOL_EXTRA;
Willy Tarreau50e608d2007-05-13 18:26:08 +020046
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020047 start = &pools;
Willy Tarreau50e608d2007-05-13 18:26:08 +020048 pool = NULL;
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020049
50 list_for_each_entry(entry, &pools, list) {
51 if (entry->size == size) {
52 /* either we can share this place and we take it, or
53 * we look for a sharable one or for the next position
54 * before which we will insert a new one.
55 */
56 if (flags & entry->flags & MEM_F_SHARED) {
57 /* we can share this one */
Willy Tarreau50e608d2007-05-13 18:26:08 +020058 pool = entry;
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +020059 DPRINTF(stderr, "Sharing %s with %s\n", name, pool->name);
Willy Tarreau50e608d2007-05-13 18:26:08 +020060 break;
61 }
62 }
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020063 else if (entry->size > size) {
64 /* insert before this one */
65 start = &entry->list;
66 break;
67 }
Willy Tarreau50e608d2007-05-13 18:26:08 +020068 }
69
70 if (!pool) {
71 pool = CALLOC(1, sizeof(*pool));
72 if (!pool)
73 return NULL;
74 if (name)
75 strlcpy2(pool->name, name, sizeof(pool->name));
76 pool->size = size;
77 pool->flags = flags;
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020078 LIST_ADDQ(start, &pool->list);
Willy Tarreau50e608d2007-05-13 18:26:08 +020079 }
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020080 pool->users++;
Willy Tarreau50e608d2007-05-13 18:26:08 +020081 return pool;
82}
83
Willy Tarreaua885f6d2014-12-03 15:25:28 +010084/* Allocates new entries for pool <pool> until there are at least <avail> + 1
85 * available, then returns the last one for immediate use, so that at least
86 * <avail> are left available in the pool upon return. NULL is returned if the
87 * last entry could not be allocated. It's important to note that at least one
88 * allocation is always performed even if there are enough entries in the pool.
89 * A call to the garbage collector is performed at most once in case malloc()
90 * returns an error, before returning NULL.
Willy Tarreau50e608d2007-05-13 18:26:08 +020091 */
Willy Tarreaua885f6d2014-12-03 15:25:28 +010092void *pool_refill_alloc(struct pool_head *pool, unsigned int avail)
Willy Tarreau50e608d2007-05-13 18:26:08 +020093{
Willy Tarreaua885f6d2014-12-03 15:25:28 +010094 void *ptr = NULL;
95 int failed = 0;
Willy Tarreau50e608d2007-05-13 18:26:08 +020096
Willy Tarreaua885f6d2014-12-03 15:25:28 +010097 /* stop point */
98 avail += pool->used;
99
100 while (1) {
101 if (pool->limit && pool->allocated >= pool->limit)
Willy Tarreau7dcd46d2007-05-14 00:16:13 +0200102 return NULL;
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100103
Willy Tarreauac421112015-10-28 15:09:29 +0100104 ptr = MALLOC(pool->size + POOL_EXTRA);
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100105 if (!ptr) {
Willy Tarreau58102cf2015-10-28 16:24:21 +0100106 pool->failed++;
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100107 if (failed)
108 return NULL;
109 failed++;
110 pool_gc2();
111 continue;
112 }
113 if (++pool->allocated > avail)
114 break;
115
Willy Tarreauac421112015-10-28 15:09:29 +0100116 *POOL_LINK(pool, ptr) = (void *)pool->free_list;
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100117 pool->free_list = ptr;
Willy Tarreau7dcd46d2007-05-14 00:16:13 +0200118 }
Willy Tarreau50e608d2007-05-13 18:26:08 +0200119 pool->used++;
Willy Tarreaude30a682015-10-28 15:23:51 +0100120#ifdef DEBUG_MEMORY_POOLS
121 /* keep track of where the element was allocated from */
122 *POOL_LINK(pool, ptr) = (void *)pool;
123#endif
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100124 return ptr;
Willy Tarreau50e608d2007-05-13 18:26:08 +0200125}
126
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200127/*
128 * This function frees whatever can be freed in pool <pool>.
129 */
130void pool_flush2(struct pool_head *pool)
131{
132 void *temp, *next;
Willy Tarreau4d2d0982007-05-14 00:39:29 +0200133 if (!pool)
134 return;
135
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200136 next = pool->free_list;
137 while (next) {
138 temp = next;
Willy Tarreauac421112015-10-28 15:09:29 +0100139 next = *POOL_LINK(pool, temp);
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200140 pool->allocated--;
141 FREE(temp);
142 }
143 pool->free_list = next;
144
145 /* here, we should have pool->allocate == pool->used */
146}
147
148/*
149 * This function frees whatever can be freed in all pools, but respecting
Willy Tarreaub7f9d122009-04-21 02:17:45 +0200150 * the minimum thresholds imposed by owners. It takes care of avoiding
151 * recursion because it may be called from a signal handler.
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200152 */
153void pool_gc2()
154{
Willy Tarreaub7f9d122009-04-21 02:17:45 +0200155 static int recurse;
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200156 struct pool_head *entry;
Willy Tarreaub7f9d122009-04-21 02:17:45 +0200157
158 if (recurse++)
159 goto out;
160
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200161 list_for_each_entry(entry, &pools, list) {
162 void *temp, *next;
163 //qfprintf(stderr, "Flushing pool %s\n", entry->name);
164 next = entry->free_list;
165 while (next &&
Willy Tarreau57767b82014-12-22 21:40:55 +0100166 (int)(entry->allocated - entry->used) > (int)entry->minavail) {
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200167 temp = next;
Willy Tarreauac421112015-10-28 15:09:29 +0100168 next = *POOL_LINK(entry, temp);
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200169 entry->allocated--;
170 FREE(temp);
171 }
172 entry->free_list = next;
173 }
Willy Tarreaub7f9d122009-04-21 02:17:45 +0200174 out:
175 recurse--;
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200176}
177
178/*
Willy Tarreaudae4aa82007-06-16 23:19:53 +0200179 * This function destroys a pool by freeing it completely, unless it's still
180 * in use. This should be called only under extreme circumstances. It always
181 * returns NULL if the resulting pool is empty, easing the clearing of the old
182 * pointer, otherwise it returns the pool.
183 * .
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200184 */
Willy Tarreau4d2d0982007-05-14 00:39:29 +0200185void *pool_destroy2(struct pool_head *pool)
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200186{
Willy Tarreau4d2d0982007-05-14 00:39:29 +0200187 if (pool) {
188 pool_flush2(pool);
Willy Tarreaudae4aa82007-06-16 23:19:53 +0200189 if (pool->used)
190 return pool;
191 pool->users--;
192 if (!pool->users) {
193 LIST_DEL(&pool->list);
194 FREE(pool);
195 }
Willy Tarreau4d2d0982007-05-14 00:39:29 +0200196 }
197 return NULL;
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200198}
199
Willy Tarreau12833bb2014-01-28 16:49:56 +0100200/* This function dumps memory usage information into the trash buffer. */
201void dump_pools_to_trash()
Willy Tarreau50e608d2007-05-13 18:26:08 +0200202{
203 struct pool_head *entry;
204 unsigned long allocated, used;
205 int nbpools;
206
207 allocated = used = nbpools = 0;
Willy Tarreau12833bb2014-01-28 16:49:56 +0100208 chunk_printf(&trash, "Dumping pools usage. Use SIGQUIT to flush them.\n");
Willy Tarreau50e608d2007-05-13 18:26:08 +0200209 list_for_each_entry(entry, &pools, list) {
Willy Tarreau58102cf2015-10-28 16:24:21 +0100210 chunk_appendf(&trash, " - Pool %s (%d bytes) : %d allocated (%u bytes), %d used, %d failures, %d users%s\n",
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200211 entry->name, entry->size, entry->allocated,
Willy Tarreau58102cf2015-10-28 16:24:21 +0100212 entry->size * entry->allocated, entry->used, entry->failed,
Willy Tarreau7dcd46d2007-05-14 00:16:13 +0200213 entry->users, (entry->flags & MEM_F_SHARED) ? " [SHARED]" : "");
Willy Tarreau50e608d2007-05-13 18:26:08 +0200214
215 allocated += entry->allocated * entry->size;
216 used += entry->used * entry->size;
217 nbpools++;
218 }
Willy Tarreau12833bb2014-01-28 16:49:56 +0100219 chunk_appendf(&trash, "Total: %d pools, %lu bytes allocated, %lu used.\n",
Willy Tarreau50e608d2007-05-13 18:26:08 +0200220 nbpools, allocated, used);
221}
222
Willy Tarreau12833bb2014-01-28 16:49:56 +0100223/* Dump statistics on pools usage. */
224void dump_pools(void)
225{
226 dump_pools_to_trash();
227 qfprintf(stderr, "%s", trash.str);
228}
229
Willy Tarreau58102cf2015-10-28 16:24:21 +0100230/* This function returns the total number of failed pool allocations */
231int pool_total_failures()
232{
233 struct pool_head *entry;
234 int failed = 0;
235
236 list_for_each_entry(entry, &pools, list)
237 failed += entry->failed;
238 return failed;
239}
240
241/* This function returns the total amount of memory allocated in pools (in bytes) */
242unsigned long pool_total_allocated()
243{
244 struct pool_head *entry;
245 unsigned long allocated = 0;
246
247 list_for_each_entry(entry, &pools, list)
248 allocated += entry->allocated * entry->size;
249 return allocated;
250}
251
252/* This function returns the total amount of memory used in pools (in bytes) */
253unsigned long pool_total_used()
254{
255 struct pool_head *entry;
256 unsigned long used = 0;
257
258 list_for_each_entry(entry, &pools, list)
259 used += entry->used * entry->size;
260 return used;
261}
262
Willy Tarreau50e608d2007-05-13 18:26:08 +0200263/*
264 * Local variables:
265 * c-indent-level: 8
266 * c-basic-offset: 8
267 * End:
268 */