summaryrefslogtreecommitdiff
path: root/kernel/printf.c
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2019-07-27 03:49:03 -0400
committerRobert Morris <[email protected]>2019-07-27 03:49:03 -0400
commit281d450a088b348b898f2e23f6951e6d4f1efac0 (patch)
tree7dc504a77980ffb2c7cf2fe742952dadc9b1e737 /kernel/printf.c
parent734faa27acfe136f4cab3ea06e70193c0ecc5402 (diff)
downloadxv6-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.c134
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;
+}