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