The functions to register and probe enumerator classes are added.

Signed-off-by: Christophe Milard <christophe.mil...@linaro.org>
---
 platform/linux-generic/Makefile.am                 |   1 +
 platform/linux-generic/_modules.c                  |   4 +
 platform/linux-generic/drv_driver.c                | 212 ++++++++++++++++++++-
 .../linux-generic/include/drv_driver_internal.h    |  22 +++
 platform/linux-generic/include/odp_internal.h      |   5 +
 platform/linux-generic/odp_init.c                  |  21 +-
 6 files changed, 260 insertions(+), 5 deletions(-)
 create mode 100644 platform/linux-generic/include/drv_driver_internal.h

diff --git a/platform/linux-generic/Makefile.am 
b/platform/linux-generic/Makefile.am
index 66ff53d..b7d1b1a 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -133,6 +133,7 @@ noinst_HEADERS = \
                  ${srcdir}/include/_ishm_internal.h \
                  ${srcdir}/include/_ishmphy_internal.h \
                  ${srcdir}/include/_ishmpool_internal.h \
+                 ${srcdir}/include/drv_driver_internal.h\
                  ${srcdir}/include/odp_align_internal.h \
                  ${srcdir}/include/odp_atomic_internal.h \
                  ${srcdir}/include/odp_buffer_inlines.h \
diff --git a/platform/linux-generic/_modules.c 
b/platform/linux-generic/_modules.c
index 6bb854e..b23c81f 100644
--- a/platform/linux-generic/_modules.c
+++ b/platform/linux-generic/_modules.c
@@ -9,6 +9,7 @@
 #include <odp/api/std_types.h>
 #include <odp/api/debug.h>
 #include <odp_debug_internal.h>
+#include <drv_driver_internal.h>
 #include <libconfig.h>
 #include <dlfcn.h>
 
@@ -40,6 +41,9 @@ static int load_modules(void)
                ODP_DBG("module %s loaded.\n", module_name);
        }
 
+       /* give a chance top the driver interface to probe for new things: */
+       _odpdrv_driver_probe_drv_items();
+
        return 0;
 }
 
diff --git a/platform/linux-generic/drv_driver.c 
b/platform/linux-generic/drv_driver.c
index 529da48..50956a7 100644
--- a/platform/linux-generic/drv_driver.c
+++ b/platform/linux-generic/drv_driver.c
@@ -4,20 +4,131 @@
  * SPDX-License-Identifier:     BSD-3-Clause
  */
 
+#include <string.h>
+
 #include <odp_config_internal.h>
+#include <_ishmpool_internal.h>
 
 #include <odp/api/std_types.h>
 #include <odp/api/debug.h>
+#include <odp/api/rwlock_recursive.h>
 #include <odp/drv/driver.h>
+#include <odp/drv/spec/driver.h>
 #include <odp_debug_internal.h>
+#include <drv_driver_internal.h>
+
+static enum {UNDONE, IN_PROGRESS, DONE} init_global_status;
+
+/* pool from which different list elements are alocated: */
+#define ELT_POOL_SIZE (1 << 20)  /* 1Mb */
+static _odp_ishm_pool_t *list_elt_pool;
+
+typedef struct _odpdrv_enumr_class_s _odpdrv_enumr_class_t;
+
+/* an enumerator class (list element) */
+struct _odpdrv_enumr_class_s {
+       odpdrv_enumr_class_param_t param;
+       int probed;
+       _odp_ishm_pool_t *pool;
+       struct _odpdrv_enumr_class_s *next;
+};
+
+/* the enumerator class list: */
+typedef struct _odpdrv_enumr_class_lst_t {
+       odp_rwlock_recursive_t lock;
+       _odpdrv_enumr_class_t *head;
+} _odpdrv_enumr_class_lst_t;
+static struct _odpdrv_enumr_class_lst_t enumr_class_lst;
+
+/* some driver elements (such as enumeraor classes, drivers, devio) may
+ * register before init_global and init_local complete. Mutex will fail
+ * in this cases but should be used later on.
+ * These functions disable the usage of Mutex while it is global init i.e.
+ * while single threaded*/
+static void enumr_class_list_read_lock(void)
+{
+       if (init_global_status == DONE)
+               odp_rwlock_recursive_read_lock(&enumr_class_lst.lock);
+}
+
+static void enumr_class_list_read_unlock(void)
+{
+       if (init_global_status == DONE)
+               odp_rwlock_recursive_read_unlock(&enumr_class_lst.lock);
+}
+
+static void enumr_class_list_write_lock(void)
+{
+       if (init_global_status == DONE)
+               odp_rwlock_recursive_write_lock(&enumr_class_lst.lock);
+}
+
+static void enumr_class_list_write_unlock(void)
+{
+       if (init_global_status == DONE)
+               odp_rwlock_recursive_write_unlock(&enumr_class_lst.lock);
+}
+
 
 odpdrv_enumr_class_t odpdrv_enumr_class_register(odpdrv_enumr_class_param_t
                                                 *param)
 {
-       ODP_ERR("NOT Supported yet! Enumerator Class %s Registration!\n.",
-               param->name);
+       _odpdrv_enumr_class_t *enumr_c;
 
-       return ODPDRV_ENUMR_CLASS_INVALID;
+       /* parse the list of already registered enumerator class to make
+        * sure no enumerator with identical name already exists:
+        */
+       enumr_class_list_read_lock();
+       enumr_c = enumr_class_lst.head;
+       while (enumr_c) {
+               if (strncmp(param->name, enumr_c->param.name,
+                           ODPDRV_NAME_SIZE) == 0) {
+                       ODP_ERR("enumerator class %s already exists!\n",
+                               param->name);
+                       enumr_class_list_read_unlock();
+                       return ODPDRV_ENUMR_CLASS_INVALID;
+               }
+               enumr_c = enumr_c->next;
+       }
+       enumr_class_list_read_unlock();
+
+       /* allocate memory for the new enumerator class:
+        * If init_global has not been done yet, then, we cannot allocate
+        * from any _ishm pool (ishm has not even been initialised at this
+        * stage...this happens when statically linked enumerator classes
+        * register: their __constructor__ function is run before main()
+        * is called). But any malloc performed here(before init_global)
+        * will be inherited by any odpthreads (process or pthreads) as we
+        * are still running in the ODP instantiation processes and all
+        * other processes are guaranteed to be descendent of this one...
+        * If init_global has been done, then we allocate from the _ishm pool
+        * to guarantee visibility from any ODP thread.
+        */
+
+       if (init_global_status == UNDONE) {
+               enumr_c = malloc(sizeof(_odpdrv_enumr_class_t));
+               if (!enumr_c)
+                       return ODPDRV_ENUMR_CLASS_INVALID;
+               enumr_c->pool = NULL;
+       } else {
+               enumr_c = _odp_ishm_pool_alloc(list_elt_pool,
+                                              sizeof(_odpdrv_enumr_class_t));
+               if (!enumr_c) {
+                       ODP_ERR("_odp_ishm_pool_alloc failed!\n");
+                       return ODPDRV_ENUMR_CLASS_INVALID;
+               }
+               enumr_c->pool = list_elt_pool;
+       }
+
+       /* save init parameters and insert enumerator class in list */
+       enumr_c->param = *param;
+       enumr_c->probed = 0;
+       enumr_class_list_write_lock();
+       enumr_c->next = enumr_class_lst.head;
+       enumr_class_lst.head = enumr_c;
+       enumr_class_list_write_unlock();
+
+       return (odpdrv_enumr_class_t)enumr_c;
 }
 
 odpdrv_enumr_t odpdrv_enumr_register(odpdrv_enumr_param_t *param)
@@ -57,8 +168,101 @@ odpdrv_driver_t 
odpdrv_driver_register(odpdrv_driver_param_t *param)
        return ODPDRV_DRIVER_INVALID;
 }
 
+/* the following function is called each time probing is needed, i.e.
+ * at init or after loading a new module as a module can be anything,
+ * including enumerators or drivers */
+void _odpdrv_driver_probe_drv_items(void)
+{
+       _odpdrv_enumr_class_t *enumr_c;
+
+       /* probe unprobed enumerators: */
+       enumr_class_list_read_lock();
+       enumr_c = enumr_class_lst.head;
+       while (enumr_c) {
+               if (!enumr_c->probed) {
+                       enumr_c->param.probe();
+                       enumr_c->probed = 1;
+               }
+               enumr_c = enumr_c->next;
+       }
+       enumr_class_list_read_unlock();
+}
+
 int odpdrv_print_all(void)
 {
-       ODP_ERR("odpdrv_print_all not Supported yet!\n.");
+       _odpdrv_enumr_class_t *enumr_c;
+
+       /* we cannot use ODP_DBG before ODP init... */
+       if (init_global_status == UNDONE)
+               return 0;
+
+       ODP_DBG("ODP Driver status:\n");
+
+       /* print the list of registered enumerator classes: */
+       enumr_class_list_read_lock();
+       enumr_c = enumr_class_lst.head;
+       ODP_DBG("The following enumerator classes have been registered:\n");
+       while (enumr_c) {
+               ODP_DBG(" class: %s\n", enumr_c->param.name);
+               enumr_c = enumr_c->next;
+       }
+       enumr_class_list_read_unlock();
+       return 0;
+}
+
+int _odpdrv_driver_init_global(void)
+{
+       /* create a memory pool to for list elements: */
+       list_elt_pool = _odp_ishm_pool_create(NULL, ELT_POOL_SIZE,
+                                             0, ELT_POOL_SIZE, 0);
+
+       /* remember that init global is being done so the further list allocs
+        * are made from the list_elt_pool: */
+       init_global_status = IN_PROGRESS;
+
+       /* from now, we want to ensure mutex on the list: init lock: */
+       odp_rwlock_recursive_init(&enumr_class_lst.lock);
+
+       /* probe things... */
+       _odpdrv_driver_probe_drv_items();
+
+       return 0;
+}
+
+int _odpdrv_driver_init_local(void)
+{
+       /* remember that init global is done, so list mutexes are used from
+        * now */
+       init_global_status = DONE;
+       return 0;
+}
+
+int _odpdrv_driver_term_global(void)
+{
+       _odpdrv_enumr_class_t *enumr_c;
+
+       if (init_global_status == UNDONE)
+               return 0;
+
+       /* remove all enumerator classes which are registered: */
+       enumr_class_list_write_lock();
+       while (enumr_class_lst.head) {
+               enumr_c = enumr_class_lst.head;
+               if (enumr_c->param.remove) { /* run remove callback, if any */
+                       if (enumr_c->param.remove())
+                               ODP_ERR("Enumerator class %s removal failed.\n",
+                                       enumr_c->param.name);
+               }
+               enumr_class_lst.head = enumr_c->next;
+               if (enumr_c->pool)
+                       _odp_ishm_pool_free(list_elt_pool, enumr_c);
+               else
+                       free(enumr_c);
+       }
+       enumr_class_list_write_unlock();
+
+       /* destroy the list element pool: */
+       _odp_ishm_pool_destroy(list_elt_pool);
+
        return 0;
 }
diff --git a/platform/linux-generic/include/drv_driver_internal.h 
b/platform/linux-generic/include/drv_driver_internal.h
new file mode 100644
index 0000000..eb06c1b
--- /dev/null
+++ b/platform/linux-generic/include/drv_driver_internal.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef DRV_DRIVER_INTERNAL_H_
+#define DRV_DRIVER_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+void _odpdrv_driver_probe_drv_items(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp_internal.h 
b/platform/linux-generic/include/odp_internal.h
index 05c8a42..1760b56 100644
--- a/platform/linux-generic/include/odp_internal.h
+++ b/platform/linux-generic/include/odp_internal.h
@@ -71,6 +71,7 @@ enum init_stage {
        CLASSIFICATION_INIT,
        TRAFFIC_MNGR_INIT,
        NAME_TABLE_INIT,
+       DRIVER_INIT,
        MODULES_INIT,
        ALL_INIT      /* All init stages completed */
 };
@@ -130,6 +131,10 @@ int _odp_ishm_init_local(void);
 int _odp_ishm_term_global(void);
 int _odp_ishm_term_local(void);
 
+int _odpdrv_driver_init_global(void);
+int _odpdrv_driver_init_local(void);
+int _odpdrv_driver_term_global(void);
+
 int _odp_modules_init_global(void);
 
 int cpuinfo_parser(FILE *file, system_info_t *sysinfo);
diff --git a/platform/linux-generic/odp_init.c 
b/platform/linux-generic/odp_init.c
index 685e02f..c59cc28 100644
--- a/platform/linux-generic/odp_init.c
+++ b/platform/linux-generic/odp_init.c
@@ -266,6 +266,12 @@ int odp_init_global(odp_instance_t *instance,
        }
        stage = NAME_TABLE_INIT;
 
+       if (_odpdrv_driver_init_global()) {
+               ODP_ERR("ODP drivers init failed\n");
+               goto init_failed;
+       }
+       stage = DRIVER_INIT;
+
        if (_odp_modules_init_global()) {
                ODP_ERR("ODP modules init failed\n");
                goto init_failed;
@@ -296,6 +302,13 @@ int _odp_term_global(enum init_stage stage)
        switch (stage) {
        case ALL_INIT:
        case MODULES_INIT:
+       case DRIVER_INIT:
+               if (_odpdrv_driver_term_global()) {
+                       ODP_ERR("driver term failed.\n");
+                       rc = -1;
+               }
+               /* Fall through */
+
        case NAME_TABLE_INIT:
                if (_odp_int_name_tbl_term_global()) {
                        ODP_ERR("Name table term failed.\n");
@@ -445,7 +458,13 @@ int odp_init_local(odp_instance_t instance, 
odp_thread_type_t thr_type)
                ODP_ERR("ODP schedule local init failed.\n");
                goto init_fail;
        }
-       /* stage = SCHED_INIT; */
+       stage = SCHED_INIT;
+
+       if (_odpdrv_driver_init_local()) {
+               ODP_ERR("ODP driver local init failed.\n");
+               goto init_fail;
+       }
+       /* stage = DRIVER_INIT; */
 
        return 0;
 
-- 
2.7.4

Reply via email to