X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_eal%2Fcommon%2Feal_common_memalloc.c;h=e872c6533b3d269fd775ec54c489cc4bdb8cc6f3;hb=e863fe3a13da89787fdf3b5c590101a3c0f10af6;hp=2d2d46f0abf010bcb9b2c1dd233091901597e5c5;hpb=56efb4c117537fed58c6a7ebc7dc148464b4e8c8;p=dpdk.git diff --git a/lib/librte_eal/common/eal_common_memalloc.c b/lib/librte_eal/common/eal_common_memalloc.c index 2d2d46f0ab..e872c6533b 100644 --- a/lib/librte_eal/common/eal_common_memalloc.c +++ b/lib/librte_eal/common/eal_common_memalloc.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include "eal_private.h" @@ -20,23 +20,48 @@ struct mem_event_callback_entry { TAILQ_ENTRY(mem_event_callback_entry) next; char name[RTE_MEM_EVENT_CALLBACK_NAME_LEN]; rte_mem_event_callback_t clb; + void *arg; +}; + +struct mem_alloc_validator_entry { + TAILQ_ENTRY(mem_alloc_validator_entry) next; + char name[RTE_MEM_ALLOC_VALIDATOR_NAME_LEN]; + rte_mem_alloc_validator_t clb; + int socket_id; + size_t limit; }; /** Double linked list of actions. */ TAILQ_HEAD(mem_event_callback_entry_list, mem_event_callback_entry); +TAILQ_HEAD(mem_alloc_validator_entry_list, mem_alloc_validator_entry); static struct mem_event_callback_entry_list mem_event_callback_list = TAILQ_HEAD_INITIALIZER(mem_event_callback_list); - static rte_rwlock_t mem_event_rwlock = RTE_RWLOCK_INITIALIZER; +static struct mem_alloc_validator_entry_list mem_alloc_validator_list = + TAILQ_HEAD_INITIALIZER(mem_alloc_validator_list); +static rte_rwlock_t mem_alloc_validator_rwlock = RTE_RWLOCK_INITIALIZER; + static struct mem_event_callback_entry * -find_mem_event_callback(const char *name) +find_mem_event_callback(const char *name, void *arg) { struct mem_event_callback_entry *r; TAILQ_FOREACH(r, &mem_event_callback_list, next) { - if (!strcmp(r->name, name)) + if (!strcmp(r->name, name) && r->arg == arg) + break; + } + return r; +} + +static struct mem_alloc_validator_entry * +find_mem_alloc_validator(const char *name, int socket_id) +{ + struct mem_alloc_validator_entry *r; + + TAILQ_FOREACH(r, &mem_alloc_validator_list, next) { + if (!strcmp(r->name, name) && r->socket_id == socket_id) break; } return r; @@ -49,13 +74,15 @@ eal_memalloc_is_contig(const struct rte_memseg_list *msl, void *start, void *end, *aligned_start, *aligned_end; size_t pgsz = (size_t)msl->page_sz; const struct rte_memseg *ms; + const struct internal_config *internal_conf = + eal_get_internal_configuration(); /* for IOVA_VA, it's always contiguous */ - if (rte_eal_iova_mode() == RTE_IOVA_VA) + if (rte_eal_iova_mode() == RTE_IOVA_VA && !msl->external) return true; /* for legacy memory, it's always contiguous */ - if (internal_config.legacy_mem) + if (internal_conf->legacy_mem) return true; end = RTE_PTR_ADD(start, len); @@ -121,7 +148,7 @@ eal_memalloc_is_contig(const struct rte_memseg_list *msl, void *start, int eal_memalloc_mem_event_callback_register(const char *name, - rte_mem_event_callback_t clb) + rte_mem_event_callback_t clb, void *arg) { struct mem_event_callback_entry *entry; int ret, len; @@ -139,7 +166,7 @@ eal_memalloc_mem_event_callback_register(const char *name, } rte_rwlock_write_lock(&mem_event_rwlock); - entry = find_mem_event_callback(name); + entry = find_mem_event_callback(name, arg); if (entry != NULL) { rte_errno = EEXIST; ret = -1; @@ -155,12 +182,14 @@ eal_memalloc_mem_event_callback_register(const char *name, /* callback successfully created and is valid, add it to the list */ entry->clb = clb; - snprintf(entry->name, RTE_MEM_EVENT_CALLBACK_NAME_LEN, "%s", name); + entry->arg = arg; + strlcpy(entry->name, name, RTE_MEM_EVENT_CALLBACK_NAME_LEN); TAILQ_INSERT_TAIL(&mem_event_callback_list, entry, next); ret = 0; - RTE_LOG(DEBUG, EAL, "Mem event callback '%s' registered\n", name); + RTE_LOG(DEBUG, EAL, "Mem event callback '%s:%p' registered\n", + name, arg); unlock: rte_rwlock_write_unlock(&mem_event_rwlock); @@ -168,7 +197,7 @@ unlock: } int -eal_memalloc_mem_event_callback_unregister(const char *name) +eal_memalloc_mem_event_callback_unregister(const char *name, void *arg) { struct mem_event_callback_entry *entry; int ret, len; @@ -187,7 +216,7 @@ eal_memalloc_mem_event_callback_unregister(const char *name) } rte_rwlock_write_lock(&mem_event_rwlock); - entry = find_mem_event_callback(name); + entry = find_mem_event_callback(name, arg); if (entry == NULL) { rte_errno = ENOENT; ret = -1; @@ -198,7 +227,8 @@ eal_memalloc_mem_event_callback_unregister(const char *name) ret = 0; - RTE_LOG(DEBUG, EAL, "Mem event callback '%s' unregistered\n", name); + RTE_LOG(DEBUG, EAL, "Mem event callback '%s:%p' unregistered\n", + name, arg); unlock: rte_rwlock_write_unlock(&mem_event_rwlock); @@ -214,10 +244,122 @@ eal_memalloc_mem_event_notify(enum rte_mem_event event, const void *start, rte_rwlock_read_lock(&mem_event_rwlock); TAILQ_FOREACH(entry, &mem_event_callback_list, next) { - RTE_LOG(DEBUG, EAL, "Calling mem event callback %s", - entry->name); - entry->clb(event, start, len); + RTE_LOG(DEBUG, EAL, "Calling mem event callback '%s:%p'\n", + entry->name, entry->arg); + entry->clb(event, start, len, entry->arg); } rte_rwlock_read_unlock(&mem_event_rwlock); } + +int +eal_memalloc_mem_alloc_validator_register(const char *name, + rte_mem_alloc_validator_t clb, int socket_id, size_t limit) +{ + struct mem_alloc_validator_entry *entry; + int ret, len; + if (name == NULL || clb == NULL || socket_id < 0) { + rte_errno = EINVAL; + return -1; + } + len = strnlen(name, RTE_MEM_ALLOC_VALIDATOR_NAME_LEN); + if (len == 0) { + rte_errno = EINVAL; + return -1; + } else if (len == RTE_MEM_ALLOC_VALIDATOR_NAME_LEN) { + rte_errno = ENAMETOOLONG; + return -1; + } + rte_rwlock_write_lock(&mem_alloc_validator_rwlock); + + entry = find_mem_alloc_validator(name, socket_id); + if (entry != NULL) { + rte_errno = EEXIST; + ret = -1; + goto unlock; + } + + entry = malloc(sizeof(*entry)); + if (entry == NULL) { + rte_errno = ENOMEM; + ret = -1; + goto unlock; + } + + /* callback successfully created and is valid, add it to the list */ + entry->clb = clb; + entry->socket_id = socket_id; + entry->limit = limit; + strlcpy(entry->name, name, RTE_MEM_ALLOC_VALIDATOR_NAME_LEN); + TAILQ_INSERT_TAIL(&mem_alloc_validator_list, entry, next); + + ret = 0; + + RTE_LOG(DEBUG, EAL, "Mem alloc validator '%s' on socket %i with limit %zu registered\n", + name, socket_id, limit); + +unlock: + rte_rwlock_write_unlock(&mem_alloc_validator_rwlock); + return ret; +} + +int +eal_memalloc_mem_alloc_validator_unregister(const char *name, int socket_id) +{ + struct mem_alloc_validator_entry *entry; + int ret, len; + + if (name == NULL || socket_id < 0) { + rte_errno = EINVAL; + return -1; + } + len = strnlen(name, RTE_MEM_ALLOC_VALIDATOR_NAME_LEN); + if (len == 0) { + rte_errno = EINVAL; + return -1; + } else if (len == RTE_MEM_ALLOC_VALIDATOR_NAME_LEN) { + rte_errno = ENAMETOOLONG; + return -1; + } + rte_rwlock_write_lock(&mem_alloc_validator_rwlock); + + entry = find_mem_alloc_validator(name, socket_id); + if (entry == NULL) { + rte_errno = ENOENT; + ret = -1; + goto unlock; + } + TAILQ_REMOVE(&mem_alloc_validator_list, entry, next); + free(entry); + + ret = 0; + + RTE_LOG(DEBUG, EAL, "Mem alloc validator '%s' on socket %i unregistered\n", + name, socket_id); + +unlock: + rte_rwlock_write_unlock(&mem_alloc_validator_rwlock); + return ret; +} + +int +eal_memalloc_mem_alloc_validate(int socket_id, size_t new_len) +{ + struct mem_alloc_validator_entry *entry; + int ret = 0; + + rte_rwlock_read_lock(&mem_alloc_validator_rwlock); + + TAILQ_FOREACH(entry, &mem_alloc_validator_list, next) { + if (entry->socket_id != socket_id || entry->limit > new_len) + continue; + RTE_LOG(DEBUG, EAL, "Calling mem alloc validator '%s' on socket %i\n", + entry->name, entry->socket_id); + if (entry->clb(socket_id, entry->limit, new_len) < 0) + ret = -1; + } + + rte_rwlock_read_unlock(&mem_alloc_validator_rwlock); + + return ret; +}