Signed-off-by: Ola Liljedahl <[email protected]>
---
(This document/code contribution attached is provided under the terms of 
agreement LES-LTM-21309)
Log API for internal ODP use.
Logging can be compile time and run time disabled.
Compile out all log levels: -DODP_LOG_LEVEL=0
Compile in all log levels: -DODP_LOG_LEVEL=7
Enable all log levels: -DODP_LOG_DEFAULT_MASK=7 (default: fatal+error)
Run time setting: odp_log_set_level("module_name", level);
Log messages can be redirected: odp_log_set_callback(fn);

Usage:
ODP_LOG_DECLARE(my_mod); /* File-scope declaration */
ODP_LOG_REGISTER(my_mod); /* Init call */
ODP_LOG_ERROR(my_mod, "Error %u has occured\n", 242);

 platform/linux-generic/Makefile.am                |   2 +
 platform/linux-generic/include/api/odp_log.h      |  59 +++++++
 platform/linux-generic/include/odp_log_internal.h | 115 +++++++++++++
 platform/linux-generic/odp_init.c                 |  26 +--
 platform/linux-generic/odp_log.c                  | 189 ++++++++++++++++++++++
 5 files changed, 382 insertions(+), 9 deletions(-)
 create mode 100644 platform/linux-generic/include/api/odp_log.h
 create mode 100644 platform/linux-generic/include/odp_log_internal.h
 create mode 100644 platform/linux-generic/odp_log.c

diff --git a/platform/linux-generic/Makefile.am 
b/platform/linux-generic/Makefile.am
index f4dfdc1..f30c6ff 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -20,6 +20,7 @@ include_HEADERS = \
                  $(top_srcdir)/platform/linux-generic/include/api/odp_debug.h \
                  $(top_srcdir)/platform/linux-generic/include/api/odp_hints.h \
                  $(top_srcdir)/platform/linux-generic/include/api/odp_init.h \
+                 $(top_srcdir)/platform/linux-generic/include/api/odp_log.h \
                  
$(top_srcdir)/platform/linux-generic/include/api/odp_packet_flags.h \
                  $(top_srcdir)/platform/linux-generic/include/api/odp_packet.h 
\
                  
$(top_srcdir)/platform/linux-generic/include/api/odp_packet_io.h \
@@ -58,6 +59,7 @@ __LIB__libodp_la_SOURCES = \
                           odp_crypto.c \
                           odp_init.c \
                           odp_linux.c \
+                          odp_log.c \
                           odp_packet.c \
                           odp_packet_flags.c \
                           odp_packet_io.c \
diff --git a/platform/linux-generic/include/api/odp_log.h 
b/platform/linux-generic/include/api/odp_log.h
new file mode 100644
index 0000000..b8c49e3
--- /dev/null
+++ b/platform/linux-generic/include/api/odp_log.h
@@ -0,0 +1,59 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP internal logging facility - public management API
+ */
+
+#ifndef ODP_LOG_H_
+#define ODP_LOG_H_
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Fatal error for function, may not return to caller */
+#define ODP_LOG_LVL_FATAL   1U
+/** Error prevented function to succeed but caller should be able to recover */
+#define ODP_LOG_LVL_ERROR   2U
+/** Problem detected in function but recovered locally */
+#define ODP_LOG_LVL_WARNING 3U
+/** Informational message intended for user */
+#define ODP_LOG_LVL_INFORM  4U
+/** Debug message intended for developer */
+#define ODP_LOG_LVL_DEBUG   5U
+
+#define ODP_LOG_LVL_NONE 0U  /**< Disable all log levels */
+#define ODP_LOG_LVL_ALL  7U /**< Enable all log levels */
+
+typedef volatile uint32_t odp_log_t;
+#define ODP_LOG_INVALID 0U
+
+/** Call-back type definition for user-defined log facility */
+typedef void (*odp_log_callback_t)(const char *name,
+                                  unsigned level,
+                                  const char *fmt,
+                                  va_list ap);
+
+/** Set the log level for a source identified by name */
+int odp_log_set_level(const char *name, unsigned level);
+/** Install a user-defined call-back for handling log messages */
+void odp_log_set_callback(odp_log_callback_t cb);
+/** Iterate through all registered log sources */
+int odp_log_next(odp_log_t *phdl, char *name, size_t namelen, unsigned *level);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp_log_internal.h 
b/platform/linux-generic/include/odp_log_internal.h
new file mode 100644
index 0000000..7ac3ab1
--- /dev/null
+++ b/platform/linux-generic/include/odp_log_internal.h
@@ -0,0 +1,115 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP internal logging facility - client API
+ */
+
+#ifndef ODP_LOG_INTERNAL_H_
+#define ODP_LOG_INTERNAL_H_
+
+#include <stdint.h>
+#include <odp_log.h>
+#include <odp_hints.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef ODP_LOG_LEVEL
+#define ODP_LOG_LEVEL ODP_LOG_LVL_ALL
+#endif
+
+/* Report a message to the log */
+#define ODP_LOG_MSG(_lvl, _hdl, _fmt, ...) \
+do { \
+       unsigned __lvl = (_lvl); \
+       odp_log_t __hdl = (_hdl); \
+       const char *__fmt = (_fmt); \
+       if (odp_unlikely((__hdl & 0x7) >= __lvl)) \
+               odp_log_printf(__lvl, __hdl, __fmt, ##__VA_ARGS__); \
+} while (0)
+
+#if ODP_LOG_LEVEL >= ODP_LOG_LVL_FATAL
+#define ODP_LOG_FATAL(_src, _fmt, ...) \
+ODP_LOG_MSG(ODP_LOG_LVL_FATAL, (_odp_log_src_ ## _src), (_fmt), ##__VA_ARGS__)
+#else
+#define ODP_LOG_FATAL(_src, _fmt, ...) (void)0
+#endif
+
+#if ODP_LOG_LEVEL >= ODP_LOG_LVL_ERROR
+#define ODP_LOG_ERROR(_src, _fmt, ...) \
+ODP_LOG_MSG(ODP_LOG_LVL_ERROR, (_odp_log_src_ ## _src), (_fmt), ##__VA_ARGS__)
+#else
+#define ODP_LOG_ERROR(_src, _fmt, ...) (void)0
+#endif
+
+#if ODP_LOG_LEVEL >= ODP_LOG_LVL_WARNING
+#define ODP_LOG_WARNING(_src, _fmt, ...) \
+ODP_LOG_MSG(ODP_LOG_LVL_WARNING, (_odp_log_src_ ## _src), (_fmt), 
##__VA_ARGS__)
+#else
+#define ODP_LOG_WARNING(_src, _fmt, ...) (void)0
+#endif
+
+#if ODP_LOG_LEVEL >= ODP_LOG_LVL_INFORM
+#define ODP_LOG_INFORM(_src, _fmt, ...) \
+ODP_LOG_MSG(ODP_LOG_LVL_INFORM, (_odp_log_src_ ## _src), (_fmt), ##__VA_ARGS__)
+#else
+#define ODP_LOG_INFORM(_src, _fmt, ...) (void)0
+#endif
+
+#if ODP_LOG_LEVEL >= ODP_LOG_LVL_DEBUG
+#define ODP_LOG_DEBUG(_src, _fmt, ...) \
+ODP_LOG_MSG(ODP_LOG_LVL_DEBUG, (_odp_log_src_ ## _src), (_fmt), ##__VA_ARGS__)
+#else
+#define ODP_LOG_DEBUG(_src, _fmt, ...) (void)0
+#endif
+
+
+#define ODP_LOG_DECLARE(src) odp_log_t _odp_log_src_ ## src
+#define ODP_LOG_REGISTER(src) odp_log_register(&_odp_log_src_ ## src, #src)
+
+/* Calls indirectly used by log clients. Use macros above! */
+/* Register a log source with the specified name */
+void odp_log_register(odp_log_t *hdl, const char *name);
+/* Report a log message */
+void odp_log_printf(unsigned lvl, odp_log_t hdl, const char *fmt, ...);
+
+/* Init log module, specify call-back (or NULL for default behaviour) */
+void odp_log_init(odp_log_callback_t cb);
+
+
+/* Example usage:
+
+ODP_LOG_DECLARE(odp_queue);
+
+//Use default output mechanism
+odp_log_init(NULL);
+
+//Register log source and set default log level
+ODP_LOG_REGISTER(odp_queue);
+
+//Log a message with severity error
+ODP_LOG_ERROR(odp_queue, "Failed to create queue, param=%u\n", 242);
+
+//Set log level for a source to log everything
+(void)odp_log_set_level("odp_queue", ODP_LOG_LVL_ALL);
+
+//Install a custom vprintf function to handle log messages
+odp_log_set_callback(my_vprintf);
+
+//Log a message that will be forwarded to the user-specified log
+ODP_LOG_INFORM(odp_queue, "Message printed using user-defined call-back\n");
+
+*/
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/platform/linux-generic/odp_init.c 
b/platform/linux-generic/odp_init.c
index 5b7e192..3677f1b 100644
--- a/platform/linux-generic/odp_init.c
+++ b/platform/linux-generic/odp_init.c
@@ -7,46 +7,54 @@
 #include <odp_init.h>
 #include <odp_internal.h>
 #include <odp_debug.h>
+#include <odp_log_internal.h>
 
+ODP_LOG_DECLARE(odp_init);
 
 int odp_init_global(void)
 {
+       /* Init log mechanism first so that it can be used by all other
+          modules (including init) */
+       odp_log_init(NULL); /* NULL => Use default output mechanism */
+
+       ODP_LOG_REGISTER(odp_init);
+
        odp_thread_init_global();
 
        odp_system_info_init();
 
        if (odp_shm_init_global()) {
-               ODP_ERR("ODP shm init failed.\n");
+               ODP_LOG_FATAL(odp_init, "ODP shm init failed.\n");
                return -1;
        }
 
        if (odp_buffer_pool_init_global()) {
-               ODP_ERR("ODP buffer pool init failed.\n");
+               ODP_LOG_FATAL(odp_init, "ODP buffer pool init failed.\n");
                return -1;
        }
 
        if (odp_queue_init_global()) {
-               ODP_ERR("ODP queue init failed.\n");
+               ODP_LOG_FATAL(odp_init, "ODP queue init failed.\n");
                return -1;
        }
 
        if (odp_schedule_init_global()) {
-               ODP_ERR("ODP schedule init failed.\n");
+               ODP_LOG_FATAL(odp_init, "ODP schedule init failed.\n");
                return -1;
        }
 
        if (odp_pktio_init_global()) {
-               ODP_ERR("ODP packet io init failed.\n");
+               ODP_LOG_FATAL(odp_init, "ODP packet io init failed.\n");
                return -1;
        }
 
        if (odp_timer_init_global()) {
-               ODP_ERR("ODP timer init failed.\n");
+               ODP_LOG_FATAL(odp_init, "ODP timer init failed.\n");
                return -1;
        }
 
        if (odp_crypto_init_global()) {
-               ODP_ERR("ODP crypto init failed.\n");
+               ODP_LOG_FATAL(odp_init, "ODP crypto init failed.\n");
                return -1;
        }
 
@@ -59,12 +67,12 @@ int odp_init_local(int thr_id)
        odp_thread_init_local(thr_id);
 
        if (odp_pktio_init_local()) {
-               ODP_ERR("ODP packet io local init failed.\n");
+               ODP_LOG_FATAL(odp_init, "ODP packet io local init failed.\n");
                return -1;
        }
 
        if (odp_schedule_init_local()) {
-               ODP_ERR("ODP schedule local init failed.\n");
+               ODP_LOG_FATAL(odp_init, "ODP schedule local init failed.\n");
                return -1;
        }
 
diff --git a/platform/linux-generic/odp_log.c b/platform/linux-generic/odp_log.c
new file mode 100644
index 0000000..99b2803
--- /dev/null
+++ b/platform/linux-generic/odp_log.c
@@ -0,0 +1,189 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP logging utility
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <odp_debug.h>
+#include <odp_spinlock.h>
+#include <odp_sync.h>
+#include <odp_log.h>
+#include <odp_log_internal.h>
+
+#ifndef ODP_LOG_DEFAULT_MASK
+#define ODP_LOG_DEFAULT_MASK (ODP_LOG_LVL_FATAL | ODP_LOG_LVL_ERROR)
+#endif
+
+/* Maximum number of log sources */
+#ifndef ODP_LOG_MAX
+#define ODP_LOG_MAX 64
+#endif
+
+ODP_STATIC_ASSERT(ODP_LOG_LVL_ALL == 7U, "ODP_LOG_LVL_ALL_ERROR");
+
+#define HDL_TO_LVL(hdl) ((hdl) & 0x7U)
+#define HDL_TO_SLOT(hdl) (((hdl) >> 3U) - 1U)
+#define SLOT_LVL_TO_HDL(slot, lvl) ((((slot) + 1U) << 3U) | (lvl))
+#define INVALID_SLOT ~0U
+
+struct source {
+       odp_log_t *phdl;        /* Pointer to the user's odp_log_t variable */
+       const char *name;
+};
+
+static odp_spinlock_t lock;
+static volatile odp_log_callback_t callback;
+ODP_LOG_DECLARE(odp_log);
+static struct source sources[ODP_LOG_MAX];
+
+void
+odp_log_init(odp_log_callback_t cb)
+{
+       odp_spinlock_init(&lock);
+       callback = cb;
+       memset(sources, 0, sizeof(sources));
+       odp_sync_stores();
+       ODP_LOG_REGISTER(odp_log);
+       odp_log_set_level("odp_log", ODP_LOG_LVL_ALL);
+}
+
+/* Register a log source with the specified name */
+void
+odp_log_register(odp_log_t *phdl, const char *name)
+{
+       unsigned i;
+       unsigned slot = INVALID_SLOT;
+       odp_spinlock_lock(&lock);
+       *phdl = ODP_LOG_INVALID;
+       for (i = 0; i < ODP_LOG_MAX; i++) {
+               /* Check for unused slot */
+               if (sources[i].phdl == NULL && slot == INVALID_SLOT) {
+                       /* Found first unused slot */
+                       slot = i;
+               }
+               /* Check for source already present */
+               if (sources[i].name != NULL &&
+                   strcmp(sources[i].name, name) == 0) {
+                       odp_spinlock_unlock(&lock);
+                       ODP_LOG_ERROR(odp_log,
+                                     "Attempt to re-register source %s\n",
+                                     name);
+                       return;
+               }
+       }
+       if (slot != INVALID_SLOT) {
+               sources[slot].phdl = phdl;
+               sources[slot].name = name;
+               *phdl = SLOT_LVL_TO_HDL(slot, ODP_LOG_DEFAULT_MASK);
+       }
+       odp_spinlock_unlock(&lock);
+       if (slot != INVALID_SLOT)
+               ODP_LOG_DEBUG(odp_log, "Registered source %s level %u\n",
+                             name, ODP_LOG_DEFAULT_MASK);
+       else
+               ODP_LOG_FATAL(odp_log, "Failed to register source %s\n", name);
+}
+
+/* Set the log level for a source identified by name */
+int
+odp_log_set_level(const char *name, unsigned level)
+{
+       unsigned i;
+       bool found = false;
+       if (level > ODP_LOG_LVL_ALL)
+               level = ODP_LOG_LVL_ALL;
+       odp_spinlock_lock(&lock);
+       for (i = 0; i < ODP_LOG_MAX; i++) {
+               if (name == NULL ||
+                   (sources[i].name != NULL &&
+                    strcmp(sources[i].name, name) == 0)) {
+                       *sources[i].phdl = SLOT_LVL_TO_HDL(i, level);
+                       found = true;
+                       break;
+               }
+       }
+       odp_spinlock_unlock(&lock);
+       if (found) {
+               if (name == NULL)
+                       ODP_LOG_DEBUG(odp_log,
+                                     "Set log level for all sources to %u\n",
+                                     level);
+               else
+                       ODP_LOG_DEBUG(odp_log,
+                                     "Set log level for source %s to %u\n",
+                                     name, level);
+       } else {
+               errno = ENOENT;
+       }
+       return found ? 0 : -1;
+}
+
+/* Report a log message */
+void
+odp_log_printf(unsigned lvl, odp_log_t hdl, const char *fmt, ...)
+{
+       unsigned slot = HDL_TO_SLOT(hdl);
+       if (odp_likely(slot < ODP_LOG_MAX)) {
+               const char *name = sources[slot].name;
+               va_list ap;
+               odp_log_callback_t cb;
+               va_start(ap, fmt);
+               cb = callback;
+               if (cb != NULL) {
+                       cb(name, lvl, fmt, ap);
+               } else {
+                       fprintf(stderr, "%s/%c: ", name,
+                               " FEWID67"[lvl & 0x7U]);
+                       vfprintf(stderr, fmt, ap);
+               }
+               va_end(ap);
+       }
+       /* Else ignore call with invalid handle */
+}
+
+/* Install a user-defined call-back for handling log messages */
+void
+odp_log_set_callback(odp_log_callback_t cb)
+{
+       callback = cb;
+       odp_sync_stores();
+}
+
+/* Iterate through all registered log sources */
+int
+odp_log_next(odp_log_t *phdl, char *name, size_t namelen, unsigned *plvl)
+{
+       int another;
+       unsigned slot;
+       odp_spinlock_lock(&lock);
+       if (*phdl == ODP_LOG_INVALID)
+               slot = 0;       /* First slot */
+       else
+               slot = HDL_TO_SLOT(*phdl) + 1U; /* Next slot */
+       if (slot < ODP_LOG_MAX && sources[slot].phdl != NULL) {
+               *phdl = SLOT_LVL_TO_HDL(slot, 0);
+               strncpy(name, sources[slot].name, namelen - 1U);
+               name[namelen - 1U] = 0;
+               *plvl = HDL_TO_LVL(*sources[slot].phdl);
+               another = 1;    /* true */
+       } else {
+               another = 0;    /* false */
+       }
+       odp_spinlock_unlock(&lock);
+       return another;
+}
-- 
1.9.1


_______________________________________________
lng-odp mailing list
[email protected]
http://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to