1*368c31abSDavid du Colombier #include <u.h>
2*368c31abSDavid du Colombier #include <libc.h>
3*368c31abSDavid du Colombier #include <venti.h>
4*368c31abSDavid du Colombier #include <libsec.h>
5*368c31abSDavid du Colombier #include <thread.h>
6*368c31abSDavid du Colombier
7*368c31abSDavid du Colombier
8*368c31abSDavid du Colombier enum { STACK = 32768 };
9*368c31abSDavid du Colombier void xxxsrand(long);
10*368c31abSDavid du Colombier long xxxlrand(void);
11*368c31abSDavid du Colombier
12*368c31abSDavid du Colombier Channel *cw;
13*368c31abSDavid du Colombier Channel *cr;
14*368c31abSDavid du Colombier char *host;
15*368c31abSDavid du Colombier int blocksize, seed, randpct;
16*368c31abSDavid du Colombier int doread, dowrite, packets, permute;
17*368c31abSDavid du Colombier vlong totalbytes, cur;
18*368c31abSDavid du Colombier VtConn *z;
19*368c31abSDavid du Colombier int multi;
20*368c31abSDavid du Colombier int maxpackets;
21*368c31abSDavid du Colombier int sequence;
22*368c31abSDavid du Colombier int doublecheck = 1;
23*368c31abSDavid du Colombier uint *order;
24*368c31abSDavid du Colombier
25*368c31abSDavid du Colombier void
usage(void)26*368c31abSDavid du Colombier usage(void)
27*368c31abSDavid du Colombier {
28*368c31abSDavid du Colombier fprint(2, "usage: randtest [-q] [-h host] [-s seed] [-b blocksize] [-p randpct] [-n totalbytes] [-M maxblocks] [-P] [-r] [-w]\n");
29*368c31abSDavid du Colombier threadexitsall("usage");
30*368c31abSDavid du Colombier }
31*368c31abSDavid du Colombier
32*368c31abSDavid du Colombier void
wr(char * buf,char * buf2)33*368c31abSDavid du Colombier wr(char *buf, char *buf2)
34*368c31abSDavid du Colombier {
35*368c31abSDavid du Colombier uchar score[VtScoreSize], score2[VtScoreSize];
36*368c31abSDavid du Colombier DigestState ds;
37*368c31abSDavid du Colombier
38*368c31abSDavid du Colombier USED(buf2);
39*368c31abSDavid du Colombier memset(&ds, 0, sizeof ds);
40*368c31abSDavid du Colombier if(doublecheck)
41*368c31abSDavid du Colombier sha1((uchar*)buf, blocksize, score, &ds);
42*368c31abSDavid du Colombier if(vtwrite(z, score2, VtDataType, (uchar*)buf, blocksize) < 0)
43*368c31abSDavid du Colombier sysfatal("vtwrite %V at %,lld: %r", score, cur);
44*368c31abSDavid du Colombier if(doublecheck && memcmp(score, score2, VtScoreSize) != 0)
45*368c31abSDavid du Colombier sysfatal("score mismatch! %V %V", score, score2);
46*368c31abSDavid du Colombier }
47*368c31abSDavid du Colombier
48*368c31abSDavid du Colombier void
wrthread(void * v)49*368c31abSDavid du Colombier wrthread(void *v)
50*368c31abSDavid du Colombier {
51*368c31abSDavid du Colombier char *p;
52*368c31abSDavid du Colombier
53*368c31abSDavid du Colombier USED(v);
54*368c31abSDavid du Colombier while((p = recvp(cw)) != nil){
55*368c31abSDavid du Colombier wr(p, nil);
56*368c31abSDavid du Colombier free(p);
57*368c31abSDavid du Colombier }
58*368c31abSDavid du Colombier }
59*368c31abSDavid du Colombier
60*368c31abSDavid du Colombier void
rd(char * buf,char * buf2)61*368c31abSDavid du Colombier rd(char *buf, char *buf2)
62*368c31abSDavid du Colombier {
63*368c31abSDavid du Colombier uchar score[VtScoreSize];
64*368c31abSDavid du Colombier DigestState ds;
65*368c31abSDavid du Colombier
66*368c31abSDavid du Colombier memset(&ds, 0, sizeof ds);
67*368c31abSDavid du Colombier sha1((uchar*)buf, blocksize, score, &ds);
68*368c31abSDavid du Colombier if(vtread(z, score, VtDataType, (uchar*)buf2, blocksize) < 0)
69*368c31abSDavid du Colombier sysfatal("vtread %V at %,lld: %r", score, cur);
70*368c31abSDavid du Colombier if(memcmp(buf, buf2, blocksize) != 0)
71*368c31abSDavid du Colombier sysfatal("bad data read! %V", score);
72*368c31abSDavid du Colombier }
73*368c31abSDavid du Colombier
74*368c31abSDavid du Colombier void
rdthread(void * v)75*368c31abSDavid du Colombier rdthread(void *v)
76*368c31abSDavid du Colombier {
77*368c31abSDavid du Colombier char *p, *buf2;
78*368c31abSDavid du Colombier
79*368c31abSDavid du Colombier buf2 = vtmalloc(blocksize);
80*368c31abSDavid du Colombier USED(v);
81*368c31abSDavid du Colombier while((p = recvp(cr)) != nil){
82*368c31abSDavid du Colombier rd(p, buf2);
83*368c31abSDavid du Colombier free(p);
84*368c31abSDavid du Colombier }
85*368c31abSDavid du Colombier }
86*368c31abSDavid du Colombier
87*368c31abSDavid du Colombier char *template;
88*368c31abSDavid du Colombier
89*368c31abSDavid du Colombier void
run(void (* fn)(char *,char *),Channel * c)90*368c31abSDavid du Colombier run(void (*fn)(char*, char*), Channel *c)
91*368c31abSDavid du Colombier {
92*368c31abSDavid du Colombier int i, t, j, packets;
93*368c31abSDavid du Colombier char *buf2, *buf;
94*368c31abSDavid du Colombier
95*368c31abSDavid du Colombier buf2 = vtmalloc(blocksize);
96*368c31abSDavid du Colombier buf = vtmalloc(blocksize);
97*368c31abSDavid du Colombier cur = 0;
98*368c31abSDavid du Colombier packets = totalbytes/blocksize;
99*368c31abSDavid du Colombier if(maxpackets == 0)
100*368c31abSDavid du Colombier maxpackets = packets;
101*368c31abSDavid du Colombier order = vtmalloc(packets*sizeof order[0]);
102*368c31abSDavid du Colombier for(i=0; i<packets; i++)
103*368c31abSDavid du Colombier order[i] = i;
104*368c31abSDavid du Colombier if(permute){
105*368c31abSDavid du Colombier for(i=1; i<packets; i++){
106*368c31abSDavid du Colombier j = nrand(i+1);
107*368c31abSDavid du Colombier t = order[i];
108*368c31abSDavid du Colombier order[i] = order[j];
109*368c31abSDavid du Colombier order[j] = t;
110*368c31abSDavid du Colombier }
111*368c31abSDavid du Colombier }
112*368c31abSDavid du Colombier for(i=0; i<packets && i<maxpackets; i++){
113*368c31abSDavid du Colombier memmove(buf, template, blocksize);
114*368c31abSDavid du Colombier *(uint*)buf = order[i];
115*368c31abSDavid du Colombier if(c){
116*368c31abSDavid du Colombier sendp(c, buf);
117*368c31abSDavid du Colombier buf = vtmalloc(blocksize);
118*368c31abSDavid du Colombier }else
119*368c31abSDavid du Colombier (*fn)(buf, buf2);
120*368c31abSDavid du Colombier cur += blocksize;
121*368c31abSDavid du Colombier }
122*368c31abSDavid du Colombier free(order);
123*368c31abSDavid du Colombier }
124*368c31abSDavid du Colombier
125*368c31abSDavid du Colombier #define TWID64 ((u64int)~(u64int)0)
126*368c31abSDavid du Colombier
127*368c31abSDavid du Colombier u64int
unittoull(char * s)128*368c31abSDavid du Colombier unittoull(char *s)
129*368c31abSDavid du Colombier {
130*368c31abSDavid du Colombier char *es;
131*368c31abSDavid du Colombier u64int n;
132*368c31abSDavid du Colombier
133*368c31abSDavid du Colombier if(s == nil)
134*368c31abSDavid du Colombier return TWID64;
135*368c31abSDavid du Colombier n = strtoul(s, &es, 0);
136*368c31abSDavid du Colombier if(*es == 'k' || *es == 'K'){
137*368c31abSDavid du Colombier n *= 1024;
138*368c31abSDavid du Colombier es++;
139*368c31abSDavid du Colombier }else if(*es == 'm' || *es == 'M'){
140*368c31abSDavid du Colombier n *= 1024*1024;
141*368c31abSDavid du Colombier es++;
142*368c31abSDavid du Colombier }else if(*es == 'g' || *es == 'G'){
143*368c31abSDavid du Colombier n *= 1024*1024*1024;
144*368c31abSDavid du Colombier es++;
145*368c31abSDavid du Colombier }else if(*es == 't' || *es == 'T'){
146*368c31abSDavid du Colombier n *= 1024*1024;
147*368c31abSDavid du Colombier n *= 1024*1024;
148*368c31abSDavid du Colombier }
149*368c31abSDavid du Colombier if(*es != '\0')
150*368c31abSDavid du Colombier return TWID64;
151*368c31abSDavid du Colombier return n;
152*368c31abSDavid du Colombier }
153*368c31abSDavid du Colombier
154*368c31abSDavid du Colombier void
threadmain(int argc,char * argv[])155*368c31abSDavid du Colombier threadmain(int argc, char *argv[])
156*368c31abSDavid du Colombier {
157*368c31abSDavid du Colombier int i, max;
158*368c31abSDavid du Colombier vlong t0;
159*368c31abSDavid du Colombier double t;
160*368c31abSDavid du Colombier
161*368c31abSDavid du Colombier blocksize = 8192;
162*368c31abSDavid du Colombier seed = 0;
163*368c31abSDavid du Colombier randpct = 50;
164*368c31abSDavid du Colombier host = nil;
165*368c31abSDavid du Colombier doread = 0;
166*368c31abSDavid du Colombier dowrite = 0;
167*368c31abSDavid du Colombier totalbytes = 1*1024*1024*1024;
168*368c31abSDavid du Colombier fmtinstall('V', vtscorefmt);
169*368c31abSDavid du Colombier fmtinstall('F', vtfcallfmt);
170*368c31abSDavid du Colombier
171*368c31abSDavid du Colombier ARGBEGIN{
172*368c31abSDavid du Colombier case 'b':
173*368c31abSDavid du Colombier blocksize = unittoull(EARGF(usage()));
174*368c31abSDavid du Colombier break;
175*368c31abSDavid du Colombier case 'h':
176*368c31abSDavid du Colombier host = EARGF(usage());
177*368c31abSDavid du Colombier break;
178*368c31abSDavid du Colombier case 'M':
179*368c31abSDavid du Colombier maxpackets = unittoull(EARGF(usage()));
180*368c31abSDavid du Colombier break;
181*368c31abSDavid du Colombier case 'm':
182*368c31abSDavid du Colombier multi = atoi(EARGF(usage()));
183*368c31abSDavid du Colombier break;
184*368c31abSDavid du Colombier case 'n':
185*368c31abSDavid du Colombier totalbytes = unittoull(EARGF(usage()));
186*368c31abSDavid du Colombier break;
187*368c31abSDavid du Colombier case 'p':
188*368c31abSDavid du Colombier randpct = atoi(EARGF(usage()));
189*368c31abSDavid du Colombier break;
190*368c31abSDavid du Colombier case 'P':
191*368c31abSDavid du Colombier permute = 1;
192*368c31abSDavid du Colombier break;
193*368c31abSDavid du Colombier case 'S':
194*368c31abSDavid du Colombier doublecheck = 0;
195*368c31abSDavid du Colombier ventidoublechecksha1 = 0;
196*368c31abSDavid du Colombier break;
197*368c31abSDavid du Colombier case 's':
198*368c31abSDavid du Colombier seed = atoi(EARGF(usage()));
199*368c31abSDavid du Colombier break;
200*368c31abSDavid du Colombier case 'r':
201*368c31abSDavid du Colombier doread = 1;
202*368c31abSDavid du Colombier break;
203*368c31abSDavid du Colombier case 'w':
204*368c31abSDavid du Colombier dowrite = 1;
205*368c31abSDavid du Colombier break;
206*368c31abSDavid du Colombier case 'V':
207*368c31abSDavid du Colombier chattyventi++;
208*368c31abSDavid du Colombier break;
209*368c31abSDavid du Colombier default:
210*368c31abSDavid du Colombier usage();
211*368c31abSDavid du Colombier }ARGEND
212*368c31abSDavid du Colombier
213*368c31abSDavid du Colombier if(doread==0 && dowrite==0){
214*368c31abSDavid du Colombier doread = 1;
215*368c31abSDavid du Colombier dowrite = 1;
216*368c31abSDavid du Colombier }
217*368c31abSDavid du Colombier
218*368c31abSDavid du Colombier z = vtdial(host);
219*368c31abSDavid du Colombier if(z == nil)
220*368c31abSDavid du Colombier sysfatal("could not connect to server: %r");
221*368c31abSDavid du Colombier if(vtconnect(z) < 0)
222*368c31abSDavid du Colombier sysfatal("vtconnect: %r");
223*368c31abSDavid du Colombier
224*368c31abSDavid du Colombier if(multi){
225*368c31abSDavid du Colombier cr = chancreate(sizeof(void*), 0);
226*368c31abSDavid du Colombier cw = chancreate(sizeof(void*), 0);
227*368c31abSDavid du Colombier for(i=0; i<multi; i++){
228*368c31abSDavid du Colombier proccreate(wrthread, nil, STACK);
229*368c31abSDavid du Colombier proccreate(rdthread, nil, STACK);
230*368c31abSDavid du Colombier }
231*368c31abSDavid du Colombier }
232*368c31abSDavid du Colombier
233*368c31abSDavid du Colombier template = vtmalloc(blocksize);
234*368c31abSDavid du Colombier xxxsrand(seed);
235*368c31abSDavid du Colombier max = (256*randpct)/100;
236*368c31abSDavid du Colombier if(max == 0)
237*368c31abSDavid du Colombier max = 1;
238*368c31abSDavid du Colombier for(i=0; i<blocksize; i++)
239*368c31abSDavid du Colombier template[i] = xxxlrand()%max;
240*368c31abSDavid du Colombier if(dowrite){
241*368c31abSDavid du Colombier t0 = nsec();
242*368c31abSDavid du Colombier run(wr, cw);
243*368c31abSDavid du Colombier for(i=0; i<multi; i++)
244*368c31abSDavid du Colombier sendp(cw, nil);
245*368c31abSDavid du Colombier t = (nsec() - t0)/1.e9;
246*368c31abSDavid du Colombier print("write: %lld bytes / %.3f seconds = %.6f MB/s\n",
247*368c31abSDavid du Colombier totalbytes, t, (double)totalbytes/1e6/t);
248*368c31abSDavid du Colombier }
249*368c31abSDavid du Colombier if(doread){
250*368c31abSDavid du Colombier t0 = nsec();
251*368c31abSDavid du Colombier run(rd, cr);
252*368c31abSDavid du Colombier for(i=0; i<multi; i++)
253*368c31abSDavid du Colombier sendp(cr, nil);
254*368c31abSDavid du Colombier t = (nsec() - t0)/1.e9;
255*368c31abSDavid du Colombier print("read: %lld bytes / %.3f seconds = %.6f MB/s\n",
256*368c31abSDavid du Colombier totalbytes, t, (double)totalbytes/1e6/t);
257*368c31abSDavid du Colombier }
258*368c31abSDavid du Colombier threadexitsall(nil);
259*368c31abSDavid du Colombier }
260*368c31abSDavid du Colombier
261*368c31abSDavid du Colombier
262*368c31abSDavid du Colombier /*
263*368c31abSDavid du Colombier * algorithm by
264*368c31abSDavid du Colombier * D. P. Mitchell & J. A. Reeds
265*368c31abSDavid du Colombier */
266*368c31abSDavid du Colombier
267*368c31abSDavid du Colombier #define LEN 607
268*368c31abSDavid du Colombier #define TAP 273
269*368c31abSDavid du Colombier #define MASK 0x7fffffffL
270*368c31abSDavid du Colombier #define A 48271
271*368c31abSDavid du Colombier #define M 2147483647
272*368c31abSDavid du Colombier #define Q 44488
273*368c31abSDavid du Colombier #define R 3399
274*368c31abSDavid du Colombier #define NORM (1.0/(1.0+MASK))
275*368c31abSDavid du Colombier
276*368c31abSDavid du Colombier static ulong rng_vec[LEN];
277*368c31abSDavid du Colombier static ulong* rng_tap = rng_vec;
278*368c31abSDavid du Colombier static ulong* rng_feed = 0;
279*368c31abSDavid du Colombier
280*368c31abSDavid du Colombier static void
isrand(long seed)281*368c31abSDavid du Colombier isrand(long seed)
282*368c31abSDavid du Colombier {
283*368c31abSDavid du Colombier long lo, hi, x;
284*368c31abSDavid du Colombier int i;
285*368c31abSDavid du Colombier
286*368c31abSDavid du Colombier rng_tap = rng_vec;
287*368c31abSDavid du Colombier rng_feed = rng_vec+LEN-TAP;
288*368c31abSDavid du Colombier seed = seed%M;
289*368c31abSDavid du Colombier if(seed < 0)
290*368c31abSDavid du Colombier seed += M;
291*368c31abSDavid du Colombier if(seed == 0)
292*368c31abSDavid du Colombier seed = 89482311;
293*368c31abSDavid du Colombier x = seed;
294*368c31abSDavid du Colombier /*
295*368c31abSDavid du Colombier * Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1)
296*368c31abSDavid du Colombier */
297*368c31abSDavid du Colombier for(i = -20; i < LEN; i++) {
298*368c31abSDavid du Colombier hi = x / Q;
299*368c31abSDavid du Colombier lo = x % Q;
300*368c31abSDavid du Colombier x = A*lo - R*hi;
301*368c31abSDavid du Colombier if(x < 0)
302*368c31abSDavid du Colombier x += M;
303*368c31abSDavid du Colombier if(i >= 0)
304*368c31abSDavid du Colombier rng_vec[i] = x;
305*368c31abSDavid du Colombier }
306*368c31abSDavid du Colombier }
307*368c31abSDavid du Colombier
308*368c31abSDavid du Colombier void
xxxsrand(long seed)309*368c31abSDavid du Colombier xxxsrand(long seed)
310*368c31abSDavid du Colombier {
311*368c31abSDavid du Colombier isrand(seed);
312*368c31abSDavid du Colombier }
313*368c31abSDavid du Colombier
314*368c31abSDavid du Colombier long
xxxlrand(void)315*368c31abSDavid du Colombier xxxlrand(void)
316*368c31abSDavid du Colombier {
317*368c31abSDavid du Colombier ulong x;
318*368c31abSDavid du Colombier
319*368c31abSDavid du Colombier rng_tap--;
320*368c31abSDavid du Colombier if(rng_tap < rng_vec) {
321*368c31abSDavid du Colombier if(rng_feed == 0) {
322*368c31abSDavid du Colombier isrand(1);
323*368c31abSDavid du Colombier rng_tap--;
324*368c31abSDavid du Colombier }
325*368c31abSDavid du Colombier rng_tap += LEN;
326*368c31abSDavid du Colombier }
327*368c31abSDavid du Colombier rng_feed--;
328*368c31abSDavid du Colombier if(rng_feed < rng_vec)
329*368c31abSDavid du Colombier rng_feed += LEN;
330*368c31abSDavid du Colombier x = (*rng_feed + *rng_tap) & MASK;
331*368c31abSDavid du Colombier *rng_feed = x;
332*368c31abSDavid du Colombier
333*368c31abSDavid du Colombier return x;
334*368c31abSDavid du Colombier }
335*368c31abSDavid du Colombier
336