@@ -141,6 +141,7 @@ typedef struct ishm_fragment {
* will allocate both a block and a fragment.
* Blocks contain only global data common to all processes.
*/
+typedef enum {UNKNOWN, HUGE, NORMAL, EXTERNAL} huge_flag_t;
typedef struct ishm_block {
char name[ISHM_NAME_MAXLEN]; /* name for the ishm block (if any) */
char filename[ISHM_FILENAME_MAXLEN]; /* name of the .../odp-* file */
@@ -151,7 +152,7 @@ typedef struct ishm_block {
void *start; /* only valid if _ODP_ISHM_SINGLE_VA is set*/
uint64_t len; /* length. multiple of page size. 0 if free*/
ishm_fragment_t *fragment; /* used when _ODP_ISHM_SINGLE_VA is used */
- int huge; /* true if this segment is mapped using huge pages */
+ huge_flag_t huge; /* page type: external means unknown here. */
uint64_t seq; /* sequence number, incremented on alloc and free */
uint64_t refcnt;/* number of linux processes mapping this block */
} ishm_block_t;
@@ -389,7 +390,8 @@ static void free_fragment(ishm_fragment_t *fragmnt)
* or /mnt/huge/odp-<pid>-<sequence_or_name> (for huge pages)
* Return the new file descriptor, or -1 on error.
*/
-static int create_file(int block_index, int huge, uint64_t len, uint32_t flags)
+static int create_file(int block_index, huge_flag_t huge,
+ uint64_t len, uint32_t flags)
{
char *name;
int fd;
@@ -406,10 +408,11 @@ static int create_file(int block_index, int huge, uint64_t len, uint32_t flags)
ishm_tbl->dev_seq++);
/* huge dir must be known to create files there!: */
- if (huge && !odp_global_data.hugepage_info.default_huge_page_dir)
+ if ((huge == HUGE) &&
+ (!odp_global_data.hugepage_info.default_huge_page_dir))
return -1;
- if (huge)
+ if (huge == HUGE)
snprintf(filename, ISHM_FILENAME_MAXLEN,
ISHM_FILENAME_FORMAT,
odp_global_data.hugepage_info.default_huge_page_dir,
@@ -465,7 +468,7 @@ static int create_file(int block_index, int huge, uint64_t len, uint32_t flags)
* Mutex must be assured by the caller.
*/
static void *do_map(int block_index, uint64_t len, uint32_t align,
- uint32_t flags, int huge, int *fd)
+ uint32_t flags, huge_flag_t huge, int *fd)
{
ishm_block_t *new_block; /* entry in the main block table */
void *addr = NULL;
@@ -519,8 +522,6 @@ static void *do_map(int block_index, uint64_t len, uint32_t align,
return NULL;
}
- new_block->huge = huge;
-
return mapped_addr;
}
@@ -723,27 +724,21 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
int new_index; /* index in the main block table*/
ishm_block_t *new_block; /* entry in the main block table*/
uint64_t page_sz; /* normal page size. usually 4K*/
- uint64_t alloc_size; /* includes extra for alignement*/
uint64_t page_hp_size; /* huge page size */
- uint64_t alloc_hp_size; /* includes extra for alignement*/
uint32_t hp_align;
uint64_t len; /* mapped length */
void *addr = NULL; /* mapping address */
int new_proc_entry;
-
- page_sz = odp_sys_page_size();
+ struct stat statbuf;
odp_spinlock_lock(&ishm_tbl->lock);
/* update this process view... */
procsync();
- /* roundup to page size */
- alloc_size = (size + (page_sz - 1)) & (-page_sz);
-
+ /* Get system page sizes: page_hp_size is 0 if no huge page available*/
+ page_sz = odp_sys_page_size();
page_hp_size = odp_sys_huge_page_size();
- /* roundup to page size */
- alloc_hp_size = (size + (page_hp_size - 1)) & (-page_hp_size);
/* check if name already exists */
if (name && (find_block_by_name(name) >= 0)) {
@@ -776,8 +771,24 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
else
new_block->name[0] = 0;
- /* Try first huge pages when possible and needed: */
- if (page_hp_size && (alloc_size > page_sz)) {
+ /* If a file descriptor is provided, get the real size and map: */
+ if (fd >= 0) {
+ fstat(fd, &statbuf);
+ len = statbuf.st_size;
+ /* note that the huge page flag is meningless here as huge
+ * page is determined by the provided file descriptor: */
+ addr = do_map(new_index, len, align, flags, EXTERNAL, &fd);
+ if (addr == NULL) {
+ close(fd);
+ odp_spinlock_unlock(&ishm_tbl->lock);
+ ODP_ERR("_ishm_reserve failed.\n");
+ return -1;
+ }
+ new_block->huge = EXTERNAL;
+ }
+
+ /* Otherwise, Try first huge pages when possible and needed: */
+ if ((fd < 0) && page_hp_size && (size > page_sz)) {
/* at least, alignment in VA should match page size, but user
* can request more: If the user requirement exceeds the page
* size then we have to make sure the block will be mapped at
@@ -788,18 +799,20 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
hp_align = odp_sys_huge_page_size();
else
flags |= _ODP_ISHM_SINGLE_VA;
- len = alloc_hp_size;
- addr = do_map(new_index, len, hp_align, flags, 1, &fd);
+
+ /* roundup to page size */
+ len = (size + (page_hp_size - 1)) & (-page_hp_size);
+ addr = do_map(new_index, len, hp_align, flags, HUGE, &fd);
if (addr == NULL)
ODP_DBG("No huge pages, fall back to normal pages, "
"check: /proc/sys/vm/nr_hugepages.\n");
else
- new_block->huge = 1;
+ new_block->huge = HUGE;
}
- /* try normal pages if huge pages failed */
- if (addr == NULL) {
+ /* Try normal pages if huge pages failed */
+ if (fd < 0) {
/* at least, alignment in VA should match page size, but user
* can request more: If the user requirement exceeds the page
* size then we have to make sure the block will be mapped at
@@ -810,13 +823,14 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
else
flags |= _ODP_ISHM_SINGLE_VA;
- len = alloc_size;
- addr = do_map(new_index, len, align, flags, 0, &fd);
- new_block->huge = 0;
+ /* roundup to page size */
+ len = (size + (page_sz - 1)) & (-page_sz);
+ addr = do_map(new_index, len, align, flags, NORMAL, &fd);
+ new_block->huge = NORMAL;
}
/* if neither huge pages or normal pages works, we cannot proceed: */
- if ((addr == NULL) || (len == 0)) {
+ if ((fd < 0) || (addr == NULL) || (len == 0)) {
if ((new_block->filename[0]) && (fd >= 0))
close(fd);
odp_spinlock_unlock(&ishm_tbl->lock);
@@ -850,6 +864,41 @@ int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
}
/*
+ * Try to map an memory block mapped by another ODP instance into the
+ * current ODP instance.
+ * returns 0 on success.
+ */
+int _odp_ishm_reserve_exported(const char *remote_name, pid_t external_odp_pid,
+ const char *local_name,
+ uint32_t align,
+ uint32_t flags, uint32_t user_flags)
+{
+ char linkname[ISHM_FILENAME_MAXLEN];
+ int fd;
+ int ret;
+
+ snprintf(linkname, ISHM_FILENAME_MAXLEN,
+ ISHM_LINKNAME_FORMAT,
+ external_odp_pid,
+ remote_name);
+
+ fd = open(linkname, O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (fd == -1) {
+ ODP_ERR("open failed for %s: %s.\n",
+ linkname, strerror(errno));
+ return -1;
+ }
+
+ ret = _odp_ishm_reserve(local_name, 0, fd, align, flags, user_flags);
+ if (ret < 0) {
+ close(fd);
+ return ret;
+ }
+
+ return ret;
+}
+
+/*
* Free and unmap internal shared memory:
* The file descriptor is closed and the .../odp-* file deleted,
* unless fd was externally provided at reserve() time.
@@ -1160,7 +1209,7 @@ int _odp_ishm_info(int block_index, _odp_ishm_info_t *info)
info->name = ishm_tbl->block[block_index].name;
info->addr = ishm_proctable->entry[proc_index].start;
info->size = ishm_tbl->block[block_index].user_len;
- info->page_size = ishm_tbl->block[block_index].huge ?
+ info->page_size = (ishm_tbl->block[block_index].huge == HUGE) ?
odp_sys_huge_page_size() : odp_sys_page_size();
info->flags = ishm_tbl->block[block_index].flags;
info->user_flags = ishm_tbl->block[block_index].user_flags;
@@ -1454,7 +1503,19 @@ int _odp_ishm_status(const char *title)
flags[1] = (ishm_tbl->block[i].flags & _ODP_ISHM_LOCK) ?
'L' : '.';
flags[2] = 0;
- huge = (ishm_tbl->block[i].huge) ? 'H' : '.';
+ switch (ishm_tbl->block[i].huge) {
+ case HUGE:
+ huge = 'H';
+ break;
+ case NORMAL:
+ huge = 'N';
+ break;
+ case EXTERNAL:
+ huge = 'E';
+ break;
+ default:
+ huge = '?';
+ }
proc_index = procfind_block(i);
ODP_DBG("%-3d: name:%-.24s file:%-.24s"
" flags:%s,%c len:0x%-08lx"
@@ -11,6 +11,8 @@
extern "C" {
#endif
+#include <sys/types.h>
+
/* flags available at ishm_reserve: */
#define _ODP_ISHM_SINGLE_VA 1
#define _ODP_ISHM_LOCK 2
@@ -36,6 +38,11 @@ int _odp_ishm_free_by_address(void *addr);
void *_odp_ishm_lookup_by_index(int block_index);
int _odp_ishm_lookup_by_name(const char *name);
int _odp_ishm_lookup_by_address(void *addr);
+int _odp_ishm_reserve_exported(const char *remote_name,
+ pid_t external_odp_pid,
+ const char *local_name,
+ uint32_t align,
+ uint32_t flags, uint32_t user_flags);
void *_odp_ishm_address(int block_index);
int _odp_ishm_info(int block_index, _odp_ishm_info_t *info);
int _odp_ishm_status(const char *title);
functionality to export and map memory between ODP instance is added: This includes: - a bit of simplification in _odp_ishm_reserve() for externaly provided file descriptors. - a new function, _odp_ishm_reserve_exported() to map memory from other ODP instances (On same OS) Signed-off-by: Christophe Milard <christophe.milard@linaro.org> --- platform/linux-generic/_ishm.c | 119 ++++++++++++++++++------ platform/linux-generic/include/_ishm_internal.h | 7 ++ 2 files changed, 97 insertions(+), 29 deletions(-) -- 2.7.4