1 /* ----------------------------------------------------------------------------------------------- */
2 /* MHash-384 - Generate tables utility program */
3 /* Copyright(c) 2016 LoRd_MuldeR <mulder2@gmx.de> */
5 /* Permission is hereby granted, free of charge, to any person obtaining a copy of this software */
6 /* and associated documentation files(the "Software"), to deal in the Software without */
7 /* restriction, including without limitation the rights to use, copy, modify, merge, publish, */
8 /* distribute, sublicense, and / or sell copies of the Software, and to permit persons to whom the */
9 /* Software is furnished to do so, subject to the following conditions: */
11 /* The above copyright notice and this permission notice shall be included in all copies or */
12 /* substantial portions of the Software. */
14 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING */
15 /* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
16 /* NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, */
17 /* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
18 /* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
19 /* ----------------------------------------------------------------------------------------------- */
22 #include "thread_utils.h"
32 //-----------------------------------------------------------------------------
34 //-----------------------------------------------------------------------------
38 #define DISTANCE_MIN 180
39 #define DISTANCE_MAX DISTANCE_MIN + 32
41 #define THREAD_COUNT 8
43 #define ROW_NUM (UINT8_MAX+2) /*total number of rows*/
44 #define ROW_LEN (HASH_LEN / CHAR_BIT) /*number of bits per row*/
46 #define __DISTANCE_STR(X) #X
47 #define _DISTANCE_STR(X) __DISTANCE_STR(X)
48 #define DISTANCE_STR _DISTANCE_STR(DISTANCE_MIN)
50 #define MAGIC_NUMBER 0X3C6058A7C1132CB2ui64
52 //-----------------------------------------------------------------------------
54 //-----------------------------------------------------------------------------
56 static uint8_t g_table[ROW_NUM][ROW_LEN];
57 static uint8_t g_thread_buffer[THREAD_COUNT][ROW_LEN];
59 static size_t g_spinpos = 0;
60 static char SPINNER[4] = { '/', '-', '\\', '|' };
62 //-----------------------------------------------------------------------------
64 //-----------------------------------------------------------------------------
67 static inline bool check_distance_rows(const size_t index_1, const size_t index_2)
69 const uint32_t dist = hamming_distance(&g_table[index_1][0], &g_table[index_2][0], ROW_LEN);
70 return (dist <= DISTANCE_MAX) && (dist >= DISTANCE_MIN);
73 static inline bool check_distance_next(const size_t index, const uint8_t *const row_buffer)
75 for (size_t k = 0; k < index; k++)
77 const uint32_t dist = hamming_distance(&g_table[k][0], row_buffer, ROW_LEN);
78 if ((dist > DISTANCE_MAX) || (dist < DISTANCE_MIN))
86 static dump_table(FILE *out)
88 fputs("uint8_t MHASH_384_TABLE_XOR[UINT8_MAX+2][MHASH_384_LEN] =\n{\n", out);
89 for (size_t i = 0; i < ROW_NUM; i++)
92 for (size_t j = 0; j < ROW_LEN; j++)
98 fprintf(out, "0x%02X", g_table[i][j]);
100 fprintf(out, " }%s /*%02X*/\n", (i != (ROW_NUM - 1)) ? "," : " ", (uint32_t)(i % 0x100));
105 //-----------------------------------------------------------------------------
107 //-----------------------------------------------------------------------------
114 pthread_mutex_t *mutex;
119 static void* thread_main(void *const param)
121 const thread_data_t *const data = ((const thread_data_t*)param);
122 uint16_t counter = 0, reseed = 0;
125 if ((++counter) == 0)
127 if (SEM_TRYWAIT(data->stop))
131 if (((++reseed) % 997U) == 0)
133 rand_init(data->rand, make_seed());
138 rand_next_bytes(data->rand, data->row_buffer, ROW_LEN);
142 invert_byte_buffer(data->row_buffer, ROW_LEN);
145 while (!check_distance_next(data->index, data->row_buffer));
147 MUTEX_LOCK(data->mutex);
148 if (SEM_TRYWAIT(data->stop))
150 MUTEX_UNLOCK(data->mutex);
154 SEM_POST(data->stop, THREAD_COUNT);
155 MUTEX_UNLOCK(data->mutex);
156 return data->row_buffer; /*success*/
159 static void* thread_spin(void *const param)
161 unsigned long delay = 0;
162 sem_t *const stop = ((sem_t*)param);
165 if (SEM_TRYWAIT(stop))
172 printf("\b\b\b[%c]", SPINNER[g_spinpos]);
173 g_spinpos = (g_spinpos + 1) % 4;
177 delay = (delay > 0) ? (2 * delay) : 1;
182 //-----------------------------------------------------------------------------
184 //-----------------------------------------------------------------------------
186 static bool save_table_data(const wchar_t *const filename, const size_t rows_completed_in)
188 FILE *const file = _wfopen(filename, L"wb");
192 const uint64_t magic_number = MAGIC_NUMBER;
193 const uint32_t hash_len = HASH_LEN, distance_min = DISTANCE_MIN, distance_max = DISTANCE_MAX, rows_completed = (uint32_t)rows_completed_in;
194 fwrite(&magic_number, sizeof(uint64_t), 1, file);
195 fwrite(&hash_len, sizeof(uint32_t), 1, file);
196 fwrite(&distance_min, sizeof(uint32_t), 1, file);
197 fwrite(&distance_max, sizeof(uint32_t), 1, file);
198 fwrite(&rows_completed, sizeof(uint32_t), 1, file);
199 for (uint32_t i = 0; i < rows_completed; ++i)
201 const uint32_t checksum = adler32(&g_table[i][0], ROW_LEN);
202 fwrite(&checksum, sizeof(uint32_t), 1, file);
203 fwrite(&g_table[i][0], sizeof(uint8_t), ROW_LEN, file);
207 printf("ERROR: Failed to write table data!\n");
215 printf("ERROR: Failed to open table file for writing!\n");
220 static bool load_table_data(const wchar_t *const filename, size_t *const rows_completed_out)
222 FILE *const file = _wfopen(filename, L"rb");
226 uint64_t magic_number;
227 uint32_t hash_len, distance_min, distance_max, rows_completed;
228 fread(&magic_number, sizeof(uint64_t), 1, file);
229 fread(&hash_len, sizeof(uint32_t), 1, file);
230 fread(&distance_min, sizeof(uint32_t), 1, file);
231 fread(&distance_max, sizeof(uint32_t), 1, file);
232 fread(&rows_completed, sizeof(uint32_t), 1, file);
233 if (ferror(file) || feof(file))
235 printf("ERROR: Failed to read the table header!\n");
239 if (magic_number != MAGIC_NUMBER)
241 printf("ERROR: Table file format could not be recognized!\n");
245 if ((hash_len != HASH_LEN) || (distance_min != DISTANCE_MIN) || (distance_max != DISTANCE_MAX) || (rows_completed > ROW_NUM))
247 printf("ERROR: Table properties are incompatibe with this instance!\n");
251 for (size_t i = 0; i < rows_completed; ++i)
253 uint32_t checksum_expected;
254 if ((fread(&checksum_expected, sizeof(uint32_t), 1, file) != 1) || (fread(&g_table[i][0], sizeof(uint8_t), ROW_LEN, file) != ROW_LEN))
256 printf("ERROR: Failed to read table data from file!\n");
260 if (adler32(&g_table[i][0], ROW_LEN) != checksum_expected)
262 printf("ERROR: Table checksum does *not* match table contents!\n");
266 for (size_t j = 0; j < i; j++)
268 if (!check_distance_rows(i, j))
270 printf("ERROR: Table distance verification has failed!\n");
278 if (success && rows_completed_out)
280 *rows_completed_out = (size_t)rows_completed;
286 printf("ERROR: Failed to open table file for reading!\n");
291 //-----------------------------------------------------------------------------
293 //-----------------------------------------------------------------------------
295 int wmain(int argc, wchar_t *argv[])
297 pthread_t thread_id[THREAD_COUNT + 1];
298 thread_data_t thread_data[THREAD_COUNT];
299 twister_t thread_rand[THREAD_COUNT];
301 pthread_mutex_t stop_mutex;
302 FILE *file_out = NULL;
303 size_t initial_row_index = 0;
305 printf("MHash GenTableXOR [%s]\n\n", __DATE__);
306 printf("HashLen: %d, Distance Min/Max: %d/%d, Threads: %d\n\n", HASH_LEN, DISTANCE_MIN, DISTANCE_MAX, THREAD_COUNT);
308 if ((HASH_LEN % (8 * sizeof(uint32_t))) != 0)
310 crit_exit("FATAL: Hash length must be a multiple of 32 bits!");
315 printf("Table file not specified!\n\n");
317 printf(" GenTables_XOR.exe <table_file>\n\n");
321 for (size_t i = 0; i < ROW_NUM; i++)
323 memset(&g_table[i][0], 0, sizeof(uint8_t) * ROW_LEN);
326 memset(&thread_id, 0, sizeof(pthread_t) * (THREAD_COUNT + 1));
327 memset(&thread_data, 0, sizeof(thread_data_t) * THREAD_COUNT);
328 for (size_t t = 0; t < THREAD_COUNT; t++)
330 memset(&g_thread_buffer[t][0], 0, sizeof(uint8_t) * ROW_LEN);
331 rand_init(&thread_rand[t], make_seed());
334 SEM_INIT(&stop_flag);
335 MUTEX_INIT(&stop_mutex);
337 if (_waccess(argv[1], 4) == 0)
339 printf("Loading existing table data and proceeding...\n");
340 if (!load_table_data(argv[1], &initial_row_index))
346 for (size_t i = initial_row_index; i < ROW_NUM; i++)
348 char time_string[64];
349 printf("Row %03u of %03u [%c]", (uint32_t)(i+1U), ROW_NUM, SPINNER[g_spinpos]);
350 g_spinpos = (g_spinpos + 1) % 4;
352 PTHREAD_CREATE(&thread_id[THREAD_COUNT], NULL, thread_spin, &stop_flag);
353 for (size_t t = 0; t < THREAD_COUNT; t++)
355 thread_data[t].index = i;
356 thread_data[t].row_buffer = &g_thread_buffer[t][0];
357 thread_data[t].stop = &stop_flag;
358 thread_data[t].mutex = &stop_mutex;
359 thread_data[t].rand = &thread_rand[t];
360 PTHREAD_CREATE(&thread_id[t], NULL, thread_main, &thread_data[t]);
363 for (size_t t = 0; t < THREAD_COUNT; t++)
365 void *return_value = NULL;
366 PTHREAD_JOIN(thread_id[t], &return_value);
369 memcpy(&g_table[i][0], return_value, sizeof(uint8_t) * ROW_LEN);
373 PTHREAD_JOIN(thread_id[THREAD_COUNT], NULL);
374 get_time_str(time_string, 64);
375 printf("\b\b\b[#] - %s\n", time_string);
377 if (!save_table_data(argv[1], i + 1U))
379 return 1; /*failed to save current table data*/
383 printf("\n-----\n\n");
386 if (fopen_s(&file_out, "table_out." DISTANCE_STR ".txt", "w") == 0)
388 dump_table(file_out);
392 printf("\n-----\n\n");
394 for (size_t i = 0; i < ROW_NUM; i++)
396 for (size_t j = 0; j < ROW_NUM; j++)
402 if (!check_distance_rows(i, j))
404 crit_exit("FATAL: Table verification has failed!");
409 SEM_DESTROY(&stop_flag);
410 MUTEX_DESTROY(&stop_mutex);
412 printf("COMPLETED.\n\n");