wireshark/epan/wmem_scopes.c

168 lines
3.8 KiB
C

/* wmem_scopes.c
* Wireshark Memory Manager Scopes
* Copyright 2012, Evan Huus <eapache@gmail.com>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <glib.h>
#include "wmem_scopes.h"
#include <wsutil/ws_assert.h>
/* One of the supposed benefits of wmem over the old emem was going to be that
* the scoping of the various memory pools would be obvious, since they would
* no longer be global. Instead, the pools would be managed as variables scoped
* by the compiler, so functions outside of that scope wouldn't have access to
* the pools and wouldn't be able to allocate memory in a scope to which they
* didn't belong.
*
* That idea fell apart rather quickly :P
*
* The principle still stands, and most pools should be managed in that way.
* The three in this file are *exceptions*. They are the three scopes that emem
* provided as globals. Converting all of the code that used them to pass an
* extra parameter (or three) around would have been a nightmare of epic
* proportions, so we provide these three as globals still.
*
* We do, however, use some extra booleans and a mountain of assertions to try
* and catch anybody accessing the pools out of the correct scope. It's not
* perfect, but it should stop most of the bad behaviour that emem permitted.
*/
/* TODO: Make these thread-local */
static wmem_allocator_t *packet_scope = NULL;
static wmem_allocator_t *file_scope = NULL;
static wmem_allocator_t *epan_scope = NULL;
/* Packet Scope */
wmem_allocator_t *
wmem_packet_scope(void)
{
ws_assert(packet_scope);
return packet_scope;
}
void
wmem_enter_packet_scope(void)
{
ws_assert(packet_scope);
ws_assert(wmem_in_scope(file_scope));
ws_assert(!wmem_in_scope(packet_scope));
wmem_enter_scope(packet_scope);
}
void
wmem_leave_packet_scope(void)
{
ws_assert(packet_scope);
ws_assert(wmem_in_scope(packet_scope));
wmem_leave_scope(packet_scope);
}
/* File Scope */
wmem_allocator_t *
wmem_file_scope(void)
{
ws_assert(file_scope);
return file_scope;
}
void
wmem_enter_file_scope(void)
{
ws_assert(file_scope);
ws_assert(!wmem_in_scope(file_scope));
wmem_enter_scope(file_scope);
}
void
wmem_leave_file_scope(void)
{
ws_assert(file_scope);
ws_assert(wmem_in_scope(file_scope));
ws_assert(!wmem_in_scope(packet_scope));
wmem_leave_scope(file_scope);
/* this seems like a good time to do garbage collection */
wmem_gc(file_scope);
wmem_gc(packet_scope);
}
/* Epan Scope */
wmem_allocator_t *
wmem_epan_scope(void)
{
ws_assert(epan_scope);
return epan_scope;
}
/* Scope Management */
void
wmem_init_scopes(void)
{
ws_assert(packet_scope == NULL);
ws_assert(file_scope == NULL);
ws_assert(epan_scope == NULL);
wmem_init();
packet_scope = wmem_allocator_new(WMEM_ALLOCATOR_BLOCK_FAST);
file_scope = wmem_allocator_new(WMEM_ALLOCATOR_BLOCK);
epan_scope = wmem_allocator_new(WMEM_ALLOCATOR_BLOCK);
/* Scopes are initialized to TRUE by default on creation */
wmem_leave_scope(packet_scope);
wmem_leave_scope(file_scope);
}
void
wmem_cleanup_scopes(void)
{
ws_assert(packet_scope);
ws_assert(file_scope);
ws_assert(epan_scope);
ws_assert(!wmem_in_scope(packet_scope));
ws_assert(!wmem_in_scope(file_scope));
wmem_destroy_allocator(packet_scope);
wmem_destroy_allocator(file_scope);
wmem_destroy_allocator(epan_scope);
wmem_cleanup();
packet_scope = NULL;
file_scope = NULL;
epan_scope = NULL;
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* 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:
*/