Hi Bill :
The first is false positive, if I remember right
The second has been addressed since coverity was run but I did not rerun as
it obvioulsy had an impact on the "main repo stat"

Christophe.

On 19 August 2016 at 17:44, Bill Fischofer <bill.fischo...@linaro.org>
wrote:

> Coverity flagged a number of issues against this module (as well as
> _fdserver.c). These should be addressed now rather than later:
>
> On Fri, Aug 19, 2016 at 10:48 AM, Christophe Milard <
> christophe.mil...@linaro.org> wrote:
>
>> A new ODP internal memory allocator, called ishm (for internal shmem)
>> is introduced here.
>> This memory allocator enables the following:
>> - works for odpthreads being linux processes, regardless for fork time.
>> - guarantees the uniqueness of the virtual space mapping address over
>> all ODP threads (even processes and regardless of fork time),
>> when the required _ODP_ISHM_SINGLE_VA flag is used.
>>
>> Signed-off-by: Christophe Milard <christophe.mil...@linaro.org>
>> ---
>>  platform/linux-generic/Makefile.am                 |    4 +
>>  platform/linux-generic/_ishm.c                     | 1336
>> ++++++++++++++++++++
>>  platform/linux-generic/_ishmphy.c                  |  168 +++
>>  platform/linux-generic/arch/arm/odp/api/cpu_arch.h |   25 +-
>>  platform/linux-generic/arch/arm/odp_cpu_arch.c     |   49 +-
>>  .../linux-generic/arch/arm/odp_sysinfo_parse.c     |   28 +-
>>  platform/linux-generic/arch/powerpc/odp_cpu_arch.c |   49 +-
>>  .../linux-generic/include/_fdserver_internal.h     |    1 +
>>  platform/linux-generic/include/_ishm_internal.h    |   45 +
>>  platform/linux-generic/include/_ishmphy_internal.h |   25 +
>>  platform/linux-generic/include/ishmphy_internal.h  |   24 +
>>  .../linux-generic/include/odp_config_internal.h    |   10 +
>>  platform/linux-generic/include/odp_internal.h      |    6 +
>>  platform/linux-generic/odp_init.c                  |   26 +
>>  14 files changed, 1792 insertions(+), 4 deletions(-)
>>  create mode 100644 platform/linux-generic/_ishm.c
>>  create mode 100644 platform/linux-generic/_ishmphy.c
>>  mode change 120000 => 100644 platform/linux-generic/arch/ar
>> m/odp/api/cpu_arch.h
>>  mode change 120000 => 100644 platform/linux-generic/arch/ar
>> m/odp_cpu_arch.c
>>  mode change 120000 => 100644 platform/linux-generic/arch/ar
>> m/odp_sysinfo_parse.c
>>  mode change 120000 => 100644 platform/linux-generic/arch/po
>> werpc/odp_cpu_arch.c
>>  create mode 100644 platform/linux-generic/include/_ishm_internal.h
>>  create mode 100644 platform/linux-generic/include/_ishmphy_internal.h
>>  create mode 100644 platform/linux-generic/include/ishmphy_internal.h
>>
>> diff --git a/platform/linux-generic/Makefile.am
>> b/platform/linux-generic/Makefile.am
>> index cb7c8e9..ac2b2da 100644
>> --- a/platform/linux-generic/Makefile.am
>> +++ b/platform/linux-generic/Makefile.am
>> @@ -113,6 +113,8 @@ odpdrvplatinclude_HEADERS = \
>>
>>  noinst_HEADERS = \
>>                   ${srcdir}/include/_fdserver_internal.h \
>> +                 ${srcdir}/include/_ishm_internal.h \
>> +                 ${srcdir}/include/_ishmphy_internal.h \
>>                   ${srcdir}/include/odp_align_internal.h \
>>                   ${srcdir}/include/odp_atomic_internal.h \
>>                   ${srcdir}/include/odp_buffer_inlines.h \
>> @@ -156,6 +158,8 @@ noinst_HEADERS = \
>>
>>  __LIB__libodp_linux_la_SOURCES = \
>>                            _fdserver.c \
>> +                          _ishm.c \
>> +                          _ishmphy.c \
>>                            odp_atomic.c \
>>                            odp_barrier.c \
>>                            odp_buffer.c \
>> diff --git a/platform/linux-generic/_ishm.c
>> b/platform/linux-generic/_ishm.c
>> new file mode 100644
>> index 0000000..a92d5cc
>> --- /dev/null
>> +++ b/platform/linux-generic/_ishm.c
>> @@ -0,0 +1,1336 @@
>> +/* Copyright (c) 2016, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +/* This file handles the internal shared memory: internal shared memory
>> + * is memory which is sharable by all ODP threads regardless of how the
>> + * ODP thread is implemented (pthread or process) and regardless of
>> fork()
>> + * time.
>> + * Moreover, when reserved with the _ODP_ISHM_SINGLE_VA flag,
>> + * internal shared memory is guaranteed to always be located at the same
>> virtual
>> + * address, i.e. pointers to internal shared memory are fully shareable
>> + * between odp threads (regardless of thread type or fork time) in that
>> case.
>> + * Internal shared memory is mainly meant to be used internaly within ODP
>> + * (hence its name), but may also be allocated by odp applications and
>> drivers,
>> + * in the future (through these interfaces).
>> + * To guarrentee this full pointer shareability (when reserved with the
>> + * _ODP_ISHM_SINGLE_VA flag) internal shared memory is handled as
>> follows:
>> + * At global_init time, a huge virtual address space reservation is
>> performed.
>> + * Note that this is just reserving virtual space, not physical memory.
>> + * Because all ODP threads (pthreads or processes) are descendants of
>> the ODP
>> + * instantiation process, this VA space is inherited by all ODP threads.
>> + * When internal shmem reservation actually occurs, and
>> + * when reserved with the _ODP_ISHM_SINGLE_VA flag, physical memory is
>> + * allocated, and mapped (MAP_FIXED) to some part in the huge
>> preallocated
>> + * address space area:
>> + * because this virtual address space is common to all ODP threads, we
>> + * know this mapping will succeed, and not clash with anything else.
>> + * Hence, an ODP threads which perform a lookup for the same ishm block
>> + * can map it at the same VA address.
>> + * When internal shared memory is released, the physical memory is
>> released
>> + * and the corresponding virtual space returned to its "pool" of
>> preallocated
>> + * virtual space (assuming it was allocated from there).
>> + * Note, though, that, if 2 linux processes share the same ishm block,
>> + * the virtual space is marked as released as soon as one of the
>> processes
>> + * releases the ishm block, but the physical memory space is actually
>> released
>> + * by the kernel once all processes have done a ishm operation (i,e. a
>> sync).
>> + * This is due to the fact that linux does not contain any syscall to
>> unmap
>> + * memory from a different process.
>> + *
>> + * This file contains functions to handle the VA area (handling
>> fragmentation
>> + * and defragmentation resulting from different allocs/release) and also
>> + * define the functions to allocate, release and lookup internal shared
>> + * memory:
>> + *  _odp_ishm_reserve(), _odp_ishm_free*() and _odp_ishm_lookup*()...
>> + */
>> +#include <odp_posix_extensions.h>
>> +#include <odp_config_internal.h>
>> +#include <odp_internal.h>
>> +#include <odp/api/spinlock.h>
>> +#include <odp/api/align.h>
>> +#include <odp/api/system_info.h>
>> +#include <odp/api/debug.h>
>> +#include <odp_shm_internal.h>
>> +#include <odp_debug_internal.h>
>> +#include <odp_align_internal.h>
>> +#include <_fdserver_internal.h>
>> +#include <_ishm_internal.h>
>> +#include <_ishmphy_internal.h>
>> +#include <stdlib.h>
>> +#include <stdio.h>
>> +#include <unistd.h>
>> +#include <string.h>
>> +#include <errno.h>
>> +#include <sys/mman.h>
>> +#include <sys/stat.h>
>> +#include <sys/syscall.h>
>> +#include <fcntl.h>
>> +#include <sys/types.h>
>> +#include <inttypes.h>
>> +#include <sys/wait.h>
>> +
>> +/*
>> + * Maximum number of internal shared memory blocks.
>> + *
>> + * This the the number of separate ISHM areas that can be reserved
>> concurrently
>> + * (Note that freeing such blocks may take time, or possibly never happen
>> + * if some of the block ownwers never procsync() after free). This number
>> + * should take that into account)
>> + */
>> +#define ISHM_MAX_NB_BLOCKS 128
>> +
>> +/*
>> + * Maximum internal shared memory block name length in chars
>> + * probably taking the same number as SHM name size make sense at this
>> stage
>> + */
>> +#define ISHM_NAME_MAXLEN 32
>> +
>> +/*
>> + * Linux underlying file name: <directory>/odp-<odp_pid>-ishm-<name>
>> + * The <name> part may be replaced by a sequence number if no specific
>> + * name is given at reserve time
>> + * <directory> is either /tmp or the hugepagefs mount point for default
>> size.
>> + * (searched at init time)
>> + */
>> +#define ISHM_FILENAME_MAXLEN (ISHM_NAME_MAXLEN + 64)
>> +#define ISHM_FILENAME_FORMAT "%s/odp-%d-ishm-%s"
>> +#define ISHM_FILENAME_NORMAL_PAGE_DIR "/tmp"
>> +
>> +/*
>> + * At worse case the virtual space gets so fragmented that there is
>> + * a unallocated fragment between each allocated fragment:
>> + * In that case, the number of fragments to take care of is twice the
>> + * number of ISHM blocks + 1.
>> + */
>> +#define ISHM_NB_FRAGMNTS (ISHM_MAX_NB_BLOCKS * 2 + 1)
>> +
>> +/*
>> + * A block describes a piece of reserved memory: Any successful
>> ishm_reserve()
>> + * will allocate a block. A ishm_reserve() with the _ODP_ISHM_SINGLE_VA
>> flag set
>> + * will allocated both a block and a fragment.
>> + * Blocks contain only global data common to all processes.
>> + */
>> +typedef struct ishm_fragment ishm_fragment_t; /*forward decl. see below.
>> */
>> +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  */
>> +       int  main_odpthread;     /* The thread which did the initial
>> reserve*/
>> +       uint32_t user_flags;     /* any flags the user want to remember.
>>   */
>> +       uint32_t flags;          /* block creation flags.
>>    */
>> +       uint64_t user_len;       /* length, as requested at reserve
>> time.   */
>> +       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  */
>> +       uint64_t seq;   /* sequence number, incremented on alloc and
>> free   */
>> +       uint64_t refcnt;/* number of linux processes mapping this block
>>    */
>> +} ishm_block_t;
>> +
>> +/*
>> + * Table of blocks describing allocated internal shared memory
>> + * This table is visible to every ODP thread (linux process or pthreads).
>> + * (it is allocated shared at odp init time and is therefore inherited
>> by all)
>> + * Table index is used as handle, so it cannot move!. Entry is regarded
>> as
>> + * free when len==0
>> + */
>> +typedef struct {
>> +       odp_spinlock_t  lock;
>> +       uint64_t dev_seq;       /* used when creating device names */
>> +       ishm_block_t  block[ISHM_MAX_NB_BLOCKS];
>> +} ishm_table_t;
>> +static ishm_table_t *ishm_tbl;
>> +
>> +/*
>> + * Process local table containing the list of (believed) allocated
>> blocks seen
>> + * from the current process. There is one such table per linux process.
>> linux
>> + * threads within a process shares this table.
>> + * The contents within this table may become obsolete when other
>> processes
>> + * reserve/free ishm blocks. This is what the procsync() function
>> + * catches by comparing the block sequence number with the one in this
>> table.
>> + * This table is filled at ishm_reserve and ishm_lookup time.
>> + * Entries are removed at ishm_free or procsync time.
>> + * Note that flags and len are present in this table and seems to be
>> redundant
>> + * with those present in the ishm block table: but this is not fully
>> true:
>> + * When ishm_sync() detects obsolete mappings and tries to remove them,
>> + * the entry in the ishm block table is then obsolete, and the values
>> which are
>> + * found in this table must be used to perform the ummap.
>> + * (and the values in the block tables are needed at lookup time...)
>> + */
>> +typedef struct {
>> +       int thrd_refcnt; /* number of pthreads in this process, really */
>> +       struct {
>> +               int   block_index; /* entry in the ishm_tbl       */
>> +               uint32_t flags;    /* flags used at creation time */
>> +               uint64_t seq;
>> +               void *start;  /* start of block (VA)
>>     */
>> +               uint64_t len; /* length of block. multiple of page size
>>      */
>> +               int fd;       /* file descriptor used for this block
>>     */
>> +       } entry[ISHM_MAX_NB_BLOCKS];
>> +       int nb_entries;
>> +} ishm_proctable_t;
>> +static ishm_proctable_t *ishm_proctable;
>> +
>> +/*
>> + * A fragment describes a piece of the shared virtual address space,
>> + * and is allocated only when allocation is done with the
>> _ODP_ISHM_SINGLE_VA
>> + * flag:
>> + * A fragment is said to be used when it actually does represent some
>> + * portion of the virtual address space, and is said to be unused when
>> + * it does not (so at start, one single fragment is used -describing the
>> + * whole address space as unallocated-, and all others are unused).
>> + * Fragments get used as address space fragmentation increases.
>> + * A fragment is allocated if the piece of address space it
>> + * describes is actually used by a shared memory block.
>> + * Allocated fragments get their block_index set >=0.
>> + */
>> +typedef struct ishm_fragment {
>> +       struct ishm_fragment *prev; /* not used when the fragment is
>> unused */
>> +       struct ishm_fragment *next;
>> +       void *start;            /* start of segment (VA) */
>> +       uintptr_t   len;        /* length of segment. multiple of page
>> size */
>> +       int   block_index;      /* -1 for unallocated fragments */
>> +} ishm_fragment_t;
>> +
>> +/*
>> + * Table of fragments describing the common virtual address space:
>> + * This table is visible to every ODP thread (linux process or pthreads).
>> + * (it is allocated at odp init time and is therefore inherited by all)
>> + */
>> +typedef struct {
>> +       ishm_fragment_t  fragment[ISHM_NB_FRAGMNTS];
>> +       ishm_fragment_t  *used_fragmnts; /* ordered by increasing start
>> addr */
>> +       ishm_fragment_t  *unused_fragmnts;
>> +} ishm_ftable_t;
>> +static ishm_ftable_t *ishm_ftbl;
>> +
>> +#ifndef MAP_ANONYMOUS
>> +#define MAP_ANONYMOUS MAP_ANON
>> +#endif
>> +
>> +/* prototypes: */
>> +static void procsync(void);
>> +
>> +/*
>> + * Take a piece of the preallocated virtual space to fit "size" bytes.
>> + * (best fit). Size must be rounded up to an integer number of pages
>> size.
>> + * Possibly split the fragment to keep track of remaining space.
>> + * Returns the allocated fragment (best_fragmnt) and the corresponding
>> address.
>> + * External caller must ensure mutex before the call!
>> + */
>> +static void *alloc_fragment(uintptr_t size, int block_index, intptr_t
>> align,
>> +                           ishm_fragment_t **best_fragmnt)
>> +{
>> +       ishm_fragment_t *fragmnt;
>> +       *best_fragmnt = NULL;
>> +       ishm_fragment_t *rem_fragmnt;
>> +       uintptr_t border;/* possible start of new fragment (next
>> alignement)  */
>> +       intptr_t left;   /* room remaining after, if the segment is
>> allocated */
>> +       uintptr_t remainder = ODP_CONFIG_ISHM_VA_PREALLOC_SZ;
>> +
>> +       /*
>> +        * search for the best bit, i.e. search for the unallocated
>> fragment
>> +        * would give less remainder if the new fragment was allocated
>> within
>> +        * it:
>> +        */
>> +       for (fragmnt = ishm_ftbl->used_fragmnts;
>> +            fragmnt; fragmnt = fragmnt->next) {
>> +               /* skip allocated segment: */
>> +               if (fragmnt->block_index >= 0)
>> +                       continue;
>> +               /* skip too short segment: */
>> +               border = ((uintptr_t)fragmnt->start + align - 1) &
>> (-align);
>> +               left =
>> +                  ((uintptr_t)fragmnt->start + fragmnt->len) - (border +
>> size);
>> +               if (left < 0)
>> +                       continue;
>> +               /* remember best fit: */
>> +               if ((uintptr_t)left < remainder) {
>> +                       remainder = left; /* best, so far */
>> +                       *best_fragmnt = fragmnt;
>> +               }
>> +       }
>> +
>> +       if (!(*best_fragmnt)) {
>> +               ODP_ERR("unable to get virtual address for shmem
>> block!\n.");
>> +               return NULL;
>> +       }
>> +
>> +       (*best_fragmnt)->block_index = block_index;
>> +       border = ((uintptr_t)(*best_fragmnt)->start + align - 1) &
>> (-align);
>> +
>> +       /*
>> +        * if there is room between previous fragment and new one, (due to
>> +        * alignement requirement) then fragment (split) the space between
>> +        * the end of the previous fragment and the beginning of the new
>> one:
>> +        */
>> +       if (border - (uintptr_t)(*best_fragmnt)->start > 0) {
>> +               /* frangment space, i.e. take a new fragment
>> descriptor... */
>> +               rem_fragmnt = ishm_ftbl->unused_fragmnts;
>> +               if (!rem_fragmnt) {
>> +                       ODP_ERR("unable to get shmem fragment
>> descriptor!\n.");
>> +                       return NULL;
>> +               }
>> +               ishm_ftbl->unused_fragmnts = rem_fragmnt->next;
>> +
>> +               /* and link it between best_fragmnt->prev and
>> best_fragmnt */
>> +               if ((*best_fragmnt)->prev)
>> +                       (*best_fragmnt)->prev->next = rem_fragmnt;
>> +               else
>> +                       ishm_ftbl->used_fragmnts = rem_fragmnt;
>> +               rem_fragmnt->prev = (*best_fragmnt)->prev;
>> +               (*best_fragmnt)->prev = rem_fragmnt;
>> +               rem_fragmnt->next = (*best_fragmnt);
>> +
>> +               /* update length: rem_fragmnt getting space before border
>> */
>> +               rem_fragmnt->block_index = -1;
>> +               rem_fragmnt->start = (*best_fragmnt)->start;
>> +               rem_fragmnt->len = border - (uintptr_t)(*best_fragmnt)->st
>> art;
>> +               (*best_fragmnt)->start =
>> +                    (void *)((uintptr_t)rem_fragmnt->start +
>> rem_fragmnt->len);
>> +               (*best_fragmnt)->len -= rem_fragmnt->len;
>> +       }
>> +
>> +       /* if this was a perfect fit, i.e. no free space follows, we are
>> done */
>> +       if (remainder == 0)
>> +               return (*best_fragmnt)->start;
>> +
>> +       /* otherwise, frangment space, i.e. take a new fragment
>> descriptor... */
>> +       rem_fragmnt = ishm_ftbl->unused_fragmnts;
>> +       if (!rem_fragmnt) {
>> +               ODP_ERR("unable to get shmem fragment descriptor!\n.");
>> +               return (*best_fragmnt)->start;
>> +       }
>> +       ishm_ftbl->unused_fragmnts = rem_fragmnt->next;
>> +
>> +       /* ... double link it... */
>> +       rem_fragmnt->next = (*best_fragmnt)->next;
>> +       rem_fragmnt->prev = (*best_fragmnt);
>> +       if ((*best_fragmnt)->next)
>> +               (*best_fragmnt)->next->prev = rem_fragmnt;
>> +       (*best_fragmnt)->next = rem_fragmnt;
>> +
>> +       /* ... and keep track of the remainder */
>> +       (*best_fragmnt)->len = size;
>> +       rem_fragmnt->len = remainder;
>> +       rem_fragmnt->start = (void *)((char *)(*best_fragmnt)->start +
>> size);
>> +       rem_fragmnt->block_index = -1;
>> +
>> +       return (*best_fragmnt)->start;
>> +}
>> +
>> +/*
>> + * Free a portion of virtual space.
>> + * Possibly defragment, if the freed fragment is adjacent to another
>> + * free virtual fragment.
>> + * External caller must ensure mutex before the call!
>> + */
>> +static void free_fragment(ishm_fragment_t *fragmnt)
>> +{
>> +       ishm_fragment_t *prev_f;
>> +       ishm_fragment_t *next_f;
>> +
>> +       /* sanity check */
>> +       if (!fragmnt)
>> +               return;
>> +
>> +       prev_f = fragmnt->prev;
>> +       next_f = fragmnt->next;
>> +
>> +       /* free the fragment */
>> +       fragmnt->block_index = -1;
>> +
>> +       /* check if the previous fragment is also free: if so, defragment
>> */
>> +       if (prev_f && (prev_f->block_index < 0)) {
>> +               fragmnt->start = prev_f->start;
>> +               fragmnt->len += prev_f->len;
>> +               if (prev_f->prev) {
>> +                       prev_f->prev->next = fragmnt;
>> +               } else {
>> +                       if (ishm_ftbl->used_fragmnts == prev_f)
>> +                               ishm_ftbl->used_fragmnts = fragmnt;
>> +                       else
>> +                               ODP_ERR("corrupted fragment list!.\n");
>> +               }
>> +               fragmnt->prev = prev_f->prev;
>> +
>> +               /* put removed fragment in free list */
>> +               prev_f->prev = NULL;
>> +               prev_f->next = ishm_ftbl->unused_fragmnts;
>> +               ishm_ftbl->unused_fragmnts = prev_f;
>> +       }
>> +
>> +       /* check if the next fragment is also free: if so, defragment */
>> +       if (next_f && (next_f->block_index < 0)) {
>> +               fragmnt->len += next_f->len;
>> +               if (next_f->next)
>> +                       next_f->next->prev = fragmnt;
>> +               fragmnt->next = next_f->next;
>> +
>> +               /* put removed fragment in free list */
>> +               next_f->prev = NULL;
>> +               next_f->next = ishm_ftbl->unused_fragmnts;
>> +               ishm_ftbl->unused_fragmnts = next_f;
>> +       }
>> +}
>> +
>> +/*
>> + * Create file with size len. returns -1 on error
>> + * Creates a file to /tmp/odp-<pid>-<sequence_or_name> (for normal
>> pages)
>> + * 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)
>> +{
>> +       char *name;
>> +       int  fd;
>> +       ishm_block_t *new_block;          /* entry in the main block
>> table    */
>> +       char seq_string[ISHM_FILENAME_MAXLEN];   /* used to construct
>> filename*/
>> +       char filename[ISHM_FILENAME_MAXLEN];/* filename in /tmp/ or
>> /mnt/huge */
>> +       int  oflag = O_RDWR | O_CREAT | O_TRUNC; /* flags for open
>>     */
>> +
>> +       new_block = &ishm_tbl->block[block_index];
>> +       name = new_block->name;
>> +
>> +       /* create the filename: */
>> +       snprintf(seq_string, ISHM_FILENAME_MAXLEN, "%08" PRIu64,
>> +                ishm_tbl->dev_seq++);
>> +
>> +       /* huge dir must be known to create files there!: */
>> +       if (huge && !odp_global_data.hugepage_info.default_huge_page_dir)
>> +               return -1;
>> +
>> +       if (huge)
>> +               snprintf(filename, ISHM_FILENAME_MAXLEN,
>> +                        ISHM_FILENAME_FORMAT,
>> +                        odp_global_data.hugepage_info.
>> default_huge_page_dir,
>> +                        odp_global_data.main_pid,
>> +                        (name && name[0]) ? name : seq_string);
>> +       else
>> +               snprintf(filename, ISHM_FILENAME_MAXLEN,
>> +                        ISHM_FILENAME_FORMAT,
>> +                        ISHM_FILENAME_NORMAL_PAGE_DIR,
>> +                        odp_global_data.main_pid,
>> +                        (name && name[0]) ? name : seq_string);
>> +
>> +       fd = open(filename, oflag, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
>> +       if (fd < 0) {
>> +               ODP_ERR("open failed for %s: %s.\n",
>> +                       filename, strerror(errno));
>> +               return -1;
>> +       }
>> +
>> +       if (ftruncate(fd, len) == -1) {
>> +               ODP_ERR("ftruncate failed: fd=%d, err=%s.\n",
>> +                       fd, strerror(errno));
>> +               close(fd);
>> +               return -1;
>> +       }
>> +
>> +       strncpy(new_block->filename, filename, ISHM_FILENAME_MAXLEN - 1);
>> +
>> +       return fd;
>> +}
>> +
>> +/*
>> + * performs the mapping, possibly allocating a fragment of the
>> pre-reserved
>> + * VA space if the _ODP_ISHM_SINGLE_VA flag was given.
>> + * Sets fd, and returns the mapping address.
>> + * This funstion will also set the _ODP_ISHM_SINGLE_VA flag if the
>> alignment
>> + * requires it
>> + * 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)
>> +{
>> +       ishm_block_t *new_block;          /* entry in the main block
>> table   */
>> +       void *addr = NULL;
>> +       void *mapped_addr;
>> +       ishm_fragment_t *fragment = NULL;
>> +
>> +       new_block = &ishm_tbl->block[block_index];
>> +
>> +       /*
>> +        * Creates a file to /tmp/odp-<pid>-<sequence> (for normal pages)
>> +        * or /mnt/huge/odp-<pid>-<sequence> (for huge pages)
>> +        * unless a fd was already given
>> +        */
>> +       if (*fd < 0) {
>> +               *fd = create_file(block_index, huge, len);
>> +               if (*fd < 0)
>> +                       return NULL;
>> +       } else {
>> +               new_block->filename[0] = 0;
>> +       }
>> +
>> +       /* allocate an address range in the prebooked VA area if needed */
>> +       if (flags & _ODP_ISHM_SINGLE_VA) {
>> +               addr = alloc_fragment(len, block_index, align, &fragment);
>> +               if (!addr) {
>> +                       ODP_ERR("alloc_fragment failed.\n");
>> +                       if (new_block->filename[0]) {
>> +                               close(*fd);
>> +                               *fd = -1;
>> +                               unlink(new_block->filename);
>> +                       }
>> +                       return NULL;
>> +               }
>> +               ishm_tbl->block[block_index].fragment = fragment;
>> +       }
>> +
>> +       /* try to mmap: */
>> +       mapped_addr = _odp_ishmphy_map(*fd, addr, len, flags);
>> +       if (mapped_addr == NULL) {
>> +               if (flags & _ODP_ISHM_SINGLE_VA)
>> +                       free_fragment(fragment);
>> +               if (new_block->filename[0]) {
>> +                       close(*fd);
>> +                       *fd = -1;
>> +                       unlink(new_block->filename);
>> +               }
>> +               return NULL;
>> +       }
>> +
>> +       new_block->huge = huge;
>> +
>> +       return mapped_addr;
>> +}
>> +
>> +/*
>> + * Performs an extra mapping (for a process trying to see an existing
>> block
>> + * i.e. performing a lookup).
>> + * Mutex must be assured by the caller.
>> + */
>> +static void *do_remap(int block_index, int fd)
>> +{
>> +       void *mapped_addr;
>> +       ishm_fragment_t *fragment;
>> +       uint64_t len;
>> +       uint32_t flags;
>> +
>> +       len   = ishm_tbl->block[block_index].len;
>> +       flags = ishm_tbl->block[block_index].flags;
>> +
>> +       if (flags & _ODP_ISHM_SINGLE_VA) {
>> +               fragment = ishm_tbl->block[block_index].fragment;
>> +               if (!fragment) {
>> +                       ODP_ERR("invalid fragment failure.\n");
>> +                       return NULL;
>> +               }
>> +
>> +               /* try to mmap: */
>> +               mapped_addr = _odp_ishmphy_map(fd, fragment->start, len,
>> flags);
>> +               if (mapped_addr == NULL)
>> +                       return NULL;
>> +               return mapped_addr;
>> +       }
>> +
>> +       /* try to mmap: */
>> +       mapped_addr = _odp_ishmphy_map(fd, NULL, len, flags);
>> +       if (mapped_addr == NULL)
>> +               return NULL;
>> +
>> +       return mapped_addr;
>> +}
>> +
>> +/*
>> + * Performs unmapping, possibly freeing a prereserved VA space fragment,
>> + * if the _ODP_ISHM_SINGLE_VA flag was set at alloc time
>> + * Mutex must be assured by the caller.
>> + */
>> +static int do_unmap(void *start, uint64_t size, uint32_t flags,
>> +                   int block_index)
>> +{
>> +       int ret;
>> +
>> +       if (start)
>> +               ret = _odp_ishmphy_unmap(start, size, flags);
>> +       else
>> +               ret = 0;
>> +
>> +       if ((block_index >= 0) && (flags & _ODP_ISHM_SINGLE_VA)) {
>> +               /* mark reserved address space as free */
>> +               free_fragment(ishm_tbl->block[block_index].fragment);
>> +       }
>> +
>> +       return ret;
>> +}
>> +
>> +/*
>> + * Search for a given used and allocated block name.
>> + * (search is performed in the global ishm table)
>> + * Returns the index of the found block (if any) or -1 if none.
>> + * Mutex must be assured by the caller.
>> + */
>> +static int find_block_by_name(const char *name)
>> +{
>> +       int i;
>> +
>> +       if (name == NULL || name[0] == 0)
>> +               return -1;
>> +
>> +       for (i = 0; i < ISHM_MAX_NB_BLOCKS; i++) {
>> +               if ((ishm_tbl->block[i].len) &&
>> +                   (strcmp(name, ishm_tbl->block[i].name) == 0))
>> +                       return i;
>> +       }
>> +
>> +       return -1;
>> +}
>> +
>> +/*
>> + * Search for a block by address (only works when flag
>> _ODP_ISHM_SINGLE_VA
>> + * was set at reserve() time, or if the block is already known by this
>> + * process).
>> + * Search is performed in the process table and in the global ishm table.
>> + * The provided address does not have to be at start: any address
>> + * within the fragment is OK.
>> + * Returns the index to the found block (if any) or -1 if none.
>> + * Mutex must be assured by the caller.
>> + */
>> +static int find_block_by_address(void *addr)
>> +{
>> +       int block_index;
>> +       int i;
>> +       ishm_fragment_t *fragmnt;
>> +
>> +       /*
>> +        * first check if there is already a process known block for this
>> +        * address
>> +        */
>> +       for (i = 0; i < ishm_proctable->nb_entries; i++) {
>> +               block_index = ishm_proctable->entry[i].block_index;
>> +               if ((addr > ishm_proctable->entry[i].start) &&
>> +                   ((char *)addr < ((char *)ishm_proctable->entry[i].start
>> +
>> +                                    ishm_tbl->block[block_index].len)))
>> +                       return block_index;
>> +       }
>> +
>> +       /*
>> +        * then check if there is a existing single VA block known by
>> some other
>> +        * process and containing the given address
>> +        */
>> +       for (i = 0; i < ISHM_MAX_NB_BLOCKS; i++) {
>> +               if ((!ishm_tbl->block[i].len) ||
>> +                   (!(ishm_tbl->block[i].flags & _ODP_ISHM_SINGLE_VA)))
>> +                       continue;
>> +               fragmnt = ishm_tbl->block[i].fragment;
>> +               if (!fragmnt) {
>> +                       ODP_ERR("find_fragment: invalid NULL fragment\n");
>> +                       return -1;
>> +               }
>> +               if ((addr >= fragmnt->start) &&
>> +                   ((char *)addr < ((char *)fragmnt->start +
>> fragmnt->len)))
>> +                       return i;
>> +       }
>> +
>> +       /* address does not belong to any accessible block: */
>> +       return -1;
>> +}
>> +
>> +/*
>> + * Search a given ishm block in the process local table. Return its index
>> + * in the process table or -1 if not found (meaning that the ishm table
>> + * block index was not referenced in the process local table, i.e. the
>> + * block is known by some other process, but not by the current process).
>> + * Caller must assure mutex.
>> + */
>> +static int procfind_block(int block_index)
>> +{
>> +       int i;
>> +
>> +       for (i = 0; i < ishm_proctable->nb_entries; i++) {
>> +               if (ishm_proctable->entry[i].block_index == block_index)
>> +                       return i;
>> +       }
>> +       return -1;
>> +}
>> +
>> +/*
>> + * Release the physical memory mapping for blocks which have been freed
>> + * by other processes. Caller must ensure mutex.
>> + * Mutex must be assured by the caller.
>> + */
>> +static void procsync(void)
>> +{
>> +       int i = 0;
>> +       int last;
>> +       ishm_block_t *block;
>> +
>> +       last = ishm_proctable->nb_entries;
>> +       while (i < last) {
>> +               /* if the procecess sequence number doesn't match the main
>> +                * table seq number, this entry is obsolete
>> +                */
>> +               block = &ishm_tbl->block[ishm_proctabl
>> e->entry[i].block_index];
>> +               if (ishm_proctable->entry[i].seq != block->seq) {
>> +                       /* obsolete entry: free memory and remove proc
>> entry */
>> +                       close(ishm_proctable->entry[i].fd);
>> +                       _odp_ishmphy_unmap(ishm_proct
>> able->entry[i].start,
>> +                                          ishm_proctable->entry[i].len,
>> +                                          ishm_proctable->entry[i].flags
>> );
>> +                       ishm_proctable->entry[i] =
>> +                       ishm_proctable->entry[--last];
>> +               } else {
>> +                       i++;
>> +               }
>> +       }
>> +       ishm_proctable->nb_entries = last;
>> +}
>> +
>> +/*
>> + * Allocate and map internal shared memory, or other objects:
>> + * If a name is given, check that this name is not already in use.
>> + * If ok, allocate a new shared memory block and map the
>> + * provided fd in it (if fd >=0 was given).
>> + * If no fd is provided, a shared memory file desc named
>> + * /tmp/odp-<pid>-ishm-<name_or_sequence> is created and mapped.
>> + * (the name is different for huge page file as they must be on
>> hugepagefs)
>> + * The function returns the index of the newly created block in the
>> + * main block table (>=0) or -1 on error.
>> + */
>> +int _odp_ishm_reserve(const char *name, uint64_t size, int fd,
>> +                     uint32_t align, uint32_t flags, uint32_t user_flags)
>> +{
>> +       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();
>> +
>> +       odp_spinlock_lock(&ishm_tbl->lock);
>> +
>> +       /* update this process view... */
>> +       procsync();
>> +
>> +       /* roundup to page size */
>> +       alloc_size = (size + (page_sz - 1)) & (-page_sz);
>> +
>> +       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)) {
>> +               /* Found a block with the same name */
>> +               odp_spinlock_unlock(&ishm_tbl->lock);
>> +               ODP_ERR("name \"%s\" already used.\n", name);
>> +               return -1;
>> +       }
>> +
>> +       /* grab a new entry: */
>> +       for (new_index = 0; new_index < ISHM_MAX_NB_BLOCKS; new_index++) {
>> +               if (ishm_tbl->block[new_index].len == 0) {
>> +                       /* Found free block */
>> +                       break;
>> +               }
>> +       }
>> +
>> +       /* check if we have reached the maximum number of allocation: */
>> +       if (new_index >= ISHM_MAX_NB_BLOCKS) {
>> +               odp_spinlock_unlock(&ishm_tbl->lock);
>> +               ODP_ERR("ISHM_MAX_NB_BLOCKS limit reached!\n");
>> +               return -1;
>> +       }
>> +
>> +       new_block = &ishm_tbl->block[new_index];
>> +
>> +       /* save block name (if any given): */
>> +       if (name)
>> +               strncpy(new_block->name, name, ISHM_NAME_MAXLEN - 1);
>> +       else
>> +               new_block->name[0] = 0;
>> +
>> +       /* Try first huge pages when possible and needed: */
>> +       if (page_hp_size && (alloc_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
>> +                * the same address every where, otherwise alignment may
>> be
>> +                * be wrong for some process */
>> +               hp_align = align;
>> +               if (hp_align < odp_sys_huge_page_size())
>> +                       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);
>> +
>> +               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;
>> +       }
>> +
>> +       /* try normal pages if huge pages failed */
>> +       if (addr == NULL) {
>> +               /* 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
>> +                * the same address every where, otherwise alignment may
>> be
>> +                * be wrong for some process */
>> +               if (align < odp_sys_page_size())
>> +                       align = odp_sys_page_size();
>> +               else
>> +                       flags |= _ODP_ISHM_SINGLE_VA;
>> +
>> +               len = alloc_size;
>> +               addr = do_map(new_index, len, align, flags, 0, &fd);
>> +               new_block->huge = 0;
>> +       }
>> +
>> +       /* if neither huge pages or normal pages works, we cannot
>> proceed: */
>> +       if ((addr == NULL) || (len == 0)) {
>> +               if ((new_block->filename[0]) && (fd >= 0))
>> +                       close(fd);
>> +               odp_spinlock_unlock(&ishm_tbl->lock);
>> +               ODP_ERR("_ishm_reserve failed.\n");
>>
>
>
> CID 168963 (#1 of 1): Resource leak (RESOURCE_LEAK)17. leaked_handle: 
> Returning
> without closing handle fd leaks it.
>
>
>> +               return -1;
>> +       }
>> +
>> +       /* remember block data and increment block seq number to mark
>> change */
>> +       new_block->len = len;
>> +       new_block->user_len = size;
>> +       new_block->flags = flags;
>> +       new_block->user_flags = user_flags;
>> +       new_block->seq++;
>> +       new_block->refcnt = 1;
>> +       new_block->main_odpthread = odp_thread_id();
>> +       new_block->start = addr; /* only for SINGLE_VA*/
>> +
>> +       /* the allocation succeeded: update the process local view */
>> +       new_proc_entry = ishm_proctable->nb_entries++;
>> +       ishm_proctable->entry[new_proc_entry].block_index = new_index;
>> +       ishm_proctable->entry[new_proc_entry].flags = flags;
>> +       ishm_proctable->entry[new_proc_entry].seq = new_block->seq;
>> +       ishm_proctable->entry[new_proc_entry].start = addr;
>> +       ishm_proctable->entry[new_proc_entry].len = len;
>> +       ishm_proctable->entry[new_proc_entry].fd = fd;
>> +
>> +       /* register the file descriptor to the file descriptor server. */
>> +       _odp_fdserver_register_fd(FD_SRV_CTX_ISHM, new_index, fd);
>> +
>> +       odp_spinlock_unlock(&ishm_tbl->lock);
>> +       return new_index;
>> +}
>> +
>> +/*
>> + * Free and unmap internal shared memory:
>> + * The file descriptor is closed and the .../odp-* file deleted,
>> + * unless fd was externally provided at reserve() time.
>> + * return 0 if OK, and -1 on error.
>> + * Mutex must be assured by the caller.
>> + */
>> +static int block_free(int block_index)
>> +{
>> +       int proc_index;
>> +       ishm_block_t *block;          /* entry in the main block table*/
>> +       int last;
>> +
>> +       if ((block_index < 0) ||
>> +           (block_index >= ISHM_MAX_NB_BLOCKS) ||
>> +           (ishm_tbl->block[block_index].len == 0)) {
>> +               ODP_ERR("Request to free an invalid block\n");
>> +               return -1;
>> +       }
>> +
>> +       block = &ishm_tbl->block[block_index];
>> +
>> +       proc_index = procfind_block(block_index);
>> +       if (proc_index >= 0) {
>> +               /* close the fd, unless if it was externaly provided */
>>
>
>
>
> CID 168952 (#1 of 1): Array compared against 0 (NO_EFFECT)array_null:
> Comparing an array to null is not useful: block->filename, since the test
> will always evaluate as true.
>
> Was block->filename formerly declared as a pointer?
>
> +               if ((block->filename[0] != 0) ||
>> +                   (odp_thread_id() != block->main_odpthread))
>> +                       close(ishm_proctable->entry[proc_index].fd);
>> +
>> +               /* remove the mapping and possible fragment */
>> +               do_unmap(ishm_proctable->entry[proc_index].start,
>> +                        block->len,
>> +                        ishm_proctable->entry[proc_index].flags,
>> +                        block_index);
>> +
>> +               /* remove entry from process local table: */
>> +                       last = ishm_proctable->nb_entries - 1;
>> +                       ishm_proctable->entry[proc_index] =
>> +                               ishm_proctable->entry[last];
>> +                       ishm_proctable->nb_entries = last;
>> +       } else {
>> +               /* just possibly free the fragment as no mapping exist
>> here: */
>> +               do_unmap(NULL, 0, block->flags, block_index);
>> +       }
>> +
>> +       /* remove the .../odp-* file, unless fd was external: */
>> +       if (block->filename[0] != 0)
>> +               unlink(block->filename);
>> +
>> +       /* deregister the file descriptor from the file descriptor
>> server. */
>> +       _odp_fdserver_deregister_fd(FD_SRV_CTX_ISHM, block_index);
>> +
>> +       /* mark the block as free in the main block table: */
>> +       block->len = 0;
>> +
>> +       /* mark the change so other processes see this entry as obsolete:
>> */
>> +       block->seq++;
>> +
>> +       return 0;
>> +}
>> +
>> +/*
>> + * Free and unmap internal shared memory, intentified by its block
>> number:
>> + * return -1 on error. 0 if OK.
>> + */
>> +int _odp_ishm_free_by_index(int block_index)
>> +{
>> +       int ret;
>> +
>> +       odp_spinlock_lock(&ishm_tbl->lock);
>> +       procsync();
>> +
>> +       ret = block_free(block_index);
>> +       odp_spinlock_unlock(&ishm_tbl->lock);
>> +       return ret;
>> +}
>> +
>> +/*
>> + * free and unmap internal shared memory, intentified by its block name:
>> + * return -1 on error. 0 if OK.
>> + */
>> +int _odp_ishm_free_by_name(const char *name)
>> +{
>> +       int block_index;
>> +       int ret;
>> +
>> +       odp_spinlock_lock(&ishm_tbl->lock);
>> +       procsync();
>> +
>> +       /* search the block in main ishm table */
>> +       block_index = find_block_by_name(name);
>> +       if (block_index < 0) {
>> +               ODP_ERR("Request to free an non existing block..."
>> +                       " (double free?)\n");
>> +               odp_spinlock_unlock(&ishm_tbl->lock);
>> +               return -1;
>> +       }
>> +
>> +       ret = block_free(block_index);
>> +       odp_spinlock_unlock(&ishm_tbl->lock);
>> +       return ret;
>> +}
>> +
>> +/*
>> + * Free and unmap internal shared memory identified by address:
>> + * return -1 on error. 0 if OK.
>> + */
>> +int _odp_ishm_free_by_address(void *addr)
>> +{
>> +       int block_index;
>> +       int ret;
>> +
>> +       odp_spinlock_lock(&ishm_tbl->lock);
>> +       procsync();
>> +
>> +       /* search the block in main ishm table */
>> +       block_index = find_block_by_address(addr);
>> +       if (block_index < 0) {
>> +               ODP_ERR("Request to free an non existing block..."
>> +                       " (double free?)\n");
>> +               odp_spinlock_unlock(&ishm_tbl->lock);
>> +               return -1;
>> +       }
>> +
>> +       ret = block_free(block_index);
>> +
>> +       odp_spinlock_unlock(&ishm_tbl->lock);
>> +       return ret;
>> +}
>> +
>> +/*
>> + * Lookup for an ishm shared memory, identified by its block index
>> + * in the main ishm block table.
>> + * Map this ishm area in the process VA (if not already present).
>> + * Returns the block user address or NULL on error.
>> + * Mutex must be assured by the caller.
>> + */
>> +static void *block_lookup(int block_index)
>> +{
>> +       int proc_index;
>> +       int fd = -1;
>> +       ishm_block_t *block;
>> +       void *mapped_addr;
>> +       int new_entry;
>> +
>> +       if ((block_index < 0) ||
>> +           (block_index >= ISHM_MAX_NB_BLOCKS) ||
>> +           (ishm_tbl->block[block_index].len == 0)) {
>> +               ODP_ERR("Request to lookup an invalid block\n");
>> +               return NULL;
>> +       }
>> +
>> +       /* search it in process table: if there, this process knows it
>> already*/
>> +       proc_index = procfind_block(block_index);
>> +       if (proc_index >= 0)
>> +               return ishm_proctable->entry[proc_index].start;
>> +
>> +       /* this ishm is not known by this process, yet: we create the
>> mapping.*/
>> +       fd = _odp_fdserver_lookup_fd(FD_SRV_CTX_ISHM, block_index);
>> +       if (fd < 0) {
>> +               ODP_ERR("Could not find ishm file descriptor (BUG!)\n");
>> +               return NULL;
>> +       }
>> +
>> +       /* perform the mapping */
>> +       block = &ishm_tbl->block[block_index];
>> +
>> +       mapped_addr = do_remap(block_index, fd);
>> +       if (mapped_addr == NULL) {
>> +               ODP_ERR(" lookup: Could not map existing shared
>> memory!\n");
>> +               return NULL;
>> +       }
>> +
>> +       /* the mapping succeeded: update the process local view */
>> +       new_entry = ishm_proctable->nb_entries++;
>> +       ishm_proctable->entry[new_entry].block_index  = block_index;
>> +       ishm_proctable->entry[new_entry].flags        = block->flags;
>> +       ishm_proctable->entry[new_entry].seq          = block->seq;
>> +       ishm_proctable->entry[new_entry].start        = mapped_addr;
>> +       ishm_proctable->entry[new_entry].len          = block->len;
>> +       ishm_proctable->entry[new_entry].fd           = fd;
>> +       block->refcnt++;
>> +
>> +       return mapped_addr;
>> +}
>> +
>> +/*
>> + * Lookup for an ishm shared memory, identified by its block_index.
>> + * Maps this ishmem area in the process VA (if not already present).
>> + * Returns the block user address, or NULL  if the index
>> + * does not match any known ishm blocks.
>> + */
>> +void *_odp_ishm_lookup_by_index(int block_index)
>> +{
>> +       void *ret;
>> +
>> +       odp_spinlock_lock(&ishm_tbl->lock);
>> +       procsync();
>> +
>> +       ret = block_lookup(block_index);
>> +       odp_spinlock_unlock(&ishm_tbl->lock);
>> +       return ret;
>> +}
>> +
>> +/*
>> + * Lookup for an ishm shared memory, identified by its block name.
>> + * Map this ishm area in the process VA (if not already present).
>> + * Return the block index, or -1  if the index
>> + * does not match any known ishm blocks.
>> + */
>> +int _odp_ishm_lookup_by_name(const char *name)
>> +{
>> +       int block_index;
>> +
>> +       odp_spinlock_lock(&ishm_tbl->lock);
>> +       procsync();
>> +
>> +       /* search the block in main ishm table: return -1 if not found: */
>> +       block_index = find_block_by_name(name);
>> +       if ((block_index < 0) || (!block_lookup(block_index))) {
>> +               odp_spinlock_unlock(&ishm_tbl->lock);
>> +               return -1;
>> +       }
>> +
>> +       odp_spinlock_unlock(&ishm_tbl->lock);
>> +       return block_index;
>> +}
>> +
>> +/*
>> + * Lookup for an ishm shared memory block, identified by its VA address.
>> + * This works only if the block has already been looked-up (mapped) by
>> the
>> + * current process or it it was created with the _ODP_ISHM_SINGLE_VA
>> flag.
>> + * Map this ishm area in the process VA (if not already present).
>> + * Return the block index, or -1  if the address
>> + * does not match any known ishm blocks.
>> + */
>> +int _odp_ishm_lookup_by_address(void *addr)
>> +{
>> +       int block_index;
>> +
>> +       odp_spinlock_lock(&ishm_tbl->lock);
>> +       procsync();
>> +
>> +       /* search the block in main ishm table: return -1 if not found: */
>> +       block_index = find_block_by_address(addr);
>> +       if ((block_index < 0) || (!block_lookup(block_index))) {
>> +               odp_spinlock_unlock(&ishm_tbl->lock);
>> +               return -1;
>> +       }
>> +
>> +       odp_spinlock_unlock(&ishm_tbl->lock);
>> +       return block_index;
>> +}
>> +
>> +/*
>> + * Returns the VA address of a given block (which has to be known in the
>> current
>> + * process). Returns NULL if the block is unknown.
>> + */
>> +void *_odp_ishm_address(int block_index)
>> +{
>> +       int proc_index;
>> +       void *addr;
>> +
>> +       odp_spinlock_lock(&ishm_tbl->lock);
>> +       procsync();
>> +
>> +       if ((block_index < 0) ||
>> +           (block_index >= ISHM_MAX_NB_BLOCKS) ||
>> +           (ishm_tbl->block[block_index].len == 0)) {
>> +               ODP_ERR("Request for address on an invalid block\n");
>> +               odp_spinlock_unlock(&ishm_tbl->lock);
>> +               return NULL;
>> +       }
>> +
>> +       proc_index = procfind_block(block_index);
>> +       if (proc_index < 0) {
>> +               odp_spinlock_unlock(&ishm_tbl->lock);
>> +               return NULL;
>> +       }
>> +
>> +       addr = ishm_proctable->entry[proc_index].start;
>> +       odp_spinlock_unlock(&ishm_tbl->lock);
>> +       return addr;
>> +}
>> +
>> +int _odp_ishm_info(int block_index, _odp_ishm_info_t *info)
>> +{
>> +       int proc_index;
>> +
>> +       odp_spinlock_lock(&ishm_tbl->lock);
>> +       procsync();
>> +
>> +       if ((block_index < 0) ||
>> +           (block_index >= ISHM_MAX_NB_BLOCKS) ||
>> +           (ishm_tbl->block[block_index].len == 0)) {
>> +               odp_spinlock_unlock(&ishm_tbl->lock);
>> +               ODP_ERR("Request for info on an invalid block\n");
>> +               return -1;
>> +       }
>> +
>> +       /* search it in process table: if not there, need to map*/
>> +       proc_index = procfind_block(block_index);
>> +       if (proc_index < 0) {
>> +               odp_spinlock_unlock(&ishm_tbl->lock);
>> +               return -1;
>> +       }
>> +
>> +       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 ?
>> +                          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;
>> +
>> +       odp_spinlock_unlock(&ishm_tbl->lock);
>> +       return 0;
>> +}
>> +
>> +int _odp_ishm_init_global(void)
>> +{
>> +       void *addr;
>> +       void *spce_addr;
>> +       int i;
>> +
>> +       if (!odp_global_data.hugepage_info.default_huge_page_dir)
>> +               ODP_DBG("NOTE: No support for huge pages\n");
>> +       else
>> +               ODP_DBG("Huge pages mount point is: %s\n",
>> +                       odp_global_data.hugepage_
>> info.default_huge_page_dir);
>> +
>> +       /* allocate space for the internal shared mem block table: */
>> +       addr = mmap(NULL, sizeof(ishm_table_t),
>> +                   PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
>> -1, 0);
>> +       if (addr == MAP_FAILED) {
>> +               ODP_ERR("unable to mmap the main block table\n.");
>> +               goto init_glob_err1;
>> +       }
>> +       ishm_tbl = addr;
>> +       memset(ishm_tbl, 0, sizeof(ishm_table_t));
>> +       ishm_tbl->dev_seq = 0;
>> +       odp_spinlock_init(&ishm_tbl->lock);
>> +
>> +       /* allocate space for the internal shared mem fragment table: */
>> +       addr = mmap(NULL, sizeof(ishm_ftable_t),
>> +                   PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
>> -1, 0);
>> +       if (addr == MAP_FAILED) {
>> +               ODP_ERR("unable to mmap the main fragment table\n.");
>> +               goto init_glob_err2;
>> +       }
>> +       ishm_ftbl = addr;
>> +       memset(ishm_ftbl, 0, sizeof(ishm_ftable_t));
>> +
>> +       /*
>> +        *reserve the address space for _ODP_ISHM_SINGLE_VA reserved
>> blocks,
>> +        * only address space!
>> +        */
>> +       spce_addr = _odp_ishmphy_book_va(ODP_CONFIG_ISHM_VA_PREALLOC_SZ,
>> +                                        odp_sys_huge_page_size());
>> +       if (!spce_addr) {
>> +               ODP_ERR("unable to reserve virtual space\n.");
>> +               goto init_glob_err3;
>> +       }
>> +
>> +       /* use the first fragment descriptor to describe to whole VA
>> space: */
>> +       ishm_ftbl->fragment[0].block_index   = -1;
>> +       ishm_ftbl->fragment[0].start = spce_addr;
>> +       ishm_ftbl->fragment[0].len   = ODP_CONFIG_ISHM_VA_PREALLOC_SZ;
>> +       ishm_ftbl->fragment[0].prev  = NULL;
>> +       ishm_ftbl->fragment[0].next  = NULL;
>> +       ishm_ftbl->used_fragmnts   = &ishm_ftbl->fragment[0];
>> +
>> +       /* and put all other fragment descriptors in the unused list: */
>> +       for (i = 1; i < ISHM_NB_FRAGMNTS - 1; i++) {
>> +               ishm_ftbl->fragment[i].prev   = NULL;
>> +               ishm_ftbl->fragment[i].next   = &ishm_ftbl->fragment[i +
>> 1];
>> +       }
>> +       ishm_ftbl->fragment[ISHM_NB_FRAGMNTS - 1].prev   = NULL;
>> +       ishm_ftbl->fragment[ISHM_NB_FRAGMNTS - 1].next   = NULL;
>> +       ishm_ftbl->unused_fragmnts = &ishm_ftbl->fragment[1];
>> +
>> +       return 0;
>> +
>> +init_glob_err3:
>> +       if (munmap(ishm_ftbl, sizeof(ishm_ftable_t)) < 0)
>> +               ODP_ERR("unable to munmap main fragment table\n.");
>> +init_glob_err2:
>> +       if (munmap(ishm_tbl, sizeof(ishm_table_t)) < 0)
>> +               ODP_ERR("unable to munmap main block table\n.");
>> +init_glob_err1:
>> +       return -1;
>> +}
>> +
>> +int _odp_ishm_init_local(void)
>> +{
>> +       int i;
>> +       int block_index;
>> +
>> +       /*
>> +        * the ishm_process table is local to each linux process
>> +        * Check that no other linux threads (of same or ancestor
>> processes)
>> +        * have already created the table, and create it if needed.
>> +        * We protect this with the general ishm lock to avoid
>> +        * init race condition of different running threads.
>> +        */
>> +       odp_spinlock_lock(&ishm_tbl->lock);
>> +       if (!ishm_proctable) {
>> +               ishm_proctable = malloc(sizeof(ishm_proctable_t));
>> +               if (!ishm_proctable) {
>> +                       odp_spinlock_unlock(&ishm_tbl->lock);
>> +                       return -1;
>> +               }
>> +               memset(ishm_proctable, 0, sizeof(ishm_proctable_t));
>> +       }
>> +       if (syscall(SYS_gettid) != getpid())
>> +               ishm_proctable->thrd_refcnt++;  /* new linux thread  */
>> +       else
>> +               ishm_proctable->thrd_refcnt = 1;/* new linux process */
>> +
>> +       /*
>> +        * if this ODP thread is actually a new linux process, (as opposed
>> +        * to a pthread), i.e, we just forked, then all shmem blocks
>> +        * of the parent process are mapped into this child by
>> inheritance.
>> +        * (The process local table is inherited as well). We hence have
>> to
>> +        * increase the process refcount for each of the inherited
>> mappings:
>> +        */
>> +       if (syscall(SYS_gettid) == getpid()) {
>> +               for (i = 0; i < ishm_proctable->nb_entries; i++) {
>> +                       block_index = ishm_proctable->entry[i].block
>> _index;
>> +                       ishm_tbl->block[block_index].refcnt++;
>> +               }
>> +       }
>> +
>> +       odp_spinlock_unlock(&ishm_tbl->lock);
>> +       return 0;
>> +}
>> +
>> +int _odp_ishm_term_global(void)
>> +{
>> +       int ret = 0;
>> +
>> +       /* free the fragment table */
>> +       if (munmap(ishm_ftbl, sizeof(ishm_ftable_t)) < 0) {
>> +               ret = -1;
>> +               ODP_ERR("unable to munmap fragment table\n.");
>> +       }
>> +       /* free the block table */
>> +       if (munmap(ishm_tbl, sizeof(ishm_table_t)) < 0) {
>> +               ret = -1;
>> +               ODP_ERR("unable to munmap main table\n.");
>> +       }
>> +
>> +       /* free the reserved VA space */
>> +       if (_odp_ishmphy_unbook_va())
>> +               ret = -1;
>> +
>> +       return ret;
>> +}
>> +
>> +int _odp_ishm_term_local(void)
>> +{
>> +       int i;
>> +       int proc_table_refcnt = 0;
>> +       int block_index;
>> +       ishm_block_t *block;
>> +
>> +       odp_spinlock_lock(&ishm_tbl->lock);
>> +       procsync();
>> +
>> +       /*
>> +        * The ishm_process table is local to each linux process
>> +        * Check that no other linux threads (of this linux process)
>> +        * still needs the table, and free it if so.
>> +        * We protect this with the general ishm lock to avoid
>> +        * term race condition of different running threads.
>> +        */
>> +       proc_table_refcnt = --ishm_proctable->thrd_refcnt;
>> +       if (!proc_table_refcnt) {
>> +               /*
>> +                * this is the last thread of this process...
>> +                * All mappings for this process are about to be lost...
>> +                * Go through the table of visible blocks for this
>> process,
>> +                * decreasing the refcnt of each visible blocks, and
>> issuing
>> +                * warning for those no longer referenced by any process.
>> +                * Note that non-referenced blocks are nor freeed: this is
>> +                * deliberate as this would imply that the sementic of the
>> +                * freeing function would differ depending on whether we
>> run
>> +                * with odp_thread as processes or pthreads. With this
>> approach,
>> +                * the user should always free the blocks manually, which
>> is
>> +                * more consistent
>> +                */
>> +               for (i = 0; i < ishm_proctable->nb_entries; i++) {
>> +                       block_index = ishm_proctable->entry[i].block
>> _index;
>> +                       block = &ishm_tbl->block[block_index];
>> +                       if ((--block->refcnt) <= 0) {
>> +                               block->refcnt = 0;
>> +                       ODP_DBG("Warning: block %d:  name:%s "
>> +                               "no longer referenced\n",
>> +                               i,
>> +                               ishm_tbl->block[i].name[0] ?
>> +                                       ishm_tbl->block[i].name : "<no
>> name>");
>> +                       }
>> +               }
>> +
>> +               free(ishm_proctable);
>> +               ishm_proctable = NULL;
>> +       }
>> +
>> +       odp_spinlock_unlock(&ishm_tbl->lock);
>> +       return 0;
>> +}
>> diff --git a/platform/linux-generic/_ishmphy.c
>> b/platform/linux-generic/_ishmphy.c
>> new file mode 100644
>> index 0000000..cf2d531
>> --- /dev/null
>> +++ b/platform/linux-generic/_ishmphy.c
>> @@ -0,0 +1,168 @@
>> +/* Copyright (c) 2016, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +/*
>> + * This file handles the lower end of the ishm memory allocator:
>> + * It performs the physical mappings.
>> + */
>> +#include <odp_posix_extensions.h>
>> +#include <odp_config_internal.h>
>> +#include <odp_internal.h>
>> +#include <odp/api/align.h>
>> +#include <odp/api/system_info.h>
>> +#include <odp/api/debug.h>
>> +#include <odp_debug_internal.h>
>> +#include <odp_align_internal.h>
>> +#include <_ishm_internal.h>
>> +#include <_ishmphy_internal.h>
>> +
>> +#include <stdlib.h>
>> +#include <stdio.h>
>> +#include <unistd.h>
>> +#include <string.h>
>> +#include <errno.h>
>> +#include <sys/mman.h>
>> +#include <sys/stat.h>
>> +#include <fcntl.h>
>> +#include <sys/types.h>
>> +#include <sys/wait.h>
>> +#include <_ishmphy_internal.h>
>> +
>> +static void *common_va_address;
>> +static uint64_t common_va_len;
>> +
>> +#ifndef MAP_ANONYMOUS
>> +#define MAP_ANONYMOUS MAP_ANON
>> +#endif
>> +
>> +/* Book some virtual address space
>> + * This function is called at odp_init_global() time to pre-book some
>> + * virtual address space inherited by all odpthreads (i.e. descendant
>> + * processes and threads) and later used to guarantee the unicity the
>> + * the mapping VA address when memory is reserver with the
>> _ODP_ISHM_SINGLE_VA
>> + * flag.
>> + * returns the address of the mapping or NULL on error.
>> + */
>> +void *_odp_ishmphy_book_va(uintptr_t len, intptr_t align)
>> +{
>> +       void *addr;
>> +
>> +       addr = mmap(NULL, len + align, PROT_NONE,
>> +                   MAP_SHARED | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
>> +       if (addr == MAP_FAILED) {
>> +               ODP_ERR("_ishmphy_book_va failure\n");
>> +               return NULL;
>> +       }
>> +
>> +       madvise(addr, len, MADV_DONTNEED);
>> +
>> +       common_va_address = addr;
>> +       common_va_len     = len;
>> +
>> +       /* return the nearest aligned address: */
>> +       return (void *)(((uintptr_t)addr + align - 1) & (-align));
>> +}
>> +
>> +/* Un-book some virtual address space
>> + * This function is called at odp_term_global() time to unbook
>> + * the virtual address space booked by _ishmphy_book_va()
>> + */
>> +int _odp_ishmphy_unbook_va(void)
>> +{
>> +       int ret;
>> +
>> +       ret = munmap(common_va_address, common_va_len);
>> +       if (ret)
>> +               ODP_ERR("_unishmphy_book_va failure\n");
>> +       return ret;
>> +}
>> +
>> +/*
>> + * do a mapping:
>> + * Performs a mapping of the provided file descriptor to the process VA
>> + * space. If the _ODP_ISHM_SINGLE_VA flag is set, 'start' is assumed to
>> be
>> + * the VA address where the mapping is to be done.
>> + * If the flag is not set, a new VA address is taken.
>> + * returns the address of the mapping or NULL on error.
>> + */
>> +void *_odp_ishmphy_map(int fd, void *start, uint64_t size,
>> +                      int flags)
>> +{
>> +       void *mapped_addr;
>> +       int mmap_flags = 0;
>> +
>> +       if (flags & _ODP_ISHM_SINGLE_VA) {
>> +               if (!start) {
>> +                       ODP_ERR("failure: missing address\n");
>> +                       return NULL;
>> +               }
>> +               /* maps over fragment of reserved VA: */
>> +               mapped_addr = mmap(start, size, PROT_READ | PROT_WRITE,
>> +                                  MAP_SHARED | MAP_FIXED | mmap_flags,
>> fd, 0);
>> +       } else {
>> +               /* just do a new mapping in the VA space: */
>> +               mapped_addr = mmap(NULL, size, PROT_READ | PROT_WRITE,
>> +                                  MAP_SHARED | mmap_flags, fd, 0);
>> +       }
>> +
>> +       if (mapped_addr == MAP_FAILED) {
>> +               ODP_ERR("mmap failed:%s\n", strerror(errno));
>> +               return NULL;
>> +       }
>> +
>> +       /* if locking is requested, lock it...*/
>> +       if (flags & _ODP_ISHM_LOCK) {
>> +               if (mlock(mapped_addr, size)) {
>> +                       if (munmap(mapped_addr, size))
>> +                               ODP_ERR("munmap failed:%s\n",
>> strerror(errno));
>> +                       ODP_ERR("mlock failed:%s\n", strerror(errno));
>> +                       return NULL;
>> +               }
>> +       }
>> +       return mapped_addr;
>> +}
>> +
>> +/* free a mapping:
>> + * If the _ODP_ISHM_SINGLE_VA flag was given at creation time the virtual
>> + * address range must be returned to the preoallocated "pool". this is
>> + * done by mapping non accessibly memory there (hence blocking the VA but
>> + * releasing the physical memory).
>> + * If the _ODP_ISHM_SINGLE_VA flag was not given, both physical memory
>> and
>> + * virtual address space are realeased by calling the normal munmap.
>> + * return 0 on success or -1 on error.
>> + */
>> +int _odp_ishmphy_unmap(void *start, uint64_t len, int flags)
>> +{
>> +       void *addr;
>> +       int ret;
>> +       int mmap_flgs;
>> +
>> +       mmap_flgs = MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS |
>> MAP_NORESERVE;
>> +
>> +       /* if locking was requested, unlock...*/
>> +       if (flags & _ODP_ISHM_LOCK)
>> +               munlock(start, len);
>> +
>> +       if (flags & _ODP_ISHM_SINGLE_VA) {
>> +               /* map unnaccessible memory overwrites previous mapping
>> +                * and free the physical memory, but guarantees to block
>> +                * the VA range from other mappings
>> +                */
>> +               addr = mmap(start, len, PROT_NONE, mmap_flgs, -1, 0);
>> +               if (addr == MAP_FAILED) {
>> +                       ODP_ERR("_ishmphy_free failure for
>> ISHM_SINGLE_VA\n");
>> +                       return -1;
>> +               }
>> +               madvise(start, len, MADV_DONTNEED);
>> +               return 0;
>> +       }
>> +
>> +       /* just release the mapping */
>> +       ret = munmap(start, len);
>> +       if (ret)
>> +               ODP_ERR("_ishmphy_free failure: %s\n", strerror(errno));
>> +       return ret;
>> +}
>> diff --git a/platform/linux-generic/arch/arm/odp/api/cpu_arch.h
>> b/platform/linux-generic/arch/arm/odp/api/cpu_arch.h
>> deleted file mode 120000
>> index e86e132..0000000
>> --- a/platform/linux-generic/arch/arm/odp/api/cpu_arch.h
>> +++ /dev/null
>> @@ -1 +0,0 @@
>> -../../../default/odp/api/cpu_arch.h
>> \ No newline at end of file
>> diff --git a/platform/linux-generic/arch/arm/odp/api/cpu_arch.h
>> b/platform/linux-generic/arch/arm/odp/api/cpu_arch.h
>> new file mode 100644
>> index 0000000..22b1da2
>> --- /dev/null
>> +++ b/platform/linux-generic/arch/arm/odp/api/cpu_arch.h
>> @@ -0,0 +1,24 @@
>> +/* Copyright (c) 2016, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#ifndef ODP_PLAT_CPU_ARCH_H_
>> +#define ODP_PLAT_CPU_ARCH_H_
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +#define _ODP_CACHE_LINE_SIZE 64
>> +
>> +static inline void odp_cpu_pause(void)
>> +{
>> +}
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> diff --git a/platform/linux-generic/arch/arm/odp_cpu_arch.c
>> b/platform/linux-generic/arch/arm/odp_cpu_arch.c
>> deleted file mode 120000
>> index deebc47..0000000
>> --- a/platform/linux-generic/arch/arm/odp_cpu_arch.c
>> +++ /dev/null
>> @@ -1 +0,0 @@
>> -../default/odp_cpu_arch.c
>> \ No newline at end of file
>> diff --git a/platform/linux-generic/arch/arm/odp_cpu_arch.c
>> b/platform/linux-generic/arch/arm/odp_cpu_arch.c
>> new file mode 100644
>> index 0000000..2ac223e
>> --- /dev/null
>> +++ b/platform/linux-generic/arch/arm/odp_cpu_arch.c
>> @@ -0,0 +1,48 @@
>> +/* Copyright (c) 2015, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#include <odp_posix_extensions.h>
>> +
>> +#include <stdlib.h>
>> +#include <time.h>
>> +
>> +#include <odp/api/cpu.h>
>> +#include <odp/api/hints.h>
>> +#include <odp/api/system_info.h>
>> +#include <odp_debug_internal.h>
>> +
>> +#define GIGA 1000000000
>> +
>> +uint64_t odp_cpu_cycles(void)
>> +{
>> +       struct timespec time;
>> +       uint64_t sec, ns, hz, cycles;
>> +       int ret;
>> +
>> +       ret = clock_gettime(CLOCK_MONOTONIC_RAW, &time);
>> +
>> +       if (ret != 0)
>> +               ODP_ABORT("clock_gettime failed\n");
>> +
>> +       hz  = odp_cpu_hz_max();
>> +       sec = (uint64_t)time.tv_sec;
>> +       ns  = (uint64_t)time.tv_nsec;
>> +
>> +       cycles  = sec * hz;
>> +       cycles += (ns * hz) / GIGA;
>> +
>> +       return cycles;
>> +}
>> +
>> +uint64_t odp_cpu_cycles_max(void)
>> +{
>> +       return UINT64_MAX;
>> +}
>> +
>> +uint64_t odp_cpu_cycles_resolution(void)
>> +{
>> +       return 1;
>> +}
>> diff --git a/platform/linux-generic/arch/arm/odp_sysinfo_parse.c
>> b/platform/linux-generic/arch/arm/odp_sysinfo_parse.c
>> deleted file mode 120000
>> index 39962b8..0000000
>> --- a/platform/linux-generic/arch/arm/odp_sysinfo_parse.c
>> +++ /dev/null
>> @@ -1 +0,0 @@
>> -../default/odp_sysinfo_parse.c
>> \ No newline at end of file
>> diff --git a/platform/linux-generic/arch/arm/odp_sysinfo_parse.c
>> b/platform/linux-generic/arch/arm/odp_sysinfo_parse.c
>> new file mode 100644
>> index 0000000..53e2aae
>> --- /dev/null
>> +++ b/platform/linux-generic/arch/arm/odp_sysinfo_parse.c
>> @@ -0,0 +1,27 @@
>> +/* Copyright (c) 2016, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#include <odp_internal.h>
>> +#include <odp_debug_internal.h>
>> +#include <string.h>
>> +
>> +int cpuinfo_parser(FILE *file ODP_UNUSED, system_info_t *sysinfo)
>> +{
>> +       int i;
>> +
>> +       ODP_DBG("Warning: use dummy values for freq and model string\n");
>> +       for (i = 0; i < MAX_CPU_NUMBER; i++) {
>> +               sysinfo->cpu_hz_max[i] = 1400000000;
>> +               strcpy(sysinfo->model_str[i], "UNKNOWN");
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +uint64_t odp_cpu_hz_current(int id ODP_UNUSED)
>> +{
>> +       return 0;
>> +}
>> diff --git a/platform/linux-generic/arch/powerpc/odp_cpu_arch.c
>> b/platform/linux-generic/arch/powerpc/odp_cpu_arch.c
>> deleted file mode 120000
>> index deebc47..0000000
>> --- a/platform/linux-generic/arch/powerpc/odp_cpu_arch.c
>> +++ /dev/null
>> @@ -1 +0,0 @@
>> -../default/odp_cpu_arch.c
>> \ No newline at end of file
>> diff --git a/platform/linux-generic/arch/powerpc/odp_cpu_arch.c
>> b/platform/linux-generic/arch/powerpc/odp_cpu_arch.c
>> new file mode 100644
>> index 0000000..2ac223e
>> --- /dev/null
>> +++ b/platform/linux-generic/arch/powerpc/odp_cpu_arch.c
>> @@ -0,0 +1,48 @@
>> +/* Copyright (c) 2015, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#include <odp_posix_extensions.h>
>> +
>> +#include <stdlib.h>
>> +#include <time.h>
>> +
>> +#include <odp/api/cpu.h>
>> +#include <odp/api/hints.h>
>> +#include <odp/api/system_info.h>
>> +#include <odp_debug_internal.h>
>> +
>> +#define GIGA 1000000000
>> +
>> +uint64_t odp_cpu_cycles(void)
>> +{
>> +       struct timespec time;
>> +       uint64_t sec, ns, hz, cycles;
>> +       int ret;
>> +
>> +       ret = clock_gettime(CLOCK_MONOTONIC_RAW, &time);
>> +
>> +       if (ret != 0)
>> +               ODP_ABORT("clock_gettime failed\n");
>> +
>> +       hz  = odp_cpu_hz_max();
>> +       sec = (uint64_t)time.tv_sec;
>> +       ns  = (uint64_t)time.tv_nsec;
>> +
>> +       cycles  = sec * hz;
>> +       cycles += (ns * hz) / GIGA;
>> +
>> +       return cycles;
>> +}
>> +
>> +uint64_t odp_cpu_cycles_max(void)
>> +{
>> +       return UINT64_MAX;
>> +}
>> +
>> +uint64_t odp_cpu_cycles_resolution(void)
>> +{
>> +       return 1;
>> +}
>> diff --git a/platform/linux-generic/include/_fdserver_internal.h
>> b/platform/linux-generic/include/_fdserver_internal.h
>> index 480ac02..22b2802 100644
>> --- a/platform/linux-generic/include/_fdserver_internal.h
>> +++ b/platform/linux-generic/include/_fdserver_internal.h
>> @@ -23,6 +23,7 @@ extern "C" {
>>   */
>>  typedef enum fd_server_context {
>>         FD_SRV_CTX_NA,  /* Not Applicable   */
>> +       FD_SRV_CTX_ISHM,
>>         FD_SRV_CTX_END, /* upper enum limit */
>>  } fd_server_context_e;
>>
>> diff --git a/platform/linux-generic/include/_ishm_internal.h
>> b/platform/linux-generic/include/_ishm_internal.h
>> new file mode 100644
>> index 0000000..7d27477
>> --- /dev/null
>> +++ b/platform/linux-generic/include/_ishm_internal.h
>> @@ -0,0 +1,45 @@
>> +/* Copyright (c) 2016, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#ifndef ODP_ISHM_INTERNAL_H_
>> +#define ODP_ISHM_INTERNAL_H_
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +/* flags available at ishm_reserve: */
>> +#define _ODP_ISHM_SINGLE_VA            1
>> +#define _ODP_ISHM_LOCK                 2
>> +
>> +/**
>> + * Shared memory block info
>> + */
>> +typedef struct _odp_ishm_info_t {
>> +       const char *name;      /**< Block name */
>> +       void       *addr;      /**< Block address */
>> +       uint64_t    size;      /**< Block size in bytes */
>> +       uint64_t    page_size; /**< Memory page size */
>> +       uint32_t    flags;     /**< _ODP_ISHM_* flags */
>> +       uint32_t    user_flags;/**< user specific flags */
>> +} _odp_ishm_info_t;
>> +
>> +int   _odp_ishm_reserve(const char *name, uint64_t size, int fd,
>> uint32_t align,
>> +                       uint32_t flags, uint32_t user_flags);
>> +int   _odp_ishm_free_by_index(int block_index);
>> +int   _odp_ishm_free_by_name(const char *name);
>> +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);
>> +void *_odp_ishm_address(int block_index);
>> +int   _odp_ishm_info(int block_index, _odp_ishm_info_t *info);
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> diff --git a/platform/linux-generic/include/_ishmphy_internal.h
>> b/platform/linux-generic/include/_ishmphy_internal.h
>> new file mode 100644
>> index 0000000..4fe560f
>> --- /dev/null
>> +++ b/platform/linux-generic/include/_ishmphy_internal.h
>> @@ -0,0 +1,25 @@
>> +/* Copyright (c) 2016, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#ifndef _ISHMPHY_INTERNAL_H
>> +#define _ISHMPHY_INTERNAL_H
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +#include <stdint.h>
>> +
>> +void *_odp_ishmphy_book_va(uintptr_t len, intptr_t align);
>> +int   _odp_ishmphy_unbook_va(void);
>> +void *_odp_ishmphy_map(int fd, void *start, uint64_t size, int flags);
>> +int   _odp_ishmphy_unmap(void *start, uint64_t len, int flags);
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> diff --git a/platform/linux-generic/include/ishmphy_internal.h
>> b/platform/linux-generic/include/ishmphy_internal.h
>> new file mode 100644
>> index 0000000..0bc4207
>> --- /dev/null
>> +++ b/platform/linux-generic/include/ishmphy_internal.h
>> @@ -0,0 +1,24 @@
>> +/* Copyright (c) 2016, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#ifndef _ISHMPHY_INTERNAL_H_
>> +#define _ISHMPHY_INTERNAL_H_
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +void *_ishmphy_book_va(uint64_t len);
>> +int _ishmphy_unbook_va(void);
>> +void *_ishmphy_map(int fd, void *start, uint64_t size,
>> +                  int flags, int mmap_flags);
>> +int _ishmphy_unmap(void *start, uint64_t len, int flags);
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> diff --git a/platform/linux-generic/include/odp_config_internal.h
>> b/platform/linux-generic/include/odp_config_internal.h
>> index 989ea08..3eabc7b 100644
>> --- a/platform/linux-generic/include/odp_config_internal.h
>> +++ b/platform/linux-generic/include/odp_config_internal.h
>> @@ -110,6 +110,16 @@ extern "C" {
>>   */
>>  #define ODP_CONFIG_SHM_BLOCKS (ODP_CONFIG_POOLS + 48)
>>
>> +/*
>> + * Size of the virtual address space pre-reserver for ISHM
>> + *
>> + * This is just virtual space preallocation size, not memory allocation.
>> + * This address space is used by ISHM to map things at a common address
>> in
>> + * all ODP threads (when the _ODP_ISHM_SINGLE_VA flag is used).
>> + * In bytes.
>> + */
>> +#define ODP_CONFIG_ISHM_VA_PREALLOC_SZ (536870912L)
>> +
>>  #ifdef __cplusplus
>>  }
>>  #endif
>> diff --git a/platform/linux-generic/include/odp_internal.h
>> b/platform/linux-generic/include/odp_internal.h
>> index 2b21777..6ea8cf0 100644
>> --- a/platform/linux-generic/include/odp_internal.h
>> +++ b/platform/linux-generic/include/odp_internal.h
>> @@ -60,6 +60,7 @@ enum init_stage {
>>         TIME_INIT,
>>         SYSINFO_INIT,
>>         FDSERVER_INIT,
>> +       ISHM_INIT,
>>         SHM_INIT,
>>         THREAD_INIT,
>>         POOL_INIT,
>> @@ -128,6 +129,11 @@ int _odp_int_name_tbl_term_global(void);
>>  int _odp_fdserver_init_global(void);
>>  int _odp_fdserver_term_global(void);
>>
>> +int _odp_ishm_init_global(void);
>> +int _odp_ishm_init_local(void);
>> +int _odp_ishm_term_global(void);
>> +int _odp_ishm_term_local(void);
>> +
>>  int cpuinfo_parser(FILE *file, system_info_t *sysinfo);
>>  uint64_t odp_cpu_hz_current(int id);
>>
>> diff --git a/platform/linux-generic/odp_init.c
>> b/platform/linux-generic/odp_init.c
>> index ec84fd0..d33a3ae 100644
>> --- a/platform/linux-generic/odp_init.c
>> +++ b/platform/linux-generic/odp_init.c
>> @@ -57,6 +57,12 @@ int odp_init_global(odp_instance_t *instance,
>>         }
>>         stage = FDSERVER_INIT;
>>
>> +       if (_odp_ishm_init_global()) {
>> +               ODP_ERR("ODP ishm init failed.\n");
>> +               goto init_failed;
>> +       }
>> +       stage = ISHM_INIT;
>> +
>>         if (odp_shm_init_global()) {
>>                 ODP_ERR("ODP shm init failed.\n");
>>                 goto init_failed;
>> @@ -224,6 +230,13 @@ int _odp_term_global(enum init_stage stage)
>>                 }
>>                 /* Fall through */
>>
>> +       case ISHM_INIT:
>> +               if (_odp_ishm_term_global()) {
>> +                       ODP_ERR("ODP ishm term failed.\n");
>> +                       rc = -1;
>> +               }
>> +               /* Fall through */
>> +
>>         case FDSERVER_INIT:
>>                 if (_odp_fdserver_term_global()) {
>>                         ODP_ERR("ODP fdserver term failed.\n");
>> @@ -268,6 +281,12 @@ int odp_init_local(odp_instance_t instance,
>> odp_thread_type_t thr_type)
>>                 goto init_fail;
>>         }
>>
>> +       if (_odp_ishm_init_local()) {
>> +               ODP_ERR("ODP ishm local init failed.\n");
>> +               goto init_fail;
>> +       }
>> +       stage = ISHM_INIT;
>> +
>>         if (odp_shm_init_local()) {
>>                 ODP_ERR("ODP shm local init failed.\n");
>>                 goto init_fail;
>> @@ -343,6 +362,13 @@ int _odp_term_local(enum init_stage stage)
>>                 }
>>                 /* Fall through */
>>
>> +       case ISHM_INIT:
>> +               if (_odp_ishm_term_local()) {
>> +                       ODP_ERR("ODP ishm local term failed.\n");
>> +                       rc = -1;
>> +               }
>> +               /* Fall through */
>> +
>>         default:
>>                 break;
>>         }
>> --
>> 2.7.4
>>
>>
>

Reply via email to