From patchwork Mon Aug 25 15:22:32 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ola Liljedahl X-Patchwork-Id: 35923 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oi0-f69.google.com (mail-oi0-f69.google.com [209.85.218.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 8E37020565 for ; Mon, 25 Aug 2014 15:22:52 +0000 (UTC) Received: by mail-oi0-f69.google.com with SMTP id i138sf5698171oig.0 for ; Mon, 25 Aug 2014 08:22:51 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:subject :precedence:list-id:list-unsubscribe:list-archive:list-post :list-help:list-subscribe:mime-version:errors-to:sender :x-original-sender:x-original-authentication-results:mailing-list :content-type:content-transfer-encoding; bh=D4lR6maDUjc3dnb6Oaf09Gm3VgwSM8YgkcqsHUrnaWQ=; b=HbiFEUvvZMKJWKRfU6qBTJehVbXL5If+8w3yEEkCiE8sOV6AP0Khlzg/yRKriRj69V JukNcU7/mnJEm1b3R4ek4JRJcDu/OdjQi/EY192vr2VeDDL3LQftkh46nRv1c5fxp0+0 L5T3uoPPJbr/ywbJi7pOEiu4vUcYdc7LAjDa78WNbSj39jyK5k6kjE3tYN/bs41duNM+ 48isyksKxrAWPFbTEn2IrFYgZysu1g/KqnvHD9piSfW8R/I+pyfCIkB861Q4ZqnQJuxo ux/YuPMw1tx7mG6VuNJjdU5rHYMxPrGjiH2cvGVcaObKF7h3fziYkjU/0X1dSeRh3XRD Lhtg== X-Gm-Message-State: ALoCoQm5hTu8hq5Za701IQ84Z2vJfbDNIHMcNT787miXrXCRpPI0hRj8ToPVB3aH/S6AXsWBHatM X-Received: by 10.50.33.18 with SMTP id n18mr10559995igi.8.1408980171865; Mon, 25 Aug 2014 08:22:51 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.34.206 with SMTP id l72ls2083852qgl.46.gmail; Mon, 25 Aug 2014 08:22:51 -0700 (PDT) X-Received: by 10.220.97.138 with SMTP id l10mr7475207vcn.25.1408980171762; Mon, 25 Aug 2014 08:22:51 -0700 (PDT) Received: from mail-vc0-f179.google.com (mail-vc0-f179.google.com [209.85.220.179]) by mx.google.com with ESMTPS id m9si32708vcl.104.2014.08.25.08.22.51 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 25 Aug 2014 08:22:51 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.179 as permitted sender) client-ip=209.85.220.179; Received: by mail-vc0-f179.google.com with SMTP id hq11so15256018vcb.38 for ; Mon, 25 Aug 2014 08:22:51 -0700 (PDT) X-Received: by 10.221.5.137 with SMTP id og9mr19071659vcb.18.1408980171629; Mon, 25 Aug 2014 08:22:51 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.45.67 with SMTP id uj3csp125986vcb; Mon, 25 Aug 2014 08:22:50 -0700 (PDT) X-Received: by 10.140.21.177 with SMTP id 46mr12929348qgl.90.1408980170748; Mon, 25 Aug 2014 08:22:50 -0700 (PDT) Received: from ip-10-141-164-156.ec2.internal (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTPS id e109si181705qgf.40.2014.08.25.08.22.50 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Mon, 25 Aug 2014 08:22:50 -0700 (PDT) Received-SPF: none (google.com: lng-odp-bounces@lists.linaro.org does not designate permitted sender hosts) client-ip=54.225.227.206; Received: from localhost ([127.0.0.1] helo=ip-10-141-164-156.ec2.internal) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1XLw6b-0007iZ-Q6; Mon, 25 Aug 2014 15:22:49 +0000 Received: from mail-la0-f45.google.com ([209.85.215.45]) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1XLw6V-0007iU-Hy for lng-odp@lists.linaro.org; Mon, 25 Aug 2014 15:22:43 +0000 Received: by mail-la0-f45.google.com with SMTP id ty20so13268163lab.4 for ; Mon, 25 Aug 2014 08:22:37 -0700 (PDT) X-Received: by 10.112.180.69 with SMTP id dm5mr2527925lbc.19.1408980157269; Mon, 25 Aug 2014 08:22:37 -0700 (PDT) Received: from localhost.localdomain (84-217-193-102.tn.glocalnet.net. [84.217.193.102]) by mx.google.com with ESMTPSA id vl4sm205521lbb.36.2014.08.25.08.22.35 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 25 Aug 2014 08:22:36 -0700 (PDT) From: Ola Liljedahl To: lng-odp@lists.linaro.org Date: Mon, 25 Aug 2014 17:22:32 +0200 Message-Id: <1408980152-10343-1-git-send-email-ola.liljedahl@linaro.org> X-Mailer: git-send-email 1.9.1 X-Topics: patch Subject: [lng-odp] [PATCH] Log API for internal use from ODP implementation modules. X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Errors-To: lng-odp-bounces@lists.linaro.org Sender: lng-odp-bounces@lists.linaro.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ola.liljedahl@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.179 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 Signed-off-by: Ola Liljedahl --- (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 +#include +#include + +#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 +#include +#include + +#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 #include #include +#include +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +}