Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2001-2003 FhG Fokus |
3 | | * Copyright (C) 2019 OpenSIPS Solutions |
4 | | * |
5 | | * This file is part of opensips, a free SIP server. |
6 | | * |
7 | | * opensips is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 2 of the License, or |
10 | | * (at your option) any later version |
11 | | * |
12 | | * opensips is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU General Public License |
18 | | * along with this program; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | #include <stdio.h> |
23 | | #include <stdlib.h> |
24 | | #include "../config.h" |
25 | | #include "../dprint.h" |
26 | | #include "../globals.h" |
27 | | #include "mem.h" |
28 | | |
29 | | #include "shm_mem.h" |
30 | | |
31 | | enum osips_mm mem_allocator_pkg = MM_NONE; |
32 | | |
33 | | #ifndef INLINE_ALLOC |
34 | | #ifdef DBG_MALLOC |
35 | | void *(*gen_pkg_malloc)(void *blk, unsigned long size, |
36 | | const char *file, const char *func, unsigned int line); |
37 | | void *(*gen_pkg_realloc)(void *blk, void *p, unsigned long size, |
38 | | const char *file, const char *func, unsigned int line); |
39 | | void (*gen_pkg_free)(void *blk, void *p, |
40 | | const char *file, const char *func, unsigned int line); |
41 | | #else |
42 | | void *(*gen_pkg_malloc)(void *blk, unsigned long size); |
43 | | void *(*gen_pkg_realloc)(void *blk, void *p, unsigned long size); |
44 | | void (*gen_pkg_free)(void *blk, void *p); |
45 | | #endif |
46 | | void (*gen_pkg_info)(void *blk, struct mem_info *info); |
47 | | void (*gen_pkg_status)(void *blk); |
48 | | unsigned long (*gen_pkg_get_size)(void *blk); |
49 | | unsigned long (*gen_pkg_get_used)(void *blk); |
50 | | unsigned long (*gen_pkg_get_rused)(void *blk); |
51 | | unsigned long (*gen_pkg_get_mused)(void *blk); |
52 | | unsigned long (*gen_pkg_get_free)(void *blk); |
53 | | unsigned long (*gen_pkg_get_frags)(void *blk); |
54 | | #endif |
55 | | |
56 | | #ifdef PKG_MALLOC |
57 | | char *mem_pool; |
58 | | void *mem_block; |
59 | | #endif |
60 | | |
61 | | int set_pkg_mm(const char *mm_name) |
62 | 0 | { |
63 | | #ifdef PKG_MALLOC |
64 | | #ifdef INLINE_ALLOC |
65 | | LM_NOTICE("this is an inlined allocator build (see opensips -V), " |
66 | | "cannot set a custom pkg allocator (%s)\n", mm_name); |
67 | | return 0; |
68 | | #endif |
69 | | |
70 | | if (parse_mm(mm_name, &mem_allocator_pkg) < 0) |
71 | | return -1; |
72 | | |
73 | | return 0; |
74 | | #else |
75 | 0 | LM_ERR("cannot change pkg allocator when system malloc is used!\n"); |
76 | 0 | return -1; |
77 | 0 | #endif |
78 | 0 | } |
79 | | |
80 | | int init_pkg_mallocs(void) |
81 | 0 | { |
82 | | #ifdef PKG_MALLOC |
83 | | mem_pool = malloc(pkg_mem_size); |
84 | | if (!mem_pool) { |
85 | | LM_CRIT("could not initialize PKG memory: %ld\n", pkg_mem_size); |
86 | | return -1; |
87 | | } |
88 | | |
89 | | #ifdef INLINE_ALLOC |
90 | | #if defined F_MALLOC |
91 | | mem_block = fm_malloc_init(mem_pool, pkg_mem_size, "pkg"); |
92 | | #elif defined Q_MALLOC |
93 | | mem_block = qm_malloc_init(mem_pool, pkg_mem_size, "pkg"); |
94 | | #elif defined HP_MALLOC |
95 | | mem_block = hp_pkg_malloc_init(mem_pool, pkg_mem_size, "pkg"); |
96 | | #endif |
97 | | #else |
98 | | if (mem_allocator_pkg == MM_NONE) |
99 | | mem_allocator_pkg = mem_allocator; |
100 | | |
101 | | switch (mem_allocator_pkg) { |
102 | | #ifdef F_MALLOC |
103 | | case MM_F_MALLOC: |
104 | | mem_block = fm_malloc_init(mem_pool, pkg_mem_size, "pkg"); |
105 | | gen_pkg_malloc = (osips_block_malloc_f)fm_malloc; |
106 | | gen_pkg_realloc = (osips_block_realloc_f)fm_realloc; |
107 | | gen_pkg_free = (osips_block_free_f)fm_free; |
108 | | gen_pkg_info = (osips_mem_info_f)fm_info; |
109 | | gen_pkg_status = (osips_mem_status_f)fm_status; |
110 | | gen_pkg_get_size = (osips_get_mmstat_f)fm_get_size; |
111 | | gen_pkg_get_used = (osips_get_mmstat_f)fm_get_used; |
112 | | gen_pkg_get_rused = (osips_get_mmstat_f)fm_get_real_used; |
113 | | gen_pkg_get_mused = (osips_get_mmstat_f)fm_get_max_real_used; |
114 | | gen_pkg_get_free = (osips_get_mmstat_f)fm_get_free; |
115 | | gen_pkg_get_frags = (osips_get_mmstat_f)fm_get_frags; |
116 | | break; |
117 | | #endif |
118 | | #ifdef Q_MALLOC |
119 | | case MM_Q_MALLOC: |
120 | | mem_block = qm_malloc_init(mem_pool, pkg_mem_size, "pkg"); |
121 | | gen_pkg_malloc = (osips_block_malloc_f)qm_malloc; |
122 | | gen_pkg_realloc = (osips_block_realloc_f)qm_realloc; |
123 | | gen_pkg_free = (osips_block_free_f)qm_free; |
124 | | gen_pkg_info = (osips_mem_info_f)qm_info; |
125 | | gen_pkg_status = (osips_mem_status_f)qm_status; |
126 | | gen_pkg_get_size = (osips_get_mmstat_f)qm_get_size; |
127 | | gen_pkg_get_used = (osips_get_mmstat_f)qm_get_used; |
128 | | gen_pkg_get_rused = (osips_get_mmstat_f)qm_get_real_used; |
129 | | gen_pkg_get_mused = (osips_get_mmstat_f)qm_get_max_real_used; |
130 | | gen_pkg_get_free = (osips_get_mmstat_f)qm_get_free; |
131 | | gen_pkg_get_frags = (osips_get_mmstat_f)qm_get_frags; |
132 | | break; |
133 | | #endif |
134 | | #ifdef HP_MALLOC |
135 | | case MM_HP_MALLOC: |
136 | | mem_block = hp_pkg_malloc_init(mem_pool, pkg_mem_size, "pkg"); |
137 | | gen_pkg_malloc = (osips_block_malloc_f)hp_pkg_malloc; |
138 | | gen_pkg_realloc = (osips_block_realloc_f)hp_pkg_realloc; |
139 | | gen_pkg_free = (osips_block_free_f)hp_pkg_free; |
140 | | gen_pkg_info = (osips_mem_info_f)hp_info; |
141 | | gen_pkg_status = (osips_mem_status_f)hp_status; |
142 | | gen_pkg_get_size = (osips_get_mmstat_f)hp_pkg_get_size; |
143 | | gen_pkg_get_used = (osips_get_mmstat_f)hp_pkg_get_used; |
144 | | gen_pkg_get_rused = (osips_get_mmstat_f)hp_pkg_get_real_used; |
145 | | gen_pkg_get_mused = (osips_get_mmstat_f)hp_pkg_get_max_real_used; |
146 | | gen_pkg_get_free = (osips_get_mmstat_f)hp_pkg_get_free; |
147 | | gen_pkg_get_frags = (osips_get_mmstat_f)hp_pkg_get_frags; |
148 | | break; |
149 | | #endif |
150 | | #ifdef DBG_MALLOC |
151 | | #ifdef F_MALLOC |
152 | | case MM_F_MALLOC_DBG: |
153 | | mem_block = fm_malloc_init(mem_pool, pkg_mem_size, "pkg"); |
154 | | gen_pkg_malloc = (osips_block_malloc_f)fm_malloc_dbg; |
155 | | gen_pkg_realloc = (osips_block_realloc_f)fm_realloc_dbg; |
156 | | gen_pkg_free = (osips_block_free_f)fm_free_dbg; |
157 | | gen_pkg_info = (osips_mem_info_f)fm_info; |
158 | | gen_pkg_status = (osips_mem_status_f)fm_status_dbg; |
159 | | gen_pkg_get_size = (osips_get_mmstat_f)fm_get_size; |
160 | | gen_pkg_get_used = (osips_get_mmstat_f)fm_get_used; |
161 | | gen_pkg_get_rused = (osips_get_mmstat_f)fm_get_real_used; |
162 | | gen_pkg_get_mused = (osips_get_mmstat_f)fm_get_max_real_used; |
163 | | gen_pkg_get_free = (osips_get_mmstat_f)fm_get_free; |
164 | | gen_pkg_get_frags = (osips_get_mmstat_f)fm_get_frags; |
165 | | break; |
166 | | #endif |
167 | | #ifdef Q_MALLOC |
168 | | case MM_Q_MALLOC_DBG: |
169 | | mem_block = qm_malloc_init(mem_pool, pkg_mem_size, "pkg"); |
170 | | gen_pkg_malloc = (osips_block_malloc_f)qm_malloc_dbg; |
171 | | gen_pkg_realloc = (osips_block_realloc_f)qm_realloc_dbg; |
172 | | gen_pkg_free = (osips_block_free_f)qm_free_dbg; |
173 | | gen_pkg_info = (osips_mem_info_f)qm_info; |
174 | | gen_pkg_status = (osips_mem_status_f)qm_status_dbg; |
175 | | gen_pkg_get_size = (osips_get_mmstat_f)qm_get_size; |
176 | | gen_pkg_get_used = (osips_get_mmstat_f)qm_get_used; |
177 | | gen_pkg_get_rused = (osips_get_mmstat_f)qm_get_real_used; |
178 | | gen_pkg_get_mused = (osips_get_mmstat_f)qm_get_max_real_used; |
179 | | gen_pkg_get_free = (osips_get_mmstat_f)qm_get_free; |
180 | | gen_pkg_get_frags = (osips_get_mmstat_f)qm_get_frags; |
181 | | break; |
182 | | #endif |
183 | | #ifdef HP_MALLOC |
184 | | case MM_HP_MALLOC_DBG: |
185 | | mem_block = hp_pkg_malloc_init(mem_pool, pkg_mem_size, "pkg"); |
186 | | gen_pkg_malloc = (osips_block_malloc_f)hp_pkg_malloc_dbg; |
187 | | gen_pkg_realloc = (osips_block_realloc_f)hp_pkg_realloc_dbg; |
188 | | gen_pkg_free = (osips_block_free_f)hp_pkg_free_dbg; |
189 | | gen_pkg_info = (osips_mem_info_f)hp_info; |
190 | | gen_pkg_status = (osips_mem_status_f)hp_status_dbg; |
191 | | gen_pkg_get_size = (osips_get_mmstat_f)hp_pkg_get_size; |
192 | | gen_pkg_get_used = (osips_get_mmstat_f)hp_pkg_get_used; |
193 | | gen_pkg_get_rused = (osips_get_mmstat_f)hp_pkg_get_real_used; |
194 | | gen_pkg_get_mused = (osips_get_mmstat_f)hp_pkg_get_max_real_used; |
195 | | gen_pkg_get_free = (osips_get_mmstat_f)hp_pkg_get_free; |
196 | | gen_pkg_get_frags = (osips_get_mmstat_f)hp_pkg_get_frags; |
197 | | break; |
198 | | #endif |
199 | | #endif |
200 | | default: |
201 | | LM_ERR("current build does not include support for " |
202 | | "selected allocator (%s)\n", mm_str(mem_allocator_pkg)); |
203 | | return -1; |
204 | | } |
205 | | #endif |
206 | | |
207 | | if (!mem_block) { |
208 | | LM_CRIT("could not initialize memory pool\n"); |
209 | | fprintf(stderr, "Given PKG mem size is not enough: %ld\n", |
210 | | pkg_mem_size ); |
211 | | return -1; |
212 | | } |
213 | | #endif |
214 | |
|
215 | 0 | return 0; |
216 | 0 | } |
217 | | |
218 | | |
219 | | |
220 | | #if defined(PKG_MALLOC) && defined(STATISTICS) |
221 | | void set_pkg_stats(pkg_status_holder *status) |
222 | | { |
223 | | status[0][PKG_TOTAL_SIZE_IDX] = PKG_GET_SIZE(); |
224 | | status[0][PKG_USED_SIZE_IDX] = PKG_GET_USED(); |
225 | | status[0][PKG_REAL_USED_SIZE_IDX] = PKG_GET_RUSED(); |
226 | | status[0][PKG_MAX_USED_SIZE_IDX] = PKG_GET_MUSED(); |
227 | | status[0][PKG_FREE_SIZE_IDX] = PKG_GET_FREE(); |
228 | | status[0][PKG_FRAGMENTS_SIZE_IDX] = PKG_GET_FRAGS(); |
229 | | } |
230 | | |
231 | | /* event interface information */ |
232 | | #include <unistd.h> |
233 | | #include "../evi/evi_core.h" |
234 | | #include "../evi/evi_modules.h" |
235 | | |
236 | | /* events information */ |
237 | | long event_pkg_threshold = 0; |
238 | | |
239 | | // determines the last percentage triggered |
240 | | long event_pkg_last = 0; |
241 | | |
242 | | // determines if there is a pending event |
243 | | int event_pkg_pending = 0; |
244 | | |
245 | | static str pkg_usage_str = { "usage", 5 }; |
246 | | static str pkg_threshold_str = { "threshold", 9 }; |
247 | | static str pkg_used_str = { "used", 4 }; |
248 | | static str pkg_size_str = { "size", 4 }; |
249 | | static str pkg_pid_str = { "pid", 3 }; |
250 | | |
251 | | |
252 | | void pkg_event_raise(long used, long size, long perc) |
253 | | { |
254 | | evi_params_p list = 0; |
255 | | int pid; |
256 | | |
257 | | event_pkg_pending = 1; |
258 | | event_pkg_last = perc; |
259 | | |
260 | | // event has to be triggered - check for subscribers |
261 | | if (!evi_probe_event(EVI_PKG_THRESHOLD_ID)) { |
262 | | goto end; |
263 | | } |
264 | | |
265 | | if (!(list = evi_get_params())) |
266 | | goto end; |
267 | | if (evi_param_add_int(list, &pkg_usage_str, (int *)&perc)) { |
268 | | LM_ERR("unable to add usage parameter\n"); |
269 | | goto end; |
270 | | } |
271 | | if (evi_param_add_int(list, &pkg_threshold_str, (int *)&event_pkg_threshold)) { |
272 | | LM_ERR("unable to add threshold parameter\n"); |
273 | | goto end; |
274 | | } |
275 | | if (evi_param_add_int(list, &pkg_used_str, (int *)&used)) { |
276 | | LM_ERR("unable to add used parameter\n"); |
277 | | goto end; |
278 | | } |
279 | | if (evi_param_add_int(list, &pkg_size_str, (int *)&size)) { |
280 | | LM_ERR("unable to add size parameter\n"); |
281 | | goto end; |
282 | | } |
283 | | pid = getpid(); |
284 | | if (evi_param_add_int(list, &pkg_pid_str, (int *)&pid)) { |
285 | | LM_ERR("unable to add size parameter\n"); |
286 | | goto end; |
287 | | } |
288 | | |
289 | | if (evi_raise_event(EVI_PKG_THRESHOLD_ID, list)) { |
290 | | LM_ERR("unable to send pkg threshold event\n"); |
291 | | } |
292 | | list = 0; |
293 | | end: |
294 | | if (list) |
295 | | evi_free_params(list); |
296 | | event_pkg_pending = 0; |
297 | | } |
298 | | |
299 | | void pkg_threshold_check(void) |
300 | | { |
301 | | long pkg_perc, used, size; |
302 | | |
303 | | if (event_pkg_threshold == 0 || // threshold not used |
304 | | event_pkg_pending ) { // somebody else is raising the event |
305 | | // do not do anything |
306 | | return; |
307 | | } |
308 | | |
309 | | // compute the percentage |
310 | | used = PKG_GET_RUSED(); |
311 | | size = PKG_GET_SIZE(); |
312 | | pkg_perc = used * 100 / size; |
313 | | |
314 | | /* check if the event has to be raised or if it was already notified */ |
315 | | if ((pkg_perc < event_pkg_threshold && event_pkg_last <= event_pkg_threshold) || |
316 | | (pkg_perc >= event_pkg_threshold && event_pkg_last == pkg_perc)) |
317 | | return; |
318 | | |
319 | | pkg_event_raise(used, size, pkg_perc); |
320 | | } |
321 | | #endif |
322 | | |
323 | | |
324 | | |
325 | | int init_shm_mallocs(void) |
326 | 0 | { |
327 | 0 | if (shm_mem_init() < 0) { |
328 | 0 | LM_CRIT("could not initialize shared memory pool, exiting...\n"); |
329 | 0 | fprintf(stderr, "Too much shared memory demanded: %ld\n", |
330 | 0 | shm_mem_size ); |
331 | 0 | return -1; |
332 | 0 | } |
333 | | |
334 | 0 | return 0; |
335 | 0 | } |
336 | | |
337 | | int init_dbg_shm_mallocs(void) |
338 | 0 | { |
339 | | #ifdef DBG_MALLOC |
340 | | if (shm_dbg_mem_init() < 0) { |
341 | | LM_CRIT("could not initialize debug shared memory pool, exiting...\n"); |
342 | | return -1; |
343 | | } |
344 | | #endif |
345 | |
|
346 | 0 | return 0; |
347 | 0 | } |
348 | | |
349 | | #ifdef SYSTEM_MALLOC |
350 | | void * |
351 | | sys_malloc(unsigned long s, const char *file, const char *function, unsigned int line) |
352 | 6.26M | { |
353 | 6.26M | void *v; |
354 | | |
355 | 6.26M | v = malloc(s); |
356 | 6.26M | LM_DBG("%s:%s:%d: malloc %p size %lu end %p\n", file, function, line, |
357 | 6.26M | v, (unsigned long)s, (char *)v + s); |
358 | 6.26M | return v; |
359 | 6.26M | } |
360 | | |
361 | | void * |
362 | | sys_realloc(void *p, unsigned long s, const char *file, const char *function, unsigned int line) |
363 | 8 | { |
364 | 8 | void *v; |
365 | | |
366 | 8 | v = realloc(p, s); |
367 | 8 | LM_DBG("%s:%s:%d: realloc old %p to %p size %lu end %p\n", file, |
368 | 8 | function, line, p, v, (unsigned long)s, (char *)v + s); |
369 | 8 | return v; |
370 | 8 | } |
371 | | |
372 | | void |
373 | | sys_free(void *p, const char *file, const char *function, unsigned int line) |
374 | 6.26M | { |
375 | | |
376 | 6.26M | LM_DBG("%s:%s:%d: free %p\n", file, function, line, p); |
377 | 6.26M | free(p); |
378 | 6.26M | } |
379 | | #endif |