Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/mty-makai/mty.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 197 - (show annotations) (download) (as text)
Thu Jun 19 09:07:06 2008 UTC (15 years, 9 months ago) by notanpe
File MIME type: text/x-csrc
File size: 41214 byte(s)
スレッド数指定と簡易梅を追加
1 /***********************************************************************
2 *
3 * file: mty.c
4 *
5 * まあ、待て屋。
6 *
7 * $Id$
8 *
9 */
10
11 #include <assert.h>
12 #include <ctype.h>
13 #include <errno.h>
14 #include <limits.h>
15 #include <stdarg.h>
16 #include <stddef.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <time.h>
21 #include <sys/timeb.h>
22 #include <sys/types.h>
23
24 /* MAKAI start */
25 #include <unistd.h>
26 #include <libgen.h>
27 /* MAKAI end */
28
29 #if defined(WIN32)
30
31 #include <windows.h>
32 #include <process.h>
33
34 #elif defined(__GNUC__)
35
36 #include <sys/time.h>
37
38 #endif
39
40 #include "config.h"
41 #include "cp932.h"
42 #include "crypt64.h"
43 #include "desconst.h"
44 #include "expr_parse.h"
45 #include "scoreboard.h"
46 #include "synth.h"
47 #include "tr64.h"
48 #include "translate.h"
49 #include "util.h"
50 #include "wdict.h"
51
52 #if USE_DT
53 #include "dt4.h"
54 #endif
55
56 /* MAKAI start */
57 #define MIN_THREAD 1
58 #define MAX_THREAD 32
59 int nThread = 0;
60
61 #define MIN_UME 3
62 #define MAX_UME 6
63 unsigned char umeStr[10];
64 int umeLen;
65 /* MAKAI end */
66
67 /* CRYPT64 記述子 */
68 static
69 struct CRYPT64_DESC const *const crypt64_descs[] =
70 {
71 &crypt64_desc,
72 };
73
74 /* 鍵クラス */
75 static
76 struct
77 {
78 unsigned short map[256];
79 } kcls[8 + 8];
80
81 /* 拡張鍵クラス */
82 #define KCLS_DT0 64
83 #define KCLS_DT1 128
84 #define KCLS_K2 256
85
86 #if USE_DT
87 /* 鍵キメ用辞書インデクス */
88 struct DT *kd[8 + 8];
89
90 /* 辞書インデクス */
91 struct DT *dtidx[0x100 + 1];
92 #endif
93
94 /* 指定されたクラスと入っているキーから、classify を行う */
95 void
96 key_make_map(uint8_t *key, int n)
97 {
98 int i, j;
99 unsigned c = kcls[n].map[key[n]];
100
101 #if USE_DT
102 if (3 <= n && n < 7 && kd[n - 3])
103 {
104 /* 辞書のケツの文字。後ろにナニヤラキャラクタが来る */
105 c = kd[n - 3]->c[0];
106 if ((0x81 <= c && c <= 0x9F)
107 || (0xE0 <= c && c <= 0xFC))
108 c = KCLS_K2;
109 else
110 c = (cp932[256 * key[n]]
111 | cp932[256 * (key[n] ^ 0x80)]);
112 #if DEBUG>=1
113 printf("*n=%d, key=%02X, cls=%04X\n",
114 n,
115 key[n],
116 c);
117 #endif
118 }
119 else if (2 <= n && n < 6 && kd[n - 2])
120 {
121 return;
122 }
123 else if (1 <= n && n < 5 && kd[n - 1])
124 {
125 return;
126 }
127 else if (1 <= n && n < 5 && !kd[n - 1]
128 //&& (c & KCLS_K2)
129 && (c & KCLS_DT1))
130 {
131 /* 漢字2文字を拾っていきまつ */
132 #if DEBUG>=1
133 printf("(%d)%02X %02X(%02X:%02X:%02X:%02X)\n",
134 n, key[n - 1], key[n],
135 cp932[(256 * key[n - 1] + key[n])],
136 cp932[(256 * key[n - 1] + key[n]) ^ 0x0080],
137 cp932[(256 * key[n - 1] + key[n]) ^ 0x8000],
138 cp932[(256 * key[n - 1] + key[n]) ^ 0x8080]);
139 #endif
140 if (n != 1 && n != 2
141 && (cp932[(256 * key[n - 1] + key[n]) ^ 0x0080] & KCLS_DT1))
142 key[n] ^= 0x80;
143 else if (n != 2 && n != 3
144 && (cp932[(256 * key[n - 1] + key[n]) ^ 0x8000] & KCLS_DT1))
145 key[n - 1] ^= 0x80;
146 else if (n > 3 && (cp932[(256 * key[n - 1] + key[n]) ^ 0x8080] & KCLS_DT1))
147 key[n - 1] ^= 0x80, key[n] ^= 0x80;
148 if (cp932[256 * key[n - 1] + key[n]] & KCLS_DT1)
149 {
150 for (kd[n - 1] = dtidx[key[n - 1]];
151 kd[n - 1]->c[1] != key[n];
152 kd[n - 1]++)
153 assert(kd[n - 1]->c[0] == key[n - 1]);
154 #if DEBUG>=1
155 printf("(%02X%02X:%02X%02X)%c%c%c%c\n",
156 kd[n - 1]->c[0],
157 kd[n - 1]->c[1],
158 kd[n - 1]->c[2],
159 kd[n - 1]->c[3],
160 kd[n - 1]->c[0],
161 kd[n - 1]->c[1],
162 kd[n - 1]->c[2],
163 kd[n - 1]->c[3]);
164 #endif
165 return;
166 }
167 }
168 else if (n < 4 && (c & KCLS_DT0) && kd[n] == NULL)
169 {
170 /* カタカナ埋め込みいきます */
171 assert(kd[n] == NULL);
172 #if DEBUG>=1
173 printf("n=%d, key=%02X\n", n, key[n]);
174 #endif
175 kd[n] = dtidx[key[n]];
176 if (!kd[n]
177 && !(n == 1 || n == 2)
178 && dtidx[key[n] ^ 0x80])
179 {
180 key[n] ^= 0x80;
181 kd[n] = dtidx[key[n]];
182 }
183 if (kd[n])
184 return;
185 }
186 else
187 {
188 kd[n] = NULL;
189 }
190 #endif
191
192 /* 最後の部分は class map を生成する必要ナシ */
193 if (n >= 6)
194 return;
195
196 for (i = 0; i < 256; i++)
197 {
198 unsigned bm = 0;
199 #if 1
200 if (c & KCLS_K1)
201 {
202 if (cp932[256 * key[n] + i] & KCLS_K1)
203 bm |= KCLS_K2 | (cp932[256 * key[n] + i] & KCLS_DT1);
204 if (cp932[256 * (key[n] ^ 0x80) + i] & KCLS_K1)
205 bm |= KCLS_K2 | (cp932[256 * (key[n] ^ 0x80) + i] & KCLS_DT1);
206 #if 0
207 bm |= ((cp932[256 * key[n] + i] & KCLS_K1)
208 || (cp932[256 * (key[n] ^ 0x80) + i] & KCLS_K1)
209 ? KCLS_K2 : 0);
210 #endif
211 }
212 if (c & (KCLS_AN | KCLS_KA | KCLS_K2))
213 for (j = 0; j < 256; j++)
214 {
215 bm |= cp932[256 * i + j] & (KCLS_AN | KCLS_KA | KCLS_K1
216 | KCLS_DT0);
217 #if 0
218 if (j >= 127 && !(n == 0 || n == 1))
219 break;
220 #endif
221 }
222 kcls[n + 1].map[i] = bm;
223 #endif
224 if (i >= 128 && !(n == 0 || n == 1))
225 kcls[n + 1].map[i - 128] |= kcls[n + 1].map[i];
226 }
227
228 if (n < 6)
229 kcls[n + 1].map[0x00] = kcls[n + 1].map[0x80] = 0;
230 if (n == 6)
231 kcls[7].map[0x00] |= KCLS_AN;
232 }
233
234 #if USE_DT
235 unsigned
236 dt_get(int kdn,
237 int xn,
238 int n,
239 int ch)
240 {
241 int i;
242 #if DEBUG>=1
243 printf("*dt_get(%d)%c%c%c%c(%02X%02X:%02X%02X)->ch=%d",
244 n,
245 kd[kdn]->c[0], kd[kdn]->c[1], kd[kdn]->c[2], kd[kdn]->c[3],
246 kd[kdn]->c[0], kd[kdn]->c[1], kd[kdn]->c[2], kd[kdn]->c[3],
247 ch);
248 #endif
249 /* まずは数える */
250 for (i = 0;
251 kd[kdn][i].c[xn] == kd[kdn]->c[xn];
252 i++)
253 ;
254 assert(i > 0);
255 kd[kdn] += ch % i;
256 #if DEBUG>=1
257 printf("/%d\n dt_get: %c%c%c%c(%02X%02X:%02X%02X)->ch=%d\n",
258 i,
259 kd[kdn]->c[0], kd[kdn]->c[1], kd[kdn]->c[2], kd[kdn]->c[3],
260 kd[kdn]->c[0], kd[kdn]->c[1], kd[kdn]->c[2], kd[kdn]->c[3],
261 ch);
262 #endif
263 return kd[kdn]->c[n];
264 }
265 #endif
266
267 /* マップから文字を拾ってセット */
268 unsigned
269 key_set(int n, unsigned ch)
270 {
271 int cnt = 0, i;
272
273 #if USE_DT
274 if (3 <= n && n < 7 && kd[n - 3])
275 {
276 return dt_get(n - 3, 2, 3, ch);
277 return kd[n - 3]->c[3];
278 }
279 else if (2 <= n && n < 6 && kd[n - 2])
280 {
281 return dt_get(n - 2, 1, 2, ch);
282 return kd[n - 2]->c[2];
283 }
284 else if (1 <= n && n < 5 && kd[n - 1])
285 {
286 return dt_get(n - 1, 0, 1, ch);
287 return kd[n - 1]->c[1];
288 }
289 #endif
290
291 #if DEBUG>=3
292 if (cnt == 0)
293 {
294 printf("n=%d, ch=%d, (n-1)=%02X\n", n, ch, key[n - 1]);
295 int j;
296 for (i = 0; i < 16; i++)
297 {
298 printf("map[0x%02X] =", 16 * i);
299 for (j = 0; j < 16; j++)
300 printf(" %03X", kcls[n].map[16 * i + j]);
301 printf("\n");
302 }
303 }
304 #endif
305 for (i = 0; i < 256; i++)
306 {
307 if (kcls[n].map[i])
308 {
309 if (ch-- == 0)
310 return i;
311 cnt++;
312 }
313 if (n != 1 && n != 2 && i >= 127)
314 break;
315 }
316 /* 見つからなかったのでもいっぺん */
317 assert(cnt > 0);
318 ch %= cnt;
319 for (i = 0; i < 256; i++)
320 if (kcls[n].map[i])
321 {
322 if (ch-- == 0)
323 return i;
324 }
325 assert(!"not matched");
326 return 0;
327 }
328
329 /* bitwise key をセット */
330 static
331 void
332 key_set64(struct KEY *key64,
333 int n,
334 unsigned k,
335 unsigned vk,
336 unsigned sk)
337 {
338 int i, j;
339 if (!((vk | sk) & 0x7F))
340 return;
341
342 for (i = 0; i < 7; i++)
343 {
344 if (n == 7 && i < N_STRIDE) continue;
345 if (sk & (1 << i))
346 {
347 /* セット */
348 int o = tr_pc1[n][6 - i] - 1;
349 if (o < 28)
350 {
351 assert(o >= 0);
352 for (j = 0; j < N_ALU; j++)
353 key64->k[0][0][o].a[j]
354 = key64->k[0][1][o].a[j]
355 = -!!(k & (1 << i));
356 }
357 else
358 {
359 assert(o >= 28);
360 assert(o < 56);
361 for (j = 0; j < N_ALU; j++)
362 key64->k[1][0][o - 28].a[j]
363 = key64->k[1][1][o - 28].a[j]
364 = -!!(k & (1 << i));
365 }
366 }
367 else if (vk & (1 << i))
368 {
369 /* 反転 */
370 int o = tr_pc1[n][6 - i] - 1;
371 if (o < 28)
372 {
373 assert(o >= 0);
374 for (j = 0; j < N_ALU; j++)
375 key64->k[0][0][o].a[j]
376 = key64->k[0][1][o].a[j]
377 = ~key64->k[0][0][o].a[j];
378 }
379 else
380 {
381 assert(o >= 28);
382 assert(o < 56);
383 for (j = 0; j < N_ALU; j++)
384 key64->k[1][0][o - 28].a[j]
385 = key64->k[1][1][o - 28].a[j]
386 = ~key64->k[1][0][o - 28].a[j];
387 }
388 }
389 }
390 }
391
392 /* 指定されたクラスの開始値にリセット
393 直前の文字のクラスに縛られる */
394 int
395 key_reset(uint8_t *key, int n)
396 {
397 /* MAKAI start */
398 static char firstCall = 1;
399
400 if ( firstCall ) {
401 firstCall = 0;
402 } else {
403 if ( umeStr[0] != '\0' && n == 0 ) {
404 exit( 0 );
405 }
406 }
407 /* MAKAI end */
408
409 if (n >= 8)
410 return 1;
411 if (n == 7)
412 {
413 key[7] = 0;
414 return 1;
415 }
416
417 /* MAKAI start */
418 if (n >= umeLen)
419 key[n] = key_set(n, 0);
420 else {
421 if ( umeStr[0] == '\0' ) {
422 key[n] = key_set(n, rand());
423 } else {
424 key[n] = umeStr[n];
425 }
426 }
427 /* MAKAI end */
428
429 #if DEBUG>=3
430 printf("key[%d]=%02X ncls=%04X\n", n, key[n], kcls[n].map[key[n]]);
431 #endif
432
433 /* セットされた文字を元に、次キャラの文字クラスを決める */
434 key_make_map(key, n);
435
436 return key_reset(key, n + 1);
437 }
438
439 /* 指定された鍵空間の中で、キーをひとつ進める
440 安全にインクリメントできた場合 true を返す */
441 static
442 int
443 key_inc(uint8_t *key, int n)
444 {
445 if (n >= 8)
446 return 0;
447 else if (n == 7)
448 {
449 /* 最後のバイト */
450 uint8_t o_k = (key[7] + (1 << N_STRIDE)) & 0x7F;
451 if (!o_k)
452 return 0; /* インクリメントできなかったときは次へ進めず待つ */
453
454 /* 進める */
455 key[7] = o_k;
456 return 1;
457 }
458 else if (key_inc(key, n + 1)
459 /*
460 && key_inc(n + 1)
461 && key_inc(n + 1)
462 && key_inc(n + 1)*/
463 )
464 return 1;
465
466 /* Salt はインクリメントしない約束にする */
467 if (n == 1 || n == 2)
468 return 1;
469
470 #if DEBUG>=3
471 printf("key_inc(n=%d,ck=%02X)\n", n, key[n]);
472 #endif
473
474 #if USE_DT
475 /* 辞書語はインクリメントしていい約束にする */
476 if (3 <= n && n < 7 && kd[n - 3])
477 {
478 if ((key[n - 3] & 0x7F) == ((kd[n - 3] + 1)->c[0] & 0x7F)
479 && (key[n - 2] & 0x7F) == ((kd[n - 3] + 1)->c[1] & 0x7F)
480 && (key[n - 1] & 0x7F) == ((kd[n - 3] + 1)->c[2] & 0x7F))
481 {
482 memcpy(&key[n - 3], &(++kd[n - 3])->c[0], 4);
483 #if DEBUG>=2
484 printf(">dt_get:%c%c%c%c(%02X%02X:%02X%02X)\n",
485 kd[n - 3]->c[0], kd[n - 3]->c[1], kd[n - 3]->c[2], kd[n - 3]->c[3],
486 kd[n - 3]->c[0], kd[n - 3]->c[1], kd[n - 3]->c[2], kd[n - 3]->c[3]);
487 #endif
488 return 1;
489 }
490 else
491 {
492 return 0;
493 }
494 }
495 else if (2 <= n && n < 6 && kd[n - 2])
496 {
497 if ((key[n - 2] & 0x7F) == ((kd[n - 2] + 1)->c[0] & 0x7F)
498 && (key[n - 1] & 0x7F) == ((kd[n - 2] + 1)->c[1] & 0x7F))
499 {
500 memcpy(&key[n - 2], &(++kd[n - 2])->c[0], 4);
501 #if DEBUG>=2
502 printf(">dt_get:%c%c%c%c(%02X%02X:%02X%02X)\n",
503 kd[n - 2]->c[0], kd[n - 2]->c[1], kd[n - 2]->c[2], kd[n - 2]->c[3],
504 kd[n - 2]->c[0], kd[n - 2]->c[1], kd[n - 2]->c[2], kd[n - 2]->c[3]);
505 #endif
506 return 1;
507 }
508 else
509 {
510 return 0;
511 }
512 if (kd[n - 2]->c[0] == key[n - 2])
513 return 1;
514 else
515 return 0;
516 }
517 else if (1 <= n && n < 5 && kd[n - 1])
518 {
519 unsigned c2 = kd[n - 1]->c[0];
520 if ((0x81 <= c2 && c2 <= 0x9F)
521 || (0xE0 <= c2 && c2 <= 0xFC))
522 {
523 kd[n - 1] = NULL;
524 #if 0
525 if (!(n == 1 && n == 2))
526 key[n] &= 0x7F;
527 if (!(n == 2 && n == 3))
528 key[n - 1] &= 0x7F;
529 #endif
530 key_make_map(n - 1);
531 }
532 else if ((key[n - 1] & 0x7F) == ((kd[n - 1] + 1)->c[0] & 0x7F))
533 {
534 memcpy(&key[n - 1], &(++kd[n - 1])->c[0], 4);
535 #if DEBUG>=2
536 printf(">dt_get:%c%c%c%c(%02X%02X:%02X%02X)\n",
537 kd[n - 1]->c[0], kd[n - 1]->c[1], kd[n - 1]->c[2], kd[n - 1]->c[3],
538 kd[n - 1]->c[0], kd[n - 1]->c[1], kd[n - 1]->c[2], kd[n - 1]->c[3]);
539 #endif
540 return 1;
541 }
542 else
543 {
544 return 0;
545 }
546 #if 0
547 if (kd[n - 1]->c[0] == key[n - 1])
548 return 1;
549 else
550 return 0;
551 #endif
552 }
553 else if (n < 4 && kd[n])
554 {
555 if (0 && kd[n]->c[0] == key[n])
556 return 1;
557 kd[n] = NULL;
558 #if 0
559 if (!(n == 1 || n == 2))
560 key[n] &= 0x7F;
561 #endif
562 }
563 #endif
564
565 /* 実際に増やしてみる */
566 assert(n >= 3);
567 for (;;)
568 {
569 if (n <= 3
570 && !(key[n] & 0x80)
571 && kcls[n].map[key[n] ^ 0x80] & (KCLS_DT0))
572 {
573 /* 半角カタカナの1バイト目 */
574 key[n] ^= 0x80;
575 }
576 else
577 {
578 key[n] = (key[n] & 0x7F) + 1;
579 if (key[n] >= 0x80)
580 {
581 key[n] = 0xFF; /* 次に突入させないため */
582 return 0;
583 }
584 }
585
586 if (kcls[n].map[key[n]])
587 {
588 key_make_map(key, n);
589 key_reset(key, n + 1);
590 return 1;
591 }
592 }
593 }
594
595 /* 鍵を完全にリセットする
596 Saltもセットし直す */
597 static
598 void
599 key_init(uint8_t *key)
600 {
601 int i, j;
602
603 #if USE_DT
604 /* 辞書を、インデクスを作りながらマップにはめこんで逝く
605 辞書はコード順昇順に並んでるものとする */
606 for (i = 0; i < dtcnt; i++)
607 {
608 unsigned c = dt[i].c[0];
609
610 assert(dt[i].c[0]
611 && dt[i].c[1]
612 && dt[i].c[2]
613 && dt[i].c[3]);
614
615 /* BSD 鯖でしにそうな文字は残念ながら除外 */
616 assert((dt[i].c[0] & 0x7F)
617 && (dt[i].c[1] & 0x7F)
618 && (dt[i].c[2] & 0x7F)
619 && (dt[i].c[3] & 0x7F));
620
621 /* インデクス */
622 if (!dtidx[c])
623 dtidx[c] = &dt[i];
624
625 if ((0x81 <= c && c <= 0x9F)
626 || (0xE0 <= c && c <= 0xFC))
627 {
628 /* 全角なので、2バイトきまった時点で立てる */
629 cp932[256 * c + dt[i].c[1]] |= KCLS_DT1;
630 }
631 else if (0xA1 <= c && c <= 0xDF)
632 {
633 /* 半角カナ */
634 for (j = 0; j < 256; j++)
635 cp932[256 * c + j] |= KCLS_DT0;
636 }
637 }
638 /* ケツ、ちうか番人 */
639 dtidx[0x100] = &dt[i];
640 #endif
641
642 key[8] = 0;
643
644 /* 初期マップを組む */
645 for (i = 0; i < 256; i++)
646 {
647 unsigned bm = 0;
648 kcls[0].map[i] = 0;
649 for (j = 0; j < 256; j++)
650 bm |= cp932[256 * i + j];
651 kcls[0].map[i] = bm & (KCLS_AN | KCLS_KA | KCLS_K1
652 | KCLS_DT0
653 );
654 if (i >= 128)
655 kcls[0].map[i - 128] |= kcls[0].map[i];
656 }
657
658 key_reset(key, 0);
659 }
660
661 /***************************************************************
662 *
663 * 固定キーの生成
664 *
665 * 一見 Big Endian に非対応のように見えるだろうが
666 * 随所でに散らばっている kludge により
667 * ALU_T が 64 ビットである限り、これで問題なく動く。
668 *
669 */
670
671 static
672 void
673 key_init_sk(struct KEY *key)
674 {
675 int i, j;
676 int o;
677 uint64_t m;
678
679 for (i = 5, m = 0xFFFFFFFF00000000ULL;
680 i >= 0;
681 m ^= (m >> (1 << --i)))
682 {
683 o = tr_pc1[7][6 - i] - 1;
684 #if DEBUG>=2
685 printf("%d:%d->%2d: %08X%08X\n",
686 N_Q, i, o,
687 (unsigned)(m >> 32),
688 (unsigned)m);
689 #endif
690 for (j = 0; j < N_Q; j++)
691 if (o < 28)
692 key->k[0][0][o ].q[j] = key->k[0][1][o ].q[j] = m;
693 else
694 key->k[1][0][o - 28].q[j] = key->k[1][1][o - 28].q[j] = m;
695 }
696 #if N_STRIDE==7
697 /* bit 6 は Little Endian として扱う */
698 o = 0;
699 assert(tr_pc1[7][0] - 1 == o);
700 assert(N_Q == 2);
701 key->k[0][0][o].q[0] = key->k[0][1][o].q[0] = 0x0000000000000000ULL;
702 key->k[0][0][o].q[1] = key->k[0][1][o].q[1] = 0xFFFFFFFFFFFFFFFFULL;
703 #endif
704 }
705
706 /***************************************************************
707 *
708 * Salt のセット
709 * オペランドのオフセットを書き換えて回ってるので注意
710 *
711 */
712
713 void
714 set_salt(CODE_T *code,
715 struct CRYPT64_DESC const *desc,
716 uint8_t const *k)
717 {
718 int i, j;
719
720 for (i = 0; i < 2; i++)
721 {
722 unsigned s = k[1 + i] & 255;
723 if (s > 'z')
724 s = 0;
725 else if (s >= 'a')
726 s = s - 'a' + 2 + 10 + 26;
727 else if (s >= 'A')
728 s = s - 'A' + 2 + 10;
729 else if (s >= '.')
730 s = s - '.';
731 else
732 s = 0;
733
734 #if DEBUG>=1
735 printf("Salt %d:%3o\n", i, s & 63);
736 #endif
737 for (j = 0; j < 6; j++)
738 {
739 #if DEBUG>=2
740 //printf("Salt %d:%d %+3d:%+3d",
741 printf("Salt %d:%d %08lX:%08lX",
742 i, j,
743 LSALT(desc, code, 0, i, j, 0),
744 LSALT(desc, code, 0, i, j, 24));
745 #endif
746 if (s & (1 << j))
747 {
748 LSALT(desc, code, 0, i, j, 0) = sizeof(WS_T) * (((4 * i + j + 15) & 31) - 16);
749 LSALT(desc, code, 0, i, j, 24) = sizeof(WS_T) * (((4 * i + j - 1) & 31) - 16);
750 }
751 else
752 {
753 LSALT(desc, code, 0, i, j, 0) = sizeof(WS_T) * (((4 * i + j - 1) & 31) - 16);
754 LSALT(desc, code, 0, i, j, 24) = sizeof(WS_T) * (((4 * i + j + 15) & 31) - 16);
755 }
756 LSALT(desc, code, 0, i, j, 12) = sizeof(WS_T) * (((4 * i + j + 7) & 31) - 16);
757 LSALT(desc, code, 0, i, j, 36) = sizeof(WS_T) * (((4 * i + j + 23) & 31) - 16);
758 #if DEBUG>=2
759 //printf(" => %+3d:%+3d\n",
760 printf(" => %08lX:%08lX\n",
761 LSALT(desc, code, 0, i, j, 0),
762 LSALT(desc, code, 0, i, j, 24));
763 #endif
764 }
765 }
766 }
767
768 #define USEC_SEC 1000 /* 1秒 */
769
770 static
771 uint64_t
772 usec(void)
773 {
774 uint32_t sec, msec;
775
776 #if !defined(WIN32)
777 struct timeval tv;
778 gettimeofday(&tv, NULL);
779 sec = tv.tv_sec;
780 msec = tv.tv_usec / (1000000 / USEC_SEC);
781 #else
782 struct timeb tm;
783 ftime(&tm);
784 sec = tm.time;
785 msec = tm.millitm / (1000 / USEC_SEC);
786 #endif
787
788 return (uint64_t)USEC_SEC * sec + msec;
789 }
790
791 static
792 int
793 log_printf(FILE *ofp, char const *fmt, ...)
794 {
795 int r;
796 va_list ap;
797 va_start(ap, fmt);
798 vfprintf(stdout, fmt, ap);
799 r = vfprintf(ofp, fmt, ap);
800 va_end(ap);
801 if (r > 0)
802 return r;
803 perror("log_printf");
804 exit(errno);
805 }
806
807 /***************************************************************
808 *
809 * CPU capabilities を取得
810 * [XXX] あまりにも古いプロセッサのことは考えない。
811 *
812 * a[4] = {EAX,EBX,ECX,EDX}
813 *
814 */
815
816 #if defined(__GNUC__)
817
818 #define cpuid(n,a,b,c,d) \
819 asm("cpuid" \
820 : "=a"(a), "=b"(b), "=c"(c), "=d"(d) \
821 : "a"(n))
822
823 #elif defined(WIN32)
824
825 #define cpuid(n,a,b,c,d) \
826 do {int r[4]; __cpuid(r,n); \
827 (a) = r[0]; (b) = r[1]; (c) = r[2]; (d) = r[3];} while (0)
828
829 #endif
830
831 static
832 unsigned
833 cpuid_getfflags(void)
834 {
835 unsigned a, b, c, d;
836 cpuid(1, a, b, c, d);
837 return d;
838 }
839
840 static
841 int
842 cpuid_issupported(void)
843 {
844 unsigned m = REQUIRED_CAPS;
845 return !((cpuid_getfflags() ^ m) & m);
846 }
847
848 /***************************************************************
849 *
850 * バッチ処理用パケット
851 *
852 */
853
854 static
855 struct PACKET_CRYPT64 *
856 packet_create(int n, /* パケット数 */
857 int tn, /* 末尾要素にて必要なワーク数 */
858 uint8_t const *ini_key)
859 {
860 int i;
861 int siz;
862 void *p;
863 intptr_t a = 128;
864 struct PACKET_CRYPT64 *pkts;
865 assert(IS_POWER2(sizeof(struct PACKET_CRYPT64)));
866 assert(n >= 1);
867
868 siz = (a - 1
869 + (n - 1) * sizeof(struct PACKET_CRYPT64)
870 + offsetof(struct PACKET_CRYPT64, param64.hit[tn]));
871 p = calloc(siz, 1);
872 /* バンダリあわせ */
873 pkts = (struct PACKET_CRYPT64 *)(((intptr_t)p
874 + a - 1)
875 & -a);
876 #if DEBUG>=1
877 fprintf(stderr,
878 "packet(n=%d,tn=%d) %d allocated; %p aligned to %p\n",
879 n, tn,
880 siz, p, pkts);
881 #endif
882
883 /* 内部の初期化
884 コピーして回るのは、厳密には
885 最終要素のケツを破ってしまうことになるので
886 どうせ速度も要求されないしベタコード */
887 for (i = 0; i < n; i++)
888 {
889 int j, k;
890
891 /* t[16] は、内部演算で使用する、all 1 が入っている */
892 memset(&pkts[i].param64.t[T_INV], -1, sizeof(SLICE));
893
894 /* 固定キーの生成 */
895 key_init_sk(&pkts[i].key64);
896
897 /* キースケジュールをここに押し込めておく
898 従来は crypt64.S 内で完結するように引いていた */
899 for (j = 0; j < 28; j++)
900 for (k = 0; k < N_ALU; k++)
901 pkts[i].key64.ks[j].a[k] = sizeof(WS_T) * ks_ls[j];
902
903 /* 念のため、鍵をここで落ち着けておく(不要?) */
904 for (j = 0; j < 8; j++)
905 key_set64(&pkts[i].key64, j, pkts[i].uk.key[j] = ini_key[j], 0, 0x7F);
906 }
907
908 return pkts;
909 }
910
911 /***************************************************************
912 *
913 * thread
914 *
915 */
916
917 #define NQ_CRYPT 64
918 #define NQ_CMP 32
919
920 #if defined(__GNUC__)
921
922 typedef int32_t ATOMWORD_T;
923
924 #define LOCK_INC(p) \
925 asm volatile ("lock incl %0" \
926 : "=m"(*(p)) \
927 : /*nil*/ \
928 : "memory")
929
930 #define LOCK_DEC(p) \
931 asm volatile ("lock decl %0" \
932 : "=m"(*(p)) \
933 : /*nil*/ \
934 : "memory")
935
936 #define LOCK_CAS(pd,s,r) \
937 ({ ATOMWORD_T a; \
938 asm volatile ("lock cmpxchg %2,%1" \
939 : "=a"(a) \
940 : "m"(*(pd)), "r"(s), "0"(r) \
941 : "memory");a;})
942
943 #define LOCK_CASP(pd,s,r) \
944 ({ void *a; \
945 asm volatile ("lock cmpxchg %2,%1" \
946 : "=a"(a) \
947 : "m"(*(pd)), "r"(s), "0"(r) \
948 : "memory");a;})
949
950 #elif defined(WIN32)
951
952 typedef LONG ATOMWORD_T;
953
954 #define LOCK_INC(p) InterlockedIncrement((LONG *)(p))
955 #define LOCK_DEC(p) InterlockedDecrement((LONG *)(p))
956 #define LOCK_CAS(pd,s,r) InterlockedCompareExchange((LONG *)(pd), s, r)
957 #define LOCK_CASP(pd,s,r) InterlockedCompareExchangePointer((PVOID *)(pd), (PVOID)(s), (PVOID)r)
958
959 #else
960 #error "configuration not implemented"
961 #endif
962
963 #if defined(WIN32)
964
965 typedef DWORD THREAD_TIMEOUT_T;
966
967 #define THREAD_INFINITE INFINITE
968
969 typedef HANDLE THREAD_TH_T;
970 typedef HANDLE THREAD_EV_T;
971
972 #define thread_sleep(n) Sleep(n)
973 #define thread_create(th, proc, arg) {(th) = (HANDLE)_beginthread(proc, 8192, arg);}
974 #define thread_create_event(ev, f) {(ev) = CreateEvent(NULL, TRUE, f, NULL);}
975 #define thread_signal_event(ev) SetEvent(ev)
976 #define thread_clear_event(ev) ResetEvent(ev)
977 #define thread_get_tid() GetCurrentThread()
978 #define thread_set_priority(tid,n) SetThreadPriority(tid, n)
979 #define thread_set_affinity(tid,m) SetThreadAffinityMask(tid, (DWORD_PTR)1 << (m))
980
981 static
982 int
983 thread_wait_event(THREAD_EV_T ev, DWORD tmo)
984 {
985 DWORD r = WaitForSingleObject(ev, tmo);
986 return (r < 0
987 ? r
988 : (r == WAIT_TIMEOUT
989 ? -1
990 : r));
991 }
992
993 #elif defined(_POSIX_SOURCE)
994
995 #include <pthread.h>
996 #include <unistd.h>
997
998 typedef int THREAD_TIMEOUT_T;
999
1000 #define THREAD_INFINITE INT_MAX
1001
1002 #if defined(THREAD_PRIORITY_BELOW_NOROMAL) || defined(THREAD_PRIORITY_IDLE)
1003 #error "unsupported implementation"
1004 #endif
1005
1006 #define THREAD_PRIORITY_NORMAL 14
1007 #define THREAD_PRIORITY_BELOW_NORMAL 15
1008 #define THREAD_PRIORITY_IDLE 16
1009
1010 typedef pthread_t THREAD_TH_T;
1011 typedef struct
1012 {
1013 pthread_mutex_t m;
1014 pthread_cond_t c;
1015 int volatile f;
1016 } THREAD_EV_T;
1017
1018 #define thread_sleep(n) (usleep(1000 * (n)) != EINVAL || sleep((n) / 1000))
1019 #define thread_create(th, proc, arg) thread_create_p(&(th), proc, arg)
1020 #define thread_create_event(ev, f) thread_create_event_p(&(ev), f)
1021 #define thread_signal_event(ev) thread_set_event_p(&(ev), 1)
1022 #define thread_clear_event(ev) thread_set_event_p(&(ev), 0)
1023 #define thread_wait_event(ev,tmo) thread_wait_event_p(&(ev), tmo)
1024
1025 static
1026 void
1027 thread_create_p(pthread_t *th, NORETURN (*proc)(void *), void *param)
1028 {
1029 pthread_create(th, NULL, (void *(*)(void *))proc, param);
1030 }
1031
1032 static
1033 void
1034 thread_create_event_p(THREAD_EV_T *ev, int f)
1035 {
1036 ev->f = f;
1037 pthread_cond_init(&ev->c, NULL);
1038 pthread_mutex_init(&ev->m, NULL);
1039 }
1040
1041 static
1042 void
1043 thread_set_event_p(THREAD_EV_T *ev, int f)
1044 {
1045 pthread_mutex_lock(&ev->m);
1046 if (ev->f != f)
1047 {
1048 ev->f = f;
1049 pthread_cond_broadcast(&ev->c);
1050 }
1051 pthread_mutex_unlock(&ev->m);
1052 }
1053
1054 static
1055 int
1056 thread_wait_event_p(THREAD_EV_T *ev, int a_tmo)
1057 {
1058 int timeout = a_tmo;
1059 struct timeval now;
1060 struct timespec tmo;
1061 int r;
1062
1063 pthread_mutex_lock(&ev->m);
1064
1065 /* 現在時刻からタイムアウト時刻を求める
1066 めんどくせー */
1067 gettimeofday(&now, NULL);
1068 tmo.tv_sec = now.tv_sec + (timeout / 1000);
1069 timeout %= 1000;
1070 timeout *= 1000;
1071 if (now.tv_usec >= 1000000 - timeout)
1072 {
1073 timeout -= 1000000;
1074 tmo.tv_sec++;
1075 }
1076 tmo.tv_nsec = 1000 * (now.tv_usec + timeout);
1077 r = 0;
1078 while (!ev->f)
1079 {
1080 r = pthread_cond_timedwait(&ev->c, &ev->m, &tmo);
1081 if (r == ETIMEDOUT
1082 && a_tmo < THREAD_INFINITE)
1083 break;
1084 }
1085
1086 pthread_mutex_unlock(&ev->m);
1087
1088 return (r == ETIMEDOUT
1089 ? (ETIMEDOUT < 0 ? ETIMEDOUT : -1)
1090 : 0);
1091 }
1092
1093 #if defined(__linux__)
1094
1095 /* デフォルトスケジューリングポリシーでは
1096 優先度設定したりアイドルスレッド起こしても
1097 おもしろくないので、そのへんは今後の研究課題。 */
1098
1099 #include <linux/unistd.h>
1100 _syscall0(pid_t,gettid)
1101
1102 #define thread_get_tid() gettid()
1103
1104 static
1105 int thread_set_affinity(pid_t tid, int i)
1106 {
1107 cpu_set_t m;
1108 CPU_ZERO(&m);
1109 CPU_SET(i, &m);
1110 return sched_setaffinity(tid, sizeof(m), &m);
1111 }
1112
1113 #else
1114
1115 /* POSIX では、スレッド単位のスケジューリングに介入できない。 */
1116
1117 #endif
1118
1119 #else
1120 #error "configuration not supported"
1121 #endif
1122
1123 struct THREAD_PARAM
1124 {
1125 /* 以下は共通情報のコピー */
1126 CODE_T *code;
1127 THREAD_EV_T *p_ev_ks_activated;
1128 ATOMWORD_T volatile *p_nidle; /* 待ちに入ったら増加 */
1129
1130 /* 以下はスレッド固有 */
1131 #ifdef thread_set_priority
1132 THREAD_TH_T th;
1133 int pri;
1134 #endif
1135 };
1136
1137 static
1138 volatile ATOMWORD_T wp_crypt, rp_crypt;
1139 static
1140 struct PACKET_CRYPT64 *volatile q_crypt[NQ_CRYPT];
1141
1142 static
1143 volatile ATOMWORD_T wp_cmp, rp_cmp;
1144 static
1145 struct PACKET_CRYPT64 *volatile q_cmp[NQ_CMP];
1146
1147 static
1148 uint64_t
1149 thread_avail(void)
1150 {
1151 #if !USE_MT
1152
1153 return 0x1U;
1154
1155 #elif defined(WIN32) /* Win32 API */
1156 DWORD_PTR mask, mask_s;
1157 if (!GetProcessAffinityMask(GetCurrentProcess(),
1158 &mask,
1159 &mask_s)
1160 || !mask
1161 || !mask_s)
1162 return 0x1U;
1163 #if DEBUG>=1
1164 fprintf(stderr,
1165 "m=%08X s=%08X\n",
1166 (unsigned)mask,
1167 (unsigned)mask_s);
1168 #endif
1169 if (popcnt64(mask_s) == 1)
1170 /* 何も言うまい */;
1171 else if (mask == mask_s)
1172 fprintf(stderr,
1173 "通常の%d倍とはよく言ったものです。\n",
1174 popcnt64(mask));
1175 else
1176 fprintf(stderr,
1177 "最高速力の%g倍の力でてきとうにがんばるよ。\n",
1178 (double)popcnt64(mask) / popcnt64(mask_s));
1179 return mask;
1180
1181 #elif defined(__linux__) /* sched.h 拡張 */
1182
1183 int i;
1184 uint64_t m = 0;
1185 cpu_set_t am;
1186 if (sched_getaffinity(getpid(), sizeof(am), &am) < 0)
1187 return 0x1U;
1188
1189 for (i = 0; i < 64 && i < CPU_SETSIZE; i++)
1190 if (CPU_ISSET(i, &am))
1191 m |= 1ULL << i;
1192
1193 return m;
1194 #else
1195
1196 /* XXX プロセッサ数を調べ上げてください */
1197 return 0x01U;
1198
1199 #endif
1200 }
1201
1202 static
1203 NORETURN
1204 thread_crypt64(void *a_param)
1205 {
1206 struct THREAD_PARAM *param = a_param;
1207 CODE_T *code = param->code;
1208 struct PACKET_CRYPT64 *pkt;
1209 #ifdef thread_set_priority
1210 THREAD_TH_T th = thread_get_tid();
1211 thread_set_priority(th, param->pri);
1212 #endif
1213
1214 for(;;)
1215 {
1216 ATOMWORD_T rp;
1217 ATOMWORD_T wp;
1218
1219 /* キューから要求を取り出す */
1220 for (;;)
1221 {
1222 while ((rp = rp_crypt,
1223 WRAP(wp_crypt, NQ_CRYPT) == WRAP(rp, NQ_CRYPT)
1224 /*|| q_crypt[WRAP(rp, NQ_CRYPT)] == NULL*/))
1225 {
1226 THREAD_TIMEOUT_T tmo = (WRAP(wp_crypt, NQ_CRYPT) == WRAP(rp, NQ_CRYPT)
1227 ? THREAD_INFINITE
1228 : 1);
1229 int r;
1230
1231 /* 寝た */
1232 if (tmo == THREAD_INFINITE)
1233 {
1234 LOCK_INC(param->p_nidle);
1235 }
1236
1237 /* 要求待ち */
1238 r = thread_wait_event(*param->p_ev_ks_activated, tmo);
1239
1240 if (tmo == THREAD_INFINITE)
1241 {
1242 /* 起こされた */
1243 LOCK_DEC(param->p_nidle);
1244 }
1245 else if (r >= 0)
1246 {
1247 /* もうちょっと寝てみる */
1248 thread_sleep(tmo);
1249 }
1250
1251 /* 自らの優先度を戻す
1252 (外からブーストされてるかも) */
1253 #ifdef thread_set_priority
1254 if (r >= 0)
1255 thread_set_priority(th, param->pri);
1256 #endif
1257 }
1258
1259 if (LOCK_CAS(&rp_crypt, rp + 1, rp) != rp)
1260 continue;
1261 rp = WRAP(rp, NQ_CRYPT);
1262 break;
1263 }
1264
1265 pkt = q_crypt[rp];
1266 assert(pkt != NULL);
1267 pkt = LOCK_CASP(&q_crypt[rp], NULL, pkt);
1268 assert(pkt != NULL);
1269
1270 /* 実行してみる */
1271 CALL_CRYPT64(code, &pkt->key64, &pkt->param64);
1272
1273 /* 結果をキューにたたき込む */
1274 for (;;)
1275 {
1276 while ((wp = wp_cmp,
1277 WRAP(rp_cmp - 1, NQ_CMP) == WRAP(wp, NQ_CMP))
1278 || q_cmp[WRAP(wp, NQ_CMP)] != NULL)
1279 {
1280 #if DEBUG>=1
1281 fprintf(stderr,
1282 "q_cmp stalled(%d,%d) %p\n",
1283 (unsigned)WRAP(wp, NQ_CMP),
1284 (unsigned)WRAP(rp_cmp - 1, NQ_CMP),
1285 q_cmp[WRAP(wp, NQ_CMP)]);
1286 #endif
1287 thread_sleep(1);
1288 }
1289
1290 if (LOCK_CAS(&wp_cmp, wp + 1, wp) != wp)
1291 continue;
1292 wp = WRAP(wp, NQ_CMP);
1293 break;
1294 }
1295
1296 pkt = LOCK_CASP(&q_cmp[wp], pkt, NULL);
1297 assert(pkt == NULL);
1298 }
1299 }
1300
1301 /* MAKAI start */
1302 void
1303 usage( path )
1304 char *path;
1305 {
1306 char *myName, *chPtr;
1307
1308 myName = basename( path );
1309 for ( chPtr = myName; *chPtr != '\0'; chPtr++ ) {
1310 if ( *chPtr == '.' ) {
1311 *chPtr = '\0';
1312 break;
1313 }
1314 }
1315 printf( "%s [-t num] [\"str\"]\n", myName );
1316 printf( " -t num : 検索スレッド数 ( %d ≦ num ≦ %d )\n",
1317 MIN_THREAD, MAX_THREAD );
1318 printf( " str : 先頭に埋め込む文字列 ( %d ≦ str のバイト数 ≦ %d )\n",
1319 MIN_UME, MAX_UME );
1320 }
1321 /* MAKAI end */
1322
1323 /***************************************************************
1324 *
1325 * メインループとか
1326 *
1327 */
1328
1329 int
1330 main(int argc, char *argv[])
1331 {
1332 int i;
1333 int mincnt;
1334 int nblk_hit, nblk_total;
1335 int nap_hit, nap_total;
1336 CODE_T *code = NULL;
1337 off_t code_cmp;
1338 FILE *ofp;
1339 FILE *sfp; /* scoreboard */
1340 struct ITREE *root_expr;
1341 uint64_t proc_mask;
1342 int ks_activated;
1343 static THREAD_EV_T event_ks_activated;
1344 static ATOMWORD_T volatile nidle;
1345 struct THREAD_PARAM *threads = NULL;
1346 int nthreads;
1347 int npkts;
1348 struct PACKET_CRYPT64 *pkts, *pkt_hit;
1349 uint64_t pkts_vacant;
1350 int tn;
1351 int cr;
1352
1353 /* 鍵文字列 */
1354 uint8_t key[8 + 8];
1355
1356 int xhash_loaded;
1357
1358 #define UPDATE_INTERVAL 8 /* 速度表示の間隔 秒 */
1359 struct status {
1360 uint64_t startTime; /* 開始時刻 ミリ秒 */
1361 uint64_t lastTime; /* 最後に表示した時刻 ミリ秒 */
1362 uint64_t loop; /* 総検索個数 */
1363 uint64_t lastloop; /* 最後に表示した時の loop */
1364 } status;
1365 uint64_t curTime;
1366 uint32_t upd_int = 0;
1367
1368 /* MAKAI start */
1369 /* 実際の処理とあっていないコメントを削除 */
1370
1371 #if defined(WIN32)
1372 SetPriorityClass( GetCurrentProcess(), IDLE_PRIORITY_CLASS );
1373 #endif
1374
1375 {
1376 int optChar;
1377 extern char *optarg;
1378 extern int optind;
1379
1380 nThread = 0;
1381 while ( (optChar = getopt(argc, argv, "t:h")) != EOF ) {
1382 switch ( optChar ) {
1383 case 't':
1384 nThread = atoi( optarg );
1385 if ( nThread < MIN_THREAD || nThread > MAX_THREAD ) {
1386 usage( argv[0] );
1387 exit( 1 );
1388 }
1389 break;
1390 case 'h':
1391 usage( argv[0] );
1392 exit( 0 );
1393 break;
1394 }
1395 }
1396
1397 switch ( argc - optind ) {
1398 case 0:
1399 umeStr[0] = '\0';
1400 umeLen = KEY_SHUFFLE_POS;
1401 break;
1402 case 1:
1403 strcpy( umeStr, argv[optind] );
1404 umeLen = strlen( umeStr );
1405 if ( umeLen < MIN_UME || umeLen > MAX_UME ) {
1406 usage( argv[0] );
1407 exit( 1 );
1408 }
1409 break;
1410 default:
1411 usage( argv[0] );
1412 exit( 1 );
1413 }
1414 }
1415 /* MAKAI end */
1416
1417 if (!cpuid_issupported())
1418 {
1419 fprintf(stderr, "この環境で走らせることが想定されていません。\n");
1420 exit(1);
1421 }
1422
1423 assert((1 << N_STRIDE) == N_ALU * ALU_BITS);
1424
1425 /* タゲ読み込み */
1426 root_expr = expr_parse("target.txt");
1427
1428 /* コードを生成・展開
1429 起動予定スレッド数に応じて
1430 生成するコードを変える */
1431 sfp = scoreboard_open();
1432 fwrite(crypt64_descs[0]->pro, 1, crypt64_descs[0]->cmp_pro - crypt64_descs[0]->pro, sfp); /* prologue & コアループ */
1433
1434 /* MAKAI start */
1435 if ( nThread == 0 ) {
1436 proc_mask = thread_avail();
1437 } else {
1438 int i;
1439 proc_mask = 0U;
1440 for ( i = 0; i < nThread; i++ ) {
1441 proc_mask |= 1U;
1442 proc_mask <<= 1;
1443 }
1444 }
1445 /* MAKAI end */
1446
1447 if (proc_mask == 1U)
1448 {
1449 /* single */
1450 npkts = 1;
1451 pkts_vacant = 1;
1452 code_cmp = 0;
1453 }
1454 else
1455 {
1456 /* multi */
1457 fwrite(crypt64_descs[0]->ep, 1, crypt64_descs[0]->ep_end - crypt64_descs[0]->ep, sfp); /* epilogue */
1458
1459 /* 比較器のみを生成(前半) */
1460 code_cmp = ftell(sfp);
1461 fseek(sfp, (-code_cmp) & 63, SEEK_CUR);
1462 code_cmp = ftell(sfp);
1463 fwrite(crypt64_descs[0]->pro, 1, crypt64_descs[0]->crypt - crypt64_descs[0]->pro, sfp); /* prologue */
1464 npkts = 64;
1465 pkts_vacant = (uint64_t)-1; /* (1 << 64) - 1 を計算したくない */
1466 }
1467
1468 /* 比較部を生成 */
1469 fwrite(crypt64_descs[0]->cmp_pro, 1, crypt64_descs[0]->cmp_ep - crypt64_descs[0]->cmp_pro, sfp); /* 比較器準備 */
1470 tn = synth_synthesize(sfp, root_expr);
1471 fwrite(crypt64_descs[0]->cmp_ep, 1, crypt64_descs[0]->ep_end - crypt64_descs[0]->cmp_ep, sfp); /* epilogue */
1472
1473 /* コードをメモリに貼り付ける */
1474 code = scoreboard_map(sfp);
1475
1476 /* キーの初期化 */
1477 srand(time(NULL));
1478 key_init(key);
1479 set_salt(code, crypt64_descs[0], key);
1480
1481 /* 演算パケットを作成 */
1482 pkts = packet_create(npkts, tn, key);
1483 pkt_hit = &pkts[npkts - 1];
1484
1485 /* 働くおじさんを量産 */
1486 thread_create_event(event_ks_activated, 1);
1487 ks_activated = 1;
1488 nthreads = 0;
1489 if (code_cmp)
1490 {
1491 THREAD_TH_T h;
1492 int ots = -1;
1493 threads = calloc(2 * popcnt64(proc_mask), sizeof(*threads));
1494 for (i = 0; proc_mask; i++, proc_mask >>= 1)
1495 if (proc_mask & 1)
1496 {
1497 if (ots < 0)
1498 {
1499 /* 自分自身のスケジューリング
1500 こーゆー系のアプリは低めに設定するのが吉(かも) */
1501 #ifdef WIN32
1502 h = GetCurrentProcess();
1503 SetPriorityClass(h, BELOW_NORMAL_PRIORITY_CLASS);
1504 #endif
1505 #if defined(thread_set_priority)
1506 /* 心の隙間お埋めします */
1507 threads[nthreads].code = code;
1508 threads[nthreads].p_ev_ks_activated = &event_ks_activated;
1509 threads[nthreads].p_nidle = &nidle;
1510 threads[nthreads].pri = THREAD_PRIORITY_IDLE;
1511 thread_create(h, thread_crypt64, &threads[nthreads]);
1512 threads[nthreads].th = h;
1513 nthreads++;
1514 #endif
1515 if (!code_cmp)
1516 break;
1517
1518 /* 自分自身の残りの設定を、あとでやる */
1519 ots = i;
1520 }
1521 else
1522 {
1523 /* 他スレッドは、やや低めの優先度で。 */
1524 threads[nthreads].code = code;
1525 threads[nthreads].p_ev_ks_activated = &event_ks_activated;
1526 threads[nthreads].p_nidle = &nidle;
1527 #ifdef thread_set_priority
1528 threads[nthreads].pri = THREAD_PRIORITY_BELOW_NORMAL;
1529 #endif
1530 thread_create(h, thread_crypt64, &threads[nthreads]);
1531 #ifdef thread_set_priority
1532 threads[nthreads].th = h;
1533 #endif
1534 #ifdef thread_get_tid
1535 thread_set_affinity(h, i);
1536 #endif
1537 nthreads++;
1538 }
1539 }
1540 #ifdef thread_get_tid
1541 if (ots)
1542 thread_set_affinity(thread_get_tid(), ots);
1543 #endif
1544 }
1545
1546 if ((ofp = fopen("log.txt", "at")) == NULL)
1547 {
1548 perror("log.txt");
1549 return errno;
1550 }
1551
1552 setvbuf(ofp, NULL, _IONBF, BUFSIZ); /* XXX MSVCRT では _IOLBF が期待通りに動作しない */
1553
1554 mincnt = 0x7FFFFFFF;
1555 nblk_hit = nblk_total = 0;
1556 nap_hit = nap_total = 0;
1557 cr = 0;
1558 memset( &status, 0, sizeof( struct status ) );
1559 status.startTime = status.lastTime = usec();
1560 /* 探索ループだぞっと */
1561 for (;;)
1562 {
1563 struct PACKET_CRYPT64 *pkt_c;
1564 uint64_t cnt;
1565 int cnt1, cnt2;
1566 int k, kk;
1567
1568 /* 比較器候補(may be NULL)
1569 先にキューから取り出す */
1570 pkt_c = q_cmp[WRAP(rp_cmp, NQ_CMP)];
1571 if (pkt_c != NULL && WRAP(rp_cmp, NQ_CMP) != WRAP(wp_cmp, NQ_CMP))
1572 {
1573 pkt_c = LOCK_CASP(&q_cmp[WRAP(rp_cmp, NQ_CMP)], NULL, pkt_c);
1574 assert(pkt_c != NULL);
1575 LOCK_INC(&rp_cmp);
1576
1577 /* パケットを vacant に回しておく */
1578 pkts_vacant |= 1ULL << (pkt_c - pkts);
1579 }
1580
1581 /* Saltチェンジ待ち */
1582 if (!ks_activated)
1583 {
1584 ATOMWORD_T rp;
1585
1586 if (pkt_c == NULL)
1587 {
1588 if ((rp = rp_crypt,
1589 WRAP(rp, NQ_CRYPT) != WRAP(wp_crypt, NQ_CRYPT))
1590 && LOCK_CAS(&rp_crypt, rp + 1, rp) == rp)
1591 {
1592 /* !ks_activate 状態では、自らも要求キューをやっつけにいく */
1593 rp = WRAP(rp, NQ_CRYPT);
1594 pkt_c = q_crypt[rp];
1595 assert(pkt_c != NULL);
1596 pkt_c = LOCK_CASP(&q_crypt[rp], NULL, pkt_c);
1597 assert(pkt_c != NULL);
1598 assert(pkt_c != pkt_hit);
1599 CALL_CRYPT64(code,
1600 &pkt_c->key64,
1601 &pkt_c->param64);
1602
1603 /* パケットを vacant に回しておく */
1604 pkts_vacant |= 1ULL << (pkt_c - pkts);
1605 }
1606 else
1607 {
1608 /* やはりすることがないのでまったりと過ごす */
1609 if (nidle != nthreads)
1610 thread_sleep(1);
1611 }
1612 }
1613
1614 if (nidle == nthreads)
1615 {
1616 assert(WRAP(rp_crypt, NQ_CRYPT) == WRAP(wp_crypt, NQ_CRYPT));
1617 /* Salt チェンジが可能 */
1618 set_salt(code, crypt64_descs[0], key);
1619 if (nthreads)
1620 thread_signal_event(event_ks_activated);
1621 ks_activated = 1;
1622 }
1623 }
1624
1625 /* 鍵をキューにたたき込みまくる */
1626 if (!ks_activated)
1627 {
1628 /* 鍵を登録しない */
1629 ;
1630 }
1631 else for (i = npkts - 1; i >= 0; i--)
1632 if (pkts_vacant & (1ULL << i))
1633 {
1634 int j;
1635
1636 if (i == npkts - 1)
1637 {
1638 /* 前段で、働くおじさんから
1639 結果をもらっていたら、何もしない */
1640 if (pkt_c != NULL)
1641 continue;
1642 }
1643 else
1644 {
1645 /* 前段で取り出したばかりの
1646 働くおじさんは、尊重する */
1647 if (&pkts[i] == pkt_c)
1648 continue;
1649
1650 /* queue full の場合は見送る */
1651 if (WRAP(wp_crypt, NQ_CRYPT) == WRAP(rp_crypt - 16, NQ_CRYPT) /* XXX 16 はてきとう */
1652 || q_crypt[WRAP(wp_crypt, NQ_CRYPT)] != NULL)
1653 break;
1654 }
1655
1656 /* 鍵のセット */
1657 for (j = 0; j < 8; j++)
1658 {
1659 key_set64(&pkts[i].key64, j, key[j], key[j] ^ pkts[i].uk.key[j], 0);
1660 pkts[i].uk.key[j] = key[j];
1661 }
1662
1663 if (i == npkts - 1)
1664 {
1665 /* 次段で CRYPT64->CMP */
1666 assert(pkt_c == NULL);
1667 pkt_c = &pkts[i];
1668 assert(pkt_c == pkt_hit);
1669 }
1670 else
1671 {
1672 /* キューにたたき込む */
1673 while (LOCK_CASP(&q_crypt[WRAP(wp_crypt, NQ_CRYPT)], &pkts[i], NULL) != NULL)
1674 {
1675 /* 設計上はここに来ない */
1676 #if DEBUG>=1
1677 fprintf(stderr,
1678 "[XXX] q_crypt を汚してるのは誰だ? (rp=%3d, wp=%3d, v=%08X%08X)\n",
1679 (unsigned)WRAP(rp_crypt, NQ_CRYPT),
1680 (unsigned)WRAP(wp_crypt, NQ_CRYPT),
1681 (unsigned)(pkts_vacant >> 32),
1682 (unsigned)pkts_vacant);
1683 thread_sleep(1000);
1684 #endif
1685 thread_sleep(1);
1686 }
1687 LOCK_INC(&wp_crypt);
1688 pkts_vacant ^= 1ULL << i;
1689 assert(!(pkts_vacant & (1ULL << i))); /* 削れ */
1690 }
1691
1692 /* 鍵増加はこんなところに移動! */
1693 assert(ks_activated);
1694 /* MAKAI start */
1695 if (!key_inc(key, 6) && !key_inc(key, umeLen))
1696 /* MAKAI end */
1697 {
1698 /* 鍵のシャッフル
1699 q_crypt が捌けるまで、set_salt() はできない */
1700 #if DEBUG>=1
1701 fprintf(stderr, "********************************SHUFFLE!\n");
1702 #endif
1703 if (nthreads)
1704 thread_clear_event(event_ks_activated);
1705 key_reset(key, 0);
1706
1707 /* キューの鍵が捌けるまでアイドル状態に */
1708 ks_activated = 0;
1709
1710 /* スレッドをブーストして回る */
1711 #ifdef thread_set_priority
1712 for (j = 0; j < nthreads; j++)
1713 {
1714 assert(threads != NULL);
1715 thread_set_priority(threads[j].th, THREAD_PRIORITY_NORMAL);
1716 }
1717 #endif
1718
1719 /* ループ続行はもはや不要 */
1720 break;
1721 }
1722 }
1723
1724 /* することがなくなっている場合 */
1725 if (pkt_c == NULL)
1726 {
1727 assert(!ks_activated);
1728 continue;
1729 }
1730
1731 /* 呼ぶ!
1732 LR 初期化は、サブモジュール内で行うべし
1733 FASTCALL に準じた呼び出しのため、
1734 ホントはいろいろレジスタが破壊されるハズ…なんだが。 */
1735 if (pkt_c != pkt_hit)
1736 {
1737 assert(code_cmp != 0);
1738 cnt = CALL_CMP64(code + code_cmp,
1739 pkt_hit->param64.hit,
1740 pkt_c->param64.lr);
1741 }
1742 else
1743 {
1744 /* ようやく自スレッドで回せる */
1745 cnt = CALL_CRYPT64(code,
1746 &pkt_c->key64,
1747 &pkt_c->param64);
1748 if (code_cmp)
1749 cnt = CALL_CMP64(code + code_cmp,
1750 pkt_c->param64.hit,
1751 pkt_c->param64.lr);
1752 }
1753
1754 #if DEBUG>=1
1755 cnt2 = (int32_t)(cnt >> 32);
1756 cnt1 = (int32_t)cnt;
1757 if (mincnt > cnt1 && cnt1 > 0)
1758 {
1759 mincnt = cnt1;
1760 if (cr)
1761 fprintf(stderr, "\n");
1762 cr = 0;
1763 fprintf(stderr, "cycle=%6d/%6d\n", cnt1, cnt2);
1764 }
1765 #endif
1766
1767 /* ヒットしたときの処理
1768 key および lr は pkt_c に
1769 合致判定は pkt_hit に入っているハズ */
1770 xhash_loaded = 0;
1771 for (kk = 0; kk < N_ALU; kk++)
1772 {
1773 ALU_T t;
1774 if (!(kk & (N_ALU / N_Q - 1)))
1775 nblk_total++, xhash_loaded = 0;
1776
1777 t = pkt_hit->param64.hit[HIT_ANY].a[kk];
1778 if (!t)
1779 continue;
1780
1781 nap_total += ALU_BITS;
1782
1783 for (k = 0; k < ALU_BITS; k++)
1784 {
1785 static uint64_t xhash[64];
1786 char hash[16];
1787 uint8_t buf[32];
1788 struct timeb tb;
1789 struct tm *plt;
1790 /* MAKAI start */
1791 int hitLen;
1792 /* MAKAI end */
1793
1794 if (!(t & ((ALU_T)1 << k)))
1795 continue;
1796
1797 nap_hit++;
1798
1799 /* 転置 */
1800 if (!xhash_loaded)
1801 {
1802 nblk_hit++;
1803 CALL_TR64(&pkt_c->param64.lr[0][0].q[kk / (N_ALU / N_Q)], xhash);
1804 xhash_loaded = 1;
1805 }
1806
1807 /* 辞書を調べる */
1808 /* MAKAI hitLen 追加 */
1809 if (!((pkt_hit->param64.hit[HIT_BOOL].a[kk] & ((ALU_T)1 << k))
1810 || (hitLen = wdict_ishit(pkt_hit->param64.hit,
1811 kk, k,
1812 xhash[(ALU_BITS * kk + k) & 0x3F]))))
1813 continue;
1814
1815 /* ヒット時刻; 魔改造とちょっと違う */
1816 ftime(&tb);
1817 plt = localtime(&tb.time);
1818
1819 for (i = 1; i < 11; i++)
1820 {
1821 unsigned c = 0;
1822 c = (xhash[(ALU_BITS * kk + k) & 63] >> (6 * (i - 1))) & 0x3F; /* XXX */
1823 hash[i - 1] = C64[c];
1824 }
1825 hash[10] = 0;
1826
1827 memcpy(buf, pkt_c->uk.key, 8);
1828 buf[8] = buf[9] = 0;
1829 buf[7] = (buf[7] & -(1 << N_STRIDE) & 0x7F) + ALU_BITS * kk + k;
1830 if (translate(buf, 0, 1))
1831 {
1832 if (cr)
1833 fprintf(stderr, "\n");
1834 cr = 0;
1835 #if DEBUG>=1
1836 fprintf(stderr, "%3d:", pkt_c - pkts);
1837 #endif
1838 log_printf(ofp,
1839 "◆%s #%s"
1840 "\t%04d/%02d/%02d %02d:%02d:%02d.%03d"
1841 /* MAKAI start */
1842 "\t(%02X %02X %02X %02X %02X %02X %02X %02X/%02X) %02d\n",
1843 /* MAKAI end */
1844 hash,
1845 buf,
1846 plt->tm_year + 1900,
1847 plt->tm_mon + 1,
1848 plt->tm_mday,
1849 plt->tm_hour,
1850 plt->tm_min,
1851 plt->tm_sec,
1852 tb.millitm,
1853 buf[0], buf[1], buf[2], buf[3],
1854 buf[4], buf[5], buf[6], buf[7],
1855 /* MAKAI start */
1856 buf[8], hitLen);
1857 /* MAKAI end */
1858 }
1859 else
1860 {
1861 /* MAKAI start */
1862 log_printf( ofp, "◆%s 残念でした"
1863 "\t%04d/%02d/%02d %02d:%02d:%02d.%03d"
1864 "\t(%02X %02X %02X %02X %02X %02X %02X %02X/%02X) %02d\n",
1865 hash,
1866 plt->tm_year + 1900, plt->tm_mon + 1, plt->tm_mday,
1867 plt->tm_hour, plt->tm_min, plt->tm_sec, tb.millitm,
1868 buf[0], buf[1], buf[2], buf[3],
1869 buf[4], buf[5], buf[6], buf[7], buf[8], hitLen );
1870 /* MAKAI end */
1871
1872 #if DEBUG>=1
1873 if (cr)
1874 fprintf(stderr, "\n");
1875 cr = 0;
1876 fprintf(stderr, "%3d:", pkt_c - pkts);
1877 log_printf(ofp,
1878 "◆%s (%02X %02X %02X %02X %02X %02X %02X %02X )\n",
1879 hash,
1880 buf[0], buf[1], buf[2], buf[3],
1881 buf[4], buf[5], buf[6], buf[7]);
1882 #endif
1883 }
1884 }
1885 }
1886
1887 /* 速度計測 */
1888 status.loop += N_ALU * ALU_BITS;
1889 if (status.loop>= status.lastloop + upd_int
1890 && (curTime = usec()) != status.lastTime)
1891 {
1892 uint64_t diffTime;
1893 int a, b, c;
1894
1895 /* 通算(単位 ktrips/sec) */
1896 diffTime = curTime - status.startTime;
1897 a = status.loop / ((1000 / USEC_SEC) * diffTime);
1898
1899 /* 区間(単位 trips/sec) */
1900 diffTime = curTime - status.lastTime;
1901 b = USEC_SEC * (status.loop - status.lastloop) / diffTime;
1902
1903 /* 予測 */
1904 c = UPDATE_INTERVAL * b;
1905
1906 /* 立ち上がりなど、誤差があり upd_int が小さすぎたときは
1907 いきなり全補正せず 1 秒(==b)づつ収斂させる。 */
1908 upd_int = (upd_int + b < c
1909 ? upd_int + b
1910 : c);
1911
1912 status.lastTime = curTime;
1913 status.lastloop = status.loop;
1914 #if DEBUG>=1
1915 fprintf(stderr,
1916 "%5d/%5d(%3d%%)",
1917 nblk_hit, nblk_total, 100 * nblk_hit / nblk_total);
1918 nblk_hit = nblk_total = 0;
1919 if (nap_total)
1920 fprintf(stderr,
1921 " %5d/%5d(%3d%%)",
1922 nap_hit, nap_total, 100 * nap_hit / nap_total);
1923 else
1924 fprintf(stderr,
1925 " -----/-----(---%%)");
1926 nap_hit = nap_total = 0;
1927 #endif
1928 fprintf( stderr,
1929 "%6dktrips/s [%6d.%03dktrips/s]\r",
1930 a, b / 1000, b % 1000 );
1931 cr++;
1932 }
1933 }
1934
1935 return 0;
1936 }
1937
1938 /*
1939 * Local Variables:
1940 * tab-width: 4
1941 * End:
1942 *
1943 * EOF */

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Rev URL

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26