blob: 0363f36d8fb965497df6cb71d3f67b04f68f98f5 [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) {
106 if (failed)
107 return NULL;
108 failed++;
109 pool_gc2();
110 continue;
111 }
112 if (++pool->allocated > avail)
113 break;
114
Willy Tarreauac421112015-10-28 15:09:29 +0100115 *POOL_LINK(pool, ptr) = (void *)pool->free_list;
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100116 pool->free_list = ptr;
Willy Tarreau7dcd46d2007-05-14 00:16:13 +0200117 }
Willy Tarreau50e608d2007-05-13 18:26:08 +0200118 pool->used++;
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100119 return ptr;
Willy Tarreau50e608d2007-05-13 18:26:08 +0200120}
121
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200122/*
123 * This function frees whatever can be freed in pool <pool>.
124 */
125void pool_flush2(struct pool_head *pool)
126{
127 void *temp, *next;
Willy Tarreau4d2d0982007-05-14 00:39:29 +0200128 if (!pool)
129 return;
130
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200131 next = pool->free_list;
132 while (next) {
133 temp = next;
Willy Tarreauac421112015-10-28 15:09:29 +0100134 next = *POOL_LINK(pool, temp);
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200135 pool->allocated--;
136 FREE(temp);
137 }
138 pool->free_list = next;
139
140 /* here, we should have pool->allocate == pool->used */
141}
142
143/*
144 * This function frees whatever can be freed in all pools, but respecting
Willy Tarreaub7f9d122009-04-21 02:17:45 +0200145 * the minimum thresholds imposed by owners. It takes care of avoiding
146 * recursion because it may be called from a signal handler.
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200147 */
148void pool_gc2()
149{
Willy Tarreaub7f9d122009-04-21 02:17:45 +0200150 static int recurse;
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200151 struct pool_head *entry;
Willy Tarreaub7f9d122009-04-21 02:17:45 +0200152
153 if (recurse++)
154 goto out;
155
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200156 list_for_each_entry(entry, &pools, list) {
157 void *temp, *next;
158 //qfprintf(stderr, "Flushing pool %s\n", entry->name);
159 next = entry->free_list;
160 while (next &&
Willy Tarreau57767b82014-12-22 21:40:55 +0100161 (int)(entry->allocated - entry->used) > (int)entry->minavail) {
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200162 temp = next;
Willy Tarreauac421112015-10-28 15:09:29 +0100163 next = *POOL_LINK(entry, temp);
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200164 entry->allocated--;
165 FREE(temp);
166 }
167 entry->free_list = next;
168 }
Willy Tarreaub7f9d122009-04-21 02:17:45 +0200169 out:
170 recurse--;
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200171}
172
173/*
Willy Tarreaudae4aa82007-06-16 23:19:53 +0200174 * This function destroys a pool by freeing it completely, unless it's still
175 * in use. This should be called only under extreme circumstances. It always
176 * returns NULL if the resulting pool is empty, easing the clearing of the old
177 * pointer, otherwise it returns the pool.
178 * .
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200179 */
Willy Tarreau4d2d0982007-05-14 00:39:29 +0200180void *pool_destroy2(struct pool_head *pool)
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200181{
Willy Tarreau4d2d0982007-05-14 00:39:29 +0200182 if (pool) {
183 pool_flush2(pool);
Willy Tarreaudae4aa82007-06-16 23:19:53 +0200184 if (pool->used)
185 return pool;
186 pool->users--;
187 if (!pool->users) {
188 LIST_DEL(&pool->list);
189 FREE(pool);
190 }
Willy Tarreau4d2d0982007-05-14 00:39:29 +0200191 }
192 return NULL;
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200193}
194
Willy Tarreau12833bb2014-01-28 16:49:56 +0100195/* This function dumps memory usage information into the trash buffer. */
196void dump_pools_to_trash()
Willy Tarreau50e608d2007-05-13 18:26:08 +0200197{
198 struct pool_head *entry;
199 unsigned long allocated, used;
200 int nbpools;
201
202 allocated = used = nbpools = 0;
Willy Tarreau12833bb2014-01-28 16:49:56 +0100203 chunk_printf(&trash, "Dumping pools usage. Use SIGQUIT to flush them.\n");
Willy Tarreau50e608d2007-05-13 18:26:08 +0200204 list_for_each_entry(entry, &pools, list) {
Willy Tarreau12833bb2014-01-28 16:49:56 +0100205 chunk_appendf(&trash, " - Pool %s (%d bytes) : %d allocated (%u bytes), %d used, %d users%s\n",
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200206 entry->name, entry->size, entry->allocated,
207 entry->size * entry->allocated, entry->used,
Willy Tarreau7dcd46d2007-05-14 00:16:13 +0200208 entry->users, (entry->flags & MEM_F_SHARED) ? " [SHARED]" : "");
Willy Tarreau50e608d2007-05-13 18:26:08 +0200209
210 allocated += entry->allocated * entry->size;
211 used += entry->used * entry->size;
212 nbpools++;
213 }
Willy Tarreau12833bb2014-01-28 16:49:56 +0100214 chunk_appendf(&trash, "Total: %d pools, %lu bytes allocated, %lu used.\n",
Willy Tarreau50e608d2007-05-13 18:26:08 +0200215 nbpools, allocated, used);
216}
217
Willy Tarreau12833bb2014-01-28 16:49:56 +0100218/* Dump statistics on pools usage. */
219void dump_pools(void)
220{
221 dump_pools_to_trash();
222 qfprintf(stderr, "%s", trash.str);
223}
224
Willy Tarreau50e608d2007-05-13 18:26:08 +0200225/*
226 * Local variables:
227 * c-indent-level: 8
228 * c-basic-offset: 8
229 * End:
230 */