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.mil...@linaro.org>
---
 platform/linux-generic/_ishm.c                  | 119 ++++++++++++++++++------
 platform/linux-generic/include/_ishm_internal.h |   7 ++
 2 files changed, 97 insertions(+), 29 deletions(-)

diff --git a/platform/linux-generic/_ishm.c b/platform/linux-generic/_ishm.c
index dabd426..7624eca 100644
--- a/platform/linux-generic/_ishm.c
+++ b/platform/linux-generic/_ishm.c
@@ -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"
diff --git a/platform/linux-generic/include/_ishm_internal.h 
b/platform/linux-generic/include/_ishm_internal.h
index 4fa6d9c..e49bc12 100644
--- a/platform/linux-generic/include/_ishm_internal.h
+++ b/platform/linux-generic/include/_ishm_internal.h
@@ -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);
-- 
2.7.4

Reply via email to