]>
Commit | Line | Data |
---|---|---|
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 |