2012-10-24 02:04:40 +00:00
|
|
|
/* wmem_core.c
|
|
|
|
* Wireshark Memory Manager Core
|
|
|
|
* Copyright 2012, Evan Huus <eapache@gmail.com>
|
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2018-02-08 16:31:35 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
2012-10-24 02:04:40 +00:00
|
|
|
*/
|
|
|
|
|
2012-12-19 00:43:36 +00:00
|
|
|
#include <stdlib.h>
|
2012-10-24 02:04:40 +00:00
|
|
|
#include <string.h>
|
2012-12-19 00:43:36 +00:00
|
|
|
#include <glib.h>
|
2012-10-24 02:04:40 +00:00
|
|
|
|
|
|
|
#include "wmem_core.h"
|
2012-11-03 15:49:15 +00:00
|
|
|
#include "wmem_scopes.h"
|
2014-04-22 00:30:06 +00:00
|
|
|
#include "wmem_map_int.h"
|
2013-05-08 01:14:01 +00:00
|
|
|
#include "wmem_user_cb_int.h"
|
2012-10-24 02:04:40 +00:00
|
|
|
#include "wmem_allocator.h"
|
2012-12-19 00:43:36 +00:00
|
|
|
#include "wmem_allocator_simple.h"
|
|
|
|
#include "wmem_allocator_block.h"
|
2014-04-29 06:57:40 +00:00
|
|
|
#include "wmem_allocator_block_fast.h"
|
2012-12-28 17:04:23 +00:00
|
|
|
#include "wmem_allocator_strict.h"
|
2012-10-27 02:42:05 +00:00
|
|
|
|
2021-03-20 13:13:27 +00:00
|
|
|
#include <wsutil/ws_assert.h>
|
|
|
|
|
2013-10-15 23:16:35 +00:00
|
|
|
/* Set according to the WIRESHARK_DEBUG_WMEM_OVERRIDE environment variable in
|
|
|
|
* wmem_init. Should not be set again. */
|
|
|
|
static gboolean do_override = FALSE;
|
|
|
|
static wmem_allocator_type_t override_type;
|
|
|
|
|
2012-10-24 02:04:40 +00:00
|
|
|
void *
|
2012-11-08 23:18:26 +00:00
|
|
|
wmem_alloc(wmem_allocator_t *allocator, const size_t size)
|
2012-10-24 02:04:40 +00:00
|
|
|
{
|
2013-02-14 16:23:22 +00:00
|
|
|
if (allocator == NULL) {
|
|
|
|
return g_malloc(size);
|
|
|
|
}
|
|
|
|
|
2021-03-20 13:13:27 +00:00
|
|
|
ws_assert(allocator->in_scope);
|
2013-06-19 18:28:13 +00:00
|
|
|
|
2013-01-23 01:11:36 +00:00
|
|
|
if (size == 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-05-12 17:39:15 +00:00
|
|
|
return allocator->walloc(allocator->private_data, size);
|
2012-10-24 02:04:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
2012-11-08 23:18:26 +00:00
|
|
|
wmem_alloc0(wmem_allocator_t *allocator, const size_t size)
|
2012-10-24 02:04:40 +00:00
|
|
|
{
|
|
|
|
void *buf;
|
2013-01-23 01:11:36 +00:00
|
|
|
|
2012-10-24 02:04:40 +00:00
|
|
|
buf = wmem_alloc(allocator, size);
|
|
|
|
|
2013-06-19 18:28:13 +00:00
|
|
|
if (buf) {
|
|
|
|
memset(buf, 0, size);
|
|
|
|
}
|
2013-03-20 00:10:07 +00:00
|
|
|
|
|
|
|
return buf;
|
2012-10-24 02:04:40 +00:00
|
|
|
}
|
|
|
|
|
2013-01-23 00:59:38 +00:00
|
|
|
void
|
|
|
|
wmem_free(wmem_allocator_t *allocator, void *ptr)
|
|
|
|
{
|
2013-02-14 16:23:22 +00:00
|
|
|
if (allocator == NULL) {
|
|
|
|
g_free(ptr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-20 13:13:27 +00:00
|
|
|
ws_assert(allocator->in_scope);
|
2013-06-19 18:28:13 +00:00
|
|
|
|
2013-01-23 01:11:36 +00:00
|
|
|
if (ptr == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-05-12 17:39:15 +00:00
|
|
|
allocator->wfree(allocator->private_data, ptr);
|
2013-01-23 00:59:38 +00:00
|
|
|
}
|
|
|
|
|
2013-01-23 01:11:36 +00:00
|
|
|
void *
|
|
|
|
wmem_realloc(wmem_allocator_t *allocator, void *ptr, const size_t size)
|
|
|
|
{
|
2013-02-14 16:23:22 +00:00
|
|
|
if (allocator == NULL) {
|
|
|
|
return g_realloc(ptr, size);
|
|
|
|
}
|
|
|
|
|
2013-01-23 01:11:36 +00:00
|
|
|
if (ptr == NULL) {
|
|
|
|
return wmem_alloc(allocator, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (size == 0) {
|
|
|
|
wmem_free(allocator, ptr);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-03-20 13:13:27 +00:00
|
|
|
ws_assert(allocator->in_scope);
|
2013-06-19 18:28:13 +00:00
|
|
|
|
2016-05-12 17:39:15 +00:00
|
|
|
return allocator->wrealloc(allocator->private_data, ptr, size);
|
2013-01-23 01:11:36 +00:00
|
|
|
}
|
|
|
|
|
2013-05-08 01:14:01 +00:00
|
|
|
static void
|
|
|
|
wmem_free_all_real(wmem_allocator_t *allocator, gboolean final)
|
2012-10-24 02:04:40 +00:00
|
|
|
{
|
2013-06-16 22:37:55 +00:00
|
|
|
wmem_call_callbacks(allocator,
|
2013-06-16 22:07:24 +00:00
|
|
|
final ? WMEM_CB_DESTROY_EVENT : WMEM_CB_FREE_EVENT);
|
2012-10-24 02:04:40 +00:00
|
|
|
allocator->free_all(allocator->private_data);
|
|
|
|
}
|
|
|
|
|
2013-01-23 00:59:38 +00:00
|
|
|
void
|
2013-05-08 01:14:01 +00:00
|
|
|
wmem_free_all(wmem_allocator_t *allocator)
|
2013-01-23 00:59:38 +00:00
|
|
|
{
|
2013-05-08 01:14:01 +00:00
|
|
|
wmem_free_all_real(allocator, FALSE);
|
2013-01-23 00:59:38 +00:00
|
|
|
}
|
|
|
|
|
2013-05-07 19:23:10 +00:00
|
|
|
void
|
2013-05-08 01:14:01 +00:00
|
|
|
wmem_gc(wmem_allocator_t *allocator)
|
2013-05-07 19:23:10 +00:00
|
|
|
{
|
2013-05-08 01:14:01 +00:00
|
|
|
allocator->gc(allocator->private_data);
|
2013-05-07 19:23:10 +00:00
|
|
|
}
|
|
|
|
|
2012-10-27 02:29:46 +00:00
|
|
|
void
|
|
|
|
wmem_destroy_allocator(wmem_allocator_t *allocator)
|
|
|
|
{
|
2013-05-07 19:23:10 +00:00
|
|
|
|
2013-05-08 01:14:01 +00:00
|
|
|
wmem_free_all_real(allocator, TRUE);
|
2013-05-22 15:42:12 +00:00
|
|
|
allocator->cleanup(allocator->private_data);
|
2013-09-01 13:37:38 +00:00
|
|
|
wmem_free(NULL, allocator);
|
2012-10-27 02:29:46 +00:00
|
|
|
}
|
|
|
|
|
2012-12-19 00:43:36 +00:00
|
|
|
wmem_allocator_t *
|
|
|
|
wmem_allocator_new(const wmem_allocator_type_t type)
|
|
|
|
{
|
2012-12-27 22:51:33 +00:00
|
|
|
wmem_allocator_t *allocator;
|
|
|
|
wmem_allocator_type_t real_type;
|
2012-12-27 22:31:42 +00:00
|
|
|
|
2013-10-15 23:16:35 +00:00
|
|
|
if (do_override) {
|
|
|
|
real_type = override_type;
|
2012-12-28 17:04:23 +00:00
|
|
|
}
|
2012-12-27 22:51:33 +00:00
|
|
|
else {
|
|
|
|
real_type = type;
|
2012-12-19 00:43:36 +00:00
|
|
|
}
|
|
|
|
|
2013-09-01 13:37:38 +00:00
|
|
|
allocator = wmem_new(NULL, wmem_allocator_t);
|
2013-06-19 18:28:13 +00:00
|
|
|
allocator->type = real_type;
|
2013-05-22 15:42:12 +00:00
|
|
|
allocator->callbacks = NULL;
|
2013-06-19 18:28:13 +00:00
|
|
|
allocator->in_scope = TRUE;
|
2013-05-22 15:42:12 +00:00
|
|
|
|
2012-12-27 22:51:33 +00:00
|
|
|
switch (real_type) {
|
2012-12-19 00:43:36 +00:00
|
|
|
case WMEM_ALLOCATOR_SIMPLE:
|
2013-05-22 15:42:12 +00:00
|
|
|
wmem_simple_allocator_init(allocator);
|
2012-12-27 22:31:42 +00:00
|
|
|
break;
|
2012-12-19 00:43:36 +00:00
|
|
|
case WMEM_ALLOCATOR_BLOCK:
|
2013-05-22 15:42:12 +00:00
|
|
|
wmem_block_allocator_init(allocator);
|
2012-12-27 22:31:42 +00:00
|
|
|
break;
|
2014-04-29 06:57:40 +00:00
|
|
|
case WMEM_ALLOCATOR_BLOCK_FAST:
|
|
|
|
wmem_block_fast_allocator_init(allocator);
|
|
|
|
break;
|
2012-12-28 17:04:23 +00:00
|
|
|
case WMEM_ALLOCATOR_STRICT:
|
2013-05-22 15:42:12 +00:00
|
|
|
wmem_strict_allocator_init(allocator);
|
2012-12-28 17:04:23 +00:00
|
|
|
break;
|
2012-12-19 00:43:36 +00:00
|
|
|
default:
|
2021-03-20 13:13:27 +00:00
|
|
|
ws_assert_not_reached();
|
|
|
|
break;
|
2012-12-19 00:43:36 +00:00
|
|
|
};
|
2012-12-27 22:31:42 +00:00
|
|
|
|
|
|
|
return allocator;
|
2012-12-19 00:43:36 +00:00
|
|
|
}
|
|
|
|
|
2012-10-27 02:42:05 +00:00
|
|
|
void
|
|
|
|
wmem_init(void)
|
|
|
|
{
|
2013-10-15 23:16:35 +00:00
|
|
|
const char *override_env;
|
|
|
|
|
|
|
|
/* Our valgrind script uses this environment variable to override the
|
|
|
|
* usual allocator choice so that everything goes through system-level
|
|
|
|
* allocations that it understands and can track. Otherwise it will get
|
|
|
|
* confused by the block allocator etc. */
|
|
|
|
override_env = getenv("WIRESHARK_DEBUG_WMEM_OVERRIDE");
|
|
|
|
|
|
|
|
if (override_env == NULL) {
|
|
|
|
do_override = FALSE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
do_override = TRUE;
|
|
|
|
if (strncmp(override_env, "simple", strlen("simple")) == 0) {
|
|
|
|
override_type = WMEM_ALLOCATOR_SIMPLE;
|
|
|
|
}
|
|
|
|
else if (strncmp(override_env, "block", strlen("block")) == 0) {
|
|
|
|
override_type = WMEM_ALLOCATOR_BLOCK;
|
|
|
|
}
|
|
|
|
else if (strncmp(override_env, "strict", strlen("strict")) == 0) {
|
|
|
|
override_type = WMEM_ALLOCATOR_STRICT;
|
|
|
|
}
|
2014-04-29 06:57:40 +00:00
|
|
|
else if (strncmp(override_env, "block_fast", strlen("block_fast")) == 0) {
|
|
|
|
override_type = WMEM_ALLOCATOR_BLOCK_FAST;
|
|
|
|
}
|
2013-10-15 23:16:35 +00:00
|
|
|
else {
|
2018-09-18 17:09:31 +00:00
|
|
|
g_warning("Unrecognized wmem override");
|
2013-10-15 23:16:35 +00:00
|
|
|
do_override = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-03 15:49:15 +00:00
|
|
|
wmem_init_scopes();
|
2014-04-22 00:30:06 +00:00
|
|
|
wmem_init_hashing();
|
2012-10-27 02:42:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
wmem_cleanup(void)
|
|
|
|
{
|
2012-11-03 15:49:15 +00:00
|
|
|
wmem_cleanup_scopes();
|
2012-10-27 02:42:05 +00:00
|
|
|
}
|
|
|
|
|
2012-10-24 02:04:40 +00:00
|
|
|
/*
|
2019-07-26 18:43:17 +00:00
|
|
|
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
2012-10-24 02:04:40 +00:00
|
|
|
*
|
|
|
|
* Local variables:
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
|
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
|
|
|
*/
|