blob: dd542252bbbae3a25f62a9665e0b944b3e783c93 [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
13#include <common/config.h>
14#include <common/memory.h>
15#include <common/mini-clist.h>
16#include <common/standard.h>
17
18#include <proto/log.h>
19
20static struct list pools = LIST_HEAD_INIT(pools);
21
22/* Try to find an existing shared pool with the same characteristics and
23 * returns it, otherwise creates this one. NULL is returned if no memory
24 * is available for a new creation.
25 */
26struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags)
27{
28 struct pool_head *pool;
29 unsigned int align;
30
31 /* We need to store at least a (void *) in the chunks. Since we know
32 * that the malloc() function will never return such a small size,
33 * let's round the size up to something slightly bigger, in order to
34 * ease merging of entries. Note that the rounding is a power of two.
35 */
36
37 align = 4 * sizeof(void *);
38 size = (size + align - 1) & -align;
39
40 pool = NULL;
41 if (flags & MEM_F_SHARED) {
42 struct pool_head *entry;
43 list_for_each_entry(entry, &pools, list) {
44 if (!(entry->flags & MEM_F_SHARED))
45 continue;
46 if (entry->size == size) {
47 pool = entry;
48 break;
49 }
50 }
51 }
52
53 if (!pool) {
54 pool = CALLOC(1, sizeof(*pool));
55 if (!pool)
56 return NULL;
57 if (name)
58 strlcpy2(pool->name, name, sizeof(pool->name));
59 pool->size = size;
60 pool->flags = flags;
61 LIST_ADDQ(&pools, &pool->list);
62 }
63 return pool;
64}
65
66/* Allocate a new entry for pool <pool>, and return it for immediate use.
67 * NULL is returned if no memory is available for a new creation.
68 */
Willy Tarreaue6ce59d2007-05-13 19:38:49 +020069void *pool_refill_alloc(struct pool_head *pool)
Willy Tarreau50e608d2007-05-13 18:26:08 +020070{
71 void *ret;
72
73 if (pool->limit && (pool->allocated >= pool->limit))
74 return NULL;
75 ret = MALLOC(pool->size);
76 if (!ret)
77 return NULL;
78 pool->allocated++;
79 pool->used++;
80 return ret;
81}
82
Willy Tarreaue6ce59d2007-05-13 19:38:49 +020083/*
84 * This function frees whatever can be freed in pool <pool>.
85 */
86void pool_flush2(struct pool_head *pool)
87{
88 void *temp, *next;
89 next = pool->free_list;
90 while (next) {
91 temp = next;
92 next = *(void **)temp;
93 pool->allocated--;
94 FREE(temp);
95 }
96 pool->free_list = next;
97
98 /* here, we should have pool->allocate == pool->used */
99}
100
101/*
102 * This function frees whatever can be freed in all pools, but respecting
103 * the minimum thresholds imposed by owners.
104 */
105void pool_gc2()
106{
107 struct pool_head *entry;
108 list_for_each_entry(entry, &pools, list) {
109 void *temp, *next;
110 //qfprintf(stderr, "Flushing pool %s\n", entry->name);
111 next = entry->free_list;
112 while (next &&
113 entry->allocated > entry->minavail &&
114 entry->allocated > entry->used) {
115 temp = next;
116 next = *(void **)temp;
117 entry->allocated--;
118 FREE(temp);
119 }
120 entry->free_list = next;
121 }
122}
123
124/*
125 * This function destroys a pull by freeing it completely.
126 * This should be called only under extreme circumstances.
127 */
128void pool_destroy2(struct pool_head *pool)
129{
130 pool_flush2(pool);
131 FREE(pool);
132}
133
Willy Tarreau50e608d2007-05-13 18:26:08 +0200134/* Dump statistics on pools usage.
135 */
136void dump_pools(void)
137{
138 struct pool_head *entry;
139 unsigned long allocated, used;
140 int nbpools;
141
142 allocated = used = nbpools = 0;
143 qfprintf(stderr, "Dumping pools usage.\n");
144 list_for_each_entry(entry, &pools, list) {
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200145 qfprintf(stderr, " - Pool %s (%d bytes) : %d allocated (%lu bytes), %d used%s\n",
146 entry->name, entry->size, entry->allocated,
147 entry->size * entry->allocated, entry->used,
148 (entry->flags & MEM_F_SHARED) ? " [SHARED]" : "");
Willy Tarreau50e608d2007-05-13 18:26:08 +0200149
150 allocated += entry->allocated * entry->size;
151 used += entry->used * entry->size;
152 nbpools++;
153 }
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200154 qfprintf(stderr, "Total: %d pools, %lu bytes allocated, %lu used.\n",
Willy Tarreau50e608d2007-05-13 18:26:08 +0200155 nbpools, allocated, used);
156}
157
158/*
159 * Local variables:
160 * c-indent-level: 8
161 * c-basic-offset: 8
162 * End:
163 */