X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_eal%2Fcommon%2Feal_common_fbarray.c;h=1312f936b83371aaca9cada5f40b9df6cacb1c89;hb=70c7747689082abba6452803b6e23e6aed649ace;hp=819d097bfac3836b2a2ce1608805614164cd2a8c;hpb=5b61c62cfd76703d487a28d69a52fc3037d943ed;p=dpdk.git diff --git a/lib/librte_eal/common/eal_common_fbarray.c b/lib/librte_eal/common/eal_common_fbarray.c index 819d097bfa..1312f936b8 100644 --- a/lib/librte_eal/common/eal_common_fbarray.c +++ b/lib/librte_eal/common/eal_common_fbarray.c @@ -709,7 +709,7 @@ fully_validate(const char *name, unsigned int elt_sz, unsigned int len) return 0; } -int __rte_experimental +int rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len, unsigned int elt_sz) { @@ -736,15 +736,19 @@ rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len, } page_sz = sysconf(_SC_PAGESIZE); - if (page_sz == (size_t)-1) - goto fail; + if (page_sz == (size_t)-1) { + free(ma); + return -1; + } /* calculate our memory limits */ mmap_len = calc_data_size(page_sz, elt_sz, len); data = eal_get_virtual_area(NULL, &mmap_len, page_sz, 0, 0); - if (data == NULL) - goto fail; + if (data == NULL) { + free(ma); + return -1; + } rte_spinlock_lock(&mem_area_lock); @@ -829,7 +833,7 @@ fail: return -1; } -int __rte_experimental +int rte_fbarray_attach(struct rte_fbarray *arr) { struct mem_area *ma = NULL, *tmp = NULL; @@ -859,8 +863,10 @@ rte_fbarray_attach(struct rte_fbarray *arr) } page_sz = sysconf(_SC_PAGESIZE); - if (page_sz == (size_t)-1) - goto fail; + if (page_sz == (size_t)-1) { + free(ma); + return -1; + } mmap_len = calc_data_size(page_sz, arr->elt_sz, arr->len); @@ -906,6 +912,7 @@ rte_fbarray_attach(struct rte_fbarray *arr) /* we're done */ + rte_spinlock_unlock(&mem_area_lock); return 0; fail: if (data) @@ -913,10 +920,11 @@ fail: if (fd >= 0) close(fd); free(ma); + rte_spinlock_unlock(&mem_area_lock); return -1; } -int __rte_experimental +int rte_fbarray_detach(struct rte_fbarray *arr) { struct mem_area *tmp = NULL; @@ -970,7 +978,7 @@ out: return ret; } -int __rte_experimental +int rte_fbarray_destroy(struct rte_fbarray *arr) { struct mem_area *tmp = NULL; @@ -1047,12 +1055,15 @@ rte_fbarray_destroy(struct rte_fbarray *arr) TAILQ_REMOVE(&mem_area_tailq, tmp, next); free(tmp); ret = 0; + + /* reset the fbarray structure */ + memset(arr, 0, sizeof(*arr)); out: rte_spinlock_unlock(&mem_area_lock); return ret; } -void * __rte_experimental +void * rte_fbarray_get(const struct rte_fbarray *arr, unsigned int idx) { void *ret = NULL; @@ -1071,19 +1082,19 @@ rte_fbarray_get(const struct rte_fbarray *arr, unsigned int idx) return ret; } -int __rte_experimental +int rte_fbarray_set_used(struct rte_fbarray *arr, unsigned int idx) { return set_used(arr, idx, true); } -int __rte_experimental +int rte_fbarray_set_free(struct rte_fbarray *arr, unsigned int idx) { return set_used(arr, idx, false); } -int __rte_experimental +int rte_fbarray_is_used(struct rte_fbarray *arr, unsigned int idx) { struct used_mask *msk; @@ -1152,25 +1163,25 @@ out: return ret; } -int __rte_experimental +int rte_fbarray_find_next_free(struct rte_fbarray *arr, unsigned int start) { return fbarray_find(arr, start, true, false); } -int __rte_experimental +int rte_fbarray_find_next_used(struct rte_fbarray *arr, unsigned int start) { return fbarray_find(arr, start, true, true); } -int __rte_experimental +int rte_fbarray_find_prev_free(struct rte_fbarray *arr, unsigned int start) { return fbarray_find(arr, start, false, false); } -int __rte_experimental +int rte_fbarray_find_prev_used(struct rte_fbarray *arr, unsigned int start) { return fbarray_find(arr, start, false, true); @@ -1228,28 +1239,28 @@ out: return ret; } -int __rte_experimental +int rte_fbarray_find_next_n_free(struct rte_fbarray *arr, unsigned int start, unsigned int n) { return fbarray_find_n(arr, start, n, true, false); } -int __rte_experimental +int rte_fbarray_find_next_n_used(struct rte_fbarray *arr, unsigned int start, unsigned int n) { return fbarray_find_n(arr, start, n, true, true); } -int __rte_experimental +int rte_fbarray_find_prev_n_free(struct rte_fbarray *arr, unsigned int start, unsigned int n) { return fbarray_find_n(arr, start, n, false, false); } -int __rte_experimental +int rte_fbarray_find_prev_n_used(struct rte_fbarray *arr, unsigned int start, unsigned int n) { @@ -1308,31 +1319,140 @@ out: return ret; } -int __rte_experimental +static int +fbarray_find_biggest(struct rte_fbarray *arr, unsigned int start, bool used, + bool rev) +{ + int cur_idx, next_idx, cur_len, biggest_idx, biggest_len; + /* don't stack if conditions, use function pointers instead */ + int (*find_func)(struct rte_fbarray *, unsigned int); + int (*find_contig_func)(struct rte_fbarray *, unsigned int); + + if (arr == NULL || start >= arr->len) { + rte_errno = EINVAL; + return -1; + } + /* the other API calls already do their fair share of cheap checks, so + * no need to do them here. + */ + + /* the API's called are thread-safe, but something may still happen + * inbetween the API calls, so lock the fbarray. all other API's are + * read-locking the fbarray, so read lock here is OK. + */ + rte_rwlock_read_lock(&arr->rwlock); + + /* pick out appropriate functions */ + if (used) { + if (rev) { + find_func = rte_fbarray_find_prev_used; + find_contig_func = rte_fbarray_find_rev_contig_used; + } else { + find_func = rte_fbarray_find_next_used; + find_contig_func = rte_fbarray_find_contig_used; + } + } else { + if (rev) { + find_func = rte_fbarray_find_prev_free; + find_contig_func = rte_fbarray_find_rev_contig_free; + } else { + find_func = rte_fbarray_find_next_free; + find_contig_func = rte_fbarray_find_contig_free; + } + } + + cur_idx = start; + biggest_idx = -1; /* default is error */ + biggest_len = 0; + for (;;) { + cur_idx = find_func(arr, cur_idx); + + /* block found, check its length */ + if (cur_idx >= 0) { + cur_len = find_contig_func(arr, cur_idx); + /* decide where we go next */ + next_idx = rev ? cur_idx - cur_len : cur_idx + cur_len; + /* move current index to start of chunk */ + cur_idx = rev ? next_idx + 1 : cur_idx; + + if (cur_len > biggest_len) { + biggest_idx = cur_idx; + biggest_len = cur_len; + } + cur_idx = next_idx; + /* in reverse mode, next_idx may be -1 if chunk started + * at array beginning. this means there's no more work + * to do. + */ + if (cur_idx < 0) + break; + } else { + /* nothing more to find, stop. however, a failed API + * call has set rte_errno, which we want to ignore, as + * reaching the end of fbarray is not an error. + */ + rte_errno = 0; + break; + } + } + /* if we didn't find anything at all, set rte_errno */ + if (biggest_idx < 0) + rte_errno = used ? ENOENT : ENOSPC; + + rte_rwlock_read_unlock(&arr->rwlock); + return biggest_idx; +} + +int +rte_fbarray_find_biggest_free(struct rte_fbarray *arr, unsigned int start) +{ + return fbarray_find_biggest(arr, start, false, false); +} + +int +rte_fbarray_find_biggest_used(struct rte_fbarray *arr, unsigned int start) +{ + return fbarray_find_biggest(arr, start, true, false); +} + +int +rte_fbarray_find_rev_biggest_free(struct rte_fbarray *arr, unsigned int start) +{ + return fbarray_find_biggest(arr, start, false, true); +} + +int +rte_fbarray_find_rev_biggest_used(struct rte_fbarray *arr, unsigned int start) +{ + return fbarray_find_biggest(arr, start, true, true); +} + + +int rte_fbarray_find_contig_free(struct rte_fbarray *arr, unsigned int start) { return fbarray_find_contig(arr, start, true, false); } -int __rte_experimental +int rte_fbarray_find_contig_used(struct rte_fbarray *arr, unsigned int start) { return fbarray_find_contig(arr, start, true, true); } -int __rte_experimental +int rte_fbarray_find_rev_contig_free(struct rte_fbarray *arr, unsigned int start) { return fbarray_find_contig(arr, start, false, false); } -int __rte_experimental +int rte_fbarray_find_rev_contig_used(struct rte_fbarray *arr, unsigned int start) { return fbarray_find_contig(arr, start, false, true); } -int __rte_experimental +int rte_fbarray_find_idx(const struct rte_fbarray *arr, const void *elt) { void *end; @@ -1358,7 +1478,7 @@ rte_fbarray_find_idx(const struct rte_fbarray *arr, const void *elt) return ret; } -void __rte_experimental +void rte_fbarray_dump_metadata(struct rte_fbarray *arr, FILE *f) { struct used_mask *msk;