diff --git a/Makefile b/Makefile index 7f6d032..c6360fd 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ OBJS = \ $K/entry.o \ $K/start.o \ $K/console.o \ + $K/printf.o \ $K/uart.o \ $K/kalloc.o \ $K/spinlock.o \ diff --git a/kernel/console.c b/kernel/console.c index fe21405..8023405 100644 --- a/kernel/console.c +++ b/kernel/console.c @@ -1,6 +1,7 @@ -// Console input and output. -// Input is from the keyboard or serial port. -// Output is written to the screen and serial port. +// +// Console input and output, to the uart. +// Implements erase/kill processing. +// #include @@ -15,122 +16,13 @@ #include "defs.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 void consputc(int c) { + extern volatile int panicked; // from printf.c + if(panicked){ for(;;) ; @@ -142,13 +34,16 @@ consputc(int c) uartputc(c); } -#define INPUT_BUF 128 struct { + struct spinlock lock; + + // input +#define INPUT_BUF 128 char buf[INPUT_BUF]; uint r; // Read index uint w; // Write index uint e; // Edit index -} input; +} cons; #define C(x) ((x)-'@') // Contro @@ -162,19 +57,19 @@ consoleread(int user_dst, uint64 dst, int n) target = n; acquire(&cons.lock); while(n > 0){ - while(input.r == input.w){ + while(cons.r == cons.w){ if(myproc()->killed){ release(&cons.lock); 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(n < target){ // Save ^D for next time, to make sure // caller gets a 0-byte result. - input.r--; + cons.r--; } break; } @@ -221,26 +116,26 @@ consoleintr(int c) doprocdump = 1; break; case C('U'): // Kill line. - while(input.e != input.w && - input.buf[(input.e-1) % INPUT_BUF] != '\n'){ - input.e--; + while(cons.e != cons.w && + cons.buf[(cons.e-1) % INPUT_BUF] != '\n'){ + cons.e--; consputc(BACKSPACE); } break; case C('H'): case '\x7f': // Backspace - if(input.e != input.w){ - input.e--; + if(cons.e != cons.w){ + cons.e--; consputc(BACKSPACE); } break; default: - if(c != 0 && input.e-input.r < INPUT_BUF){ + if(c != 0 && cons.e-cons.r < INPUT_BUF){ c = (c == '\r') ? '\n' : c; - input.buf[input.e++ % INPUT_BUF] = c; + cons.buf[cons.e++ % INPUT_BUF] = c; consputc(c); - if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){ - input.w = input.e; - wakeup(&input.r); + if(c == '\n' || c == C('D') || cons.e == cons.r+INPUT_BUF){ + cons.w = cons.e; + wakeup(&cons.r); } } break; @@ -255,9 +150,8 @@ consoleintr(int c) void consoleinit(void) { - initlock(&cons.lock, "console"); + initlock(&cons.lock, "cons"); devsw[CONSOLE].write = consolewrite; devsw[CONSOLE].read = consoleread; - cons.locking = 1; } diff --git a/kernel/defs.h b/kernel/defs.h index fa9dd13..52fca8e 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -17,9 +17,8 @@ void bwrite(struct buf*); // console.c void consoleinit(void); -void printf(char*, ...); void consoleintr(int); -void panic(char*) __attribute__((noreturn)); +void consputc(int); // exec.c int exec(char*, char**); @@ -74,6 +73,11 @@ void pipeclose(struct pipe*, int); int piperead(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 int cpuid(void); void exit(void); diff --git a/kernel/main.c b/kernel/main.c index 17bd5d1..09580e0 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -13,6 +13,7 @@ main() if(cpuid() == 0){ uartinit(); // serial port consoleinit(); + printfinit(); printf("hart %d starting\n", cpuid()); kinit(); // physical page allocator kvminit(); // create kernel page table diff --git a/kernel/printf.c b/kernel/printf.c new file mode 100644 index 0000000..777cc5f --- /dev/null +++ b/kernel/printf.c @@ -0,0 +1,134 @@ +// +// formatted console output -- printf, panic. +// + +#include + +#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; +}