@@ -67,6 +67,7 @@ odpplatinclude_HEADERS = \
$(srcdir)/include/odp/plat/packet_types.h \
$(srcdir)/include/odp/plat/pool_types.h \
$(srcdir)/include/odp/plat/queue_types.h \
+ $(srcdir)/include/odp/plat/shared_resource.h \
$(srcdir)/include/odp/plat/state.h \
$(srcdir)/include/odp/plat/ti_mcsdk.h \
$(linux_generic_srcdir)/include/odp/plat/atomic_types.h \
@@ -140,6 +141,7 @@ __LIB__libodp_la_SOURCES = \
mcsdk/mcsdk_navig.c \
mcsdk/mcsdk_rmclient.c \
mcsdk/sockutils.c \
+ odp_shr.c \
../linux-generic/odp_barrier.c \
../linux-generic/odp_cpumask.c \
../linux-generic/odp_errno.c \
new file mode 100644
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ * Copyright (c) 2015, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ODP_PLAT_SHM_TABLE_H_
+#define ODP_PLAT_SHM_TABLE_H_
+
+#include <odp/spinlock.h>
+#include <odp_debug_internal.h>
+
+typedef struct entry_head {
+ struct entry_head *next;
+ uint16_t id;
+ odp_spinlock_t lock;
+ bool allocated;
+} odp_shr_head_t;
+
+typedef struct odp_shr_table_s {
+ struct entry_head *top_free;
+ odp_spinlock_t lock;
+ struct entry_head *base;
+ uint32_t entry_size;
+ uint32_t entry_num;
+} *odp_shr_table_t;
+
+/* Define typeof for C99 compatibility */
+#define typeof __typeof__
+
+#define ODP_SHR_TABLE_INVALID ((odp_shr_table_t)NULL)
+
+odp_shr_table_t _odp_shr_table_create(const char *name,
+ uint32_t entry_size,
+ uint32_t entry_num,
+ uint32_t entry_align,
+ uint16_t head_offset);
+void odp_shr_table_destroy(odp_shr_table_t table);
+
+void odp_shr_table_lock(odp_shr_table_t table);
+void odp_shr_table_unlock(odp_shr_table_t table);
+odp_shr_head_t *_odp_shr_alloc_nolock(odp_shr_table_t table);
+odp_shr_head_t *_odp_shr_alloc(odp_shr_table_t table);
+void _odp_shr_free(odp_shr_table_t table, odp_shr_head_t *head);
+odp_shr_head_t *_odp_shr_next(odp_shr_table_t table, odp_shr_head_t *head);
+odp_shr_head_t *_odp_shr_first_allocated(odp_shr_table_t table);
+odp_shr_head_t *_odp_shr_next_allocated(odp_shr_table_t table,
+ odp_shr_head_t *head);
+
+static inline
+uint16_t _odp_shr_id(odp_shr_head_t *entry)
+{
+ ODP_ASSERT(entry, "Bad entry");
+ return entry->id;
+}
+
+static inline
+uint32_t _odp_shr_table_num_entries(odp_shr_table_t table)
+{
+ ODP_ASSERT(table, "Bad table");
+ return table->entry_num;
+}
+
+static inline
+uint32_t _odp_shr_size(odp_shr_table_t table)
+{
+ ODP_ASSERT(table, "Bad table");
+ return table->entry_size;
+}
+
+static inline
+odp_shr_head_t *_odp_shr_from_id(odp_shr_table_t table, uint16_t id)
+{
+ ODP_ASSERT(table, "Bad table");
+ ODP_ASSERT(id < table->entry_num, "Wrong entry ID");
+ return (odp_shr_head_t *)((uintptr_t)table->base +
+ id * table->entry_size);
+}
+
+static inline
+bool _odp_shr_is_allocated(odp_shr_head_t *entry)
+{
+ ODP_ASSERT(entry, "Bad entry");
+ return entry->allocated;
+}
+
+static inline
+void _odp_shr_lock(odp_shr_head_t *head)
+{
+ odp_spinlock_lock(&head->lock);
+}
+
+static inline
+void _odp_shr_unlock(odp_shr_head_t *head)
+{
+ odp_spinlock_unlock(&head->lock);
+}
+
+#define odp_shr(head, type) \
+ ({ typeof(head) __head = (head); \
+ (__head ? ODP_CONTAINEROF(__head, type, entry_head) : NULL);\
+ })
+
+#define odp_shr_from_id(table, id, type) \
+ odp_shr(_odp_shr_from_id(table, id), \
+ type)
+
+#define odp_shr_next(entry) \
+ odp_shr(_odp_shr_next(&(entry)->entry_head), \
+ typeof(*entry))
+
+#define odp_shr_first_allocated(table, type) \
+ odp_shr(_odp_shr_first_allocated(table), \
+ type)
+
+#define odp_shr_next_allocated(table, entry) \
+ odp_shr(_odp_shr_next_allocated(table, &(entry)->entry_head), \
+ typeof(*entry))
+
+#define odp_shr_table_for_each_entry(table, entry) \
+ for (entry = odp_shr_from_id(table, 0, typeof(*entry)); \
+ entry; \
+ entry = odp_shr_next(entry))
+
+#define odp_shr_table_for_each_allocated_entry(table, entry) \
+ for (entry = odp_shr_first_allocated(table, typeof(*entry)); \
+ entry; \
+ entry = odp_shr_next_allocated(table, entry))
+
+#define odp_shr_table_create(name, type, num) \
+ _odp_shr_table_create(name, sizeof(type), num, ODP_ALIGNOF(type), \
+ ODP_OFFSETOF(type, entry_head))
+
+#define odp_shr_alloc(table, type) odp_shr(_odp_shr_alloc(table), type)
+
+#define odp_shr_alloc_nolock(table, type) \
+ odp_shr(_odp_shr_alloc_nolock(table), type)
+
+#define odp_shr_free(table, entry) _odp_shr_free(table, &(entry)->entry_head)
+
+#define odp_shr_is_allocated(entry) \
+ _odp_shr_is_allocated(&(entry)->entry_head)
+
+#define odp_shr_lock(entry) _odp_shr_lock(&(entry)->entry_head)
+#define odp_shr_unlock(entry) _odp_shr_unlock(&(entry)->entry_head)
+
+#define odp_shr_id(entry) _odp_shr_id(&(entry)->entry_head)
+#endif
new file mode 100644
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ * Copyright (c) 2015, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/shared_memory.h>
+#include <odp/align.h>
+#include <odp/plat/align.h>
+#include <odp/plat/shared_resource.h>
+
+static void push_entry(odp_shr_head_t **top,
+ odp_shr_head_t *head)
+{
+ head->next = *top;
+ *top = head;
+}
+
+static odp_shr_head_t *pop_entry(odp_shr_head_t **top)
+{
+ odp_shr_head_t *head;
+
+ head = *top;
+ if (!head)
+ return NULL;
+ *top = head->next;
+ return head;
+}
+
+void odp_shr_table_lock(odp_shr_table_t table)
+{
+ odp_spinlock_lock(&table->lock);
+}
+
+void odp_shr_table_unlock(odp_shr_table_t table)
+{
+ odp_spinlock_unlock(&table->lock);
+}
+
+odp_shr_head_t *_odp_shr_alloc_nolock(odp_shr_table_t table)
+{
+ ODP_ASSERT(table, "Bad table");
+ odp_shr_head_t *head;
+ head = pop_entry(&table->top_free);
+ ODP_ASSERT(!head->allocated, "Got already allocated entry");
+ head->allocated = 1;
+ return head;
+}
+
+odp_shr_head_t *_odp_shr_alloc(odp_shr_table_t table)
+{
+ ODP_ASSERT(table, "Bad table");
+ odp_shr_head_t *head;
+ odp_shr_table_lock(table);
+ head = _odp_shr_alloc_nolock(table);
+ odp_shr_table_unlock(table);
+ ODP_DBG("Allocated entry head: %p\n", head);
+ return head;
+}
+
+void _odp_shr_free(odp_shr_table_t table, odp_shr_head_t *head)
+{
+ ODP_ASSERT(head, "Bad head");
+ ODP_ASSERT(head->allocated, "Freeing already freed entry");
+ ODP_ASSERT(table, "Bad table");
+ odp_shr_table_lock(table);
+ head->allocated = 0;
+ push_entry(&table->top_free, head);
+ odp_shr_table_unlock(table);
+}
+
+odp_shr_table_t _odp_shr_table_create(const char *name,
+ uint32_t entry_size,
+ uint32_t entry_num,
+ uint32_t entry_align,
+ uint16_t head_offset)
+{
+ odp_shm_t shm;
+ void *addr;
+ uint32_t size;
+ uint32_t table_head_size;
+ odp_shr_table_t table;
+ odp_shr_head_t *head;
+ uint32_t i;
+
+ if (entry_align == 0)
+ entry_align = ODP_CACHE_LINE_SIZE;
+
+ table_head_size = ODP_ALIGN_ROUNDUP(sizeof(odp_shr_table_t),
+ entry_align);
+ entry_size = ODP_ALIGN_ROUNDUP(entry_size, entry_align);
+ size = table_head_size + entry_size * entry_num;
+
+ shm = odp_shm_reserve(name, size, entry_align, ODP_SHM_SW_ONLY);
+ if (shm == ODP_SHM_INVALID)
+ return ODP_SHR_TABLE_INVALID;
+
+ addr = odp_shm_addr(shm);
+ if (addr == NULL) {
+ odp_shm_free(shm);
+ return ODP_SHR_TABLE_INVALID;
+ }
+
+ memset(addr, 0, size);
+
+ table = addr;
+ odp_spinlock_init(&table->lock);
+ table->top_free = NULL;
+ table->entry_num = entry_num;
+ table->entry_size = entry_size;
+
+ addr = (uint8_t *)addr + table_head_size + head_offset;
+ table->base = addr;
+
+ for (i = 0; i < entry_num; i++) {
+ ODP_ASSERT(ODP_ALIGNED_CHECK((uint8_t *)addr - head_offset,
+ entry_align),
+ "Wrong entry alignment");
+ head = addr;
+ head->id = i;
+ odp_spinlock_init(&head->lock);
+ push_entry(&table->top_free, head);
+ addr = (uint8_t *)addr + entry_size;
+ }
+
+ return table;
+}
+
+void odp_shr_table_destroy(odp_shr_table_t table)
+{
+ (void)table;
+ ODP_UNIMPLEMENTED();
+}
+
+odp_shr_head_t *_odp_shr_next(odp_shr_table_t table, odp_shr_head_t *head)
+{
+ ODP_ASSERT(head, "Bad head");
+ ODP_ASSERT(table, "Bad table");
+ uint16_t id = _odp_shr_id(head);
+ if (++id >= _odp_shr_table_num_entries(table))
+ return NULL;
+ return _odp_shr_from_id(table, id);
+}
+
+
+#define _odp_shr_table_for_each(table, head) \
+ for (head = _odp_shr_from_id(table, 0); \
+ head; \
+ head = _odp_shr_next(table, head))
+
+#define _odp_shr_table_for_each_continue(table, head) \
+ for (head = _odp_shr_next(table, head); \
+ head; \
+ head = _odp_shr_next(table, head))
+
+odp_shr_head_t *_odp_shr_first_allocated(odp_shr_table_t table)
+{
+ odp_shr_head_t *head;
+ _odp_shr_table_for_each(table, head) {
+ if (head->allocated)
+ return head;
+ }
+ return NULL;
+}
+
+odp_shr_head_t *_odp_shr_next_allocated(odp_shr_table_t table,
+ odp_shr_head_t *head)
+{
+ ODP_ASSERT(head, "Bad head");
+ ODP_ASSERT(table, "Bad table");
+
+ _odp_shr_table_for_each_continue(table, head) {
+ if (head->allocated)
+ return head;
+ }
+ return NULL;
+}