blob: d039eea793161e03bd1d41ab8db0070bb13a5964 [file] [log] [blame]
/*
* debug.c
*
* Copyright (C) 2004 - 2018 Vladislav Bolkhovitin <vst@vlnb.net>
* Copyright (C) 2004 - 2005 Leonid Stoljar
* Copyright (C) 2007 - 2018 Western Digital Corporation
*
* Contains helper functions for execution tracing and error reporting.
* Intended to be included in main .c file.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#include "debug.h"
pid_t gettid(void)
{
return syscall(__NR_gettid);
}
#if defined(DEBUG) || defined(TRACING)
#define TRACE_BUF_SIZE 512
static char trace_buf[TRACE_BUF_SIZE];
static pthread_spinlock_t trace_buf_lock;
int debug_print_prefix(unsigned long trace_flag, const char *prefix,
const char *func, int line)
{
int i = 0;
pthread_spin_lock(&trace_buf_lock);
if (trace_flag & TRACE_TIME) {
struct tm t;
time_t tt;
time(&tt);
localtime_r(&tt, &t);
i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%d:%d:%d ",
t.tm_hour, t.tm_min, t.tm_sec);
}
if (trace_flag & TRACE_PID)
i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "[%d]: ",
gettid());
if (prefix != NULL)
i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%s:", prefix);
if (trace_flag & TRACE_FUNCTION)
i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%s:", func);
if (trace_flag & TRACE_LINE)
i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%i:", line);
if (i > 0)
PRINTN(LOG_INFO, "%s", trace_buf);
pthread_spin_unlock(&trace_buf_lock);
return i;
}
void debug_print_buffer(const void *data, int len)
{
int z, z1, i;
const unsigned char *buf = (const unsigned char *) data;
int f = 0;
if (buf == NULL)
return;
pthread_spin_lock(&trace_buf_lock);
PRINT(LOG_INFO, " (h)___0__1__2__3__4__5__6__7__8__9__A__B__C__D__E__F");
for (z = 0, z1 = 0, i = 0; z < len; z++) {
if (z % 16 == 0) {
if (z != 0) {
i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i,
" ");
for (; (z1 < z) && (i < TRACE_BUF_SIZE - 1);
z1++) {
if ((buf[z1] >= 0x20) &&
(buf[z1] < 0x80))
trace_buf[i++] = buf[z1];
else
trace_buf[i++] = '.';
}
trace_buf[i] = '\0';
PRINT(LOG_INFO, "%s", trace_buf);
i = 0;
f = 1;
}
i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i,
"%4x: ", z);
}
i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%02x ",
buf[z]);
}
i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, " ");
for (; (z1 < z) && (i < TRACE_BUF_SIZE - 1); z1++) {
if ((buf[z1] > 0x20) && (buf[z1] < 0x80))
trace_buf[i++] = buf[z1];
else
trace_buf[i++] = '.';
}
trace_buf[i] = '\0';
if (f)
PRINT(LOG_INFO, "%s", trace_buf);
else
PRINT(LOG_INFO, "%s", trace_buf);
pthread_spin_unlock(&trace_buf_lock);
}
int debug_init(void)
{
int res;
res = pthread_spin_init(&trace_buf_lock, PTHREAD_PROCESS_PRIVATE);
if (res != 0) {
res = errno;
PRINT_ERROR("pthread_spin_init() failed: %s", strerror(res));
}
return res;
}
void debug_done(void)
{
pthread_spin_destroy(&trace_buf_lock);
}
#endif /* DEBUG || TRACING */