#include <sys/types.h>
#include <sys/varargs.h>
#include <sys/cmn_err.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/ib/clients/rds/rdsib_debug.h>
#define RDS_DEBUG_SIZE_EXTRA_ALLOC 8
#define RDS_MIN_DEBUG_BUF_SIZE 0x1000
#define RDS_FUNCNAME_LEN 40
#define RDS_PRINTBUF_LEN 4096
#ifdef DEBUG
#define RDS_DEBUG_BUF_SIZE 0x10000
#else
#define RDS_DEBUG_BUF_SIZE 0x2000
#endif
#define RDS_PRINT_BUF_LEN 4096
int rds_suppress_dprintf;
int rds_buffer_dprintf = 1;
int rds_debug_buf_size = RDS_DEBUG_BUF_SIZE;
int rds_allow_intr_msgs = 0;
char *rds_debug_buf = NULL;
char *rds_buf_sptr, *rds_buf_eptr;
int rds_clear_debug_buf_flag = 0;
extern uint_t rdsdbglvl;
static kmutex_t rds_debug_mutex;
static char rds_print_buf[RDS_PRINT_BUF_LEN];
static void rds_clear_print_buf();
void
rds_logging_initialization()
{
boolean_t flag = B_FALSE;
mutex_init(&rds_debug_mutex, NULL, MUTEX_DRIVER, NULL);
mutex_enter(&rds_debug_mutex);
if (rds_debug_buf_size <= RDS_DEBUG_SIZE_EXTRA_ALLOC) {
rds_debug_buf_size = RDS_MIN_DEBUG_BUF_SIZE;
flag = B_TRUE;
}
rds_debug_buf_size = max(RDS_MIN_DEBUG_BUF_SIZE,
rds_debug_buf_size);
rds_debug_buf = (char *)kmem_alloc(rds_debug_buf_size, KM_SLEEP);
rds_clear_print_buf();
mutex_exit(&rds_debug_mutex);
if (flag == B_TRUE) {
RDS_DPRINTF2("RDS", "rds_debug_buf_size was too small, "
"adjusted to %x", rds_debug_buf_size);
}
}
void
rds_logging_destroy()
{
mutex_enter(&rds_debug_mutex);
if (rds_debug_buf) {
kmem_free(rds_debug_buf, rds_debug_buf_size);
rds_debug_buf = NULL;
}
mutex_exit(&rds_debug_mutex);
mutex_destroy(&rds_debug_mutex);
}
static void
rds_clear_print_buf()
{
ASSERT(MUTEX_HELD(&rds_debug_mutex));
if (rds_debug_buf) {
rds_buf_sptr = rds_debug_buf;
rds_buf_eptr = rds_debug_buf + rds_debug_buf_size -
RDS_DEBUG_SIZE_EXTRA_ALLOC;
bzero(rds_debug_buf, rds_debug_buf_size);
}
}
static void
rds_vlog(char *name, uint_t level, char *fmt, va_list ap)
{
char *label = (name == NULL) ? "rds" : name;
char *msg_ptr;
size_t len;
mutex_enter(&rds_debug_mutex);
if (rds_suppress_dprintf || (rds_debug_buf == NULL)) {
mutex_exit(&rds_debug_mutex);
return;
}
if (rds_clear_debug_buf_flag != 0) {
rds_clear_print_buf();
rds_clear_debug_buf_flag = 0;
}
len = snprintf(rds_print_buf, RDS_FUNCNAME_LEN, "%s:\t", label);
msg_ptr = rds_print_buf + len;
len += vsnprintf(msg_ptr, RDS_PRINT_BUF_LEN - len - 2, fmt, ap);
len = min(len, RDS_PRINT_BUF_LEN - 2);
ASSERT(len == strlen(rds_print_buf));
rds_print_buf[len++] = '\n';
rds_print_buf[len] = '\0';
if (rds_buffer_dprintf) {
*rds_buf_sptr = '\0';
if (rds_buf_sptr + len > rds_buf_eptr) {
size_t left = (uintptr_t)rds_buf_eptr -
(uintptr_t)rds_buf_sptr;
bcopy((caddr_t)rds_print_buf,
(caddr_t)rds_buf_sptr, left);
bcopy((caddr_t)rds_print_buf + left,
(caddr_t)rds_debug_buf, len - left);
rds_buf_sptr = rds_debug_buf + len - left;
} else {
bcopy((caddr_t)rds_print_buf, rds_buf_sptr, len);
rds_buf_sptr += len;
}
(void) sprintf(rds_buf_sptr, ">>>>");
}
switch (level) {
case RDS_LOG_LINTR:
case RDS_LOG_L5:
case RDS_LOG_L4:
case RDS_LOG_L3:
case RDS_LOG_L2:
if (!rds_buffer_dprintf) {
cmn_err(CE_CONT, "^%s", rds_print_buf);
}
break;
case RDS_LOG_L1:
if (!rds_buffer_dprintf) {
cmn_err(CE_CONT, "^%s", rds_print_buf);
} else {
cmn_err(CE_CONT, "!%s", rds_print_buf);
}
break;
case RDS_LOG_L0:
if (rds_print_buf[len - 1] == '\n') {
rds_print_buf[len - 1] = '\0';
}
if (msg_ptr[len - 1] == '\n') {
msg_ptr[len - 1] = '\0';
}
cmn_err(CE_CONT, "^%s", rds_print_buf);
break;
}
mutex_exit(&rds_debug_mutex);
}
void
rds_dprintf_intr(char *name, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
rds_vlog(name, RDS_LOG_LINTR, fmt, ap);
va_end(ap);
}
#define RDS_CHECK_ERR_LEVEL(level) \
if (rdsdbglvl < level) \
return; \
void
rds_dprintf5(char *name, char *fmt, ...)
{
va_list ap;
RDS_CHECK_ERR_LEVEL(RDS_LOG_L5);
va_start(ap, fmt);
rds_vlog(name, RDS_LOG_L5, fmt, ap);
va_end(ap);
}
void
rds_dprintf4(char *name, char *fmt, ...)
{
va_list ap;
RDS_CHECK_ERR_LEVEL(RDS_LOG_L4);
va_start(ap, fmt);
rds_vlog(name, RDS_LOG_L4, fmt, ap);
va_end(ap);
}
void
rds_dprintf3(char *name, char *fmt, ...)
{
va_list ap;
RDS_CHECK_ERR_LEVEL(RDS_LOG_L3);
va_start(ap, fmt);
rds_vlog(name, RDS_LOG_L3, fmt, ap);
va_end(ap);
}
void
rds_dprintf2(char *name, char *fmt, ...)
{
va_list ap;
RDS_CHECK_ERR_LEVEL(RDS_LOG_L2);
va_start(ap, fmt);
rds_vlog(name, RDS_LOG_L2, fmt, ap);
va_end(ap);
}
void
rds_dprintf1(char *name, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
rds_vlog(name, RDS_LOG_L1, fmt, ap);
va_end(ap);
}
void
rds_dprintf0(char *name, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
rds_vlog(name, RDS_LOG_L0, fmt, ap);
va_end(ap);
}