Use mmap(), not malloc(), in vfprintf (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 1 Jul 2016 18:51:18 +0000 (14:51 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 7 Jul 2016 16:39:01 +0000 (12:39 -0400)
Using malloc created an ordering between any of the printf calls and
malloc.  If malloc itself did anything that called back into printf, such
as a diagnostic warning, a SIGSEGV (which leads to printing), an snprintf
to talk to a kernel device, etc, then malloc would be calling itself.  That
could trigger a deadlock, depending on what malloc does internally.

By relying on mmap() only, we limit the amount of code that printf depends
on.  Note that if you ever put a printf in glibc's mmap() stub, you might
have issues.  Imagine a generic printf call: grabs glibc's IO lock, mmaps,
tries to print, then deadlocks on the *IO lock*.

Rebuild glibc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/vfprintf.c

index 6e20aba..200e98d 100644 (file)
 #include <_itoa.h>
 #include <locale/localeinfo.h>
 #include <stdio.h>
+#include <ros/common.h>
+#include <sys/mman.h>
 
-/* Modified for AKAROS, uses malloc in place of large stack allocations */
+/* Modified for AKAROS, uses mmap in place of large stack allocations */
+static char *failmsg = "vfprintf mmap failed!";
 
 /* This code is shared between the standard stdio implementation found
    in GNU C library and the libio implementation originally found in
@@ -245,9 +248,15 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
   const UCHAR_T *end_of_spec;
 
   /* Buffer intermediate results.  */
-  /* AKAROS malloc work_buf */
+  /* AKAROS mmap work_buf */
   //CHAR_T work_buffer[1000];
-  CHAR_T *work_buffer = malloc(1000);
+  CHAR_T *work_buffer = mmap(0, PGSIZE, PROT_WRITE | PROT_READ, MAP_PRIVATE,
+                             -1, 0);
+
+  if (work_buffer == MAP_FAILED) {
+    write(2, failmsg, sizeof(failmsg));
+    exit(-1);
+  }
 
   CHAR_T *workstart = NULL;
   CHAR_T *workend;
@@ -2059,7 +2068,7 @@ all_done:
   _IO_cleanup_region_end (0);
 
   /* AKAROS */
-  free(work_buffer);
+  munmap(work_buffer, PGSIZE);
   return done;
 }
 \f
@@ -2283,9 +2292,16 @@ internal_function
 buffered_vfprintf (_IO_FILE *s, const CHAR_T *format,
                   _IO_va_list args)
 {
-       /* AKAROS: malloc the buf.  */
+  /* AKAROS: mmap the buf.  */
   //CHAR_T buf[_IO_BUFSIZ];
-  CHAR_T *buf = malloc(_IO_BUFSIZ);
+  CHAR_T *buf;
+
+  buf = mmap(0, ROUNDUP(_IO_BUFSIZ, PGSIZE), PROT_WRITE | PROT_READ,
+             MAP_PRIVATE, -1, 0);
+  if (buf == MAP_FAILED) {
+    write(2, failmsg, sizeof(failmsg));
+    exit(-1);
+  }
 
   struct helper_file helper;
   _IO_FILE *hp = (_IO_FILE *) &helper._f;
@@ -2348,7 +2364,7 @@ buffered_vfprintf (_IO_FILE *s, const CHAR_T *format,
   _IO_funlockfile (s);
   __libc_cleanup_region_end (0);
 
-  free(buf); /* AKAROS */
+  munmap(buf, ROUNDUP(_IO_BUFSIZ, PGSIZE)); /* AKAROS */
   return result;
 }