/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
/* Copyright (C) 2014 Stony Brook University
This file is part of Graphene Library OS.
Graphene Library OS is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Graphene Library OS 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see . */
#include
#include
#include
#include
#include
#include
#include
PAL_HANDLE debug_handle = NULL;
struct debugbuf {
int cnt;
char buf[DEBUGBUF_SIZE];
};
static inline int
debug_fputs (void * f, const char * buf, int len)
{
if (DkStreamWrite(debug_handle, 0, len, (void *) buf, NULL) == len)
return 0;
else
return -1;
}
static int
debug_fputch (void * f, int ch, void * b)
{
struct debug_buf * buf = (struct debug_buf *) b;
buf->buf[buf->end++] = ch;
if (ch == '\n') {
if (debug_fputs(NULL, buf->buf, buf->end) == -1)
return -1;
buf->end = buf->start;
return 0;
}
#if DEBUGBUF_BREAK == 1
if (buf->end == DEBUGBUF_SIZE - 4) {
buf->buf[buf->end++] = '.';
buf->buf[buf->end++] = '.';
buf->buf[buf->end++] = '\n';
debug_fputs(NULL, buf->buf, buf->end);
buf->end = buf->start;
buf->buf[buf->end++] = '.';
buf->buf[buf->end++] = '.';
}
#else
if (buf->end == DEBUGBUF_SIZE) {
debug_fputs(NULL, buf->buf, buf->end);
}
#endif
return 0;
}
void debug_puts (const char * str)
{
int len = strlen(str);
struct debug_buf * buf = (struct debug_buf *) SHIM_GET_TLS()->debug_buf;
while (len) {
int rem = DEBUGBUF_SIZE - 4 - buf->end;
bool isfull = true;
if (rem > len) {
rem = len;
isfull = false;
}
for (int i = 0 ; i < rem ; i++)
buf->buf[buf->end + i] = str[i];
buf->end += rem;
str += rem;
len -= rem;
if (isfull) {
buf->buf[buf->end++] = '.';
buf->buf[buf->end++] = '.';
buf->buf[buf->end++] = '\n';
debug_fputs(NULL, buf->buf, buf->end);
buf->end = buf->start;
buf->buf[buf->end++] = '.';
buf->buf[buf->end++] = '.';
}
}
}
void debug_putch (int ch)
{
debug_fputch(NULL, ch, SHIM_GET_TLS()->debug_buf);
}
void debug_vprintf (const char * fmt, va_list * ap)
{
vfprintfmt((void *) debug_fputch, NULL, SHIM_GET_TLS()->debug_buf,
fmt, ap);
}
void debug_printf (const char * fmt, ...)
{
va_list ap;
va_start(ap, fmt);
debug_vprintf(fmt, &ap);
va_end(ap);
}
void debug_setprefix (shim_tcb_t * tcb)
{
if (!debug_handle)
return;
struct debug_buf * buf = (struct debug_buf *) tcb->debug_buf;
buf->start = buf->end = 0;
if (tcb->tid && !IS_INTERNAL_TID(tcb->tid))
fprintfmt(debug_fputch, NULL, buf, TID_PREFIX, tcb->tid);
else if (cur_process.vmid)
fprintfmt(debug_fputch, NULL, buf, VMID_PREFIX,
cur_process.vmid % 10000);
else
fprintfmt(debug_fputch, NULL, buf, NOID_PREFIX);
buf->start = buf->end;
}
struct sysbuf {
int cnt;
char buf[SYSPRINT_BUFFER_SIZE];
} sys_putdat;
static inline void
sys_fputs (void * f, const char * str, int len)
{
DkStreamWrite((PAL_HANDLE) f, 0, len, (void *) str, NULL);
}
static void
sys_fputch (void * f, int ch, void * b)
{
sys_putdat.buf[sys_putdat.cnt++] = ch;
if (ch == '\n') {
sys_fputs(f, sys_putdat.buf, sys_putdat.cnt);
sys_putdat.cnt = 0;
}
if (sys_putdat.cnt == SYSPRINT_BUFFER_SIZE - 2) {
sys_putdat.buf[sys_putdat.cnt++] = '\n';
sys_fputs(f, sys_putdat.buf, sys_putdat.cnt);
sys_putdat.cnt = 0;
}
}
static void
sys_vfprintf (PAL_HANDLE hdl, const char * fmt, va_list * ap)
{
vfprintfmt((void *) &sys_fputch, hdl, NULL, fmt, ap);
}
void handle_printf (PAL_HANDLE hdl, const char * fmt, ...)
{
va_list ap;
va_start(ap, fmt);
sys_vfprintf(hdl, fmt, &ap);
va_end(ap);
}
void handle_vprintf (PAL_HANDLE hdl, const char * fmt, va_list * ap)
{
sys_vfprintf(hdl, fmt, ap);
}