X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_eal%2Fcommon%2Feal_common_fbarray.c;h=592ec585946a25daeb7cda45ed40649dbad63b0e;hb=e863fe3a13da89787fdf3b5c590101a3c0f10af6;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..592ec58594 100644 --- a/lib/librte_eal/common/eal_common_fbarray.c +++ b/lib/librte_eal/common/eal_common_fbarray.c @@ -5,15 +5,16 @@ #include #include #include -#include #include #include -#include #include +#include #include -#include +#include #include +#include +#include #include #include @@ -80,24 +81,18 @@ get_used_mask(void *data, unsigned int elt_sz, unsigned int len) } static int -resize_and_map(int fd, void *addr, size_t len) +resize_and_map(int fd, const char *path, void *addr, size_t len) { - char path[PATH_MAX]; void *map_addr; - if (ftruncate(fd, len)) { + if (eal_file_truncate(fd, len)) { RTE_LOG(ERR, EAL, "Cannot truncate %s\n", path); - /* pass errno up the chain */ - rte_errno = errno; return -1; } - map_addr = mmap(addr, len, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_FIXED, fd, 0); + map_addr = rte_mem_map(addr, len, RTE_PROT_READ | RTE_PROT_WRITE, + RTE_MAP_SHARED | RTE_MAP_FORCE_ADDRESS, fd, 0); if (map_addr != addr) { - RTE_LOG(ERR, EAL, "mmap() failed: %s\n", strerror(errno)); - /* pass errno up the chain */ - rte_errno = errno; return -1; } return 0; @@ -114,7 +109,7 @@ overlap(const struct mem_area *ma, const void *start, size_t len) if (start >= ma_start && start < ma_end) return 1; /* end overlap? */ - if (end >= ma_start && end < ma_end) + if (end > ma_start && end < ma_end) return 1; return 0; } @@ -709,7 +704,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) { @@ -719,6 +714,8 @@ rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len, struct mem_area *ma = NULL; void *data = NULL; int fd = -1; + const struct internal_config *internal_conf = + eal_get_internal_configuration(); if (arr == NULL) { rte_errno = EINVAL; @@ -735,28 +732,34 @@ rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len, return -1; } - page_sz = sysconf(_SC_PAGESIZE); - if (page_sz == (size_t)-1) - goto fail; + page_sz = rte_mem_page_size(); + 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); fd = -1; - if (internal_config.no_shconf) { + if (internal_conf->no_shconf) { /* remap virtual area as writable */ - void *new_data = mmap(data, mmap_len, PROT_READ | PROT_WRITE, - MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, fd, 0); - if (new_data == MAP_FAILED) { + static const int flags = RTE_MAP_FORCE_ADDRESS | + RTE_MAP_PRIVATE | RTE_MAP_ANONYMOUS; + void *new_data = rte_mem_map(data, mmap_len, + RTE_PROT_READ | RTE_PROT_WRITE, flags, fd, 0); + if (new_data == NULL) { RTE_LOG(DEBUG, EAL, "%s(): couldn't remap anonymous memory: %s\n", - __func__, strerror(errno)); + __func__, rte_strerror(rte_errno)); goto fail; } } else { @@ -768,15 +771,15 @@ rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len, * and see if we succeed. If we don't, someone else is using it * already. */ - fd = open(path, O_CREAT | O_RDWR, 0600); + fd = eal_file_open(path, EAL_OPEN_CREATE | EAL_OPEN_READWRITE); if (fd < 0) { RTE_LOG(DEBUG, EAL, "%s(): couldn't open %s: %s\n", - __func__, path, strerror(errno)); - rte_errno = errno; + __func__, path, rte_strerror(rte_errno)); goto fail; - } else if (flock(fd, LOCK_EX | LOCK_NB)) { + } else if (eal_file_lock( + fd, EAL_FLOCK_EXCLUSIVE, EAL_FLOCK_RETURN)) { RTE_LOG(DEBUG, EAL, "%s(): couldn't lock %s: %s\n", - __func__, path, strerror(errno)); + __func__, path, rte_strerror(rte_errno)); rte_errno = EBUSY; goto fail; } @@ -785,12 +788,10 @@ rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len, * still attach to it, but no other process could reinitialize * it. */ - if (flock(fd, LOCK_SH | LOCK_NB)) { - rte_errno = errno; + if (eal_file_lock(fd, EAL_FLOCK_SHARED, EAL_FLOCK_RETURN)) goto fail; - } - if (resize_and_map(fd, data, mmap_len)) + if (resize_and_map(fd, path, data, mmap_len)) goto fail; } ma->addr = data; @@ -820,7 +821,7 @@ rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len, return 0; fail: if (data) - munmap(data, mmap_len); + rte_mem_unmap(data, mmap_len); if (fd >= 0) close(fd); free(ma); @@ -829,7 +830,7 @@ fail: return -1; } -int __rte_experimental +int rte_fbarray_attach(struct rte_fbarray *arr) { struct mem_area *ma = NULL, *tmp = NULL; @@ -858,9 +859,11 @@ rte_fbarray_attach(struct rte_fbarray *arr) return -1; } - page_sz = sysconf(_SC_PAGESIZE); - if (page_sz == (size_t)-1) - goto fail; + page_sz = rte_mem_page_size(); + if (page_sz == (size_t)-1) { + free(ma); + return -1; + } mmap_len = calc_data_size(page_sz, arr->elt_sz, arr->len); @@ -882,19 +885,16 @@ rte_fbarray_attach(struct rte_fbarray *arr) eal_get_fbarray_path(path, sizeof(path), arr->name); - fd = open(path, O_RDWR); + fd = eal_file_open(path, EAL_OPEN_READWRITE); if (fd < 0) { - rte_errno = errno; goto fail; } /* lock the file, to let others know we're using it */ - if (flock(fd, LOCK_SH | LOCK_NB)) { - rte_errno = errno; + if (eal_file_lock(fd, EAL_FLOCK_SHARED, EAL_FLOCK_RETURN)) goto fail; - } - if (resize_and_map(fd, data, mmap_len)) + if (resize_and_map(fd, path, data, mmap_len)) goto fail; /* store our new memory area */ @@ -906,17 +906,19 @@ rte_fbarray_attach(struct rte_fbarray *arr) /* we're done */ + rte_spinlock_unlock(&mem_area_lock); return 0; fail: if (data) - munmap(data, mmap_len); + rte_mem_unmap(data, mmap_len); 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; @@ -936,8 +938,7 @@ rte_fbarray_detach(struct rte_fbarray *arr) * really do anything about it, things will blow up either way. */ - size_t page_sz = sysconf(_SC_PAGESIZE); - + size_t page_sz = rte_mem_page_size(); if (page_sz == (size_t)-1) return -1; @@ -956,7 +957,7 @@ rte_fbarray_detach(struct rte_fbarray *arr) goto out; } - munmap(arr->data, mmap_len); + rte_mem_unmap(arr->data, mmap_len); /* area is unmapped, close fd and remove the tailq entry */ if (tmp->fd >= 0) @@ -970,13 +971,15 @@ out: return ret; } -int __rte_experimental +int rte_fbarray_destroy(struct rte_fbarray *arr) { struct mem_area *tmp = NULL; size_t mmap_len; int fd, ret; char path[PATH_MAX]; + const struct internal_config *internal_conf = + eal_get_internal_configuration(); if (arr == NULL) { rte_errno = EINVAL; @@ -991,8 +994,7 @@ rte_fbarray_destroy(struct rte_fbarray *arr) * really do anything about it, things will blow up either way. */ - size_t page_sz = sysconf(_SC_PAGESIZE); - + size_t page_sz = rte_mem_page_size(); if (page_sz == (size_t)-1) return -1; @@ -1011,13 +1013,13 @@ rte_fbarray_destroy(struct rte_fbarray *arr) goto out; } /* with no shconf, there were never any files to begin with */ - if (!internal_config.no_shconf) { + if (!internal_conf->no_shconf) { /* * attempt to get an exclusive lock on the file, to ensure it * has been detached by all other processes */ fd = tmp->fd; - if (flock(fd, LOCK_EX | LOCK_NB)) { + if (eal_file_lock(fd, EAL_FLOCK_EXCLUSIVE, EAL_FLOCK_RETURN)) { RTE_LOG(DEBUG, EAL, "Cannot destroy fbarray - another process is using it\n"); rte_errno = EBUSY; ret = -1; @@ -1034,25 +1036,28 @@ rte_fbarray_destroy(struct rte_fbarray *arr) * we're still holding an exclusive lock, so drop it to * shared. */ - flock(fd, LOCK_SH | LOCK_NB); + eal_file_lock(fd, EAL_FLOCK_SHARED, EAL_FLOCK_RETURN); ret = -1; goto out; } close(fd); } - munmap(arr->data, mmap_len); + rte_mem_unmap(arr->data, mmap_len); /* area is unmapped, remove the tailq entry */ 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 +1076,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 +1157,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 +1233,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 +1313,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 + * between 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 +1472,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;