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