diff options
author | Robert Morris <[email protected]> | 2019-07-27 03:49:03 -0400 |
---|---|---|
committer | Robert Morris <[email protected]> | 2019-07-27 03:49:03 -0400 |
commit | 281d450a088b348b898f2e23f6951e6d4f1efac0 (patch) | |
tree | 7dc504a77980ffb2c7cf2fe742952dadc9b1e737 /kernel/printf.c | |
parent | 734faa27acfe136f4cab3ea06e70193c0ecc5402 (diff) | |
download | xv6-labs-281d450a088b348b898f2e23f6951e6d4f1efac0.tar.gz xv6-labs-281d450a088b348b898f2e23f6951e6d4f1efac0.tar.bz2 xv6-labs-281d450a088b348b898f2e23f6951e6d4f1efac0.zip |
split printf into a separate file, to make console.c more like a driver
Diffstat (limited to 'kernel/printf.c')
-rw-r--r-- | kernel/printf.c | 134 |
1 files changed, 134 insertions, 0 deletions
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 <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; +} |