This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "".
The branch, cloud-dev has been updated via 370f93139e16633390cb28acda6296da8fee006d (commit) via 5f738a79248183a252478856de88bafa37344445 (commit) via 3058124d5c307149272c1b37651056451939c3bf (commit) from 1ba26aa5650c05718c177842178de6d0f70b7fc1 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit 370f93139e16633390cb28acda6296da8fee006d Author: Yi He yi.he@linaro.org Date: Thu Jul 20 13:56:36 2017 +0800
odp: add modular framework
Add modular programming framework to support selectable implementations for variant software subsystems.
Signed-off-by: Yi He yi.he@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org
diff --git a/frameworks/modular/list.h b/frameworks/modular/list.h new file mode 100644 index 00000000..cc42b714 --- /dev/null +++ b/frameworks/modular/list.h @@ -0,0 +1,271 @@ +/* Adopted and modified Rusty Russell CCAN Project + * https://github.com/rustyrussell/ccan + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Copyright (c) 2017, ARM Limited. All rights reserved. + * + * Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CCAN_LIST_H +#define CCAN_LIST_H + +#include <stddef.h> +#include <stdbool.h> + +/* Always assume the availabilities of typeof or __typeof__ */ +#if defined(__STDC__) +#define typeof __typeof__ +#endif + +/** + * struct list_node - an entry in a doubly-linked list + * @next: next entry (self if empty) + * @prev: previous entry (self if empty) + * + * This is used as an entry in a linked list. + * Example: + * struct child { + * const char *name; + * // Linked list of all us children. + * struct list_node list; + * }; + */ +struct list_node { + struct list_node *next, *prev; +}; + +/** + * struct list_head - the head of a doubly-linked list + * @node: the head node + * + * This is used as the head of a linked list. + * Example: + * struct parent { + * const char *name; + * struct list_head children; + * unsigned int num_children; + * }; + */ +struct list_head { + struct list_node node; +}; + +/** + * LIST_HEAD_INIT - initializer for an empty list_head + * @name: the name of the list. + * + * Explicit initializer for an empty list. + * + * See also: + * LIST_HEAD, list_head_init() + * + * Example: + * static struct list_head my_list = LIST_HEAD_INIT(my_list); + */ +#define LIST_HEAD_INIT(name) { { &(name).node, &(name).node } } + +/** + * list_head_init - initialize a list_head + * @h: the list_head to set to the empty list + * + * Example: + * ... + * struct parent *parent = malloc(sizeof(*parent)); + * + * list_head_init(&parent->children); + * parent->num_children = 0; + */ +static inline void list_head_init(struct list_head *h) +{ + h->node.next = &h->node; + h->node.prev = &h->node; +} + +/** + * list_node_init - initialize a list_node + * @n: the list_node to link to itself. + * + * You don't need to use this normally! But it lets you list_del(@n) + * safely. + */ +static inline void list_node_init(struct list_node *n) +{ + n->next = n; + n->prev = n; +} + +/** + * list_add_after - add an entry after an existing node in a linked list + * @p: the existing list_node to add the node after + * @n: the new list_node to add to the list. + * + * The existing list_node must already be a member of the list. + * The new list_node does not need to be initialized; it will be overwritten. + * + * Example: + * struct child c1, c2, c3; + * LIST_HEAD(h); + * + * list_add_tail(&h, &c1.list); + * list_add_tail(&h, &c3.list); + * list_add_after(&c1.list, &c2.list); + */ +static inline void list_add_after(struct list_node *p, + struct list_node *n) +{ + n->next = p->next; + n->prev = p; + p->next->prev = n; + p->next = n; +} + +/** + * list_add - add an entry at the start of a linked list. + * @h: the list_head to add the node to + * @n: the list_node to add to the list. + * + * The list_node does not need to be initialized; it will be overwritten. + * Example: + * struct child *child = malloc(sizeof(*child)); + * + * child->name = "marvin"; + * list_add(&parent->children, &child->list); + * parent->num_children++; + */ +static inline void list_add(struct list_head *h, + struct list_node *n) +{ + list_add_after(&h->node, n); +} + +/** + * list_add_before - add an entry before an existing node in a linked list + * @p: the existing list_node to add the node before + * @n: the new list_node to add to the list. + * + * The existing list_node must already be a member of the list. + * The new list_node does not need to be initialized; it will be overwritten. + * + * Example: + * list_head_init(&h); + * list_add_tail(&h, &c1.list); + * list_add_tail(&h, &c3.list); + * list_add_before(&c3.list, &c2.list); + */ +static inline void list_add_before(struct list_node *p, + struct list_node *n) +{ + n->next = p; + n->prev = p->prev; + p->prev->next = n; + p->prev = n; +} + +/** + * list_add_tail - add an entry at the end of a linked list. + * @h: the list_head to add the node to + * @n: the list_node to add to the list. + * + * The list_node does not need to be initialized; it will be overwritten. + * Example: + * list_add_tail(&parent->children, &child->list); + * parent->num_children++; + */ +static inline void list_add_tail(struct list_head *h, + struct list_node *n) +{ + list_add_before(&h->node, n); +} + +/** + * list_empty - is a list empty? + * @h: the list_head + * + * If the list is empty, returns true. + * + * Example: + * assert(list_empty(&parent->children) == (parent->num_children == 0)); + */ +static inline bool list_empty(const struct list_head *h) +{ + return (h->node.next == &h->node); +} + +/** + * list_node_detached - is a node detached from any lists? + * @n: the list_node + * + * If the list node is initialized and detached, return true. + * Always use list_node_init() and list_del_init() on list nodes. + */ +static inline bool list_node_detached(const struct list_node *n) +{ + return (n->next == n); +} + +/** + * list_del - delete an entry from an (unknown) linked list. + * @n: the list_node to delete from the list. + * + * Note that this leaves @n in an undefined state; it can be added to + * another list, but not deleted again. + * + * See also: + * list_del_from(), list_del_init() + * + * Example: + * list_del(&child->list); + * parent->num_children--; + */ +static inline void list_del(struct list_node *n) +{ + n->next->prev = n->prev; + n->prev->next = n->next; + + /* Catch use-after-del. */ + n->next = NULL; + n->prev = NULL; +} + +/** + * list_del_init - delete a node, and reset it so it can be deleted again. + * @n: the list_node to be deleted. + * + * list_del(@n) or list_del_init() again after this will be safe, + * which can be useful in some cases. + * + * See also: + * list_del_from(), list_del() + * + * Example: + * list_del_init(&child->list); + * parent->num_children--; + */ +static inline void list_del_init(struct list_node *n) +{ + list_del(n); + list_node_init(n); +} + +#endif /* CCAN_LIST_H */ diff --git a/frameworks/modular/odp_module.c b/frameworks/modular/odp_module.c new file mode 100644 index 00000000..89b7cb0d --- /dev/null +++ b/frameworks/modular/odp_module.c @@ -0,0 +1,179 @@ +/* Copyright (c) 2017, ARM Limited. All rights reserved. + * + * Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdio.h> +#include <errno.h> +#include "odp_module.h" + +#define MODULE_FRAMEWORK_VERSION 0x00010000UL +ODP_SUBSYSTEM_DEFINE(module, "module framework", MODULE_FRAMEWORK_VERSION); + +/* Bootstrap log facility, enable if ODP_DEBUG_PRINT flag is set. */ +#define DBG(format, ...) \ + do { \ + if (ODP_DEBUG_PRINT == 1) \ + fprintf(stderr, format, ##__VA_ARGS__); \ + } while (0) + +/* Keep it simple, allow one registration session at a time. */ +static struct { + odp_rwlock_t lock; + odp_subsystem_t *subsystem; + odp_module_base_t *module; +} registration = { + .lock = ODP_RWLOCK_UNLOCKED, + .subsystem = NULL, + .module = NULL, +}; + +static inline int registration_sanity_check( + odp_subsystem_t *subsystem, odp_module_base_t *module) +{ + if (subsystem == NULL || module == NULL) + return -ENOENT; + + if (!list_node_detached(&module->list)) { + DBG("module %s was already registered.\n", module->name); + return -EAGAIN; + } + + return 0; +} + +/* Module is linked statically or dynamically, and are loaded by + * program loader (execve) or dynamic linker/loader (ld.so) + * + * subsystem_register_module() should complete the whole registration + * session and link the module into subsystem's module array. + */ +static int linker_register_module( + odp_subsystem_t *subsystem, odp_module_base_t *module) +{ + int sanity = registration_sanity_check(subsystem, module); + + if (sanity < 0) /* sanity check errors */ + return sanity; + + /* Allow one registration session at a time */ + odp_rwlock_write_lock(®istration.lock); + + /* Block the subsystem API calls in load new + * implementation modules. */ + odp_rwlock_write_lock(&subsystem->lock); + module->handler = NULL; /* no DSO handler */ + list_add_tail(&subsystem->modules, &module->list); + odp_rwlock_write_unlock(&subsystem->lock); + + odp_rwlock_write_unlock(®istration.lock); + return 0; +} + +static int (*do_register_module)(odp_subsystem_t *, odp_module_base_t *) + = &linker_register_module; + +static int loader_register_module( + odp_subsystem_t *subsystem, odp_module_base_t *module) +{ + int sanity = registration_sanity_check(subsystem, module); + + if (sanity < 0) /* sanity check errors */ + return sanity; + + /* Registration session lock must be held by + * module_loader_start(). */ + if (odp_rwlock_write_trylock(®istration.lock) == 0) { + registration.subsystem = subsystem; + registration.module = module; + return 0; + } + + odp_rwlock_write_unlock(®istration.lock); + return -EACCES; +} + +void odp_module_loader_start(void) +{ + odp_rwlock_write_lock(®istration.lock); + + if (registration.module != NULL || + registration.subsystem != NULL) { + DBG("module loader start warn, A previous " + "registration did not complete yet.\n"); + } + + registration.module = NULL; + registration.subsystem = NULL; + do_register_module = &loader_register_module; +} + +void odp_module_loader_end(void) +{ + if (registration.module != NULL || + registration.subsystem != NULL) { + DBG("module loader end warn, A previous " + "registration did not complete yet.\n"); + } + + registration.module = NULL; + registration.subsystem = NULL; + do_register_module = &linker_register_module; + + odp_rwlock_write_unlock(®istration.lock); +} + +int odp_module_install(void *dso, bool active) +{ + /* Bottom halves of the registration, context exclusion + * is guaranteed by module_loader_start() + */ + if (odp_rwlock_write_trylock(®istration.lock) == 0) { + odp_subsystem_t *subsystem = registration.subsystem; + odp_module_base_t *module = registration.module; + + if (subsystem != NULL && module != NULL) { + odp_rwlock_write_lock(&subsystem->lock); + + module->handler = dso; + list_add_tail(&subsystem->modules, &module->list); + + /* install as active implementation */ + if (active) /* warn: replaceable */ + subsystem->active = module; + + odp_rwlock_write_unlock(&subsystem->lock); + } + + registration.subsystem = NULL; + registration.module = NULL; + return 0; + } + + odp_rwlock_write_unlock(®istration.lock); + return -EACCES; +} + +int odp_module_abandon(void) +{ + /* Bottom halves of the registration, context exclusion + * is guaranteed by module_loader_start() + */ + if (odp_rwlock_write_trylock(®istration.lock) == 0) { + registration.subsystem = NULL; + registration.module = NULL; + return 0; + } + + odp_rwlock_write_unlock(®istration.lock); + return -EACCES; +} + +int __subsystem_register_module( + odp_subsystem_t *subsystem, odp_module_base_t *module) +{ + return do_register_module(subsystem, module); +} diff --git a/frameworks/modular/odp_module.h b/frameworks/modular/odp_module.h new file mode 100644 index 00000000..1a9e178c --- /dev/null +++ b/frameworks/modular/odp_module.h @@ -0,0 +1,296 @@ +/* Copyright (c) 2017, ARM Limited. All rights reserved. + * + * Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * + * Modular framework solves the problem of choosing a module + * from multiple modules of a subsystem. + * + * The choice is available during compile time or during runtime + * or initialization. The runtime choice could be using shared + * libraries or dynamic loadable libraries. + * + * Multiple modules of the same subsystem can be built into + * individual static libraries(.a), shared libraries(.so) to be + * dynamically linked or loaded, and use constructor functions + * to register themselves. + * + * A subsystem can choose one active module and provide APIs to + * switch between modules. + * + * Alternatively, subsystem can load multiple modules and + * determine the APIs route in runtime. + * + * In order to gain full possible performance, the subsystem + * allows for choosing a specific module at compile time. + * This eliminates the need to choose the module using function + * pointer table. + * + * This framework tries to minimizes dependencies to the linked + * list and rwlock facilities only. + */ + +#ifndef ODP_MODULE_H_ +#define ODP_MODULE_H_ + +#include <stdbool.h> +#include <odp/api/rwlock.h> +#include "list.h" + +/* Forward declaration */ +typedef struct odp_module_base odp_module_base_t; + +/* Subsystem */ +typedef struct odp_subsystem { + odp_rwlock_t lock; + uint32_t version; + const char *name; + const char *description; + struct list_head modules; + odp_module_base_t *active; +} odp_subsystem_t; + +/* Internally construct subsystem instance name */ +#define __subsystem(name) odp_ ## name ## _subsystem + +/* Declare an ODP subsystem in header file */ +#define ODP_SUBSYSTEM_DECLARE(name) \ + extern odp_subsystem_t __subsystem(name) + +/* Define an ODP subsystem in source file */ +#define ODP_SUBSYSTEM_DEFINE(_name, _description, _version) \ + odp_subsystem_t __subsystem(_name) = \ + { \ + .lock = ODP_RWLOCK_UNLOCKED, \ + .name = # _name, \ + .version = _version, \ + .description = _description, \ + } + +/* Internally construct subsystem API name */ +#define __odp_api(subsystem, api) odp_ ## subsystem ##_## api + +/* Subsystem API prototype name */ +#define odp_api_proto(subsystem, api) __odp_api(subsystem, api ## _proto_t) + +/* Subsystem API declaration */ +#define ODP_SUBSYSTEM_API(name, _return, api, ...) \ + extern _return __odp_api(name, api)(__VA_ARGS__); \ + typedef _return (*odp_api_proto(name, api))(__VA_ARGS__) + +/* Subsystem API stubs are weak */ +#define ODP_SUBSYSTEM_API_STUB(name, api) \ + __attribute__((weak)) __odp_api(name, api) + +/* In case a subsystem module are built as static libraries(.a) + * or preload dynamic libraries(.so), the module can use this + * macro to override the APIs weak stubs. + */ +#define ODP_SUBSYSTEM_API_OVERRIDE(name, api, _alias) \ + __attribute__((alias(#_alias))) __odp_api(name, api) + +#define odp_subsystem_constructor(name) \ + do { \ + odp_rwlock_init(&__subsystem(name).lock); \ + list_head_init(&__subsystem(name).modules); \ + __subsystem(name).active = NULL; \ + } while (0) + +#define ODP_SUBSYSTEM_CONSTRUCTOR(name) \ + static void __attribute__((constructor(101))) \ + odp_ ## name ## _subsystem_constructor(void) + +#define odp_subsystem_lock(access, name) \ + odp_rwlock_ ## access ## _lock(&__subsystem(name).lock) + +#define odp_subsystem_unlock(access, name) \ + odp_rwlock_ ## access ## _unlock(&__subsystem(name).lock) + +/* Base class to all inherited subsystem module classes */ +struct odp_module_base { + struct list_node list; + const char *name; + void *handler; /* DSO */ + int (*init_local)(void); + int (*term_local)(void); + int (*init_global)(void); + int (*term_global)(void); +}; + +/* It is required to define subsystem module class with the + * base class as its 1st member and named as "base", and also + * use ODP_MODULE_CLASS(subsystem) to create the association + * between module class name and subsystem name, like: + * + * typedef ODP_MODULE_CLASS(subsystem) { + * odp_module_base_t base; + * ...new members... + * } new_module_t; // Here pick the name you like freely + * + * It also supports forward declaration like: + * + * // Forward declaration + * typedef ODP_MODULE_CLASS(subsystem) new_module_t; + * // Laterly comes the definition + * ODP_MODULE_CLASS(subsystem) { + * odp_module_base_t base; + * ...new members... + * } + * + * Then in preprocessor macros when we have the subsystem name + * we can recover the module class type information, like: + * + * #define MACRO(subsystem) + * do { + * ODP_MODULE_CLASS(subsystem) *mod = NULL; + * odp_subsystem_foreach_module(subsystem, mod) { + * mod->xxx; // access the module class + * } + * } while(0) + */ +#define ODP_MODULE_CLASS(subsystem) struct odp_ ## subsystem ## _module + +/* Below macros assume that all subsystem module classes have + * odp_module_base_t as their 1st member named "base". + * + * This greatly reduces the complexity for module list iteration + * and module pointer recovery from its list_node member by a forced + * type conversion instead of complex calls to container_of() etc. + */ +#define __force_cast(module, node) \ + ((typeof(module))((void *)(node))) + +#define __foreach_module(pos, head) \ + for (pos = __force_cast(pos, (head)->node.next); \ + pos != __force_cast(pos, head); \ + pos = __force_cast(pos, (pos)->base.list.next)) + +#define __foreach_module_safe(pos, n, head) \ + for (pos = __force_cast(pos, (head)->node.next), \ + n = __force_cast(pos, (pos)->base.list.next); \ + pos != __force_cast(pos, head); \ + pos = n, n = __force_cast(next, (next)->base.list.next)) + +#define odp_subsystem_active_module(name, mod) \ + __force_cast(mod, __subsystem(name).active) + +#define odp_subsystem_foreach_module(name, mod) \ + __foreach_module(mod, &__subsystem(name).modules) + +#define odp_subsystem_foreach_module_safe(name, mod, next) \ + __foreach_module_safe(mod, next, &__subsystem(name).modules) + +#define odp_module_constructor(mod) list_node_init(&(mod)->base.list) + +/* Module constructors should be later than subsystem constructors, + * in statically linked scenarios (both subsystems and modules are + * linked statically). thus the priority 102 compared to the above + * subsystem constructor priority 101. + */ +#define ODP_MODULE_CONSTRUCTOR(name) \ + static void __attribute__((constructor(102))) \ + odp_ ## name ## _module_constructor(void) + +/* All subsystems' initialization and termination routines are + * the same, provide template to help generate similar routines + * automatically, examples: + * + * ODP_SUBSYSTEM_FOREACH_TEMPLATE(subsystem, init_global, DBG) + * will generate a function walk through all the modules of the + * subsystem and invoke init_global method for each. + */ +#define ODP_SUBSYSTEM_FOREACH_TEMPLATE(subs, method, print) \ +static int odp_ ## subs ##_## method(bool continue_on_errors) \ +{ \ + int result = 0; \ + ODP_MODULE_CLASS(subs) * mod = NULL; \ + \ + odp_subsystem_lock(read, subs); \ + odp_subsystem_foreach_module(subs, mod) { \ + result = mod->base.method ? \ + mod->base.method() : 0; \ + if (result < 0) { \ + print("error %d to %s subsystem %s " \ + "module %s.\n", result, #method, \ + __subsystem(subs).name, \ + mod->base.name); \ + \ + if (continue_on_errors) \ + continue; \ + else \ + goto done; \ + } \ + } \ +done: \ + odp_subsystem_unlock(read, subs); \ + return result; \ +} + +/* Subsystem Modules Registration + * + * odp_subsystem_register_module() are called by all modules in their + * constructors, whereas the modules could be: + * + * 1) built as static libraries(.a) and linked statically, or + * built as shared libraries(.so) and linked dynamically. + * + * odp_subsystem_register_module() should complete the whole + * registration session and link the module into subsystem's + * module array. + * + * 2) built as shared libraries(.so) and loaded by a module loader + * in runtime with libdl APIs + * + * The whole registration session needs to be split to aim the + * module loader to properly handle dlopen() returns, and save + * the DSO handler into module's data structure. + * + * The module loader should program in this way: + * odp_module_loader_start(); + * ...... + * for each module + * handler = dlopen(module); + * // The module constructor runs before dlopen() returns + * // which in turn calls odp_subsystem_register_module() + * if (handler is valid) + * odp_module_install(handler); + * else + * odp_module_abandon(); + * ...... + * odp_module_loader_end(); + */ + +void odp_module_loader_start(void); +void odp_module_loader_end(void); + +int odp_module_install(void *, bool active); +int odp_module_abandon(void); + +#define __maybe_unused __attribute__((unused)) +static inline void __subsystem_set_active( + odp_subsystem_t *subsystem __maybe_unused, + odp_module_base_t *module __maybe_unused) +{ +#if defined(IM_ACTIVE_MODULE) + subsystem->active = module; +#endif +} + +int __subsystem_register_module( + odp_subsystem_t *, odp_module_base_t *); + +/* Macro to allow polymorphism on module classes */ +#define odp_subsystem_register_module(name, module) \ +({ \ + odp_module_base_t *base = &(module)->base; \ + __subsystem_register_module(&__subsystem(name), base); \ + __subsystem_set_active(&__subsystem(name), base); \ +}) + +#endif diff --git a/include/odp/api/spec/atomic.h b/include/odp/api/spec/atomic.h index 408829df..54a174ea 100644 --- a/include/odp/api/spec/atomic.h +++ b/include/odp/api/spec/atomic.h @@ -59,6 +59,12 @@ extern "C" { * Atomic 32-bit unsigned integer */
+/** + * @def ODP_ATOMIC_INIT + * Compile-time atomic initializer: + * odp_atomic_xx_t atomic = ODP_ATOMIC_INIT(v); + */ + /* * 32-bit operations in RELAXED memory ordering * -------------------------------------------- diff --git a/include/odp/api/spec/rwlock.h b/include/odp/api/spec/rwlock.h index ff8a3f27..8816b6e7 100644 --- a/include/odp/api/spec/rwlock.h +++ b/include/odp/api/spec/rwlock.h @@ -36,6 +36,11 @@ extern "C" { * ODP reader/writer lock */
+/** + * @def ODP_RWLOCK_UNLOCKED + * Compile-time RW lock initializer: + * odp_rwlock_t lock = ODP_RWLOCK_UNLOCKED; + */
/** * Initialize a reader/writer lock. diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index ba4a31ea..4a7b77b8 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -6,6 +6,7 @@ include $(top_srcdir)/platform/@with_platform@/Makefile.inc
AM_CFLAGS += -I$(srcdir)/include AM_CFLAGS += -I$(top_srcdir)/include +AM_CFLAGS += -I$(top_srcdir)/frameworks/modular AM_CFLAGS += -I$(top_srcdir)/include/odp/arch/@ARCH_ABI@ AM_CFLAGS += -I$(top_builddir)/include AM_CFLAGS += -Iinclude @@ -292,6 +293,13 @@ if HAVE_PCAP __LIB__libodp_linux_la_SOURCES += pktio/pcap.c endif
+# Build modular framework into odp-linux library +modularframeworkdir = $(top_srcdir)/frameworks/modular +noinst_HEADERS += $(modularframeworkdir)/list.h \ + $(modularframeworkdir)/odp_module.h + +__LIB__libodp_linux_la_SOURCES += ../../frameworks/modular/odp_module.c + __LIB__libodp_linux_la_LIBADD = $(ATOMIC_LIBS)
# Create symlink for ABI header files. Application does not need to use the arch diff --git a/platform/linux-generic/include/odp/api/plat/atomic_types.h b/platform/linux-generic/include/odp/api/plat/atomic_types.h index a674ac99..86c9e5b0 100644 --- a/platform/linux-generic/include/odp/api/plat/atomic_types.h +++ b/platform/linux-generic/include/odp/api/plat/atomic_types.h @@ -81,6 +81,8 @@ typedef struct odp_atomic_u64_s odp_atomic_u64_t;
typedef struct odp_atomic_u32_s odp_atomic_u32_t;
+#define ODP_ATOMIC_INIT(a) { .v = a } + #ifdef __cplusplus } #endif diff --git a/platform/linux-generic/include/odp/api/plat/rwlock_types.h b/platform/linux-generic/include/odp/api/plat/rwlock_types.h index f7dc0449..2c1f3660 100644 --- a/platform/linux-generic/include/odp/api/plat/rwlock_types.h +++ b/platform/linux-generic/include/odp/api/plat/rwlock_types.h @@ -30,6 +30,8 @@ struct odp_rwlock_s {
typedef struct odp_rwlock_s odp_rwlock_t;
+#define ODP_RWLOCK_UNLOCKED { .cnt = ODP_ATOMIC_INIT(0) } + #ifdef __cplusplus } #endif
commit 5f738a79248183a252478856de88bafa37344445 Author: Yi He yi.he@linaro.org Date: Wed Jul 19 15:05:14 2017 +0800
validation: pktio: disable socket mmsg pktio
It was not working already, the problem are obscured in make check because with static pktio_if_ops array socket mmap pktio always take precedence over socket mmsg pktio.
Signed-off-by: Yi He yi.he@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org
diff --git a/test/linux-generic/validation/api/pktio/pktio_env b/test/linux-generic/validation/api/pktio/pktio_env index 345b5bd5..3a6f9e89 100644 --- a/test/linux-generic/validation/api/pktio/pktio_env +++ b/test/linux-generic/validation/api/pktio/pktio_env @@ -103,6 +103,9 @@ setup_pktio_env() return 5 fi done + + # disable socket mmsg pktio since it was not working already + export ODP_PKTIO_DISABLE_SOCKET_MMSG=1 }
cleanup_pktio_env()
commit 3058124d5c307149272c1b37651056451939c3bf Author: Yi He yi.he@linaro.org Date: Thu Jul 13 15:48:20 2017 +0800
example: ddf_app: add .gitignore
Signed-off-by: Yi He yi.he@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org
diff --git a/example/ddf_app/.gitignore b/example/ddf_app/.gitignore new file mode 100644 index 00000000..f79a1409 --- /dev/null +++ b/example/ddf_app/.gitignore @@ -0,0 +1 @@ +odp_ddf_app
-----------------------------------------------------------------------
Summary of changes: example/ddf_app/.gitignore | 1 + frameworks/modular/list.h | 271 +++++++++++++++++++ frameworks/modular/odp_module.c | 179 +++++++++++++ frameworks/modular/odp_module.h | 296 +++++++++++++++++++++ include/odp/api/spec/atomic.h | 6 + include/odp/api/spec/rwlock.h | 5 + platform/linux-generic/Makefile.am | 8 + .../include/odp/api/plat/atomic_types.h | 2 + .../include/odp/api/plat/rwlock_types.h | 2 + test/linux-generic/validation/api/pktio/pktio_env | 3 + 10 files changed, 773 insertions(+) create mode 100644 example/ddf_app/.gitignore create mode 100644 frameworks/modular/list.h create mode 100644 frameworks/modular/odp_module.c create mode 100644 frameworks/modular/odp_module.h
hooks/post-receive