/****************************************************************************
*
- * Copyright 2016 Samsung Electronics All Rights Reserved.
+ * Copyright 2016-2017 Samsung Electronics All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
LOGM_OFF /* Is this needed? */
};
+enum logm_param_type_e {
+ LOGM_BUFSIZE,
+ LOGM_INTERVAL,
+ LOGM_PRIORITY
+ /* This would grow later */
+};
+
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
void logm_start(void);
int logm_internal(int priority, const char *fmt, va_list valst);
int logm(int flag, int mod, int priority, const char *fmt, ...);
+int logm_set_values(enum logm_param_type_e type, int value);
+int logm_get_values(enum logm_param_type_e type, int* value);
#undef EXTERN
#if defined(__cplusplus)
bool "Route all syslogs through logm"
default y
-config LOGM_BUFFER_COUNT
- int "Number of buffers to store log messages"
- default 80
+config LOGM_TIMESTAMP
+ bool "Prepend timestamp to message"
+ default n
+
+config LOGM_BUFFER_SIZE
+ int "Logm Buffer size"
+ default 10240
---help---
- This is the number of messages that can
- be queued untill logm task start executing
- and start pumping the messages out.
- logm would drop messages if buffers are
- not sufficient.It depends on logm task
- priority, how frequently messages are
- written by modules and sleep duration of
- logm task which is 1 second now.
-
-config LOGM_MAX_MSG_LENGTH
- int "Maximum msg length for each message"
- default 64
+ Logm buffer size (default : 10KB)
+ This value should be sufficient to avoid buffer overflow.
+ If buffer overflow happens, some messages would be dropped.
+
+config LOGM_PRINT_INTERVAL
+ int "Interval for flusing logm buffer (ms)"
+ default 1000
---help---
- Each message through logm would be truncated
- for this length.
+ Logm queues messsages for several seconds and then spits out.
+ This value decides how frequently buffer is flushed.
+ The smaller this value is, the more frequent messages are shown.
config LOGM_TASK_PRIORITY
int "Logm Task priority"
config LOGM_TASK_STACKSIZE
int "Logm Task stack size"
- default 2048
+ default 1024
config LOGM_TEST
bool "Test code for logger module "
ASRCS =
ifeq ($(CONFIG_LOGM),y)
-CSRCS += logm_init.c logm_process.c logm.c
+CSRCS += logm_start.c logm_process.c logm.c
+CSRCS += logm_get.c logm_set.c
+ifeq ($(CONFIG_TASH),y)
+CSRCS += logm_tashcmds.c
endif
-
ifeq ($(CONFIG_LOGM_TEST),y)
CSRCS += logm_test.c
endif
+endif
DEPPATH = --dep-path .
VPATH = .
all: $(BIN)
$(AOBJS): %$(OBJEXT): %.S
- $(call ASSEMBLE, $<, $@)
+ $(call ASSEMBLE, $<, $(notdir $@))
$(COBJS): %$(OBJEXT): %.c
- $(call COMPILE, $<, $@)
+ $(call COMPILE, $<, $(notdir $@))
$(BIN): $(OBJS)
- $(call ARCHIVE, $@, $(OBJS))
+ $(call ARCHIVE, $@, $(notdir $(OBJS)))
.depend: Makefile $(SRCS)
$(Q) $(MKDEP) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
/****************************************************************************
*
- * Copyright 2016 Samsung Electronics All Rights Reserved.
+ * Copyright 2016-2017 Samsung Electronics All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
****************************************************************************/
-#include <signal.h>
-#include <pthread.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
-#include <string.h>
-#include <sched.h>
+#include <arch/irq.h>
#include <tinyara/config.h>
-#ifdef CONFIG_ARCH_LOWPUTC
+#include <tinyara/logm.h>
#include <tinyara/streams.h>
+#ifdef CONFIG_LOGM_TIMESTAMP
+#include <tinyara/clock.h>
#endif
-
#include "logm.h"
-/* An additional line is for logm buffer overflow message */
-char g_logm_rsvbuf[LOGM_RSVBUF_COUNT + 1][LOGM_MAX_MSG_LEN];
int g_logm_head;
int g_logm_tail;
-int g_logm_count;
+int g_logm_available;
+int g_logm_enqueued_count;
+int g_logm_dropmsg_count;
+int g_logm_overflow_offset;
+
+static void logm_putc(FAR struct lib_outstream_s *this, int ch)
+{
+ if (this->nput < g_logm_available - 1) {
+ g_logm_rsvbuf[(g_logm_tail + this->nput++) % logm_bufsize] = ch;
+ }
+}
+
+static void logm_initstream(FAR struct lib_outstream_s *outstream)
+{
+ outstream->put = logm_putc;
+#ifdef CONFIG_STDIO_LINEBUFFER
+ outstream->flush = lib_noflush;
+#endif
+ outstream->nput = 0;
+}
/* logm_internal hook for syslog & printfs */
int logm_internal(int priority, const char *fmt, va_list ap)
{
irqstate_t flags;
int ret = 0;
+ struct lib_outstream_s strm;
+#ifdef CONFIG_LOGM_TIMESTAMP
+ struct timespec ts;
+#endif
- if (g_logm_isready && !up_interrupt_context()) {
+ if (LOGM_STATUS(LOGM_READY) && !LOGM_STATUS(LOGM_BUFFER_RESIZE_REQ) && !up_interrupt_context()) {
flags = irqsave();
- if (g_logm_count < LOGM_RSVBUF_COUNT) {
- ret = vsnprintf((char *)&g_logm_rsvbuf[g_logm_tail], LOGM_MAX_MSG_LEN, fmt, ap);
- } else if (g_logm_count == LOGM_RSVBUF_COUNT) {
- ret = vsnprintf((char *)&g_logm_rsvbuf[g_logm_tail], LOGM_MAX_MSG_LEN, "LOGM: Buffer Overflow dropping messages\n", ap);
- } else {
+ if (LOGM_STATUS(LOGM_BUFFER_OVERFLOW)) {
+ g_logm_dropmsg_count++;
irqrestore(flags);
return 0;
}
- /* choose a available buffer */
-
- if (ret >= LOGM_MAX_MSG_LEN - 1) {
- g_logm_rsvbuf[g_logm_tail][LOGM_MAX_MSG_LEN - 1] = '\n';
+ if (g_logm_available <= 0) {
+ LOGM_STATUS_SET(LOGM_BUFFER_OVERFLOW);
+ g_logm_dropmsg_count = 1;
+ g_logm_overflow_offset = g_logm_tail;
+ irqrestore(flags);
+ return 0;
}
- g_logm_tail += 1;
- if (g_logm_tail >= (LOGM_RSVBUF_COUNT + 1)) {
- g_logm_tail -= (LOGM_RSVBUF_COUNT + 1) ;
+
+ /* Initializes a stream for use with logm buffer */
+ logm_initstream(&strm);
+
+#ifdef CONFIG_LOGM_TIMESTAMP
+ /* Get the current time and prepend timestamp to message */
+ if (clock_systimespec(&ts) == OK) {
+ (void)lib_sprintf((FAR struct lib_outstream_s *)&strm, "[%4d.%4d] ", ts.tv_sec, ts.tv_nsec / 100000);
}
- g_logm_count++;
+#endif
+ ret = lib_vsprintf(&strm, fmt, ap);
+ g_logm_rsvbuf[(g_logm_tail + ret) % logm_bufsize] = '\0';
+
+ /* set g_logm_tail for next entered message */
+ g_logm_tail = (g_logm_tail + ret + 1) % logm_bufsize;
+ g_logm_available -= (ret + 1);
+ g_logm_enqueued_count++;
irqrestore(flags);
} else {
/* Low Output: Sytem is not yet completely ready or this is called from interrupt handler */
#ifdef CONFIG_ARCH_LOWPUTC
- struct lib_outstream_s strm;
lib_lowoutstream(&strm);
ret = lib_vsprintf(&strm, fmt, ap);
#endif
/****************************************************************************
*
- * Copyright 2016 Samsung Electronics All Rights Reserved.
+ * Copyright 2016-2017 Samsung Electronics All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#ifndef __OS_LOGM_LOGM_H
#define __OS_LOGM_LOGM_H
-#include <queue.h>
-#include <stdio.h>
#include <tinyara/config.h>
+#include <stdint.h>
/****************************************************************************
* Preprocessor Definitions
****************************************************************************/
-#define LOGM_RSVBUF_COUNT CONFIG_LOGM_BUFFER_COUNT
#define LOGM_TASK_PRORITY CONFIG_LOGM_TASK_PRIORITY
#define LOGM_TASK_STACKSIZE CONFIG_LOGM_TASK_STACKSIZE
-#define LOGM_MAX_MSG_LEN CONFIG_LOGM_MAX_MSG_LENGTH
-#define LOGM_PRINTERR_AND_RETURN() do { dbg("LOGM Launch Failed \n"); return; } while (0)
+
+#ifdef CONFIG_LOGM_BUFFER_SIZE
+#define LOGM_BUFFER_SIZE CONFIG_LOGM_BUFFER_SIZE
+#else
+#define LOGM_BUFFER_SIZE (10240)
+#endif
+
+#ifdef CONFIG_LOGM_PRINT_INTERVAL
+#define LOGM_PRINT_INTERVAL CONFIG_LOGM_PRINT_INTERVAL
+#else
+#define LOGM_PRINT_INTERVAL (1000)
+#endif
+
+#ifndef BIT
+#define BIT(x) (1 << (x))
+#endif
+
+#define LOGM_READY BIT(0)
+#define LOGM_BUFFER_RESIZE_REQ BIT(1)
+#define LOGM_BUFFER_OVERFLOW BIT(2)
+
+#define LOGM_STATUS(a) (logm_status & (a))
+#define LOGM_STATUS_SET(a) (logm_status |= (a))
+#define LOGM_STATUS_CLEAR(a) (logm_status &= ~(a))
/****************************************************************************
* Private Declarations
#define EXTERN extern
#endif
-EXTERN volatile int g_logm_isready;
+EXTERN int g_logm_head;
+EXTERN int g_logm_tail;
+EXTERN int g_logm_available;
+EXTERN int g_logm_enqueued_count;
+EXTERN int g_logm_overflow_offset;
+EXTERN int g_logm_dropmsg_count;
+EXTERN char * g_logm_rsvbuf;
+EXTERN int logm_bufsize;
+EXTERN uint8_t logm_status;
+EXTERN volatile int new_logm_bufsize;
+EXTERN volatile int logm_print_interval;
/************************************************************************************
* Private Function Prototypes
************************************************************************************/
int logm_task(int argc, char *argv[]);
+void logm_register_tashcmds(void);
+static int logm_tash(int argc, char **args);
#undef EXTERN
#if defined(__cplusplus)
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+#include <tinyara/logm.h>
+#include "logm.h"
+
+/* This will be moved to upper layer or changed for protected build */
+/* Refer logm_param_type_e for getparam values */
+int logm_get_values(enum logm_param_type_e type, int *value)
+{
+ switch (type) {
+ case LOGM_BUFSIZE:
+ *value = logm_bufsize;
+ break;
+ case LOGM_INTERVAL:
+ *value = (int)(logm_print_interval / 1000);
+ break;
+ default:
+ break;
+ }
+
+ return 0; // for now, to keep compiler happy
+}
/****************************************************************************
*
- * Copyright 2016 Samsung Electronics All Rights Reserved.
+ * Copyright 2016-2017 Samsung Electronics All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* language governing permissions and limitations under the License.
*
****************************************************************************/
-#include <unistd.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <arch/irq.h>
#include <tinyara/logm.h>
+#include <tinyara/config.h>
#include "logm.h"
+#ifdef CONFIG_LOGM_TEST
+#include "logm_test.h"
+#endif
-volatile int g_logm_isready;
-extern char g_logm_rsvbuf[][LOGM_MAX_MSG_LEN];
-extern int g_logm_head;
-extern int g_logm_tail;
-extern int g_logm_count;
+uint8_t logm_status;
+int logm_bufsize = LOGM_BUFFER_SIZE;
+char * g_logm_rsvbuf = NULL;
+volatile int logm_print_interval = LOGM_PRINT_INTERVAL * 1000;
-int logm_task(int argc, char *argv[])
+static int logm_change_bufsize(int buflen)
{
- (void)argc;
- (void)argv;
+ /* Keep using old size if a parameter is invalid */
+ if (buflen < 0) {
+ LOGM_STATUS_CLEAR(LOGM_BUFFER_RESIZE_REQ);
+ return ERROR;
+ }
+
+ /* Realloc new buffer with new length */
+ g_logm_rsvbuf = (char *)realloc(g_logm_rsvbuf, buflen);
+ if (!g_logm_rsvbuf) {
+ return ERROR;
+ }
+ memset(g_logm_rsvbuf, 0, buflen);
+
+ /* Reinitialize all */
g_logm_head = 0;
g_logm_tail = 0;
- g_logm_count = 0;
+ logm_bufsize = buflen;
+ g_logm_available = buflen;
+ g_logm_enqueued_count = 0;
+ g_logm_dropmsg_count = 0;
+ g_logm_overflow_offset = -1;
+
+ LOGM_STATUS_CLEAR(LOGM_BUFFER_RESIZE_REQ);
+
+ return OK;
+}
+
+int logm_task(int argc, char *argv[])
+{
+ int ret = 0;
+ irqstate_t flags;
+
+ g_logm_rsvbuf = (char *)malloc(logm_bufsize);
+ memset(g_logm_rsvbuf, 0, logm_bufsize);
+
/* Now logm is ready */
- g_logm_isready = 1;
+ LOGM_STATUS_SET(LOGM_READY);
+ g_logm_available = logm_bufsize;
#ifdef CONFIG_LOGM_TEST
logmtest_init();
#endif
while (1) {
- while (g_logm_count > 0) {
- fputs(g_logm_rsvbuf[g_logm_head], stdout);
- g_logm_head += 1;
- if (g_logm_head >= (LOGM_RSVBUF_COUNT + 1)) {
- g_logm_head -= (LOGM_RSVBUF_COUNT + 1);
+ while (g_logm_enqueued_count > 0) {
+ ret = 0;
+ while (*(g_logm_rsvbuf + (g_logm_head + ret) % logm_bufsize)) {
+ fputc(g_logm_rsvbuf[(g_logm_head + ret++) % logm_bufsize], stdout);
+ }
+ g_logm_head = (g_logm_head + ret + 1) % logm_bufsize;
+ g_logm_available += (ret + 1);
+
+ g_logm_enqueued_count--;
+
+ if (LOGM_STATUS(LOGM_BUFFER_OVERFLOW)) {
+ LOGM_STATUS_CLEAR(LOGM_BUFFER_OVERFLOW);
+ }
+
+ if (g_logm_overflow_offset >= 0 && g_logm_overflow_offset == g_logm_head) {
+ fprintf(stdout, "\n[LOGM BUFFER OVERFLOW] %d messages are dropped\n", g_logm_dropmsg_count);
+ g_logm_overflow_offset = -1;
+ }
+ }
+
+ if (LOGM_STATUS(LOGM_BUFFER_RESIZE_REQ)) {
+ flags = irqsave();
+ if (logm_change_bufsize(new_logm_bufsize) != OK) {
+ fprintf(stdout, "\n[LOGM] Failed to change buffer size\n");
}
- g_logm_count--;
+ irqrestore(flags);
}
- sleep(1);
+ usleep(logm_print_interval);
}
return 0; // Just to make compiler happy
}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+#include <tinyara/logm.h>
+#include "logm.h"
+
+volatile int new_logm_bufsize = 0;
+
+/* This will be moved to upper layer or changed for protected build */
+/* for setparam types, refer logm_param_type_e */
+int logm_set_values(enum logm_param_type_e type, int value)
+{
+ switch (type) {
+ case LOGM_BUFSIZE:
+ /* Buffer size should be adjusted to multiples of 4 */
+ new_logm_bufsize = (value + 3) & (~0x3);
+ break;
+ case LOGM_INTERVAL:
+ logm_print_interval = value * 1000;
+ break;
+ default:
+ break;
+ }
+
+ return 0; // for now, to keep compiler happy
+}
/****************************************************************************
*
- * Copyright 2016 Samsung Electronics All Rights Reserved.
+ * Copyright 2016-2017 Samsung Electronics All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* language governing permissions and limitations under the License.
*
****************************************************************************/
-#include <debug.h>
-#include <tinyara/config.h>
-#include <tinyara/logm.h>
-#include <sys/types.h>
+#include <sched.h>
#include "logm.h"
-#ifdef CONFIG_LOGMTEST
-#include "logm_test.h"
-#endif
-
-pid_t g_logm_tid;
void logm_start(void)
{
- int priority = LOGM_TASK_PRORITY;
- int stacksize = LOGM_TASK_STACKSIZE;
+ int pid;
- g_logm_tid = task_create("logm", priority, stacksize, logm_task, NULL);
+ pid = task_create("logm", LOGM_TASK_PRORITY, LOGM_TASK_STACKSIZE, logm_task, NULL);
- if (!g_logm_tid) {
- LOGM_PRINTERR_AND_RETURN();
+ if (pid < 0) {
+ return;
}
+
+#ifdef CONFIG_TASH
+ /* Register tash commands for logm */
+ logm_register_tashcmds();
+#endif
}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <apps/shell/tash.h>
+#include <tinyara/logm.h>
+#include "logm.h"
+
+const static tash_cmdlist_t logm_tashmds[] = {
+ {"logm", logm_tash, TASH_EXECMD_SYNC},
+ {NULL, NULL, 0}
+};
+
+void logm_register_tashcmds(void)
+{
+ tash_cmdlist_install(logm_tashmds);
+}
+
+static void logm_usage(void)
+{
+ fprintf(stdout, "[LOGM USAGE]\n");
+ fprintf(stdout, "usage: logm [-b <BUFSIZE>] [-i <TIME>]\n");
+
+ fprintf(stdout, "options:\n");
+ fprintf(stdout, " -b BUFSIZE\n");
+ fprintf(stdout, " Set logm buffer size (bytes)\n");
+ fprintf(stdout, " -i TIME\n");
+ fprintf(stdout, " Set buffer flusing interval (ms)\n");
+
+}
+
+static void logm_info(void)
+{
+ int bufsize;
+ int interval;
+
+ logm_get_values(LOGM_BUFSIZE, &bufsize);
+ logm_get_values(LOGM_INTERVAL, &interval);
+
+ fprintf(stdout, "[LOGM CONFIGURATIONS]\n");
+ fprintf(stdout, " Buffer size : %d (bytes)\n", bufsize);
+ fprintf(stdout, " Flusing interval : %d (ms)\n", interval);
+}
+
+static int logm_tash(int argc, char **args)
+{
+ int opt;
+
+ if (argc < 2) {
+ /* TASH>> logm */
+ /* show current logm configurations */
+ logm_info();
+ return 0;
+ }
+
+ if (strcmp(args[1], "--help") == 0) {
+ /* TASH>> logm --help */
+ /* show usage of logm commands */
+ logm_usage();
+ return 0;
+ }
+
+ /*
+ * -b [bufsize] : set buffer size (bytes)
+ * -i [time] : set buffer flushing interval (ms)
+ */
+ while ((opt = getopt(argc, args, "b:i:")) != -1) {
+ switch (opt) {
+ case 'b':
+ /* TASH>> logm -b 10240 */
+ /* set buffer size as 10240 (=10KB) */
+ if (optarg != NULL && atoi(optarg) > 0) {
+ logm_set_values(LOGM_BUFSIZE, atoi(optarg));
+ LOGM_STATUS_SET(LOGM_BUFFER_RESIZE_REQ);
+ }
+ break;
+ case 'i':
+ /* TASH>> logm -i 1000 */
+ /* sets interval for flushing buffer as 1000ms (=1sec) */
+ if (optarg != NULL && atoi(optarg) > 0) {
+ logm_set_values(LOGM_INTERVAL, atoi(optarg));
+ }
+ break;
+ default:
+ logm_usage();
+ return 0;
+ }
+ }
+
+ return 0; //Just to make the compiler happy now
+}
/****************************************************************************
*
- * Copyright 2016 Samsung Electronics All Rights Reserved.
+ * Copyright 2016-2017 Samsung Electronics All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* language governing permissions and limitations under the License.
*
****************************************************************************/
-
-#include <tinyara/config.h>
+#include <stdio.h>
#include <unistd.h>
+#include <syslog.h>
#include <tinyara/kthread.h>
-#include <sched.h>
#include <tinyara/logm.h>
-#include <syslog.h>
-#include <stdio.h>
+
#include "logm.h"
/* Global Variables */