Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 197 - (hide 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 chapuni 1 /***********************************************************************
2     *
3 chapuni 26 * file: mty.c
4 chapuni 1 *
5 chapuni 2 * まあ、待て屋。
6 chapuni 1 *
7     * $Id$
8     *
9     */
10    
11     #include <assert.h>
12     #include <ctype.h>
13 chapuni 24 #include <errno.h>
14 chapuni 9 #include <limits.h>
15 chapuni 24 #include <stdarg.h>
16 chapuni 20 #include <stddef.h>
17 chapuni 1 #include <stdio.h>
18     #include <stdlib.h>
19     #include <string.h>
20     #include <time.h>
21 notanpe 192 #include <sys/timeb.h>
22 notanpe 148 #include <sys/types.h>
23 chapuni 10
24 notanpe 197 /* MAKAI start */
25     #include <unistd.h>
26     #include <libgen.h>
27     /* MAKAI end */
28    
29 chapuni 10 #if defined(WIN32)
30    
31     #include <windows.h>
32 notanpe 148 #include <process.h>
33 chapuni 10
34     #elif defined(__GNUC__)
35    
36     #include <sys/time.h>
37    
38     #endif
39    
40 chapuni 26 #include "config.h"
41 chapuni 39 #include "cp932.h"
42 chapuni 1 #include "crypt64.h"
43 chapuni 41 #include "desconst.h"
44 chapuni 46 #include "expr_parse.h"
45     #include "scoreboard.h"
46     #include "synth.h"
47 chapuni 74 #include "tr64.h"
48 chapuni 26 #include "translate.h"
49 notanpe 148 #include "util.h"
50 chapuni 99 #include "wdict.h"
51 chapuni 1
52 chapuni 39 #if USE_DT
53     #include "dt4.h"
54     #endif
55    
56 notanpe 197 /* 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 notanpe 192 /* CRYPT64 記述子 */
68     static
69     struct CRYPT64_DESC const *const crypt64_descs[] =
70     {
71     &crypt64_desc,
72     };
73    
74 chapuni 1 /* 鍵クラス */
75 chapuni 41 static
76 chapuni 1 struct
77     {
78 notanpe 148 unsigned short map[256];
79 chapuni 1 } kcls[8 + 8];
80    
81 chapuni 26 /* 拡張鍵クラス */
82 chapuni 1 #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 notanpe 148 key_make_map(uint8_t *key, int n)
97 chapuni 1 {
98     int i, j;
99     unsigned c = kcls[n].map[key[n]];
100    
101 chapuni 39 #if USE_DT
102 chapuni 1 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 chapuni 39 #endif
191 chapuni 1
192     /* 最後の部分は class map を生成する必要ナシ */
193     if (n >= 6)
194     return;
195    
196     for (i = 0; i < 256; i++)
197     {
198 chapuni 25 unsigned bm = 0;
199 chapuni 1 #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 chapuni 39 #if USE_DT
235 chapuni 1 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 chapuni 39 #endif
266 chapuni 1
267     /* マップから文字を拾ってセット */
268     unsigned
269     key_set(int n, unsigned ch)
270     {
271     int cnt = 0, i;
272    
273 chapuni 39 #if USE_DT
274 chapuni 1 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 chapuni 39 #endif
290 chapuni 1
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 chapuni 6 int i, j;
339 chapuni 1 if (!((vk | sk) & 0x7F))
340     return;
341    
342     for (i = 0; i < 7; i++)
343     {
344 chapuni 6 if (n == 7 && i < N_STRIDE) continue;
345 chapuni 1 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 chapuni 6 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 chapuni 1 }
357     else
358     {
359     assert(o >= 28);
360     assert(o < 56);
361 chapuni 6 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 chapuni 1 }
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 chapuni 10 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 chapuni 1 }
379     else
380     {
381     assert(o >= 28);
382     assert(o < 56);
383 chapuni 10 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 chapuni 1 }
388     }
389     }
390     }
391    
392     /* 指定されたクラスの開始値にリセット
393     直前の文字のクラスに縛られる */
394     int
395 notanpe 148 key_reset(uint8_t *key, int n)
396 chapuni 1 {
397 notanpe 197 /* 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 chapuni 1 if (n >= 8)
410     return 1;
411     if (n == 7)
412     {
413     key[7] = 0;
414     return 1;
415     }
416    
417 notanpe 197 /* MAKAI start */
418     if (n >= umeLen)
419 chapuni 1 key[n] = key_set(n, 0);
420 notanpe 197 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 chapuni 1
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 notanpe 148 key_make_map(key, n);
435 chapuni 1
436 notanpe 148 return key_reset(key, n + 1);
437 chapuni 1 }
438    
439     /* 指定された鍵空間の中で、キーをひとつ進める
440     安全にインクリメントできた場合 true を返す */
441     static
442     int
443 notanpe 148 key_inc(uint8_t *key, int n)
444 chapuni 1 {
445     if (n >= 8)
446     return 0;
447     else if (n == 7)
448     {
449 chapuni 6 /* 最後のバイト */
450 notanpe 148 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 chapuni 1 }
458 notanpe 148 else if (key_inc(key, n + 1)
459 chapuni 1 /*
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 chapuni 39 #if USE_DT
475 chapuni 1 /* 辞書語はインクリメントしていい約束にする */
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 chapuni 39 #endif
564 chapuni 1
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 notanpe 148 {
581     key[n] = 0xFF; /* 次に突入させないため */
582     return 0;
583     }
584 chapuni 1 }
585    
586     if (kcls[n].map[key[n]])
587     {
588 notanpe 148 key_make_map(key, n);
589     key_reset(key, n + 1);
590 chapuni 1 return 1;
591     }
592     }
593     }
594    
595     /* 鍵を完全にリセットする
596     Saltもセットし直す */
597     static
598     void
599 notanpe 148 key_init(uint8_t *key)
600 chapuni 1 {
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 notanpe 148 key_reset(key, 0);
659 chapuni 1 }
660    
661     /***************************************************************
662     *
663 chapuni 122 * 固定キーの生成
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 chapuni 123 #if DEBUG>=2
685 chapuni 122 printf("%d:%d->%2d: %08X%08X\n",
686     N_Q, i, o,
687     (unsigned)(m >> 32),
688     (unsigned)m);
689 chapuni 123 #endif
690 chapuni 122 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 chapuni 1 * Salt のセット
709     * オペランドのオフセットを書き換えて回ってるので注意
710     *
711     */
712    
713     void
714 notanpe 148 set_salt(CODE_T *code,
715 notanpe 192 struct CRYPT64_DESC const *desc,
716 notanpe 148 uint8_t const *k)
717 chapuni 1 {
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 chapuni 6 //printf("Salt %d:%d %+3d:%+3d",
741     printf("Salt %d:%d %08lX:%08lX",
742 chapuni 1 i, j,
743 notanpe 192 LSALT(desc, code, 0, i, j, 0),
744     LSALT(desc, code, 0, i, j, 24));
745 chapuni 1 #endif
746     if (s & (1 << j))
747     {
748 notanpe 192 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 chapuni 1 }
751     else
752     {
753 notanpe 192 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 chapuni 1 }
756 notanpe 192 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 chapuni 1 #if DEBUG>=2
759 chapuni 6 //printf(" => %+3d:%+3d\n",
760     printf(" => %08lX:%08lX\n",
761 notanpe 192 LSALT(desc, code, 0, i, j, 0),
762     LSALT(desc, code, 0, i, j, 24));
763 chapuni 1 #endif
764     }
765     }
766     }
767    
768 notanpe 192 #define USEC_SEC 1000 /* 1秒 */
769    
770 chapuni 1 static
771 notanpe 192 uint64_t
772 notanpe 148 usec(void)
773 notanpe 119 {
774 notanpe 120 uint32_t sec, msec;
775    
776 notanpe 119 #if !defined(WIN32)
777     struct timeval tv;
778     gettimeofday(&tv, NULL);
779 notanpe 120 sec = tv.tv_sec;
780 notanpe 192 msec = tv.tv_usec / (1000000 / USEC_SEC);
781 notanpe 119 #else
782     struct timeb tm;
783     ftime(&tm);
784 notanpe 120 sec = tm.time;
785 notanpe 192 msec = tm.millitm / (1000 / USEC_SEC);
786 notanpe 119 #endif
787 notanpe 120
788 notanpe 192 return (uint64_t)USEC_SEC * sec + msec;
789 notanpe 119 }
790    
791     static
792 chapuni 24 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 chapuni 1 /***************************************************************
808     *
809 notanpe 192 * CPU capabilities を取得
810     * [XXX] あまりにも古いプロセッサのことは考えない。
811 chapuni 1 *
812 notanpe 192 * a[4] = {EAX,EBX,ECX,EDX}
813     *
814 chapuni 1 */
815    
816 notanpe 192 #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 notanpe 148 {
835 notanpe 192 unsigned a, b, c, d;
836     cpuid(1, a, b, c, d);
837     return d;
838     }
839 chapuni 1
840 notanpe 148 static
841 notanpe 192 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 notanpe 148 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 notanpe 192 intptr_t a = 128;
864 notanpe 148 struct PACKET_CRYPT64 *pkts;
865     assert(IS_POWER2(sizeof(struct PACKET_CRYPT64)));
866     assert(n >= 1);
867    
868 notanpe 192 siz = (a - 1
869 notanpe 148 + (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 notanpe 192 + a - 1)
875     & -a);
876 notanpe 148 #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 notanpe 192 int j, k;
890 notanpe 148
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 notanpe 192 for (k = 0; k < N_ALU; k++)
901     pkts[i].key64.ks[j].a[k] = sizeof(WS_T) * ks_ls[j];
902 notanpe 148
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 chapuni 1 int
983 notanpe 148 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 notanpe 192 #elif defined(_POSIX_SOURCE)
994 notanpe 148
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 notanpe 192 THREAD_EV_T *p_ev_ks_activated;
1128 notanpe 148 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 notanpe 192 /* 寝た */
1232 notanpe 148 if (tmo == THREAD_INFINITE)
1233     {
1234     LOCK_INC(param->p_nidle);
1235     }
1236    
1237     /* 要求待ち */
1238 notanpe 192 r = thread_wait_event(*param->p_ev_ks_activated, tmo);
1239 notanpe 148
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 notanpe 197 /* 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 notanpe 148 /***************************************************************
1324     *
1325     * メインループとか
1326     *
1327     */
1328    
1329     int
1330 chapuni 1 main(int argc, char *argv[])
1331     {
1332 chapuni 74 int i;
1333 chapuni 1 int mincnt;
1334 chapuni 77 int nblk_hit, nblk_total;
1335 chapuni 84 int nap_hit, nap_total;
1336 notanpe 148 CODE_T *code = NULL;
1337     off_t code_cmp;
1338 chapuni 1 FILE *ofp;
1339 chapuni 46 FILE *sfp; /* scoreboard */
1340     struct ITREE *root_expr;
1341 notanpe 148 uint64_t proc_mask;
1342     int ks_activated;
1343 notanpe 192 static THREAD_EV_T event_ks_activated;
1344 notanpe 148 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 chapuni 1 int cr;
1352    
1353 notanpe 148 /* 鍵文字列 */
1354     uint8_t key[8 + 8];
1355    
1356 chapuni 74 int xhash_loaded;
1357    
1358 notanpe 119 #define UPDATE_INTERVAL 8 /* 速度表示の間隔 秒 */
1359 notanpe 115 struct status {
1360 notanpe 192 uint64_t startTime; /* 開始時刻 ミリ秒 */
1361     uint64_t lastTime; /* 最後に表示した時刻 ミリ秒 */
1362     uint64_t loop; /* 総検索個数 */
1363     uint64_t lastloop; /* 最後に表示した時の loop */
1364 notanpe 115 } status;
1365 notanpe 192 uint64_t curTime;
1366     uint32_t upd_int = 0;
1367 chapuni 1
1368 notanpe 193 /* MAKAI start */
1369 notanpe 197 /* 実際の処理とあっていないコメントを削除 */
1370    
1371 notanpe 193 #if defined(WIN32)
1372     SetPriorityClass( GetCurrentProcess(), IDLE_PRIORITY_CLASS );
1373     #endif
1374 notanpe 197
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 notanpe 193 /* MAKAI end */
1416    
1417 notanpe 192 if (!cpuid_issupported())
1418 chapuni 1 {
1419 notanpe 192 fprintf(stderr, "この環境で走らせることが想定されていません。\n");
1420     exit(1);
1421 chapuni 1 }
1422    
1423 chapuni 10 assert((1 << N_STRIDE) == N_ALU * ALU_BITS);
1424    
1425 chapuni 46 /* タゲ読み込み */
1426     root_expr = expr_parse("target.txt");
1427 chapuni 2
1428 notanpe 148 /* コードを生成・展開
1429     起動予定スレッド数に応じて
1430     生成するコードを変える */
1431 chapuni 46 sfp = scoreboard_open();
1432 notanpe 192 fwrite(crypt64_descs[0]->pro, 1, crypt64_descs[0]->cmp_pro - crypt64_descs[0]->pro, sfp); /* prologue & コアループ */
1433 notanpe 197
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 notanpe 148 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 notanpe 192 fwrite(crypt64_descs[0]->ep, 1, crypt64_descs[0]->ep_end - crypt64_descs[0]->ep, sfp); /* epilogue */
1458 chapuni 2
1459 notanpe 148 /* 比較器のみを生成(前半) */
1460     code_cmp = ftell(sfp);
1461     fseek(sfp, (-code_cmp) & 63, SEEK_CUR);
1462     code_cmp = ftell(sfp);
1463 notanpe 192 fwrite(crypt64_descs[0]->pro, 1, crypt64_descs[0]->crypt - crypt64_descs[0]->pro, sfp); /* prologue */
1464 notanpe 148 npkts = 64;
1465     pkts_vacant = (uint64_t)-1; /* (1 << 64) - 1 を計算したくない */
1466     }
1467    
1468     /* 比較部を生成 */
1469 notanpe 192 fwrite(crypt64_descs[0]->cmp_pro, 1, crypt64_descs[0]->cmp_ep - crypt64_descs[0]->cmp_pro, sfp); /* 比較器準備 */
1470 notanpe 148 tn = synth_synthesize(sfp, root_expr);
1471 notanpe 192 fwrite(crypt64_descs[0]->cmp_ep, 1, crypt64_descs[0]->ep_end - crypt64_descs[0]->cmp_ep, sfp); /* epilogue */
1472 notanpe 148
1473 chapuni 46 /* コードをメモリに貼り付ける */
1474     code = scoreboard_map(sfp);
1475 chapuni 1
1476     /* キーの初期化 */
1477 notanpe 192 srand(time(NULL));
1478 notanpe 148 key_init(key);
1479 notanpe 192 set_salt(code, crypt64_descs[0], key);
1480 chapuni 1
1481 notanpe 148 /* 演算パケットを作成 */
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 chapuni 1 #endif
1505 notanpe 148 #if defined(thread_set_priority)
1506     /* 心の隙間お埋めします */
1507     threads[nthreads].code = code;
1508 notanpe 192 threads[nthreads].p_ev_ks_activated = &event_ks_activated;
1509 notanpe 148 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 chapuni 1
1518 notanpe 148 /* 自分自身の残りの設定を、あとでやる */
1519     ots = i;
1520     }
1521     else
1522     {
1523     /* 他スレッドは、やや低めの優先度で。 */
1524     threads[nthreads].code = code;
1525 notanpe 192 threads[nthreads].p_ev_ks_activated = &event_ks_activated;
1526 notanpe 148 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 chapuni 24 if ((ofp = fopen("log.txt", "at")) == NULL)
1547     {
1548     perror("log.txt");
1549     return errno;
1550     }
1551 chapuni 1
1552 chapuni 24 setvbuf(ofp, NULL, _IONBF, BUFSIZ); /* XXX MSVCRT では _IOLBF が期待通りに動作しない */
1553    
1554 chapuni 1 mincnt = 0x7FFFFFFF;
1555 chapuni 77 nblk_hit = nblk_total = 0;
1556 chapuni 84 nap_hit = nap_total = 0;
1557 chapuni 1 cr = 0;
1558 notanpe 120 memset( &status, 0, sizeof( struct status ) );
1559 notanpe 119 status.startTime = status.lastTime = usec();
1560 chapuni 1 /* 探索ループだぞっと */
1561     for (;;)
1562     {
1563 notanpe 148 struct PACKET_CRYPT64 *pkt_c;
1564 chapuni 121 uint64_t cnt;
1565     int cnt1, cnt2;
1566 chapuni 1 int k, kk;
1567    
1568 notanpe 148 /* 比較器候補(may be NULL)
1569     先にキューから取り出す */
1570     pkt_c = q_cmp[WRAP(rp_cmp, NQ_CMP)];
1571 notanpe 192 if (pkt_c != NULL && WRAP(rp_cmp, NQ_CMP) != WRAP(wp_cmp, NQ_CMP))
1572 chapuni 1 {
1573 notanpe 148 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 chapuni 1 }
1580    
1581 notanpe 148 /* Saltチェンジ待ち */
1582     if (!ks_activated)
1583     {
1584 notanpe 192 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 notanpe 148 if (nidle == nthreads)
1615     {
1616     assert(WRAP(rp_crypt, NQ_CRYPT) == WRAP(wp_crypt, NQ_CRYPT));
1617     /* Salt チェンジが可能 */
1618 notanpe 192 set_salt(code, crypt64_descs[0], key);
1619     if (nthreads)
1620 notanpe 148 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 notanpe 192 if (WRAP(wp_crypt, NQ_CRYPT) == WRAP(rp_crypt - 16, NQ_CRYPT) /* XXX 16 はてきとう */
1652 notanpe 148 || 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 notanpe 197 /* MAKAI start */
1695     if (!key_inc(key, 6) && !key_inc(key, umeLen))
1696     /* MAKAI end */
1697 notanpe 148 {
1698     /* 鍵のシャッフル
1699     q_crypt が捌けるまで、set_salt() はできない */
1700     #if DEBUG>=1
1701     fprintf(stderr, "********************************SHUFFLE!\n");
1702     #endif
1703 notanpe 192 if (nthreads)
1704     thread_clear_event(event_ks_activated);
1705 notanpe 148 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 chapuni 14 /* 呼ぶ!
1732     LR 初期化は、サブモジュール内で行うべし
1733     FASTCALL に準じた呼び出しのため、
1734     ホントはいろいろレジスタが破壊されるハズ…なんだが。 */
1735 notanpe 148 if (pkt_c != pkt_hit)
1736     {
1737 notanpe 192 assert(code_cmp != 0);
1738 notanpe 148 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 chapuni 42
1754 chapuni 46 #if DEBUG>=1
1755 chapuni 121 cnt2 = (int32_t)(cnt >> 32);
1756     cnt1 = (int32_t)cnt;
1757     if (mincnt > cnt1 && cnt1 > 0)
1758 chapuni 1 {
1759 chapuni 121 mincnt = cnt1;
1760 chapuni 1 if (cr)
1761     fprintf(stderr, "\n");
1762     cr = 0;
1763 chapuni 121 fprintf(stderr, "cycle=%6d/%6d\n", cnt1, cnt2);
1764 chapuni 1 }
1765 chapuni 46 #endif
1766 chapuni 1
1767 notanpe 148 /* ヒットしたときの処理
1768     key および lr は pkt_c に
1769     合致判定は pkt_hit に入っているハズ */
1770 chapuni 74 xhash_loaded = 0;
1771 chapuni 6 for (kk = 0; kk < N_ALU; kk++)
1772 chapuni 1 {
1773 chapuni 6 ALU_T t;
1774 chapuni 84 if (!(kk & (N_ALU / N_Q - 1)))
1775 chapuni 77 nblk_total++, xhash_loaded = 0;
1776 chapuni 9
1777 notanpe 148 t = pkt_hit->param64.hit[HIT_ANY].a[kk];
1778 chapuni 1 if (!t)
1779     continue;
1780 chapuni 9
1781 chapuni 84 nap_total += ALU_BITS;
1782    
1783 chapuni 6 for (k = 0; k < ALU_BITS; k++)
1784 chapuni 1 {
1785 chapuni 74 static uint64_t xhash[64];
1786 chapuni 1 char hash[16];
1787 notanpe 148 uint8_t buf[32];
1788 notanpe 192 struct timeb tb;
1789     struct tm *plt;
1790 notanpe 196 /* MAKAI start */
1791     int hitLen;
1792     /* MAKAI end */
1793 chapuni 9
1794     if (!(t & ((ALU_T)1 << k)))
1795 chapuni 1 continue;
1796 chapuni 9
1797 chapuni 84 nap_hit++;
1798    
1799 chapuni 74 /* 転置 */
1800     if (!xhash_loaded)
1801     {
1802 chapuni 77 nblk_hit++;
1803 notanpe 148 CALL_TR64(&pkt_c->param64.lr[0][0].q[kk / (N_ALU / N_Q)], xhash);
1804 chapuni 74 xhash_loaded = 1;
1805     }
1806    
1807     /* 辞書を調べる */
1808 notanpe 196 /* MAKAI hitLen 追加 */
1809 notanpe 148 if (!((pkt_hit->param64.hit[HIT_BOOL].a[kk] & ((ALU_T)1 << k))
1810 notanpe 196 || (hitLen = wdict_ishit(pkt_hit->param64.hit,
1811 chapuni 99 kk, k,
1812 notanpe 196 xhash[(ALU_BITS * kk + k) & 0x3F]))))
1813 chapuni 74 continue;
1814    
1815 notanpe 192 /* ヒット時刻; 魔改造とちょっと違う */
1816     ftime(&tb);
1817     plt = localtime(&tb.time);
1818    
1819 chapuni 1 for (i = 1; i < 11; i++)
1820     {
1821     unsigned c = 0;
1822 chapuni 74 c = (xhash[(ALU_BITS * kk + k) & 63] >> (6 * (i - 1))) & 0x3F; /* XXX */
1823     hash[i - 1] = C64[c];
1824 chapuni 1 }
1825     hash[10] = 0;
1826    
1827 notanpe 148 memcpy(buf, pkt_c->uk.key, 8);
1828 chapuni 1 buf[8] = buf[9] = 0;
1829 chapuni 10 buf[7] = (buf[7] & -(1 << N_STRIDE) & 0x7F) + ALU_BITS * kk + k;
1830 chapuni 1 if (translate(buf, 0, 1))
1831     {
1832     if (cr)
1833     fprintf(stderr, "\n");
1834     cr = 0;
1835 notanpe 148 #if DEBUG>=1
1836     fprintf(stderr, "%3d:", pkt_c - pkts);
1837     #endif
1838 chapuni 24 log_printf(ofp,
1839 notanpe 192 "◆%s #%s"
1840     "\t%04d/%02d/%02d %02d:%02d:%02d.%03d"
1841 notanpe 196 /* MAKAI start */
1842     "\t(%02X %02X %02X %02X %02X %02X %02X %02X/%02X) %02d\n",
1843     /* MAKAI end */
1844 chapuni 24 hash,
1845     buf,
1846 notanpe 192 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 chapuni 24 buf[0], buf[1], buf[2], buf[3],
1854     buf[4], buf[5], buf[6], buf[7],
1855 notanpe 196 /* MAKAI start */
1856     buf[8], hitLen);
1857     /* MAKAI end */
1858 chapuni 1 }
1859     else
1860     {
1861 notanpe 193 /* MAKAI start */
1862     log_printf( ofp, "◆%s 残念でした"
1863     "\t%04d/%02d/%02d %02d:%02d:%02d.%03d"
1864 notanpe 196 "\t(%02X %02X %02X %02X %02X %02X %02X %02X/%02X) %02d\n",
1865 notanpe 193 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 notanpe 196 buf[4], buf[5], buf[6], buf[7], buf[8], hitLen );
1870 notanpe 193 /* MAKAI end */
1871    
1872 notanpe 192 #if DEBUG>=1
1873 chapuni 1 if (cr)
1874     fprintf(stderr, "\n");
1875     cr = 0;
1876 notanpe 148 fprintf(stderr, "%3d:", pkt_c - pkts);
1877 chapuni 24 log_printf(ofp,
1878 notanpe 192 "◆%s (%02X %02X %02X %02X %02X %02X %02X %02X )\n",
1879 chapuni 24 hash,
1880     buf[0], buf[1], buf[2], buf[3],
1881 notanpe 192 buf[4], buf[5], buf[6], buf[7]);
1882     #endif
1883 chapuni 1 }
1884     }
1885     }
1886    
1887 notanpe 192 /* 速度計測 */
1888 notanpe 115 status.loop += N_ALU * ALU_BITS;
1889 notanpe 192 if (status.loop>= status.lastloop + upd_int
1890     && (curTime = usec()) != status.lastTime)
1891 chapuni 1 {
1892 notanpe 192 uint64_t diffTime;
1893 notanpe 120 int a, b, c;
1894 notanpe 119
1895 notanpe 192 /* 通算(単位 ktrips/sec) */
1896     diffTime = curTime - status.startTime;
1897     a = status.loop / ((1000 / USEC_SEC) * diffTime);
1898    
1899     /* 区間(単位 trips/sec) */
1900 notanpe 120 diffTime = curTime - status.lastTime;
1901 notanpe 192 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 notanpe 120 status.lastTime = curTime;
1913     status.lastloop = status.loop;
1914 chapuni 77 #if DEBUG>=1
1915 notanpe 119 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 chapuni 77 #endif
1928 notanpe 119 fprintf( stderr,
1929 notanpe 120 "%6dktrips/s [%6d.%03dktrips/s]\r",
1930     a, b / 1000, b % 1000 );
1931 notanpe 192 cr++;
1932 chapuni 1 }
1933     }
1934    
1935     return 0;
1936     }
1937    
1938 chapuni 2 /*
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