forked from osmocom/wireshark
Redo r52569 in a way that doesn't break the GUI. Add a mem_pool member to
tree_data and reference it directly when allocating/freeing tree items. This lets us keep multiple around when we need them, and still lets us use wmem_free_all for a major speedup. It also, coincidentally, lets us get rid of the annoying fi_tmp hack that was needed before, since that element gets swept up in the free_all with everything else. Keep one pool cached to avoid creating/destroying a pool for each packet, another minor performance win. The various changes in approach seem to balance out pretty much exactly, this still gives ~11% over pre-52569. svn path=/trunk/; revision=52573
This commit is contained in:
parent
2e1497b532
commit
c2b2d204db
165
epan/proto.c
165
epan/proto.c
|
@ -252,28 +252,28 @@ struct _protocol {
|
|||
/* List of all protocols */
|
||||
static GList *protocols = NULL;
|
||||
|
||||
wmem_allocator_t *tree_pool = NULL;
|
||||
static wmem_allocator_t *tree_pool_cache = NULL;
|
||||
|
||||
/* Contains information about a field when a dissector calls
|
||||
* proto_tree_add_item. */
|
||||
#define FIELD_INFO_NEW(fi) fi = wmem_new(tree_pool, field_info)
|
||||
#define FIELD_INFO_FREE(fi) wmem_free(tree_pool, fi)
|
||||
#define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
|
||||
#define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
|
||||
|
||||
/* Contains the space for proto_nodes. */
|
||||
#define PROTO_NODE_NEW(node) \
|
||||
node = wmem_new(tree_pool, proto_node); \
|
||||
#define PROTO_NODE_NEW(pool, node) \
|
||||
node = wmem_new(pool, proto_node); \
|
||||
node->first_child = NULL; \
|
||||
node->last_child = NULL; \
|
||||
node->next = NULL;
|
||||
|
||||
#define PROTO_NODE_FREE(node) \
|
||||
wmem_free(tree_pool, node)
|
||||
#define PROTO_NODE_FREE(pool, node) \
|
||||
wmem_free(pool, node)
|
||||
|
||||
/* String space for protocol and field items for the GUI */
|
||||
#define ITEM_LABEL_NEW(il) \
|
||||
il = wmem_new(tree_pool, item_label_t);
|
||||
#define ITEM_LABEL_FREE(il) \
|
||||
wmem_free(tree_pool, il);
|
||||
#define ITEM_LABEL_NEW(pool, il) \
|
||||
il = wmem_new(pool, item_label_t);
|
||||
#define ITEM_LABEL_FREE(pool, il) \
|
||||
wmem_free(pool, il);
|
||||
|
||||
#define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
|
||||
if((guint)hfindex >= gpa_hfinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \
|
||||
|
@ -331,7 +331,6 @@ proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_da
|
|||
{
|
||||
proto_cleanup();
|
||||
|
||||
tree_pool = wmem_allocator_new(WMEM_ALLOCATOR_BLOCK);
|
||||
proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
|
||||
proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
|
||||
proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
|
||||
|
@ -405,10 +404,6 @@ proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_da
|
|||
void
|
||||
proto_cleanup(void)
|
||||
{
|
||||
if (tree_pool) {
|
||||
wmem_destroy_allocator(tree_pool);
|
||||
tree_pool = NULL;
|
||||
}
|
||||
/* Free the abbrev/ID GTree */
|
||||
if (gpa_name_tree) {
|
||||
g_tree_destroy(gpa_name_tree);
|
||||
|
@ -548,8 +543,25 @@ free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
|
|||
}
|
||||
|
||||
static void
|
||||
free_node_tree_data(tree_data_t *tree_data)
|
||||
proto_tree_free_node(proto_node *node, gpointer data _U_)
|
||||
{
|
||||
field_info *finfo = PNODE_FINFO(node);
|
||||
|
||||
proto_tree_children_foreach(node, proto_tree_free_node, NULL);
|
||||
|
||||
FVALUE_CLEANUP(&finfo->value);
|
||||
}
|
||||
|
||||
/* frees the resources that the dissection a proto_tree uses */
|
||||
void
|
||||
proto_tree_free(proto_tree *tree)
|
||||
{
|
||||
wmem_allocator_t *pool = PNODE_POOL(tree);
|
||||
tree_data_t *tree_data = PTREE_DATA(tree);
|
||||
|
||||
proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
|
||||
|
||||
/* free tree data */
|
||||
if (tree_data->interesting_hfids) {
|
||||
/* Free all the GPtrArray's in the interesting_hfids hash. */
|
||||
g_hash_table_foreach(tree_data->interesting_hfids,
|
||||
|
@ -558,48 +570,15 @@ free_node_tree_data(tree_data_t *tree_data)
|
|||
/* And then destroy the hash. */
|
||||
g_hash_table_destroy(tree_data->interesting_hfids);
|
||||
}
|
||||
if (tree_data->fi_tmp)
|
||||
FIELD_INFO_FREE(tree_data->fi_tmp);
|
||||
|
||||
/* And finally the tree_data_t itself. */
|
||||
g_free(tree_data);
|
||||
}
|
||||
|
||||
#define FREE_NODE_FIELD_INFO(finfo) \
|
||||
if (finfo->rep) { \
|
||||
ITEM_LABEL_FREE(finfo->rep); \
|
||||
} \
|
||||
FVALUE_CLEANUP(&finfo->value); \
|
||||
FIELD_INFO_FREE(finfo);
|
||||
|
||||
static void
|
||||
proto_tree_free_node(proto_node *node, gpointer data _U_)
|
||||
{
|
||||
field_info *finfo = PNODE_FINFO(node);
|
||||
|
||||
proto_tree_children_foreach(node, proto_tree_free_node, NULL);
|
||||
|
||||
/* free the field_info data. */
|
||||
FREE_NODE_FIELD_INFO(finfo);
|
||||
node->finfo = NULL;
|
||||
|
||||
/* Free the proto_node. */
|
||||
PROTO_NODE_FREE(node);
|
||||
}
|
||||
|
||||
/* frees the resources that the dissection a proto_tree uses */
|
||||
void
|
||||
proto_tree_free(proto_tree *tree)
|
||||
{
|
||||
tree_data_t *tree_data = PTREE_DATA(tree);
|
||||
|
||||
proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
|
||||
|
||||
/* free root node */
|
||||
PROTO_NODE_FREE(tree);
|
||||
|
||||
/* free tree data */
|
||||
free_node_tree_data(tree_data);
|
||||
if (tree_pool_cache) {
|
||||
/* if we already have one cached then just destroy it */
|
||||
wmem_destroy_allocator(pool);
|
||||
}
|
||||
else {
|
||||
wmem_free_all(pool);
|
||||
tree_pool_cache = pool;
|
||||
}
|
||||
}
|
||||
|
||||
/* Is the parsing being done for a visible proto_tree or an invisible one?
|
||||
|
@ -1054,27 +1033,12 @@ proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
|
|||
static void
|
||||
report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
|
||||
|
||||
tree_data_t *tree_data = NULL;
|
||||
field_info *fi_save = NULL;
|
||||
|
||||
if (tree) {
|
||||
tree_data = PTREE_DATA(tree);
|
||||
fi_save = tree_data->fi_tmp;
|
||||
|
||||
/* Keep the current item from getting freed by proto_tree_new_item. */
|
||||
tree_data->fi_tmp = NULL;
|
||||
}
|
||||
|
||||
if (is_error) {
|
||||
expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length);
|
||||
} else {
|
||||
expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length);
|
||||
}
|
||||
|
||||
if (tree) {
|
||||
tree_data->fi_tmp = fi_save;
|
||||
}
|
||||
|
||||
if (is_error) {
|
||||
THROW(ReportedBoundsError);
|
||||
}
|
||||
|
@ -1207,7 +1171,6 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
|
|||
tvbuff_t *tvb, gint start, gint length,
|
||||
guint encoding)
|
||||
{
|
||||
tree_data_t *tree_data = PTREE_DATA(tree);
|
||||
proto_item *pi;
|
||||
guint32 value, n;
|
||||
float floatval;
|
||||
|
@ -1218,24 +1181,6 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
|
|||
guint64 todsecs;
|
||||
gboolean length_error;
|
||||
|
||||
/* there is a possibility here that we might raise an exception
|
||||
* and thus would lose track of the field_info.
|
||||
* store it in a temp so that if we come here again we can reclaim
|
||||
* the field_info without leaking memory.
|
||||
*/
|
||||
if (tree_data->fi_tmp) {
|
||||
/* oops, last one we got must have been lost due
|
||||
* to an exception.
|
||||
* good thing we saved it, now we can reverse the
|
||||
* memory leak and reclaim it.
|
||||
*/
|
||||
FIELD_INFO_FREE(tree_data->fi_tmp);
|
||||
}
|
||||
/* we might throw an exception, keep track of this one
|
||||
* across the "dangerous" section below.
|
||||
*/
|
||||
tree_data->fi_tmp = new_fi;
|
||||
|
||||
switch (new_fi->hfinfo->type) {
|
||||
case FT_NONE:
|
||||
/* no value to set for FT_NONE */
|
||||
|
@ -1765,11 +1710,6 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
|
|||
* to know which item caused exception? */
|
||||
pi = proto_tree_add_node(tree, new_fi);
|
||||
|
||||
/* we did not raise an exception so we dont have to remember this
|
||||
* field_info struct any more.
|
||||
*/
|
||||
tree_data->fi_tmp = NULL;
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
|
@ -3344,7 +3284,7 @@ proto_tree_add_node(proto_tree *tree, field_info *fi)
|
|||
/* XXX - is it safe to continue here? */
|
||||
}
|
||||
|
||||
PROTO_NODE_NEW(pnode);
|
||||
PROTO_NODE_NEW(PNODE_POOL(tree), pnode);
|
||||
pnode->parent = tnode;
|
||||
PNODE_FINFO(pnode) = fi;
|
||||
pnode->tree_data = PTREE_DATA(tree);
|
||||
|
@ -3514,7 +3454,7 @@ new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
|
|||
{
|
||||
field_info *fi;
|
||||
|
||||
FIELD_INFO_NEW(fi);
|
||||
FIELD_INFO_NEW(PNODE_POOL(tree), fi);
|
||||
|
||||
fi->hfinfo = hfinfo;
|
||||
fi->start = start;
|
||||
|
@ -3577,7 +3517,7 @@ proto_tree_set_representation_value(proto_item *pi, const char *format, va_list
|
|||
|
||||
hf = fi->hfinfo;
|
||||
|
||||
ITEM_LABEL_NEW(fi->rep);
|
||||
ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
|
||||
if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
|
||||
guint32 val;
|
||||
char *p;
|
||||
|
@ -3619,7 +3559,7 @@ proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
|
|||
DISSECTOR_ASSERT(fi);
|
||||
|
||||
if (!PROTO_ITEM_IS_HIDDEN(pi)) {
|
||||
ITEM_LABEL_NEW(fi->rep);
|
||||
ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
|
||||
ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
|
||||
format, ap);
|
||||
if (ret >= ITEM_LABEL_LENGTH) {
|
||||
|
@ -3994,7 +3934,7 @@ proto_item_set_text(proto_item *pi, const char *format, ...)
|
|||
return;
|
||||
|
||||
if (fi->rep) {
|
||||
ITEM_LABEL_FREE(fi->rep);
|
||||
ITEM_LABEL_FREE(PNODE_POOL(pi), fi->rep);
|
||||
fi->rep = NULL;
|
||||
}
|
||||
|
||||
|
@ -4026,7 +3966,7 @@ proto_item_append_text(proto_item *pi, const char *format, ...)
|
|||
* generate the default representation.
|
||||
*/
|
||||
if (fi->rep == NULL) {
|
||||
ITEM_LABEL_NEW(fi->rep);
|
||||
ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
|
||||
proto_item_fill_label(fi, fi->rep->representation);
|
||||
}
|
||||
|
||||
|
@ -4063,7 +4003,7 @@ proto_item_prepend_text(proto_item *pi, const char *format, ...)
|
|||
* generate the default representation.
|
||||
*/
|
||||
if (fi->rep == NULL) {
|
||||
ITEM_LABEL_NEW(fi->rep);
|
||||
ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
|
||||
proto_item_fill_label(fi, representation);
|
||||
} else
|
||||
g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
|
||||
|
@ -4134,17 +4074,28 @@ proto_item_get_len(const proto_item *pi)
|
|||
proto_tree *
|
||||
proto_tree_create_root(packet_info *pinfo)
|
||||
{
|
||||
wmem_allocator_t *pool;
|
||||
proto_node *pnode;
|
||||
|
||||
if (tree_pool_cache) {
|
||||
pool = tree_pool_cache;
|
||||
tree_pool_cache = NULL;
|
||||
}
|
||||
else {
|
||||
pool = wmem_allocator_new(WMEM_ALLOCATOR_BLOCK);
|
||||
}
|
||||
|
||||
/* Initialize the proto_node */
|
||||
PROTO_NODE_NEW(pnode);
|
||||
PROTO_NODE_NEW(pool, pnode);
|
||||
pnode->parent = NULL;
|
||||
PNODE_FINFO(pnode) = NULL;
|
||||
pnode->tree_data = g_new(tree_data_t, 1);
|
||||
pnode->tree_data = wmem_new(pool, tree_data_t);
|
||||
|
||||
/* Make sure we can access pinfo everywhere */
|
||||
pnode->tree_data->pinfo = pinfo;
|
||||
|
||||
pnode->tree_data->mem_pool = pool;
|
||||
|
||||
/* Don't initialize the tree_data_t. Wait until we know we need it */
|
||||
pnode->tree_data->interesting_hfids = NULL;
|
||||
|
||||
|
@ -4160,8 +4111,6 @@ proto_tree_create_root(packet_info *pinfo)
|
|||
/* Keep track of the number of children */
|
||||
pnode->tree_data->count = 0;
|
||||
|
||||
pnode->tree_data->fi_tmp = NULL;
|
||||
|
||||
return (proto_tree *)pnode;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include <glib.h>
|
||||
|
||||
#include <epan/emem.h>
|
||||
#include <epan/wmem/wmem.h>
|
||||
|
||||
#include "ipv4.h"
|
||||
#include "wsutil/nstime.h"
|
||||
|
@ -485,7 +486,7 @@ typedef struct {
|
|||
gboolean fake_protocols;
|
||||
gint count;
|
||||
struct _packet_info *pinfo;
|
||||
field_info *fi_tmp;
|
||||
wmem_allocator_t *mem_pool;
|
||||
} tree_data_t;
|
||||
|
||||
/** Each proto_tree, proto_item is one of these. */
|
||||
|
@ -609,6 +610,9 @@ WS_DLL_PUBLIC void proto_tree_children_foreach(proto_tree *tree,
|
|||
/** Retrieve the tree_data_t from a proto_tree */
|
||||
#define PTREE_DATA(proto_tree) ((proto_tree)->tree_data)
|
||||
|
||||
/** Retrieve the wmem_allocator_t from a proto_node */
|
||||
#define PNODE_POOL(proto_node) ((proto_node)->tree_data->mem_pool)
|
||||
|
||||
/** Sets up memory used by proto routines. Called at program startup */
|
||||
void proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
|
||||
void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
|
||||
|
|
Loading…
Reference in New Issue