Coverage Report

Created: 2025-07-09 06:29

/src/opensips/mem/mem.c
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
12.1k
{
353
12.1k
  void *v;
354
355
12.1k
  v = malloc(s);
356
12.1k
  LM_DBG("%s:%s:%d: malloc %p size %lu end %p\n", file, function, line,
357
12.1k
      v, (unsigned long)s, (char *)v + s);
358
12.1k
  return v;
359
12.1k
}
360
361
void *
362
sys_realloc(void *p, unsigned long s, const char *file, const char *function, unsigned int line)
363
2
{
364
2
  void *v;
365
366
2
  v = realloc(p, s);
367
2
  LM_DBG("%s:%s:%d: realloc old %p to %p size %lu end %p\n", file,
368
2
      function, line, p, v, (unsigned long)s, (char *)v + s);
369
2
  return v;
370
2
}
371
372
void
373
sys_free(void *p, const char *file, const char *function, unsigned int line)
374
12.1k
{
375
376
12.1k
  LM_DBG("%s:%s:%d: free %p\n", file, function, line, p);
377
12.1k
  free(p);
378
12.1k
}
379
#endif