blob: 53ab4890a3da06ca03c346b2a7eb3d75712e6da1 [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
Willy Tarreau581bf812016-01-25 02:19:13 +010027 * is available for a new creation. Two flags are supported :
28 * - MEM_F_SHARED to indicate that the pool may be shared with other users
29 * - MEM_F_EXACT to indicate that the size must not be rounded up
Willy Tarreau50e608d2007-05-13 18:26:08 +020030 */
31struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags)
32{
33 struct pool_head *pool;
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020034 struct pool_head *entry;
35 struct list *start;
Willy Tarreau50e608d2007-05-13 18:26:08 +020036 unsigned int align;
37
Willy Tarreauac421112015-10-28 15:09:29 +010038 /* We need to store a (void *) at the end of the chunks. Since we know
Willy Tarreau50e608d2007-05-13 18:26:08 +020039 * that the malloc() function will never return such a small size,
40 * let's round the size up to something slightly bigger, in order to
41 * ease merging of entries. Note that the rounding is a power of two.
Willy Tarreauac421112015-10-28 15:09:29 +010042 * This extra (void *) is not accounted for in the size computation
43 * so that the visible parts outside are not affected.
Willy Tarreau50e608d2007-05-13 18:26:08 +020044 */
45
Willy Tarreau581bf812016-01-25 02:19:13 +010046 if (!(flags & MEM_F_EXACT)) {
47 align = 16;
48 size = ((size + POOL_EXTRA + align - 1) & -align) - POOL_EXTRA;
49 }
Willy Tarreau50e608d2007-05-13 18:26:08 +020050
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020051 start = &pools;
Willy Tarreau50e608d2007-05-13 18:26:08 +020052 pool = NULL;
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020053
54 list_for_each_entry(entry, &pools, list) {
55 if (entry->size == size) {
56 /* either we can share this place and we take it, or
57 * we look for a sharable one or for the next position
58 * before which we will insert a new one.
59 */
60 if (flags & entry->flags & MEM_F_SHARED) {
61 /* we can share this one */
Willy Tarreau50e608d2007-05-13 18:26:08 +020062 pool = entry;
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +020063 DPRINTF(stderr, "Sharing %s with %s\n", name, pool->name);
Willy Tarreau50e608d2007-05-13 18:26:08 +020064 break;
65 }
66 }
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020067 else if (entry->size > size) {
68 /* insert before this one */
69 start = &entry->list;
70 break;
71 }
Willy Tarreau50e608d2007-05-13 18:26:08 +020072 }
73
74 if (!pool) {
75 pool = CALLOC(1, sizeof(*pool));
76 if (!pool)
77 return NULL;
78 if (name)
79 strlcpy2(pool->name, name, sizeof(pool->name));
80 pool->size = size;
81 pool->flags = flags;
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020082 LIST_ADDQ(start, &pool->list);
Willy Tarreau50e608d2007-05-13 18:26:08 +020083 }
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020084 pool->users++;
Willy Tarreau50e608d2007-05-13 18:26:08 +020085 return pool;
86}
87
Willy Tarreaua885f6d2014-12-03 15:25:28 +010088/* Allocates new entries for pool <pool> until there are at least <avail> + 1
89 * available, then returns the last one for immediate use, so that at least
90 * <avail> are left available in the pool upon return. NULL is returned if the
91 * last entry could not be allocated. It's important to note that at least one
92 * allocation is always performed even if there are enough entries in the pool.
93 * A call to the garbage collector is performed at most once in case malloc()
94 * returns an error, before returning NULL.
Willy Tarreau50e608d2007-05-13 18:26:08 +020095 */
Willy Tarreaua885f6d2014-12-03 15:25:28 +010096void *pool_refill_alloc(struct pool_head *pool, unsigned int avail)
Willy Tarreau50e608d2007-05-13 18:26:08 +020097{
Willy Tarreaua885f6d2014-12-03 15:25:28 +010098 void *ptr = NULL;
99 int failed = 0;
Willy Tarreau50e608d2007-05-13 18:26:08 +0200100
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100101 /* stop point */
102 avail += pool->used;
103
104 while (1) {
105 if (pool->limit && pool->allocated >= pool->limit)
Willy Tarreau7dcd46d2007-05-14 00:16:13 +0200106 return NULL;
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100107
Willy Tarreauac421112015-10-28 15:09:29 +0100108 ptr = MALLOC(pool->size + POOL_EXTRA);
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100109 if (!ptr) {
Willy Tarreau58102cf2015-10-28 16:24:21 +0100110 pool->failed++;
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100111 if (failed)
112 return NULL;
113 failed++;
114 pool_gc2();
115 continue;
116 }
117 if (++pool->allocated > avail)
118 break;
119
Willy Tarreauac421112015-10-28 15:09:29 +0100120 *POOL_LINK(pool, ptr) = (void *)pool->free_list;
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100121 pool->free_list = ptr;
Willy Tarreau7dcd46d2007-05-14 00:16:13 +0200122 }
Willy Tarreau50e608d2007-05-13 18:26:08 +0200123 pool->used++;
Willy Tarreaude30a682015-10-28 15:23:51 +0100124#ifdef DEBUG_MEMORY_POOLS
125 /* keep track of where the element was allocated from */
126 *POOL_LINK(pool, ptr) = (void *)pool;
127#endif
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100128 return ptr;
Willy Tarreau50e608d2007-05-13 18:26:08 +0200129}
130
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200131/*
132 * This function frees whatever can be freed in pool <pool>.
133 */
134void pool_flush2(struct pool_head *pool)
135{
136 void *temp, *next;
Willy Tarreau4d2d0982007-05-14 00:39:29 +0200137 if (!pool)
138 return;
139
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200140 next = pool->free_list;
141 while (next) {
142 temp = next;
Willy Tarreauac421112015-10-28 15:09:29 +0100143 next = *POOL_LINK(pool, temp);
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200144 pool->allocated--;
145 FREE(temp);
146 }
147 pool->free_list = next;
148
149 /* here, we should have pool->allocate == pool->used */
150}
151
152/*
153 * This function frees whatever can be freed in all pools, but respecting
Willy Tarreaub7f9d122009-04-21 02:17:45 +0200154 * the minimum thresholds imposed by owners. It takes care of avoiding
155 * recursion because it may be called from a signal handler.
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200156 */
157void pool_gc2()
158{
Willy Tarreaub7f9d122009-04-21 02:17:45 +0200159 static int recurse;
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200160 struct pool_head *entry;
Willy Tarreaub7f9d122009-04-21 02:17:45 +0200161
162 if (recurse++)
163 goto out;
164
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200165 list_for_each_entry(entry, &pools, list) {
166 void *temp, *next;
167 //qfprintf(stderr, "Flushing pool %s\n", entry->name);
168 next = entry->free_list;
169 while (next &&
Willy Tarreau57767b82014-12-22 21:40:55 +0100170 (int)(entry->allocated - entry->used) > (int)entry->minavail) {
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200171 temp = next;
Willy Tarreauac421112015-10-28 15:09:29 +0100172 next = *POOL_LINK(entry, temp);
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200173 entry->allocated--;
174 FREE(temp);
175 }
176 entry->free_list = next;
177 }
Willy Tarreaub7f9d122009-04-21 02:17:45 +0200178 out:
179 recurse--;
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200180}
181
182/*
Willy Tarreaudae4aa82007-06-16 23:19:53 +0200183 * This function destroys a pool by freeing it completely, unless it's still
184 * in use. This should be called only under extreme circumstances. It always
185 * returns NULL if the resulting pool is empty, easing the clearing of the old
186 * pointer, otherwise it returns the pool.
187 * .
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200188 */
Willy Tarreau4d2d0982007-05-14 00:39:29 +0200189void *pool_destroy2(struct pool_head *pool)
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200190{
Willy Tarreau4d2d0982007-05-14 00:39:29 +0200191 if (pool) {
192 pool_flush2(pool);
Willy Tarreaudae4aa82007-06-16 23:19:53 +0200193 if (pool->used)
194 return pool;
195 pool->users--;
196 if (!pool->users) {
197 LIST_DEL(&pool->list);
198 FREE(pool);
199 }
Willy Tarreau4d2d0982007-05-14 00:39:29 +0200200 }
201 return NULL;
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200202}
203
Willy Tarreau12833bb2014-01-28 16:49:56 +0100204/* This function dumps memory usage information into the trash buffer. */
205void dump_pools_to_trash()
Willy Tarreau50e608d2007-05-13 18:26:08 +0200206{
207 struct pool_head *entry;
208 unsigned long allocated, used;
209 int nbpools;
210
211 allocated = used = nbpools = 0;
Willy Tarreau12833bb2014-01-28 16:49:56 +0100212 chunk_printf(&trash, "Dumping pools usage. Use SIGQUIT to flush them.\n");
Willy Tarreau50e608d2007-05-13 18:26:08 +0200213 list_for_each_entry(entry, &pools, list) {
Willy Tarreau58102cf2015-10-28 16:24:21 +0100214 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 +0200215 entry->name, entry->size, entry->allocated,
Willy Tarreau58102cf2015-10-28 16:24:21 +0100216 entry->size * entry->allocated, entry->used, entry->failed,
Willy Tarreau7dcd46d2007-05-14 00:16:13 +0200217 entry->users, (entry->flags & MEM_F_SHARED) ? " [SHARED]" : "");
Willy Tarreau50e608d2007-05-13 18:26:08 +0200218
219 allocated += entry->allocated * entry->size;
220 used += entry->used * entry->size;
221 nbpools++;
222 }
Willy Tarreau12833bb2014-01-28 16:49:56 +0100223 chunk_appendf(&trash, "Total: %d pools, %lu bytes allocated, %lu used.\n",
Willy Tarreau50e608d2007-05-13 18:26:08 +0200224 nbpools, allocated, used);
225}
226
Willy Tarreau12833bb2014-01-28 16:49:56 +0100227/* Dump statistics on pools usage. */
228void dump_pools(void)
229{
230 dump_pools_to_trash();
231 qfprintf(stderr, "%s", trash.str);
232}
233
Willy Tarreau58102cf2015-10-28 16:24:21 +0100234/* This function returns the total number of failed pool allocations */
235int pool_total_failures()
236{
237 struct pool_head *entry;
238 int failed = 0;
239
240 list_for_each_entry(entry, &pools, list)
241 failed += entry->failed;
242 return failed;
243}
244
245/* This function returns the total amount of memory allocated in pools (in bytes) */
246unsigned long pool_total_allocated()
247{
248 struct pool_head *entry;
249 unsigned long allocated = 0;
250
251 list_for_each_entry(entry, &pools, list)
252 allocated += entry->allocated * entry->size;
253 return allocated;
254}
255
256/* This function returns the total amount of memory used in pools (in bytes) */
257unsigned long pool_total_used()
258{
259 struct pool_head *entry;
260 unsigned long used = 0;
261
262 list_for_each_entry(entry, &pools, list)
263 used += entry->used * entry->size;
264 return used;
265}
266
Willy Tarreau50e608d2007-05-13 18:26:08 +0200267/*
268 * Local variables:
269 * c-indent-level: 8
270 * c-basic-offset: 8
271 * End:
272 */