printnum() is no longer recursive
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 28 Aug 2013 16:02:43 +0000 (09:02 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 28 Aug 2013 16:17:32 +0000 (09:17 -0700)
When printing a full 64 bit pointer in hex (16 'digit's), printnum()
consumed over 1KB of stack, which can run off the end of the kernel
stack.  We use about 80B per frame.

I'm not concerned about the repeated divisions; the actual output is far
more expensive than that, last I checked.

kern/src/printfmt.c

index 27947cc..4ca264e 100644 (file)
 #include <string.h>
 #include <stdarg.h>
 
-/*
- * Print a number (base <= 16) in reverse order,
- * using specified putch function and associated pointer putdat.
- */
-#ifdef __DEPUTY__
-void printnum(void (*putch)(int, TV(t)), TV(t) putdat,
-                        unsigned long long num, unsigned base, int width, int padc)
-#else
+/* Print a number (base <= 16) in reverse order,
+ * using specified putch function and associated pointer putdat. */
 void printnum(void (*putch)(int, void**), void **putdat,
-                        unsigned long long num, unsigned base, int width, int padc)
-#endif
+              unsigned long long num, unsigned base, int width, int padc)
 {
-       // first recursively print all preceding (more significant) digits
-       if (num >= base) {
-               printnum(putch, putdat, num / base, base, width - 1, padc);
-       } else {
-               // print any needed pad characters before first digit
-               while (--width > 0)
-                       putch(padc, putdat);
+       unsigned long long temp = num;
+       int nr_digits = 1;
+       /* Determine how many leading zeros we need.
+        * For every digit/nibble beyond base, we do one less width padding */
+       while ((temp /= base)) {
+               nr_digits++;
+               width--;
+       }
+       /* And another one less, since we'll always print the last digit */
+       while (--width > 0)
+               putch(padc, putdat);
+       for (int i = nr_digits; i > 0; i--) {
+               temp = num;
+               /* To get digit i, we only div (i-1) times */
+               for (int j = 0; j < i - 1; j++) {
+                       temp /= base;
+               }
+               putch("0123456789abcdef"[temp % base], putdat);
        }
-
-       // then print this (the least significant) digit
-       putch("0123456789abcdef"[num % base], putdat);
 }
 
 // Main function to format and print a string.