]> jfr.im git - irc/quakenet/newserv.git/blob - core/nsmalloc.c
merge chanserv-live into default
[irc/quakenet/newserv.git] / core / nsmalloc.c
1 /* nsmalloc: Simple pooled malloc() thing. */
2
3 #include <stdlib.h>
4 #include <string.h>
5 #include <assert.h>
6
7 #include "nsmalloc.h"
8 #define __NSMALLOC_C
9 #undef __NSMALLOC_H
10 #include "nsmalloc.h"
11
12 #include "../lib/valgrind.h"
13 #include "../lib/memcheck.h"
14 #include "../core/hooks.h"
15 #include "../core/error.h"
16
17 struct nsmpool nsmpools[MAXPOOL];
18
19 void *nsmalloc(unsigned int poolid, size_t size) {
20 struct nsminfo *nsmp;
21
22 if (poolid >= MAXPOOL)
23 return NULL;
24
25 /* Allocate enough for the structure and the required data */
26 nsmp=(struct nsminfo *)malloc(sizeof(struct nsminfo)+size);
27
28 if (!nsmp)
29 return NULL;
30
31 VALGRIND_CREATE_MEMPOOL(nsmp, 0, 0);
32
33 nsmp->size=size;
34 nsmpools[poolid].size+=size;
35 nsmpools[poolid].count++;
36
37 if (nsmpools[poolid].blocks) {
38 nsmpools[poolid].blocks->prev = nsmp;
39 }
40 nsmp->next=nsmpools[poolid].blocks;
41 nsmp->prev=NULL;
42 nsmpools[poolid].blocks=nsmp;
43
44 VALGRIND_MEMPOOL_ALLOC(nsmp, nsmp->data, nsmp->size);
45
46 nsmp->redzone = REDZONE_MAGIC;
47 VALGRIND_MAKE_MEM_NOACCESS(&nsmp->redzone, sizeof(nsmp->redzone));
48
49 return (void *)nsmp->data;
50 }
51
52 void *nscalloc(unsigned int poolid, size_t nmemb, size_t size) {
53 size_t total = nmemb * size;
54 void *m;
55
56 m = nsmalloc(poolid, total);
57 if(!m)
58 return NULL;
59
60 memset(m, 0, total);
61
62 return m;
63 }
64
65 void nsfree(unsigned int poolid, void *ptr) {
66 struct nsminfo *nsmp;
67
68 if (!ptr || poolid >= MAXPOOL)
69 return;
70
71 /* evil */
72 nsmp=(struct nsminfo*)ptr - 1;
73
74 VALGRIND_MAKE_MEM_DEFINED(&nsmp->redzone, sizeof(nsmp->redzone));
75 assert(nsmp->redzone == REDZONE_MAGIC);
76
77 if (nsmp->prev) {
78 nsmp->prev->next = nsmp->next;
79 } else
80 nsmpools[poolid].blocks = NULL;
81
82 if (nsmp->next) {
83 nsmp->next->prev = nsmp->prev;
84 }
85
86 nsmpools[poolid].size-=nsmp->size;
87 nsmpools[poolid].count--;
88
89 VALGRIND_MEMPOOL_FREE(nsmp, nsmp->data);
90 free(nsmp);
91 VALGRIND_DESTROY_MEMPOOL(nsmp);
92
93 return;
94 }
95
96 void *nsrealloc(unsigned int poolid, void *ptr, size_t size) {
97 struct nsminfo *nsmp, *nsmpn;
98
99 if (ptr == NULL)
100 return nsmalloc(poolid, size);
101
102 if (size == 0) {
103 nsfree(poolid, ptr);
104 return NULL;
105 }
106
107 if (poolid >= MAXPOOL)
108 return NULL;
109
110 /* evil */
111 nsmp=(struct nsminfo *)ptr - 1;
112
113 VALGRIND_MAKE_MEM_DEFINED(nsmp, sizeof(struct nsminfo));
114
115 if (size == nsmp->size)
116 return (void *)nsmp->data;
117
118 nsmpn=(struct nsminfo *)realloc(nsmp, sizeof(struct nsminfo)+size);
119 if (!nsmpn)
120 return NULL;
121
122 VALGRIND_MOVE_MEMPOOL(nsmp, nsmpn);
123
124 nsmpools[poolid].size+=size-nsmpn->size;
125 nsmpn->size=size;
126
127 if (nsmpn->prev) {
128 nsmpn->prev->next=nsmpn;
129 } else
130 nsmpools[poolid].blocks = nsmpn;
131
132 if (nsmpn->next) {
133 nsmpn->next->prev=nsmpn;
134 }
135
136 VALGRIND_MEMPOOL_CHANGE(nsmpn, nsmp->data, nsmpn->data, nsmpn->size);
137
138 return (void *)nsmpn->data;
139 }
140
141 void nsfreeall(unsigned int poolid) {
142 struct nsminfo *nsmp, *nnsmp;
143
144 if (poolid >= MAXPOOL)
145 return;
146
147 for (nsmp=nsmpools[poolid].blocks;nsmp;nsmp=nnsmp) {
148 nnsmp=nsmp->next;
149 VALGRIND_MEMPOOL_FREE(nsmp, nsmp->data);
150 free(nsmp);
151 VALGRIND_DESTROY_MEMPOOL(nsmp);
152 }
153
154 nsmpools[poolid].blocks=NULL;
155 nsmpools[poolid].size=0;
156 nsmpools[poolid].count=0;
157 }
158
159 void nscheckfreeall(unsigned int poolid) {
160 if (poolid >= MAXPOOL)
161 return;
162
163 if (nsmpools[poolid].blocks) {
164 Error("core",ERR_INFO,"nsmalloc: Blocks still allocated in pool #%d (%s): %zub, %lu items",poolid,nsmpoolnames[poolid]?nsmpoolnames[poolid]:"??",nsmpools[poolid].size,nsmpools[poolid].count);
165 nsfreeall(poolid);
166 }
167 }
168
169 void nsinit(void) {
170 memset(nsmpools, 0, sizeof(nsmpools));
171 }
172
173 void nsexit(void) {
174 unsigned int i;
175
176 for (i=0;i<MAXPOOL;i++)
177 nsfreeall(i);
178 }
179