wireshark/wsutil/wmem/wmem_core.h

253 lines
8.8 KiB
C

/** @file
* Definitions for the 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
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef __WMEM_CORE_H__
#define __WMEM_CORE_H__
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <glib.h>
#include <ws_symbol_export.h>
#include <ws_attributes.h>
#include <ws_posix_compat.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/** @defgroup wmem Wireshark Memory Manager
*
* Wmem is a memory management framework for Wireshark that makes it simple to
* write dissectors (and other 'user-space' code) that doesn't leak memory. The
* core module provides basic functions like malloc, realloc and free, but
* many other functions are available (see the "Modules" list at the top of
* the generated doxygen HTML).
*
* Any wmem functions which allocate memory are guaranteed to either succeed or
* abort the program. However, they *can* still legally return NULL when the
* amount of requested memory is zero.
*
* @{
*/
struct _wmem_allocator_t;
/** A public opaque type representing one wmem allocation pool. */
typedef struct _wmem_allocator_t wmem_allocator_t;
/** An enumeration of the different types of available allocators. */
typedef enum _wmem_allocator_type_t {
WMEM_ALLOCATOR_SIMPLE, /**< A trivial allocator that mallocs requested
memory and tracks allocations via a hash table. As simple as
possible, intended more as a demo than for practical usage. Also
has the benefit of being friendly to tools like valgrind. */
WMEM_ALLOCATOR_BLOCK, /**< A block allocator that grabs large chunks of
memory at a time (8 MB currently) and serves allocations out of
those chunks. Designed for efficiency, especially in the
free_all operation. */
WMEM_ALLOCATOR_STRICT, /**< An allocator that does its best to find invalid
memory usage via things like canaries and scrubbing freed
memory. Valgrind is the better choice on platforms that support
it. */
WMEM_ALLOCATOR_BLOCK_FAST /**< A block allocator like WMEM_ALLOCATOR_BLOCK
but even faster by tracking absolutely minimal metadata and
making 'free' a no-op. Useful only for very short-lived scopes
where there's no reason to free individual allocations because
the next free_all is always just around the corner. */
} wmem_allocator_type_t;
/** Allocate the requested amount of memory in the given pool.
*
* @param allocator The allocator object to use to allocate the memory.
* @param size The amount of memory to allocate.
* @return A void pointer to the newly allocated memory.
*/
WS_DLL_PUBLIC
void *
wmem_alloc(wmem_allocator_t *allocator, const size_t size)
G_GNUC_MALLOC;
/** Allocate memory sufficient to hold one object of the given type.
*
* @param allocator The allocator object to use to allocate the memory.
* @param type The type that the newly allocated memory will hold.
* @return A void pointer to the newly allocated memory.
*/
#define wmem_new(allocator, type) \
((type*)wmem_alloc((allocator), sizeof(type)))
/*
* Overflow-safe multiplication of the size of a type by a number of
* items of that type, returning 0 if the result would overflow (or
* if the number of elements is negative), and the product otherwise.
*/
#define wmem_safe_mult_type_size(type, num) \
((((num) <= 0) || ((gsize)sizeof(type) > (G_MAXSSIZE / (gsize)(num)))) ? 0 : (sizeof(type) * (num)))
/** Allocate memory sufficient to hold n objects of the given type.
*
* @param allocator The allocator object to use to allocate the memory.
* @param type The type that the newly allocated memory will hold.
* @param num The number of objects that the newly allocated memory will hold.
* @return A void pointer to the newly allocated memory.
*/
#define wmem_alloc_array(allocator, type, num) \
((type*)wmem_alloc((allocator), wmem_safe_mult_type_size(type, (num))))
/** Allocate the requested amount of memory in the given pool. Initializes the
* allocated memory with zeroes.
*
* @param allocator The allocator object to use to allocate the memory.
* @param size The amount of memory to allocate.
* @return A void pointer to the newly allocated and zeroed memory.
*/
WS_DLL_PUBLIC
void *
wmem_alloc0(wmem_allocator_t *allocator, const size_t size)
G_GNUC_MALLOC;
/** Allocate memory sufficient to hold one object of the given type.
* Initializes the allocated memory with zeroes.
*
* @param allocator The allocator object to use to allocate the memory.
* @param type The type that the newly allocated memory will hold.
* @return A void pointer to the newly allocated and zeroed memory.
*/
#define wmem_new0(allocator, type) \
((type*)wmem_alloc0((allocator), sizeof(type)))
/** Allocate memory sufficient to hold n objects of the given type.
* Initializes the allocated memory with zeroes.
*
* @param allocator The allocator object to use to allocate the memory.
* @param type The type that the newly allocated memory will hold.
* @param num The number of objects that the newly allocated memory will hold.
* @return A void pointer to the newly allocated and zeroed memory.
*/
#define wmem_alloc0_array(allocator, type, num) \
((type*)wmem_alloc0((allocator), wmem_safe_mult_type_size(type, (num))))
/** Returns the allocated memory to the allocator. This function should only
* be called directly by allocators when the allocated block is sufficiently
* large that the reduced memory usage is worth the cost of the extra function
* call. It's usually easier to just let it get cleaned up when wmem_free_all()
* is called.
*
* @param allocator The allocator object used to originally allocate the memory.
* @param ptr The pointer to the memory block to free. After this function
* returns it no longer points to valid memory.
*/
WS_DLL_PUBLIC
void
wmem_free(wmem_allocator_t *allocator, void *ptr);
/** Resizes a block of memory, potentially moving it if resizing it in place
* is not possible.
*
* @param allocator The allocator object used to originally allocate the memory.
* @param ptr The pointer to the memory block to resize.
* @param size The new size for the memory block.
* @return The new location of the memory block. If this is different from ptr
* then ptr no longer points to valid memory.
*/
WS_DLL_PUBLIC
void *
wmem_realloc(wmem_allocator_t *allocator, void *ptr, const size_t size)
G_GNUC_MALLOC;
/** Frees all the memory allocated in a pool. Depending on the allocator
* implementation used this can be significantly cheaper than calling
* wmem_free() on all the individual blocks. It also doesn't require you to have
* external pointers to those blocks.
*
* @param allocator The allocator to free the memory from.
*/
WS_DLL_PUBLIC
void
wmem_free_all(wmem_allocator_t *allocator);
/** Triggers a garbage-collection in the allocator. This does not free any
* memory, but it can return unused blocks to the operating system or perform
* other optimizations.
*
* @param allocator The allocator in which to trigger the garbage collection.
*/
WS_DLL_PUBLIC
void
wmem_gc(wmem_allocator_t *allocator);
/** Destroy the given allocator, freeing all memory allocated in it. Once this
* function has been called, no memory allocated with the allocator is valid.
*
* @param allocator The allocator to destroy.
*/
WS_DLL_PUBLIC
void
wmem_destroy_allocator(wmem_allocator_t *allocator);
/** Create a new allocator of the given type. The type may be overridden by the
* WIRESHARK_DEBUG_WMEM_OVERRIDE environment variable.
*
* @param type The type of allocator to create.
* @return The new allocator.
*/
WS_DLL_PUBLIC
wmem_allocator_t *
wmem_allocator_new(const wmem_allocator_type_t type);
/** Initialize the wmem subsystem. This must be called before any other wmem
* function, usually at the very beginning of your program.
*/
WS_DLL_PUBLIC
void
wmem_init(void);
/** Teardown the wmem subsystem. This must be called after all other wmem
* functions, usually at the very end of your program. This function will not
* destroy outstanding allocators, you must do that yourself.
*/
WS_DLL_PUBLIC
void
wmem_cleanup(void);
WS_DLL_PUBLIC
void
wmem_enter_scope(wmem_allocator_t *allocator);
WS_DLL_PUBLIC
void
wmem_leave_scope(wmem_allocator_t *allocator);
WS_DLL_PUBLIC
gboolean
wmem_in_scope(wmem_allocator_t *allocator);
/** @} */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __WMEM_CORE_H__ */
/*
* 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:
*/