00001
00002
00003
00004
00005
00006 #include "tests/vm/parallel-merge.h"
00007 #include <stdio.h>
00008 #include <syscall.h>
00009 #include "tests/arc4.h"
00010 #include "tests/lib.h"
00011 #include "tests/main.h"
00012
00013 #define CHUNK_SIZE (128 * 1024)
00014 #define CHUNK_CNT 8
00015 #define DATA_SIZE (CHUNK_CNT * CHUNK_SIZE)
00016
00017 unsigned char buf1[DATA_SIZE], buf2[DATA_SIZE];
00018 size_t histogram[256];
00019
00020
00021
00022 static void
00023 init (void)
00024 {
00025 struct arc4 arc4;
00026 size_t i;
00027
00028 msg ("init");
00029
00030 arc4_init (&arc4, "foobar", 6);
00031 arc4_crypt (&arc4, buf1, sizeof buf1);
00032 for (i = 0; i < sizeof buf1; i++)
00033 histogram[buf1[i]]++;
00034 }
00035
00036
00037
00038 static void
00039 sort_chunks (const char *subprocess, int exit_status)
00040 {
00041 pid_t children[CHUNK_CNT];
00042 size_t i;
00043
00044 for (i = 0; i < CHUNK_CNT; i++)
00045 {
00046 char fn[128];
00047 char cmd[128];
00048 int handle;
00049
00050 msg ("sort chunk %zu", i);
00051
00052
00053 snprintf (fn, sizeof fn, "buf%zu", i);
00054 create (fn, CHUNK_SIZE);
00055 quiet = true;
00056 CHECK ((handle = open (fn)) > 1, "open \"%s\"", fn);
00057 write (handle, buf1 + CHUNK_SIZE * i, CHUNK_SIZE);
00058 close (handle);
00059
00060
00061 snprintf (cmd, sizeof cmd, "%s %s", subprocess, fn);
00062 CHECK ((children[i] = exec (cmd)) != -1, "exec \"%s\"", cmd);
00063 quiet = false;
00064 }
00065
00066 for (i = 0; i < CHUNK_CNT; i++)
00067 {
00068 char fn[128];
00069 int handle;
00070
00071 CHECK (wait (children[i]) == exit_status, "wait for child %zu", i);
00072
00073
00074 quiet = true;
00075 snprintf (fn, sizeof fn, "buf%zu", i);
00076 CHECK ((handle = open (fn)) > 1, "open \"%s\"", fn);
00077 read (handle, buf1 + CHUNK_SIZE * i, CHUNK_SIZE);
00078 close (handle);
00079 quiet = false;
00080 }
00081 }
00082
00083
00084 static void
00085 merge (void)
00086 {
00087 unsigned char *mp[CHUNK_CNT];
00088 size_t mp_left;
00089 unsigned char *op;
00090 size_t i;
00091
00092 msg ("merge");
00093
00094
00095 mp_left = CHUNK_CNT;
00096 for (i = 0; i < CHUNK_CNT; i++)
00097 mp[i] = buf1 + CHUNK_SIZE * i;
00098
00099
00100 op = buf2;
00101 while (mp_left > 0)
00102 {
00103
00104 size_t min = 0;
00105 for (i = 1; i < mp_left; i++)
00106 if (*mp[i] < *mp[min])
00107 min = i;
00108
00109
00110 *op++ = *mp[min];
00111
00112
00113
00114 if ((++mp[min] - buf1) % CHUNK_SIZE == 0)
00115 mp[min] = mp[--mp_left];
00116 }
00117 }
00118
00119 static void
00120 verify (void)
00121 {
00122 size_t buf_idx;
00123 size_t hist_idx;
00124
00125 msg ("verify");
00126
00127 buf_idx = 0;
00128 for (hist_idx = 0; hist_idx < sizeof histogram / sizeof *histogram;
00129 hist_idx++)
00130 {
00131 while (histogram[hist_idx]-- > 0)
00132 {
00133 if (buf2[buf_idx] != hist_idx)
00134 fail ("bad value %d in byte %zu", buf2[buf_idx], buf_idx);
00135 buf_idx++;
00136 }
00137 }
00138
00139 msg ("success, buf_idx=%'zu", buf_idx);
00140 }
00141
00142 void
00143 parallel_merge (const char *child_name, int exit_status)
00144 {
00145 init ();
00146 sort_chunks (child_name, exit_status);
00147 merge ();
00148 verify ();
00149 }