Get rid of unnecessary barrier. Improve comment.
[pintos-anon] / grading / filesys / fslib.c
index a94a0d1bb8e8405d13a16489a3e4dfa1f3b308d2..2087d074b379949a18ff3a60030c7fe018875e34 100644 (file)
@@ -8,10 +8,19 @@
 bool quiet = false;
 
 static void
-vmsg (const char *format, va_list args) 
+vmsg (const char *format, va_list args, const char *suffix
 {
-  printf ("(%s) ", test_name);
-  vprintf (format, args);
+  /* We go to some trouble to stuff the entire message into a
+     single buffer and output it in a single system call, because
+     that'll (typically) ensure that it gets sent to the console
+     atomically.  Otherwise kernel messages like "foo: exit(0)"
+     can end up being interleaved if we're unlucky. */
+  static char buf[1024];
+
+  snprintf (buf, sizeof buf, "(%s) ", test_name);
+  vsnprintf (buf + strlen (buf), sizeof buf - strlen (buf), format, args);
+  strlcpy (buf + strlen (buf), suffix, sizeof buf - strlen (buf));
+  write (STDOUT_FILENO, buf, strlen (buf));
 }
 
 void
@@ -22,8 +31,7 @@ msg (const char *format, ...)
   if (quiet)
     return;
   va_start (args, format);
-  vmsg (format, args);
-  printf ("\n");
+  vmsg (format, args, "\n");
   va_end (args);
 }
 
@@ -33,36 +41,12 @@ fail (const char *format, ...)
   va_list args;
 
   va_start (args, format);
-  vmsg (format, args);
-  printf (": FAILED\n");
+  vmsg (format, args, ": FAILED\n");
   va_end (args);
 
   exit (1);
 }
 
-void
-check (bool success, const char *format, ...) 
-{
-  va_list args;
-
-  va_start (args, format);
-  if (success) 
-    {
-      if (!quiet) 
-        {
-          vmsg (format, args); 
-          printf ("\n"); 
-        }
-    }
-  else 
-    {
-      vmsg (format, args); 
-      printf (": FAILED\n");
-      exit (1);
-    }
-  va_end (args);
-}
-
 void 
 seq_test (const char *filename, void *buf, size_t size, size_t initial_size,
           size_t (*block_size_func) (void),
@@ -72,8 +56,8 @@ seq_test (const char *filename, void *buf, size_t size, size_t initial_size,
   int fd;
   
   random_bytes (buf, size);
-  check (create (filename, initial_size), "create \"%s\"", filename);
-  check ((fd = open (filename)) > 1, "open \"%s\"", filename);
+  CHECK (create (filename, initial_size), "create \"%s\"", filename);
+  CHECK ((fd = open (filename)) > 1, "open \"%s\"", filename);
 
   ofs = 0;
   msg ("writing \"%s\"", filename);
@@ -132,7 +116,7 @@ check_file (const char *filename, const void *buf_, size_t size)
   char block[512];
   int fd;
 
-  check ((fd = open (filename)) > 1, "open \"%s\" for verification", filename);
+  CHECK ((fd = open (filename)) > 1, "open \"%s\" for verification", filename);
 
   ofs = 0;
   while (ofs < size)
@@ -145,22 +129,74 @@ check_file (const char *filename, const void *buf_, size_t size)
         fail ("read %zu bytes at offset %zu in \"%s\" failed",
               block_size, ofs, filename);
 
-      if (memcmp (buf + ofs, block, block_size))
-        {
-          if (block_size <= 512) 
-            {
-              printf ("Expected data:\n");
-              hex_dump (ofs, buf + ofs, block_size, false);
-              printf ("Actually read data:\n");
-              hex_dump (ofs, block, block_size, false); 
-            }
-          fail ("%zu bytes at offset %zu differed from expected",
-                block_size, ofs);
-        }
-
+      compare_bytes (block, buf + ofs, block_size, ofs, filename);
       ofs += block_size;
     }
 
   msg ("close \"%s\"", filename);
   close (fd);
 }
+
+void
+compare_bytes (const void *read_data_, const void *expected_data_, size_t size,
+               size_t ofs, const char *filename) 
+{
+  const uint8_t *read_data = read_data_;
+  const uint8_t *expected_data = expected_data_;
+  size_t i, j;
+  size_t show_cnt;
+
+  if (!memcmp (read_data, expected_data, size))
+    return;
+  
+  for (i = 0; i < size; i++)
+    if (read_data[i] != expected_data[i])
+      break;
+  for (j = i + 1; j < size; j++)
+    if (read_data[j] == expected_data[j])
+      break;
+
+  quiet = false;
+  msg ("%zu bytes read starting at offset %zu in \"%s\" differ "
+       "from expected.", j - i, ofs + i, filename);
+  show_cnt = j - i;
+  if (j - i > 64) 
+    {
+      show_cnt = 64;
+      msg ("Showing first differing %zu bytes.", show_cnt);
+    }
+  msg ("Data actually read:");
+  hex_dump (ofs + i, read_data + i, show_cnt, true);
+  msg ("Expected data:");
+  hex_dump (ofs + i, expected_data + i, show_cnt, true);
+  fail ("%zu bytes read starting at offset %zu in \"%s\" differ "
+        "from expected", j - i, ofs, filename);
+}
+
+void
+exec_children (const char *child_name, pid_t pids[], size_t child_cnt) 
+{
+  size_t i;
+
+  for (i = 0; i < child_cnt; i++) 
+    {
+      char cmd_line[128];
+      snprintf (cmd_line, sizeof cmd_line, "%s %zu", child_name, i);
+      CHECK ((pids[i] = exec (cmd_line)) != PID_ERROR,
+             "exec child %zu of %zu: \"%s\"", i + 1, child_cnt, cmd_line);
+    }
+}
+
+void
+wait_children (pid_t pids[], size_t child_cnt) 
+{
+  size_t i;
+  
+  for (i = 0; i < child_cnt; i++) 
+    {
+      int status = wait (pids[i]);
+      CHECK (status == (int) i,
+             "wait for child %zu of %zu returned %d (expected %zu)",
+             i + 1, child_cnt, status, i);
+    }
+}