split printf into a separate file, to make console.c more like a driver

This commit is contained in:
Robert Morris 2019-07-27 03:49:03 -04:00
parent 734faa27ac
commit 281d450a08
5 changed files with 168 additions and 134 deletions

View file

@ -5,6 +5,7 @@ OBJS = \
$K/entry.o \ $K/entry.o \
$K/start.o \ $K/start.o \
$K/console.o \ $K/console.o \
$K/printf.o \
$K/uart.o \ $K/uart.o \
$K/kalloc.o \ $K/kalloc.o \
$K/spinlock.o \ $K/spinlock.o \

View file

@ -1,6 +1,7 @@
// Console input and output. //
// Input is from the keyboard or serial port. // Console input and output, to the uart.
// Output is written to the screen and serial port. // Implements erase/kill processing.
//
#include <stdarg.h> #include <stdarg.h>
@ -15,122 +16,13 @@
#include "defs.h" #include "defs.h"
#include "proc.h" #include "proc.h"
static void consputc(int);
static volatile int panicked = 0;
static struct {
struct spinlock lock;
int locking;
} cons;
static char digits[] = "0123456789abcdef";
static void
printint(int xx, int base, int sign)
{
char buf[16];
int i;
uint 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. only understands %d, %x, %p, %s.
void
printf(char *fmt, ...)
{
va_list ap;
int i, c, locking;
char *s;
locking = cons.locking;
if(locking)
acquire(&cons.lock);
if (fmt == 0)
panic("null fmt");
va_start(ap, fmt);
for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
if(c != '%'){
consputc(c);
continue;
}
c = fmt[++i] & 0xff;
if(c == 0)
break;
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;
}
}
if(locking)
release(&cons.lock);
}
void
panic(char *s)
{
cons.locking = 0;
printf("panic: ");
printf(s);
printf("\n");
panicked = 1; // freeze other CPU
for(;;)
;
}
#define BACKSPACE 0x100 #define BACKSPACE 0x100
void void
consputc(int c) consputc(int c)
{ {
extern volatile int panicked; // from printf.c
if(panicked){ if(panicked){
for(;;) for(;;)
; ;
@ -142,13 +34,16 @@ consputc(int c)
uartputc(c); uartputc(c);
} }
#define INPUT_BUF 128
struct { struct {
struct spinlock lock;
// input
#define INPUT_BUF 128
char buf[INPUT_BUF]; char buf[INPUT_BUF];
uint r; // Read index uint r; // Read index
uint w; // Write index uint w; // Write index
uint e; // Edit index uint e; // Edit index
} input; } cons;
#define C(x) ((x)-'@') // Contro #define C(x) ((x)-'@') // Contro
@ -162,19 +57,19 @@ consoleread(int user_dst, uint64 dst, int n)
target = n; target = n;
acquire(&cons.lock); acquire(&cons.lock);
while(n > 0){ while(n > 0){
while(input.r == input.w){ while(cons.r == cons.w){
if(myproc()->killed){ if(myproc()->killed){
release(&cons.lock); release(&cons.lock);
return -1; return -1;
} }
sleep(&input.r, &cons.lock); sleep(&cons.r, &cons.lock);
} }
c = input.buf[input.r++ % INPUT_BUF]; c = cons.buf[cons.r++ % INPUT_BUF];
if(c == C('D')){ // EOF if(c == C('D')){ // EOF
if(n < target){ if(n < target){
// Save ^D for next time, to make sure // Save ^D for next time, to make sure
// caller gets a 0-byte result. // caller gets a 0-byte result.
input.r--; cons.r--;
} }
break; break;
} }
@ -221,26 +116,26 @@ consoleintr(int c)
doprocdump = 1; doprocdump = 1;
break; break;
case C('U'): // Kill line. case C('U'): // Kill line.
while(input.e != input.w && while(cons.e != cons.w &&
input.buf[(input.e-1) % INPUT_BUF] != '\n'){ cons.buf[(cons.e-1) % INPUT_BUF] != '\n'){
input.e--; cons.e--;
consputc(BACKSPACE); consputc(BACKSPACE);
} }
break; break;
case C('H'): case '\x7f': // Backspace case C('H'): case '\x7f': // Backspace
if(input.e != input.w){ if(cons.e != cons.w){
input.e--; cons.e--;
consputc(BACKSPACE); consputc(BACKSPACE);
} }
break; break;
default: default:
if(c != 0 && input.e-input.r < INPUT_BUF){ if(c != 0 && cons.e-cons.r < INPUT_BUF){
c = (c == '\r') ? '\n' : c; c = (c == '\r') ? '\n' : c;
input.buf[input.e++ % INPUT_BUF] = c; cons.buf[cons.e++ % INPUT_BUF] = c;
consputc(c); consputc(c);
if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){ if(c == '\n' || c == C('D') || cons.e == cons.r+INPUT_BUF){
input.w = input.e; cons.w = cons.e;
wakeup(&input.r); wakeup(&cons.r);
} }
} }
break; break;
@ -255,9 +150,8 @@ consoleintr(int c)
void void
consoleinit(void) consoleinit(void)
{ {
initlock(&cons.lock, "console"); initlock(&cons.lock, "cons");
devsw[CONSOLE].write = consolewrite; devsw[CONSOLE].write = consolewrite;
devsw[CONSOLE].read = consoleread; devsw[CONSOLE].read = consoleread;
cons.locking = 1;
} }

View file

@ -17,9 +17,8 @@ void bwrite(struct buf*);
// console.c // console.c
void consoleinit(void); void consoleinit(void);
void printf(char*, ...);
void consoleintr(int); void consoleintr(int);
void panic(char*) __attribute__((noreturn)); void consputc(int);
// exec.c // exec.c
int exec(char*, char**); int exec(char*, char**);
@ -74,6 +73,11 @@ void pipeclose(struct pipe*, int);
int piperead(struct pipe*, uint64, int); int piperead(struct pipe*, uint64, int);
int pipewrite(struct pipe*, uint64, int); int pipewrite(struct pipe*, uint64, int);
// printf.c
void printf(char*, ...);
void panic(char*) __attribute__((noreturn));
void printfinit(void);
// proc.c // proc.c
int cpuid(void); int cpuid(void);
void exit(void); void exit(void);

View file

@ -13,6 +13,7 @@ main()
if(cpuid() == 0){ if(cpuid() == 0){
uartinit(); // serial port uartinit(); // serial port
consoleinit(); consoleinit();
printfinit();
printf("hart %d starting\n", cpuid()); printf("hart %d starting\n", cpuid());
kinit(); // physical page allocator kinit(); // physical page allocator
kvminit(); // create kernel page table kvminit(); // create kernel page table

134
kernel/printf.c Normal file
View file

@ -0,0 +1,134 @@
//
// 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(int xx, int base, int sign)
{
char buf[16];
int i;
uint 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. only understands %d, %x, %p, %s.
void
printf(char *fmt, ...)
{
va_list ap;
int i, c, locking;
char *s;
locking = pr.locking;
if(locking)
acquire(&pr.lock);
if (fmt == 0)
panic("null fmt");
va_start(ap, fmt);
for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
if(c != '%'){
consputc(c);
continue;
}
c = fmt[++i] & 0xff;
if(c == 0)
break;
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;
}
}
if(locking)
release(&pr.lock);
}
void
panic(char *s)
{
pr.locking = 0;
printf("panic: ");
printf(s);
printf("\n");
panicked = 1; // freeze other CPUs
for(;;)
;
}
void
printfinit(void)
{
initlock(&pr.lock, "pr");
pr.locking = 1;
}