199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson * Copyright(c) 2017-2018 Intel Corporation
399a2dd95SBruce Richardson */
499a2dd95SBruce Richardson
572b452c5SDmitry Kozlyuk #include <stdlib.h>
699a2dd95SBruce Richardson #include <string.h>
799a2dd95SBruce Richardson
899a2dd95SBruce Richardson #include <rte_errno.h>
999a2dd95SBruce Richardson #include <rte_fbarray.h>
1099a2dd95SBruce Richardson #include <rte_memory.h>
1199a2dd95SBruce Richardson #include <rte_string_fns.h>
1299a2dd95SBruce Richardson
1399a2dd95SBruce Richardson #include "eal_private.h"
1499a2dd95SBruce Richardson #include "eal_internal_cfg.h"
1599a2dd95SBruce Richardson #include "eal_memalloc.h"
1699a2dd95SBruce Richardson
1799a2dd95SBruce Richardson struct mem_event_callback_entry {
1899a2dd95SBruce Richardson TAILQ_ENTRY(mem_event_callback_entry) next;
1999a2dd95SBruce Richardson char name[RTE_MEM_EVENT_CALLBACK_NAME_LEN];
2099a2dd95SBruce Richardson rte_mem_event_callback_t clb;
2199a2dd95SBruce Richardson void *arg;
2299a2dd95SBruce Richardson };
2399a2dd95SBruce Richardson
2499a2dd95SBruce Richardson struct mem_alloc_validator_entry {
2599a2dd95SBruce Richardson TAILQ_ENTRY(mem_alloc_validator_entry) next;
2699a2dd95SBruce Richardson char name[RTE_MEM_ALLOC_VALIDATOR_NAME_LEN];
2799a2dd95SBruce Richardson rte_mem_alloc_validator_t clb;
2899a2dd95SBruce Richardson int socket_id;
2999a2dd95SBruce Richardson size_t limit;
3099a2dd95SBruce Richardson };
3199a2dd95SBruce Richardson
3299a2dd95SBruce Richardson /** Double linked list of actions. */
3399a2dd95SBruce Richardson TAILQ_HEAD(mem_event_callback_entry_list, mem_event_callback_entry);
3499a2dd95SBruce Richardson TAILQ_HEAD(mem_alloc_validator_entry_list, mem_alloc_validator_entry);
3599a2dd95SBruce Richardson
3699a2dd95SBruce Richardson static struct mem_event_callback_entry_list mem_event_callback_list =
3799a2dd95SBruce Richardson TAILQ_HEAD_INITIALIZER(mem_event_callback_list);
3899a2dd95SBruce Richardson static rte_rwlock_t mem_event_rwlock = RTE_RWLOCK_INITIALIZER;
3999a2dd95SBruce Richardson
4099a2dd95SBruce Richardson static struct mem_alloc_validator_entry_list mem_alloc_validator_list =
4199a2dd95SBruce Richardson TAILQ_HEAD_INITIALIZER(mem_alloc_validator_list);
4299a2dd95SBruce Richardson static rte_rwlock_t mem_alloc_validator_rwlock = RTE_RWLOCK_INITIALIZER;
4399a2dd95SBruce Richardson
4499a2dd95SBruce Richardson static struct mem_event_callback_entry *
find_mem_event_callback(const char * name,void * arg)4599a2dd95SBruce Richardson find_mem_event_callback(const char *name, void *arg)
4699a2dd95SBruce Richardson {
4799a2dd95SBruce Richardson struct mem_event_callback_entry *r;
4899a2dd95SBruce Richardson
4999a2dd95SBruce Richardson TAILQ_FOREACH(r, &mem_event_callback_list, next) {
5099a2dd95SBruce Richardson if (!strcmp(r->name, name) && r->arg == arg)
5199a2dd95SBruce Richardson break;
5299a2dd95SBruce Richardson }
5399a2dd95SBruce Richardson return r;
5499a2dd95SBruce Richardson }
5599a2dd95SBruce Richardson
5699a2dd95SBruce Richardson static struct mem_alloc_validator_entry *
find_mem_alloc_validator(const char * name,int socket_id)5799a2dd95SBruce Richardson find_mem_alloc_validator(const char *name, int socket_id)
5899a2dd95SBruce Richardson {
5999a2dd95SBruce Richardson struct mem_alloc_validator_entry *r;
6099a2dd95SBruce Richardson
6199a2dd95SBruce Richardson TAILQ_FOREACH(r, &mem_alloc_validator_list, next) {
6299a2dd95SBruce Richardson if (!strcmp(r->name, name) && r->socket_id == socket_id)
6399a2dd95SBruce Richardson break;
6499a2dd95SBruce Richardson }
6599a2dd95SBruce Richardson return r;
6699a2dd95SBruce Richardson }
6799a2dd95SBruce Richardson
6899a2dd95SBruce Richardson bool
eal_memalloc_is_contig(const struct rte_memseg_list * msl,void * start,size_t len)6999a2dd95SBruce Richardson eal_memalloc_is_contig(const struct rte_memseg_list *msl, void *start,
7099a2dd95SBruce Richardson size_t len)
7199a2dd95SBruce Richardson {
7299a2dd95SBruce Richardson void *end, *aligned_start, *aligned_end;
7399a2dd95SBruce Richardson size_t pgsz = (size_t)msl->page_sz;
7499a2dd95SBruce Richardson const struct rte_memseg *ms;
7599a2dd95SBruce Richardson const struct internal_config *internal_conf =
7699a2dd95SBruce Richardson eal_get_internal_configuration();
7799a2dd95SBruce Richardson
7899a2dd95SBruce Richardson /* for IOVA_VA, it's always contiguous */
7999a2dd95SBruce Richardson if (rte_eal_iova_mode() == RTE_IOVA_VA && !msl->external)
8099a2dd95SBruce Richardson return true;
8199a2dd95SBruce Richardson
8299a2dd95SBruce Richardson /* for legacy memory, it's always contiguous */
8399a2dd95SBruce Richardson if (internal_conf->legacy_mem)
8499a2dd95SBruce Richardson return true;
8599a2dd95SBruce Richardson
8699a2dd95SBruce Richardson end = RTE_PTR_ADD(start, len);
8799a2dd95SBruce Richardson
8899a2dd95SBruce Richardson /* for nohuge, we check pagemap, otherwise check memseg */
8999a2dd95SBruce Richardson if (!rte_eal_has_hugepages()) {
9099a2dd95SBruce Richardson rte_iova_t cur, expected;
9199a2dd95SBruce Richardson
9299a2dd95SBruce Richardson aligned_start = RTE_PTR_ALIGN_FLOOR(start, pgsz);
9399a2dd95SBruce Richardson aligned_end = RTE_PTR_ALIGN_CEIL(end, pgsz);
9499a2dd95SBruce Richardson
9599a2dd95SBruce Richardson /* if start and end are on the same page, bail out early */
9699a2dd95SBruce Richardson if (RTE_PTR_DIFF(aligned_end, aligned_start) == pgsz)
9799a2dd95SBruce Richardson return true;
9899a2dd95SBruce Richardson
9999a2dd95SBruce Richardson /* skip first iteration */
10099a2dd95SBruce Richardson cur = rte_mem_virt2iova(aligned_start);
10199a2dd95SBruce Richardson expected = cur + pgsz;
10299a2dd95SBruce Richardson aligned_start = RTE_PTR_ADD(aligned_start, pgsz);
10399a2dd95SBruce Richardson
10499a2dd95SBruce Richardson while (aligned_start < aligned_end) {
10599a2dd95SBruce Richardson cur = rte_mem_virt2iova(aligned_start);
10699a2dd95SBruce Richardson if (cur != expected)
10799a2dd95SBruce Richardson return false;
10899a2dd95SBruce Richardson aligned_start = RTE_PTR_ADD(aligned_start, pgsz);
10999a2dd95SBruce Richardson expected += pgsz;
11099a2dd95SBruce Richardson }
11199a2dd95SBruce Richardson } else {
11299a2dd95SBruce Richardson int start_seg, end_seg, cur_seg;
11399a2dd95SBruce Richardson rte_iova_t cur, expected;
11499a2dd95SBruce Richardson
11599a2dd95SBruce Richardson aligned_start = RTE_PTR_ALIGN_FLOOR(start, pgsz);
11699a2dd95SBruce Richardson aligned_end = RTE_PTR_ALIGN_CEIL(end, pgsz);
11799a2dd95SBruce Richardson
11899a2dd95SBruce Richardson start_seg = RTE_PTR_DIFF(aligned_start, msl->base_va) /
11999a2dd95SBruce Richardson pgsz;
12099a2dd95SBruce Richardson end_seg = RTE_PTR_DIFF(aligned_end, msl->base_va) /
12199a2dd95SBruce Richardson pgsz;
12299a2dd95SBruce Richardson
12399a2dd95SBruce Richardson /* if start and end are on the same page, bail out early */
12499a2dd95SBruce Richardson if (RTE_PTR_DIFF(aligned_end, aligned_start) == pgsz)
12599a2dd95SBruce Richardson return true;
12699a2dd95SBruce Richardson
12799a2dd95SBruce Richardson /* skip first iteration */
12899a2dd95SBruce Richardson ms = rte_fbarray_get(&msl->memseg_arr, start_seg);
12999a2dd95SBruce Richardson cur = ms->iova;
13099a2dd95SBruce Richardson expected = cur + pgsz;
13199a2dd95SBruce Richardson
13299a2dd95SBruce Richardson /* if we can't access IOVA addresses, assume non-contiguous */
13399a2dd95SBruce Richardson if (cur == RTE_BAD_IOVA)
13499a2dd95SBruce Richardson return false;
13599a2dd95SBruce Richardson
13699a2dd95SBruce Richardson for (cur_seg = start_seg + 1; cur_seg < end_seg;
13799a2dd95SBruce Richardson cur_seg++, expected += pgsz) {
13899a2dd95SBruce Richardson ms = rte_fbarray_get(&msl->memseg_arr, cur_seg);
13999a2dd95SBruce Richardson
14099a2dd95SBruce Richardson if (ms->iova != expected)
14199a2dd95SBruce Richardson return false;
14299a2dd95SBruce Richardson }
14399a2dd95SBruce Richardson }
14499a2dd95SBruce Richardson return true;
14599a2dd95SBruce Richardson }
14699a2dd95SBruce Richardson
14799a2dd95SBruce Richardson int
eal_memalloc_mem_event_callback_register(const char * name,rte_mem_event_callback_t clb,void * arg)14899a2dd95SBruce Richardson eal_memalloc_mem_event_callback_register(const char *name,
14999a2dd95SBruce Richardson rte_mem_event_callback_t clb, void *arg)
15099a2dd95SBruce Richardson {
15199a2dd95SBruce Richardson struct mem_event_callback_entry *entry;
15299a2dd95SBruce Richardson int ret, len;
15399a2dd95SBruce Richardson if (name == NULL || clb == NULL) {
15499a2dd95SBruce Richardson rte_errno = EINVAL;
15599a2dd95SBruce Richardson return -1;
15699a2dd95SBruce Richardson }
15799a2dd95SBruce Richardson len = strnlen(name, RTE_MEM_EVENT_CALLBACK_NAME_LEN);
15899a2dd95SBruce Richardson if (len == 0) {
15999a2dd95SBruce Richardson rte_errno = EINVAL;
16099a2dd95SBruce Richardson return -1;
16199a2dd95SBruce Richardson } else if (len == RTE_MEM_EVENT_CALLBACK_NAME_LEN) {
16299a2dd95SBruce Richardson rte_errno = ENAMETOOLONG;
16399a2dd95SBruce Richardson return -1;
16499a2dd95SBruce Richardson }
16599a2dd95SBruce Richardson rte_rwlock_write_lock(&mem_event_rwlock);
16699a2dd95SBruce Richardson
16799a2dd95SBruce Richardson entry = find_mem_event_callback(name, arg);
16899a2dd95SBruce Richardson if (entry != NULL) {
16999a2dd95SBruce Richardson rte_errno = EEXIST;
17099a2dd95SBruce Richardson ret = -1;
17199a2dd95SBruce Richardson goto unlock;
17299a2dd95SBruce Richardson }
17399a2dd95SBruce Richardson
17499a2dd95SBruce Richardson entry = malloc(sizeof(*entry));
17599a2dd95SBruce Richardson if (entry == NULL) {
17699a2dd95SBruce Richardson rte_errno = ENOMEM;
17799a2dd95SBruce Richardson ret = -1;
17899a2dd95SBruce Richardson goto unlock;
17999a2dd95SBruce Richardson }
18099a2dd95SBruce Richardson
18199a2dd95SBruce Richardson /* callback successfully created and is valid, add it to the list */
18299a2dd95SBruce Richardson entry->clb = clb;
18399a2dd95SBruce Richardson entry->arg = arg;
18499a2dd95SBruce Richardson strlcpy(entry->name, name, RTE_MEM_EVENT_CALLBACK_NAME_LEN);
18599a2dd95SBruce Richardson TAILQ_INSERT_TAIL(&mem_event_callback_list, entry, next);
18699a2dd95SBruce Richardson
18799a2dd95SBruce Richardson ret = 0;
18899a2dd95SBruce Richardson
189*ae67895bSDavid Marchand EAL_LOG(DEBUG, "Mem event callback '%s:%p' registered",
19099a2dd95SBruce Richardson name, arg);
19199a2dd95SBruce Richardson
19299a2dd95SBruce Richardson unlock:
19399a2dd95SBruce Richardson rte_rwlock_write_unlock(&mem_event_rwlock);
19499a2dd95SBruce Richardson return ret;
19599a2dd95SBruce Richardson }
19699a2dd95SBruce Richardson
19799a2dd95SBruce Richardson int
eal_memalloc_mem_event_callback_unregister(const char * name,void * arg)19899a2dd95SBruce Richardson eal_memalloc_mem_event_callback_unregister(const char *name, void *arg)
19999a2dd95SBruce Richardson {
20099a2dd95SBruce Richardson struct mem_event_callback_entry *entry;
20199a2dd95SBruce Richardson int ret, len;
20299a2dd95SBruce Richardson
20399a2dd95SBruce Richardson if (name == NULL) {
20499a2dd95SBruce Richardson rte_errno = EINVAL;
20599a2dd95SBruce Richardson return -1;
20699a2dd95SBruce Richardson }
20799a2dd95SBruce Richardson len = strnlen(name, RTE_MEM_EVENT_CALLBACK_NAME_LEN);
20899a2dd95SBruce Richardson if (len == 0) {
20999a2dd95SBruce Richardson rte_errno = EINVAL;
21099a2dd95SBruce Richardson return -1;
21199a2dd95SBruce Richardson } else if (len == RTE_MEM_EVENT_CALLBACK_NAME_LEN) {
21299a2dd95SBruce Richardson rte_errno = ENAMETOOLONG;
21399a2dd95SBruce Richardson return -1;
21499a2dd95SBruce Richardson }
21599a2dd95SBruce Richardson rte_rwlock_write_lock(&mem_event_rwlock);
21699a2dd95SBruce Richardson
21799a2dd95SBruce Richardson entry = find_mem_event_callback(name, arg);
21899a2dd95SBruce Richardson if (entry == NULL) {
21999a2dd95SBruce Richardson rte_errno = ENOENT;
22099a2dd95SBruce Richardson ret = -1;
22199a2dd95SBruce Richardson goto unlock;
22299a2dd95SBruce Richardson }
22399a2dd95SBruce Richardson TAILQ_REMOVE(&mem_event_callback_list, entry, next);
22499a2dd95SBruce Richardson free(entry);
22599a2dd95SBruce Richardson
22699a2dd95SBruce Richardson ret = 0;
22799a2dd95SBruce Richardson
228*ae67895bSDavid Marchand EAL_LOG(DEBUG, "Mem event callback '%s:%p' unregistered",
22999a2dd95SBruce Richardson name, arg);
23099a2dd95SBruce Richardson
23199a2dd95SBruce Richardson unlock:
23299a2dd95SBruce Richardson rte_rwlock_write_unlock(&mem_event_rwlock);
23399a2dd95SBruce Richardson return ret;
23499a2dd95SBruce Richardson }
23599a2dd95SBruce Richardson
23699a2dd95SBruce Richardson void
eal_memalloc_mem_event_notify(enum rte_mem_event event,const void * start,size_t len)23799a2dd95SBruce Richardson eal_memalloc_mem_event_notify(enum rte_mem_event event, const void *start,
23899a2dd95SBruce Richardson size_t len)
23999a2dd95SBruce Richardson {
24099a2dd95SBruce Richardson struct mem_event_callback_entry *entry;
24199a2dd95SBruce Richardson
24299a2dd95SBruce Richardson rte_rwlock_read_lock(&mem_event_rwlock);
24399a2dd95SBruce Richardson
24499a2dd95SBruce Richardson TAILQ_FOREACH(entry, &mem_event_callback_list, next) {
245*ae67895bSDavid Marchand EAL_LOG(DEBUG, "Calling mem event callback '%s:%p'",
24699a2dd95SBruce Richardson entry->name, entry->arg);
24799a2dd95SBruce Richardson entry->clb(event, start, len, entry->arg);
24899a2dd95SBruce Richardson }
24999a2dd95SBruce Richardson
25099a2dd95SBruce Richardson rte_rwlock_read_unlock(&mem_event_rwlock);
25199a2dd95SBruce Richardson }
25299a2dd95SBruce Richardson
25399a2dd95SBruce Richardson int
eal_memalloc_mem_alloc_validator_register(const char * name,rte_mem_alloc_validator_t clb,int socket_id,size_t limit)25499a2dd95SBruce Richardson eal_memalloc_mem_alloc_validator_register(const char *name,
25599a2dd95SBruce Richardson rte_mem_alloc_validator_t clb, int socket_id, size_t limit)
25699a2dd95SBruce Richardson {
25799a2dd95SBruce Richardson struct mem_alloc_validator_entry *entry;
25899a2dd95SBruce Richardson int ret, len;
25999a2dd95SBruce Richardson if (name == NULL || clb == NULL || socket_id < 0) {
26099a2dd95SBruce Richardson rte_errno = EINVAL;
26199a2dd95SBruce Richardson return -1;
26299a2dd95SBruce Richardson }
26399a2dd95SBruce Richardson len = strnlen(name, RTE_MEM_ALLOC_VALIDATOR_NAME_LEN);
26499a2dd95SBruce Richardson if (len == 0) {
26599a2dd95SBruce Richardson rte_errno = EINVAL;
26699a2dd95SBruce Richardson return -1;
26799a2dd95SBruce Richardson } else if (len == RTE_MEM_ALLOC_VALIDATOR_NAME_LEN) {
26899a2dd95SBruce Richardson rte_errno = ENAMETOOLONG;
26999a2dd95SBruce Richardson return -1;
27099a2dd95SBruce Richardson }
27199a2dd95SBruce Richardson rte_rwlock_write_lock(&mem_alloc_validator_rwlock);
27299a2dd95SBruce Richardson
27399a2dd95SBruce Richardson entry = find_mem_alloc_validator(name, socket_id);
27499a2dd95SBruce Richardson if (entry != NULL) {
27599a2dd95SBruce Richardson rte_errno = EEXIST;
27699a2dd95SBruce Richardson ret = -1;
27799a2dd95SBruce Richardson goto unlock;
27899a2dd95SBruce Richardson }
27999a2dd95SBruce Richardson
28099a2dd95SBruce Richardson entry = malloc(sizeof(*entry));
28199a2dd95SBruce Richardson if (entry == NULL) {
28299a2dd95SBruce Richardson rte_errno = ENOMEM;
28399a2dd95SBruce Richardson ret = -1;
28499a2dd95SBruce Richardson goto unlock;
28599a2dd95SBruce Richardson }
28699a2dd95SBruce Richardson
28799a2dd95SBruce Richardson /* callback successfully created and is valid, add it to the list */
28899a2dd95SBruce Richardson entry->clb = clb;
28999a2dd95SBruce Richardson entry->socket_id = socket_id;
29099a2dd95SBruce Richardson entry->limit = limit;
29199a2dd95SBruce Richardson strlcpy(entry->name, name, RTE_MEM_ALLOC_VALIDATOR_NAME_LEN);
29299a2dd95SBruce Richardson TAILQ_INSERT_TAIL(&mem_alloc_validator_list, entry, next);
29399a2dd95SBruce Richardson
29499a2dd95SBruce Richardson ret = 0;
29599a2dd95SBruce Richardson
296*ae67895bSDavid Marchand EAL_LOG(DEBUG, "Mem alloc validator '%s' on socket %i with limit %zu registered",
29799a2dd95SBruce Richardson name, socket_id, limit);
29899a2dd95SBruce Richardson
29999a2dd95SBruce Richardson unlock:
30099a2dd95SBruce Richardson rte_rwlock_write_unlock(&mem_alloc_validator_rwlock);
30199a2dd95SBruce Richardson return ret;
30299a2dd95SBruce Richardson }
30399a2dd95SBruce Richardson
30499a2dd95SBruce Richardson int
eal_memalloc_mem_alloc_validator_unregister(const char * name,int socket_id)30599a2dd95SBruce Richardson eal_memalloc_mem_alloc_validator_unregister(const char *name, int socket_id)
30699a2dd95SBruce Richardson {
30799a2dd95SBruce Richardson struct mem_alloc_validator_entry *entry;
30899a2dd95SBruce Richardson int ret, len;
30999a2dd95SBruce Richardson
31099a2dd95SBruce Richardson if (name == NULL || socket_id < 0) {
31199a2dd95SBruce Richardson rte_errno = EINVAL;
31299a2dd95SBruce Richardson return -1;
31399a2dd95SBruce Richardson }
31499a2dd95SBruce Richardson len = strnlen(name, RTE_MEM_ALLOC_VALIDATOR_NAME_LEN);
31599a2dd95SBruce Richardson if (len == 0) {
31699a2dd95SBruce Richardson rte_errno = EINVAL;
31799a2dd95SBruce Richardson return -1;
31899a2dd95SBruce Richardson } else if (len == RTE_MEM_ALLOC_VALIDATOR_NAME_LEN) {
31999a2dd95SBruce Richardson rte_errno = ENAMETOOLONG;
32099a2dd95SBruce Richardson return -1;
32199a2dd95SBruce Richardson }
32299a2dd95SBruce Richardson rte_rwlock_write_lock(&mem_alloc_validator_rwlock);
32399a2dd95SBruce Richardson
32499a2dd95SBruce Richardson entry = find_mem_alloc_validator(name, socket_id);
32599a2dd95SBruce Richardson if (entry == NULL) {
32699a2dd95SBruce Richardson rte_errno = ENOENT;
32799a2dd95SBruce Richardson ret = -1;
32899a2dd95SBruce Richardson goto unlock;
32999a2dd95SBruce Richardson }
33099a2dd95SBruce Richardson TAILQ_REMOVE(&mem_alloc_validator_list, entry, next);
33199a2dd95SBruce Richardson free(entry);
33299a2dd95SBruce Richardson
33399a2dd95SBruce Richardson ret = 0;
33499a2dd95SBruce Richardson
335*ae67895bSDavid Marchand EAL_LOG(DEBUG, "Mem alloc validator '%s' on socket %i unregistered",
33699a2dd95SBruce Richardson name, socket_id);
33799a2dd95SBruce Richardson
33899a2dd95SBruce Richardson unlock:
33999a2dd95SBruce Richardson rte_rwlock_write_unlock(&mem_alloc_validator_rwlock);
34099a2dd95SBruce Richardson return ret;
34199a2dd95SBruce Richardson }
34299a2dd95SBruce Richardson
34399a2dd95SBruce Richardson int
eal_memalloc_mem_alloc_validate(int socket_id,size_t new_len)34499a2dd95SBruce Richardson eal_memalloc_mem_alloc_validate(int socket_id, size_t new_len)
34599a2dd95SBruce Richardson {
34699a2dd95SBruce Richardson struct mem_alloc_validator_entry *entry;
34799a2dd95SBruce Richardson int ret = 0;
34899a2dd95SBruce Richardson
34999a2dd95SBruce Richardson rte_rwlock_read_lock(&mem_alloc_validator_rwlock);
35099a2dd95SBruce Richardson
35199a2dd95SBruce Richardson TAILQ_FOREACH(entry, &mem_alloc_validator_list, next) {
35299a2dd95SBruce Richardson if (entry->socket_id != socket_id || entry->limit > new_len)
35399a2dd95SBruce Richardson continue;
354*ae67895bSDavid Marchand EAL_LOG(DEBUG, "Calling mem alloc validator '%s' on socket %i",
35599a2dd95SBruce Richardson entry->name, entry->socket_id);
35699a2dd95SBruce Richardson if (entry->clb(socket_id, entry->limit, new_len) < 0)
35799a2dd95SBruce Richardson ret = -1;
35899a2dd95SBruce Richardson }
35999a2dd95SBruce Richardson
36099a2dd95SBruce Richardson rte_rwlock_read_unlock(&mem_alloc_validator_rwlock);
36199a2dd95SBruce Richardson
36299a2dd95SBruce Richardson return ret;
36399a2dd95SBruce Richardson }
364