]> jfr.im git - irc/quakenet/newserv.git/blob - core/nsmalloc.c
Add malloc checking to lua/nterfacer/trojanscan.
[irc/quakenet/newserv.git] / core / nsmalloc.c
1 /* nsmalloc: Simple pooled malloc() thing. */
2
3 #include <stdlib.h>
4
5 #include "nsmalloc.h"
6 #define __NSMALLOC_C
7 #undef __NSMALLOC_H
8 #include "nsmalloc.h"
9
10 #include "../core/error.h"
11
12 void *nsmalloc(unsigned int poolid, size_t size);
13 void nsfree(unsigned int poolid, void *ptr);
14 void nsfreeall(unsigned int poolid);
15
16 struct nsminfo {
17 struct nsminfo *next;
18 struct nsminfo *prev;
19
20 size_t size;
21 char data[];
22 };
23
24 struct nsmpool {
25 struct nsminfo first;
26
27 unsigned long count;
28 size_t size;
29 };
30
31 struct nsmpool pools[MAXPOOL];
32
33 void *nsmalloc(unsigned int poolid, size_t size) {
34 struct nsminfo *nsmp;
35
36 if (poolid >= MAXPOOL)
37 return NULL;
38
39 /* Allocate enough for the structure and the required data */
40 nsmp=(struct nsminfo *)malloc(sizeof(struct nsminfo)+size);
41
42 if (!nsmp)
43 return NULL;
44
45 nsmp->size=size;
46 pools[poolid].size+=size;
47 pools[poolid].count++;
48
49 nsmp->next=pools[poolid].first.next;
50 nsmp->prev=&pools[poolid].first;
51 if (pools[poolid].first.next)
52 pools[poolid].first.next->prev=nsmp;
53 pools[poolid].first.next=nsmp;
54
55 return (void *)nsmp->data;
56 }
57
58 /* we dump core on ptr == NULL */
59 void nsfree(unsigned int poolid, void *ptr) {
60 struct nsminfo *nsmp;
61
62 if (poolid >= MAXPOOL)
63 return;
64
65 /* evil */
66 nsmp=(struct nsminfo*)ptr - 1;
67
68 /* always set as we have a sentinel */
69 nsmp->prev->next=nsmp->next;
70 if (nsmp->next)
71 nsmp->next->prev=nsmp->prev;
72
73 pools[poolid].size-=nsmp->size;
74 pools[poolid].count--;
75
76 free(nsmp);
77 return;
78 }
79
80 void *nsrealloc(unsigned int poolid, void *ptr, size_t size) {
81 struct nsminfo *nsmp, *nsmpn;
82
83 if (ptr == NULL)
84 return nsmalloc(poolid, size);
85
86 if (size == 0) {
87 nsfree(poolid, ptr);
88 return NULL;
89 }
90
91 if (poolid >= MAXPOOL)
92 return NULL;
93
94 /* evil */
95 nsmp=(struct nsminfo *)ptr - 1;
96
97 if (size == nsmp->size)
98 return (void *)nsmp->data;
99
100 nsmpn=(struct nsminfo *)realloc(nsmp, sizeof(struct nsminfo)+size);
101 if (!nsmpn)
102 return NULL;
103
104 pools[poolid].size+=size-nsmpn->size;
105 nsmpn->size=size;
106
107 /* always set as we have a sentinel */
108 nsmpn->prev->next=nsmpn;
109
110 if (nsmpn->next)
111 nsmpn->next->prev=nsmpn;
112
113 return (void *)nsmpn->data;
114 }
115
116 void nsfreeall(unsigned int poolid) {
117 struct nsminfo *nsmp, *nnsmp;
118
119 if (poolid >= MAXPOOL)
120 return;
121
122 for (nsmp=pools[poolid].first.next;nsmp;nsmp=nnsmp) {
123 nnsmp=nsmp->next;
124 free(nsmp);
125 }
126
127 pools[poolid].first.next=NULL;
128 pools[poolid].size=0;
129 pools[poolid].count=0;
130 }
131
132 void nscheckfreeall(unsigned int poolid) {
133 if (poolid >= MAXPOOL)
134 return;
135
136 if (pools[poolid].first.next) {
137 Error("core",ERR_INFO,"nsmalloc: Blocks still allocated in pool #%d (%s): %lub, %lu items",poolid,poolnames[poolid]?poolnames[poolid]:"??",pools[poolid].size,pools[poolid].count);
138 nsfreeall(poolid);
139 }
140 }
141
142 void nsexit() {
143 unsigned int i;
144
145 for (i=0;i<MAXPOOL;i++)
146 nscheckfreeall(i);
147 }
148
149 int nspoolstats(unsigned int poolid, size_t *size, unsigned long *count, char **poolname, size_t *realsize) {
150 if (poolid >= MAXPOOL)
151 return 0;
152
153 *size = pools[poolid].size;
154 *realsize = pools[poolid].size + pools[poolid].count * sizeof(struct nsminfo) + sizeof(struct nsmpool);
155 *count = pools[poolid].count;
156 *poolname = poolnames[poolid];
157
158 return 1;
159 }