199 lines
3.9 KiB
C
199 lines
3.9 KiB
C
//
|
||
// formatted console output -- printf, panic.
|
||
//
|
||
|
||
#include <stdarg.h>
|
||
|
||
#include "types.h"
|
||
#include "param.h"
|
||
#include "spinlock.h"
|
||
#include "sleeplock.h"
|
||
#include "fs.h"
|
||
#include "file.h"
|
||
#include "memlayout.h"
|
||
#include "riscv.h"
|
||
#include "defs.h"
|
||
#include "proc.h"
|
||
|
||
volatile int panicked = 0;
|
||
|
||
// lock to avoid interleaving concurrent printf's.
|
||
static struct {
|
||
struct spinlock lock;
|
||
int locking;
|
||
} pr;
|
||
|
||
static char digits[] = "0123456789abcdef";
|
||
|
||
static void
|
||
printint(long long xx, int base, int sign)
|
||
{
|
||
char buf[16];
|
||
int i;
|
||
unsigned long long x;
|
||
|
||
if(sign && (sign = (xx < 0)))
|
||
x = -xx;
|
||
else
|
||
x = xx;
|
||
|
||
i = 0;
|
||
do {
|
||
buf[i++] = digits[x % base];
|
||
} while((x /= base) != 0);
|
||
|
||
if(sign)
|
||
buf[i++] = '-';
|
||
|
||
while(--i >= 0)
|
||
consputc(buf[i]);
|
||
}
|
||
|
||
static void
|
||
printptr(uint64 x)
|
||
{
|
||
int i;
|
||
consputc('0');
|
||
consputc('x');
|
||
for (i = 0; i < (sizeof(uint64) * 2); i++, x <<= 4)
|
||
consputc(digits[x >> (sizeof(uint64) * 8 - 4)]);
|
||
}
|
||
|
||
// Print to the console.
|
||
int
|
||
printf(char *fmt, ...)
|
||
{
|
||
va_list ap;
|
||
int i, cx, c0, c1, c2, locking;
|
||
char *s;
|
||
|
||
locking = pr.locking;
|
||
if(locking)
|
||
acquire(&pr.lock);
|
||
|
||
va_start(ap, fmt);
|
||
for(i = 0; (cx = fmt[i] & 0xff) != 0; i++){
|
||
if(cx != '%'){
|
||
consputc(cx);
|
||
continue;
|
||
}
|
||
i++;
|
||
c0 = fmt[i+0] & 0xff;
|
||
c1 = c2 = 0;
|
||
if(c0) c1 = fmt[i+1] & 0xff;
|
||
if(c1) c2 = fmt[i+2] & 0xff;
|
||
if(c0 == 'd'){
|
||
printint(va_arg(ap, int), 10, 1);
|
||
} else if(c0 == 'l' && c1 == 'd'){
|
||
printint(va_arg(ap, uint64), 10, 1);
|
||
i += 1;
|
||
} else if(c0 == 'l' && c1 == 'l' && c2 == 'd'){
|
||
printint(va_arg(ap, uint64), 10, 1);
|
||
i += 2;
|
||
} else if(c0 == 'u'){
|
||
printint(va_arg(ap, int), 10, 0);
|
||
} else if(c0 == 'l' && c1 == 'u'){
|
||
printint(va_arg(ap, uint64), 10, 0);
|
||
i += 1;
|
||
} else if(c0 == 'l' && c1 == 'l' && c2 == 'u'){
|
||
printint(va_arg(ap, uint64), 10, 0);
|
||
i += 2;
|
||
} else if(c0 == 'x'){
|
||
printint(va_arg(ap, int), 16, 0);
|
||
} else if(c0 == 'l' && c1 == 'x'){
|
||
printint(va_arg(ap, uint64), 16, 0);
|
||
i += 1;
|
||
} else if(c0 == 'l' && c1 == 'l' && c2 == 'x'){
|
||
printint(va_arg(ap, uint64), 16, 0);
|
||
i += 2;
|
||
} else if(c0 == 'p'){
|
||
printptr(va_arg(ap, uint64));
|
||
} else if(c0 == 's'){
|
||
if((s = va_arg(ap, char*)) == 0)
|
||
s = "(null)";
|
||
for(; *s; s++)
|
||
consputc(*s);
|
||
} else if(c0 == '%'){
|
||
consputc('%');
|
||
} else if(c0 == 0){
|
||
break;
|
||
} else {
|
||
// Print unknown % sequence to draw attention.
|
||
consputc('%');
|
||
consputc(c0);
|
||
}
|
||
|
||
#if 0
|
||
switch(c){
|
||
case 'd':
|
||
printint(va_arg(ap, int), 10, 1);
|
||
break;
|
||
case 'x':
|
||
printint(va_arg(ap, int), 16, 1);
|
||
break;
|
||
case 'p':
|
||
printptr(va_arg(ap, uint64));
|
||
break;
|
||
case 's':
|
||
if((s = va_arg(ap, char*)) == 0)
|
||
s = "(null)";
|
||
for(; *s; s++)
|
||
consputc(*s);
|
||
break;
|
||
case '%':
|
||
consputc('%');
|
||
break;
|
||
default:
|
||
// Print unknown % sequence to draw attention.
|
||
consputc('%');
|
||
consputc(c);
|
||
break;
|
||
}
|
||
#endif
|
||
}
|
||
va_end(ap);
|
||
|
||
if(locking)
|
||
release(&pr.lock);
|
||
|
||
return 0;
|
||
}
|
||
|
||
void
|
||
panic(char *s)
|
||
{
|
||
pr.locking = 0;
|
||
printf("panic: ");
|
||
printf("%s\n", s);
|
||
panicked = 1; // freeze uart output from other CPUs
|
||
for(;;)
|
||
;
|
||
}
|
||
|
||
void
|
||
printfinit(void)
|
||
{
|
||
initlock(&pr.lock, "pr");
|
||
pr.locking = 1;
|
||
}
|
||
|
||
// 打印当前调用栈的返回地址,实现简单的函数回溯,用于调试。
|
||
void
|
||
backtrace(void)
|
||
{
|
||
printf("barcktrace:\n");
|
||
|
||
uint64 ra,fp = r_fp();//frame pointer -> address
|
||
uint64 pre_fp = *((uint64*)(fp - 16));
|
||
|
||
// 只要当前fp和上一个fp在同一页内,就继续回溯
|
||
while(PGROUNDDOWN(fp)==PGROUNDDOWN(pre_fp)){
|
||
ra = *(uint64 *)(fp - 8); // 取出返回地址
|
||
printf("%p\n", (void*)ra); // 打印返回地址
|
||
fp = pre_fp; // 更新fp为上一个fp
|
||
pre_fp = *((uint64*)(fp - 16)); // 获取新的上一个fp
|
||
}
|
||
|
||
ra = *(uint64 *)(fp - 8);
|
||
printf("%p\n",(void*)ra);
|
||
} |