diff --git a/src/context.c b/src/context.c index a861273d..4985aaff 100644 --- a/src/context.c +++ b/src/context.c @@ -46,6 +46,8 @@ #include "types-internal.h" #include "util-internal.h" +void *plain_mem_funcs_user_arg = MF_PLAIN; + /* Private functions */ static uint16_t *create_default_namespaces(struct getdns_context *context); static struct getdns_list *create_default_root_servers(); @@ -256,9 +258,11 @@ getdns_context_create_with_memory_functions(struct getdns_context ** context, } result->update_callback = NULL; - result->malloc = malloc; - result->realloc = realloc; - result->free = free; + + result->mf_arg = MF_PLAIN; + result->mf.pln.malloc = malloc; + result->mf.pln.realloc = realloc; + result->mf.pln.free = free; result->event_base_sync = event_base_new(); result->unbound_sync = ub_ctx_create_event(result->event_base_sync); @@ -800,9 +804,10 @@ getdns_context_set_memory_functions(struct getdns_context *context, if (!malloc || !realloc || !free) return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; - context->malloc = malloc; - context->realloc = realloc; - context->free = free; + context->mf_arg = MF_PLAIN; + context->mf.pln.malloc = malloc; + context->mf.pln.realloc = realloc; + context->mf.pln.free = free; dispatch_updated(context, GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS); diff --git a/src/context.h b/src/context.h index 2a04b147..1e5f3964 100644 --- a/src/context.h +++ b/src/context.h @@ -31,6 +31,7 @@ #define _GETDNS_CONTEXT_H_ #include +#include "types-internal.h" struct event_base; struct getdns_dns_req; @@ -58,9 +59,8 @@ struct getdns_context { uint8_t edns_do_bit; getdns_update_callback update_callback; - void *(*malloc)(size_t); - void *(*realloc)(void *, size_t); - void (*free)(void *); + void *mf_arg; + mem_funcs mf; /* Event loop for sync requests */ struct event_base *event_base_sync; diff --git a/src/dict.c b/src/dict.c index 0592ec32..97345010 100644 --- a/src/dict.c +++ b/src/dict.c @@ -64,7 +64,7 @@ getdns_dict_find(struct getdns_dict *dict, char *key, int addifnotfnd) if (!item && addifnotfnd) { /* tsearch will add a node automatically for us */ item = GETDNS_MALLOC(dict, struct getdns_dict_item); - item->node.key = getdns_strdup(dict->malloc, key); + item->node.key = getdns_strdup(dict->mf.pln.malloc, key); item->data.n = 0; ldns_rbtree_insert(&(dict->root), (ldns_rbnode_t *) item); } @@ -84,7 +84,7 @@ getdns_dict_get_names(struct getdns_dict * dict, struct getdns_list ** answer) return GETDNS_RETURN_NO_SUCH_DICT_NAME; *answer = getdns_list_create_with_memory_functions( - dict->malloc, dict->realloc, dict->free); + dict->mf.pln.malloc, dict->mf.pln.realloc, dict->mf.pln.free); if (!*answer) return GETDNS_RETURN_NO_SUCH_DICT_NAME; @@ -200,9 +200,11 @@ getdns_dict_create_with_memory_functions(void *(*malloc)(size_t), if (!dict) return NULL; - dict->malloc = malloc; - dict->realloc = realloc; - dict->free = free; + dict->mf_arg = MF_PLAIN; + dict->mf.pln.malloc = malloc; + dict->mf.pln.realloc = realloc; + dict->mf.pln.free = free; + ldns_rbtree_init(&(dict->root), (int (*)(const void *, const void *)) strcmp); return dict; @@ -214,8 +216,9 @@ struct getdns_dict * getdns_dict_create_with_context(struct getdns_context *context) { if (context) - return getdns_dict_create_with_memory_functions(context->malloc, - context->realloc, context->free); + return getdns_dict_create_with_memory_functions( + context->mf.pln.malloc, + context->mf.pln.realloc, context->mf.pln.free); else return getdns_dict_create_with_memory_functions(&malloc, &realloc, &free); @@ -252,7 +255,7 @@ getdns_dict_copy(struct getdns_dict * srcdict, struct getdns_dict ** dstdict) return GETDNS_RETURN_GOOD; } *dstdict = getdns_dict_create_with_memory_functions( - srcdict->malloc, srcdict->realloc, srcdict->free); + srcdict->mf.pln.malloc, srcdict->mf.pln.realloc, srcdict->mf.pln.free); if (!*dstdict) return GETDNS_RETURN_NO_SUCH_DICT_NAME; @@ -306,7 +309,7 @@ getdns_dict_item_free(ldns_rbnode_t * node, void *arg) switch (item->dtype) { case t_bindata: - getdns_bindata_destroy(dict->free, item->data.bindata); + getdns_bindata_destroy(dict->mf.pln.free, item->data.bindata); break; case t_dict: getdns_dict_destroy(item->data.dict); @@ -398,13 +401,13 @@ getdns_dict_set_bindata(struct getdns_dict * dict, char *name, return GETDNS_RETURN_NO_SUCH_DICT_NAME; newbindata = getdns_bindata_copy( - dict->malloc, dict->free, child_bindata); + dict->mf.pln.malloc, dict->mf.pln.free, child_bindata); if (!newbindata) return GETDNS_RETURN_NO_SUCH_DICT_NAME; item = getdns_dict_find(dict, name, 1); if (!item) { - getdns_bindata_destroy(dict->free, newbindata); + getdns_bindata_destroy(dict->mf.pln.free, newbindata); return GETDNS_RETURN_NO_SUCH_DICT_NAME; } item->dtype = t_bindata; diff --git a/src/dict.h b/src/dict.h index 26a72f96..c21a7bff 100644 --- a/src/dict.h +++ b/src/dict.h @@ -37,6 +37,7 @@ #include #include +#include "types-internal.h" union getdns_item { @@ -66,9 +67,8 @@ struct getdns_dict_item struct getdns_dict { ldns_rbtree_t root; - void *(*malloc)(size_t); - void *(*realloc)(void *, size_t); - void (*free)(void *); + void *mf_arg; + mem_funcs mf; }; #endif diff --git a/src/getdns/getdns.h b/src/getdns/getdns.h index 121aadd8..0ef5c5f3 100644 --- a/src/getdns/getdns.h +++ b/src/getdns/getdns.h @@ -506,8 +506,16 @@ getdns_return_t getdns_dict_get_int(struct getdns_dict *this_dict, char *name, struct getdns_list *getdns_list_create(); struct getdns_list *getdns_list_create_with_context(struct getdns_context *context); struct getdns_list *getdns_list_create_with_memory_functions( - void *(*malloc) (size_t), void *(*realloc) (void *, size_t), - void (*free) (void *)); + void *(*malloc) (size_t), + void *(*realloc) (void *, size_t), + void (*free) (void *) +); +struct getdns_list *getdns_list_create_with_extended_memory_functions( + void *userarg, + void *(*malloc) (void *userarg, size_t), + void *(*realloc) (void *userarg, void *, size_t), + void (*free) (void *userarg, void *) +); /** * free memory allocated to the list (also frees all children of the list) @@ -567,8 +575,16 @@ getdns_return_t getdns_list_set_int(struct getdns_list *this_list, size_t index, struct getdns_dict *getdns_dict_create(); struct getdns_dict *getdns_dict_create_with_context(struct getdns_context *context); struct getdns_dict *getdns_dict_create_with_memory_functions( - void *(*malloc) (size_t), void *(*realloc) (void *, size_t), - void (*free) (void *)); + void *(*malloc) (size_t), + void *(*realloc) (void *, size_t), + void (*free) (void *) +); +struct getdns_dict *getdns_dict_create_with_extended_memory_functions( + void *userarg, + void *(*malloc) (void *userarg, size_t), + void *(*realloc) (void *userarg, void *, size_t), + void (*free) (void *userarg, void *) +); /** * destroy a dictionary and all items within that dictionary @@ -643,16 +659,27 @@ getdns_service(struct getdns_context *context, void *userarg, getdns_transaction_t * transaction_id, getdns_callback_t callbackfn); -getdns_return_t getdns_context_create_with_memory_functions( +getdns_return_t +getdns_context_create(struct getdns_context ** context, int set_from_os); + +getdns_return_t +getdns_context_create_with_memory_functions( struct getdns_context ** context, int set_from_os, void *(*malloc) (size_t), void *(*realloc) (void *, size_t), void (*free) (void *) - ); +); -getdns_return_t getdns_context_create(struct getdns_context ** context, - int set_from_os); +getdns_return_t +getdns_context_create_with_extended_memory_functions( + struct getdns_context **context, + int set_from_os, + void *userarg, + void *(*malloc) (void *userarg, size_t), + void *(*realloc) (void *userarg, void *, size_t), + void (*free) (void *userarg, void *) +); void getdns_context_destroy(struct getdns_context *context); @@ -832,6 +859,14 @@ getdns_context_set_memory_functions(struct getdns_context *context, void (*free) (void *) ); +getdns_return_t +getdns_context_set_extended_memory_functions(struct getdns_context *context, + void *userarg, + void *(*malloc) (void *userarg, size_t sz), + void *(*realloc) (void *userarg, void *ptr, size_t sz), + void (*free) (void *userarg, void *ptr) + ); + /* Extension - refactor to abstract async evt loop */ /* For libevent, which we are using for these examples */ getdns_return_t diff --git a/src/list.c b/src/list.c index c3890487..70099bfb 100644 --- a/src/list.c +++ b/src/list.c @@ -165,7 +165,7 @@ getdns_list_copy(struct getdns_list * srclist, struct getdns_list ** dstlist) return GETDNS_RETURN_GOOD; } *dstlist = getdns_list_create_with_memory_functions( - srclist->malloc, srclist->realloc, srclist->free); + srclist->mf.pln.malloc, srclist->mf.pln.realloc, srclist->mf.pln.free); if (!dstlist) return GETDNS_RETURN_NO_SUCH_LIST_ITEM; @@ -219,9 +219,11 @@ getdns_list_create_with_memory_functions(void *(*malloc)(size_t), if (!list) return NULL; - list->malloc = malloc; - list->realloc = realloc; - list->free = free; + list->mf_arg = MF_PLAIN; + list->mf.pln.malloc = malloc; + list->mf.pln.realloc = realloc; + list->mf.pln.free = free; + list->numalloc = 0; list->numinuse = 0; list->items = NULL; @@ -237,8 +239,9 @@ struct getdns_list * getdns_list_create_with_context(struct getdns_context *context) { if (context) - return getdns_list_create_with_memory_functions(context->malloc, - context->realloc, context->free); + return getdns_list_create_with_memory_functions( + context->mf.pln.malloc, + context->mf.pln.realloc, context->mf.pln.free); else return getdns_list_create_with_memory_functions(malloc, realloc, free); @@ -271,7 +274,7 @@ getdns_list_destroy(struct getdns_list *list) break; case t_bindata: - getdns_bindata_destroy(list->free, + getdns_bindata_destroy(list->mf.pln.free, list->items[i].data.bindata); break; @@ -375,7 +378,7 @@ getdns_list_set_bindata(struct getdns_list * list, size_t index, return GETDNS_RETURN_NO_SUCH_LIST_ITEM; newbindata = getdns_bindata_copy( - list->malloc, list->free, child_bindata); + list->mf.pln.malloc, list->mf.pln.free, child_bindata); if (!newbindata) return GETDNS_RETURN_NO_SUCH_LIST_ITEM; diff --git a/src/list.h b/src/list.h index d5267769..88d5b02b 100644 --- a/src/list.h +++ b/src/list.h @@ -31,6 +31,7 @@ #define _GETDNS_LIST_H_ #include +#include "types-internal.h" #define GETDNS_LIST_BLOCKSZ 10 @@ -63,10 +64,8 @@ struct getdns_list int numalloc; int numinuse; struct getdns_list_item *items; - void *(*malloc)(size_t); - void *(*realloc)(void *, size_t); - void (*free)(void *); + void *mf_arg; + mem_funcs mf; }; - #endif diff --git a/src/request-internal.c b/src/request-internal.c index 093a90db..edbd85f6 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -44,10 +44,6 @@ #include "util-internal.h" #include -/* useful macros */ -#define gd_malloc(sz) context->malloc(sz) -#define gd_free(ptr) context->free(ptr) - void network_req_free(getdns_network_req * net_req) { @@ -58,7 +54,7 @@ network_req_free(getdns_network_req * net_req) if (net_req->result) { ldns_pkt_free(net_req->result); } - gd_free(net_req); + GETDNS_FREE(context, net_req); } getdns_network_req * @@ -68,7 +64,8 @@ network_req_new(getdns_dns_req * owner, { struct getdns_context *context = owner->context; - getdns_network_req *net_req = gd_malloc(sizeof(getdns_network_req)); + getdns_network_req *net_req = GETDNS_MALLOC( context + , getdns_network_req); if (!net_req) { return NULL; } @@ -120,7 +117,7 @@ dns_req_free(getdns_dns_req * req) /* free strduped name */ free(req->name); - gd_free(req); + GETDNS_FREE(context, req); } /* create a new dns req to be submitted */ @@ -135,7 +132,7 @@ dns_req_new(struct getdns_context *context, getdns_return_t r; uint32_t both = GETDNS_EXTENSION_FALSE; - result = gd_malloc(sizeof(getdns_dns_req)); + result = GETDNS_MALLOC(context, getdns_dns_req); if (result == NULL) { return NULL; } diff --git a/src/types-internal.h b/src/types-internal.h index 2859f6d2..59709572 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -36,8 +36,9 @@ #ifndef TYPES_INTERNAL_H_ #define TYPES_INTERNAL_H_ -#include "context.h" +#include #include +struct getdns_context; /** * \defgroup strings String Constants @@ -175,16 +176,43 @@ typedef struct getdns_dns_req } getdns_dns_req; +#define MF_PLAIN ((void *)&plain_mem_funcs_user_arg) +extern void *plain_mem_funcs_user_arg; + +typedef union { + struct { + void *(*malloc)(size_t); + void *(*realloc)(void *, size_t); + void (*free)(void *); + } pln; + struct { + void *(*malloc)(void *userarg, size_t); + void *(*realloc)(void *userarg, void *, size_t); + void (*free)(void *userarg, void *); + } ext; +} mem_funcs; + #define GETDNS_XMALLOC(obj, type, count) \ - ((obj) ? ((type *) (*(obj)->malloc)((count)*sizeof(type))) \ - : ((type *) malloc ((count)*sizeof(type)))) + ((!(obj)) ? ((type *)malloc((count)*sizeof(type))) \ + : ((obj)->mf_arg == MF_PLAIN \ + ? ((type *)(*(obj)->mf.pln.malloc)( (count)*sizeof(type))) \ + : ((type *)(*(obj)->mf.ext.malloc)((obj)->mf_arg, (count)*sizeof(type))) \ + )) #define GETDNS_XREALLOC(obj, ptr, type, count) \ - ((obj) ? ((type *) (*(obj)->realloc)((ptr),(count)*sizeof(type))) \ - : ((type *) realloc ((ptr),(count)*sizeof(type)))) + ((!(obj)) ? ((type *)realloc((ptr), (count)*sizeof(type))) \ + : ((obj)->mf_arg == MF_PLAIN \ + ? ((type *)(*(obj)->mf.pln.realloc)( (ptr), (count)*sizeof(type))) \ + : ((type *)(*(obj)->mf.ext.realloc)( (obj)->mf_arg \ + , (ptr), (count)*sizeof(type))) \ + )) -#define GETDNS_FREE(obj, ptr) \ - ((obj) ? ((*(obj)->free)(ptr)) : free(ptr)) +#define GETDNS_FREE(obj, ptr) \ + ((!(obj)) ? free(ptr) \ + : ((obj)->mf_arg == MF_PLAIN \ + ? ((*(obj)->mf.pln.free)( (ptr))) \ + : ((*(obj)->mf.ext.free)((obj)->mf_arg, (ptr))) \ + )) #define GETDNS_MALLOC(obj, type) GETDNS_XMALLOC(obj, type, 1) #define GETDNS_REALLOC(obj, ptr, type) GETDNS_XREALLOC(obj, ptr, type, 1);