Rev 108 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 108 | Rev 154 | ||
|---|---|---|---|
| Line 27... | Line 27... | ||
| 27 | * on a single cache line rather than being split across two, assuming the * |
27 | * on a single cache line rather than being split across two, assuming the * |
| 28 | * structure is 64 bytes or less of course. * |
28 | * structure is 64 bytes or less of course. * |
| 29 | * * |
29 | * * |
| 30 | ******************************************************************************* |
30 | ******************************************************************************* |
| 31 | */ |
31 | */ |
| 32 | void AlignedMalloc(void **pointer, |
32 | void AlignedMalloc(void **pointer, uint64_t alignment, size_t size) { |
| - | 33 | uint64_t temp; |
|
| - | 34 | ||
| 33 | segments[nsegments][0] = malloc(size + alignment - 1); |
35 | segments[nsegments][0] = malloc(size + alignment - 1); |
| 34 | segments[nsegments][1] = |
36 | segments[nsegments][1] = segments[nsegments][0]; |
| 35 |
|
37 | temp = (uint64_t) segments[nsegments][0]; |
| 36 |
|
38 | temp = (temp + alignment - 1) & ~(alignment - 1); |
| - | 39 | segments[nsegments][1] = (void *) temp; |
|
| 37 | *pointer = segments[nsegments][1]; |
40 | *pointer = segments[nsegments][1]; |
| 38 | nsegments++; |
41 | nsegments++; |
| 39 | } |
42 | } |
| 40 | 43 | ||
| 41 | /* |
44 | /* |
| Line 67... | Line 70... | ||
| 67 | * AlignedRemalloc() is used to change the size of a memory block that has * |
70 | * AlignedRemalloc() is used to change the size of a memory block that has * |
| 68 | * previously been allocated using AlignedMalloc(). * |
71 | * previously been allocated using AlignedMalloc(). * |
| 69 | * * |
72 | * * |
| 70 | ******************************************************************************* |
73 | ******************************************************************************* |
| 71 | */ |
74 | */ |
| 72 | void AlignedRemalloc(void **pointer, |
75 | void AlignedRemalloc(void **pointer, uint64_t alignment, size_t size) { |
| - | 76 | uint64_t temp; |
|
| 73 | int i; |
77 | int i; |
| 74 | 78 | ||
| 75 | for (i = 0; i < nsegments; i++) |
79 | for (i = 0; i < nsegments; i++) |
| 76 | if (segments[i][1] == *pointer) |
80 | if (segments[i][1] == *pointer) |
| 77 | break; |
81 | break; |
| Line 79... | Line 83... | ||
| 79 | Print(4095, "ERROR AlignedRemalloc() given an invalid pointer\n"); |
83 | Print(4095, "ERROR AlignedRemalloc() given an invalid pointer\n"); |
| 80 | exit(1); |
84 | exit(1); |
| 81 | } |
85 | } |
| 82 | free(segments[i][0]); |
86 | free(segments[i][0]); |
| 83 | segments[i][0] = malloc(size + alignment - 1); |
87 | segments[i][0] = malloc(size + alignment - 1); |
| 84 | segments[i][ |
88 | temp = (uint64_t) segments[i][0]; |
| 85 |
|
89 | temp = (temp + alignment - 1) & ~(alignment - 1); |
| 86 |
|
90 | segments[i][1] = (void *) temp; |
| 87 | *pointer = segments[i][1]; |
91 | *pointer = segments[i][1]; |
| 88 | } |
92 | } |
| 89 | 93 | ||
| 90 | /* |
94 | /* |
| 91 | ******************************************************************************* |
95 | ******************************************************************************* |
| Line 266... | Line 270... | ||
| 266 | int i; |
270 | int i; |
| 267 | static int init = 0, pipe; |
271 | static int init = 0, pipe; |
| 268 | static HANDLE inh; |
272 | static HANDLE inh; |
| 269 | DWORD dw; |
273 | DWORD dw; |
| 270 | 274 | ||
| 271 | if (!xboard && ! |
275 | if (!xboard && !isatty(fileno(stdin))) |
| 272 | return 0; |
276 | return 0; |
| 273 | if (batch_mode) |
277 | if (batch_mode) |
| 274 | return 0; |
278 | return 0; |
| 275 | if (strchr(cmd_buffer, '\n')) |
279 | if (strchr(cmd_buffer, '\n')) |
| 276 | return 1; |
280 | return 1; |
| Line 339... | Line 343... | ||
| 339 | */ |
343 | */ |
| 340 | void ClearHashTableScores(void) { |
344 | void ClearHashTableScores(void) { |
| 341 | int i; |
345 | int i; |
| 342 | 346 | ||
| 343 | if (hash_table) |
347 | if (hash_table) |
| 344 | for (i = 0; i < |
348 | for (i = 0; i < hash_table_size; i++) { |
| 345 | (hash_table + i)->word2 ^= (hash_table + i)->word1; |
349 | (hash_table + i)->word2 ^= (hash_table + i)->word1; |
| 346 | (hash_table + i)->word1 = |
350 | (hash_table + i)->word1 = |
| 347 | ((hash_table + i)->word1 & mask_clear_entry) | (uint64_t) 65536; |
351 | ((hash_table + i)->word1 & mask_clear_entry) | (uint64_t) 65536; |
| 348 | (hash_table + i)->word2 ^= (hash_table + i)->word1; |
352 | (hash_table + i)->word2 ^= (hash_table + i)->word1; |
| 349 | } |
353 | } |
| Line 717... | Line 721... | ||
| 717 | * * |
721 | * * |
| 718 | ******************************************************************************* |
722 | ******************************************************************************* |
| 719 | */ |
723 | */ |
| 720 | char *DisplayEvaluation(int value, int wtm) { |
724 | char *DisplayEvaluation(int value, int wtm) { |
| 721 | int tvalue; |
725 | int tvalue; |
| 722 | static char out[ |
726 | static char out[20]; |
| 723 | 727 | ||
| 724 | tvalue = (wtm) ? value : -value; |
728 | tvalue = (wtm) ? value : -value; |
| 725 | if (!MateScore(value)) |
729 | if (!MateScore(value) && !EGTBScore(value)) |
| 726 | sprintf(out, "%7.2f", ((float) tvalue) / 100.0); |
730 | sprintf(out, "%7.2f", ((float) tvalue) / 100.0); |
| 727 | else if (Abs(value) > MATE) { |
731 | else if (Abs(value) > MATE) { |
| 728 | if (tvalue < 0) |
732 | if (tvalue < 0) |
| 729 | sprintf(out, " -infnty"); |
733 | sprintf(out, " -infnty"); |
| 730 | else |
734 | else |
| 731 | sprintf(out, " +infnty"); |
735 | sprintf(out, " +infnty"); |
| - | 736 | } else { |
|
| - | 737 | if (EGTBScore(value)) { |
|
| - | 738 | if (wtm) { |
|
| - | 739 | if (value == TBWIN) |
|
| - | 740 | sprintf(out, " Won "); |
|
| - | 741 | else if (value == -TBWIN) |
|
| - | 742 | sprintf(out, " Lost "); |
|
| - | 743 | } else { |
|
| - | 744 | if (value == TBWIN) |
|
| - | 745 | sprintf(out, " -Won "); |
|
| - | 746 | else if (value == -TBWIN) |
|
| - | 747 | sprintf(out, " -Lost "); |
|
| - | 748 | } |
|
| - | 749 | } |
|
| - | 750 | if (MateScore(value)) { |
|
| 732 |
|
751 | if (value == MATE - 2 && wtm) |
| 733 | sprintf(out, " Mate"); |
752 | sprintf(out, " Mate"); |
| 734 | else if (value == MATE - 2 && !wtm) |
753 | else if (value == MATE - 2 && !wtm) |
| 735 | sprintf(out, " -Mate"); |
754 | sprintf(out, " -Mate"); |
| 736 | else if (value == -(MATE - 1) && wtm) |
755 | else if (value == -(MATE - 1) && wtm) |
| 737 | sprintf(out, " -Mate"); |
756 | sprintf(out, " -Mate"); |
| 738 | else if (value == -(MATE - 1) && !wtm) |
757 | else if (value == -(MATE - 1) && !wtm) |
| 739 | sprintf(out, " Mate"); |
758 | sprintf(out, " Mate"); |
| 740 | else if (value > 0 && wtm) |
759 | else if (value > 0 && wtm) |
| 741 | sprintf(out, " Mat%.2d", (MATE - value) / 2); |
760 | sprintf(out, " Mat%.2d", (MATE - value) / 2); |
| 742 | else if (value > 0 && !wtm) |
761 | else if (value > 0 && !wtm) |
| 743 | sprintf(out, " -Mat%.2d", (MATE - value) / 2); |
762 | sprintf(out, " -Mat%.2d", (MATE - value) / 2); |
| 744 | else if (wtm) |
763 | else if (wtm) |
| 745 | sprintf(out, " -Mat%.2d", (MATE - Abs(value)) / 2); |
764 | sprintf(out, " -Mat%.2d", (MATE - Abs(value)) / 2); |
| 746 | else |
765 | else |
| 747 | sprintf(out, " Mat%.2d", (MATE - Abs(value)) / 2); |
766 | sprintf(out, " Mat%.2d", (MATE - Abs(value)) / 2); |
| - | 767 | } |
|
| - | 768 | } |
|
| 748 | return out; |
769 | return out; |
| 749 | } |
770 | } |
| 750 | 771 | ||
| 751 | /* |
772 | /* |
| 752 | ******************************************************************************* |
773 | ******************************************************************************* |
| Line 819... | Line 840... | ||
| 819 | wtm = Flip(wtm); |
840 | wtm = Flip(wtm); |
| 820 | if (wtm) |
841 | if (wtm) |
| 821 | t_move_number++; |
842 | t_move_number++; |
| 822 | } |
843 | } |
| 823 | if (pv->pathh == 1) |
844 | if (pv->pathh == 1) |
| 824 | sprintf(buffer + strlen(buffer), " <HT> |
845 | sprintf(buffer + strlen(buffer), " <HT>"); |
| 825 | else if (pv->pathh == 2) |
846 | else if (pv->pathh == 2) |
| 826 | sprintf(buffer + strlen(buffer), " < |
847 | sprintf(buffer + strlen(buffer), " <3-fold>"); |
| 827 | else if (pv->pathh == 3) |
848 | else if (pv->pathh == 3) |
| 828 | sprintf(buffer + strlen(buffer), " < |
849 | sprintf(buffer + strlen(buffer), " <50-move>"); |
| 829 | else if (pv->pathh == 4) |
850 | else if (pv->pathh == 4) |
| 830 | sprintf(buffer + strlen(buffer), " < |
851 | sprintf(buffer + strlen(buffer), " <EGTB>"); |
| 831 | if (strlen(buffer) < 30) |
852 | if (strlen(buffer) < 30) |
| 832 | for (i = 0; i < 30 - |
853 | for (i = 0; i < 30 - strlen(buffer); i++) |
| 833 | strcat(buffer, " "); |
854 | strcat(buffer, " "); |
| 834 | strcpy(kibitz_text, buffer); |
855 | strcpy(kibitz_text, buffer); |
| 835 | for (i = pv->pathl - 1; i > 0; i--) { |
856 | for (i = pv->pathl - 1; i > 0; i--) { |
| 836 | wtm = Flip(wtm); |
857 | wtm = Flip(wtm); |
| 837 | UnmakeMove(tree, i, wtm, pv->path[i]); |
858 | UnmakeMove(tree, i, wtm, pv->path[i]); |
| Line 840... | Line 861... | ||
| 840 | } |
861 | } |
| 841 | 862 | ||
| 842 | /* |
863 | /* |
| 843 | ******************************************************************************* |
864 | ******************************************************************************* |
| 844 | * * |
865 | * * |
| 845 | * DisplayFail() is used to display a |
866 | * DisplayFail() is used to display a move that fails high or low during * |
| - | 867 | * the search. Normally disabled. * |
|
| 846 | * * |
868 | * * |
| 847 | ******************************************************************************* |
869 | ******************************************************************************* |
| 848 | */ |
870 | */ |
| 849 | void DisplayFail(TREE * RESTRICT tree, int type, int level, int wtm, int time, |
871 | void DisplayFail(TREE * RESTRICT tree, int type, int level, int wtm, int time, |
| 850 | int move, int value, int force) { |
872 | int move, int value, int force) { |
| Line 857... | Line 879... | ||
| 857 | * return immediately. Otherwise we add the fail high/low * |
879 | * return immediately. Otherwise we add the fail high/low * |
| 858 | * indicator (++/--) and then display the times. * |
880 | * indicator (++/--) and then display the times. * |
| 859 | * * |
881 | * * |
| 860 | ************************************************************ |
882 | ************************************************************ |
| 861 | */ |
883 | */ |
| 862 | if (time < |
884 | if (time < noise_level) |
| 863 | return; |
885 | return; |
| 864 | if (type == 1) |
886 | if (type == 1) |
| 865 | fh_indicator = (wtm) ? "++" : "--"; |
887 | fh_indicator = (wtm) ? "++" : "--"; |
| 866 | else |
888 | else |
| 867 | fh_indicator = (wtm) ? "--" : "++"; |
889 | fh_indicator = (wtm) ? "--" : "++"; |
| Line 889... | Line 911... | ||
| 889 | sprintf(buffer, "%d. (%s)", move_number, ponder_text); |
911 | sprintf(buffer, "%d. (%s)", move_number, ponder_text); |
| 890 | } |
912 | } |
| 891 | sprintf(buffer + strlen(buffer), " %s%c", OutputMove(tree, 1, wtm, move), |
913 | sprintf(buffer + strlen(buffer), " %s%c", OutputMove(tree, 1, wtm, move), |
| 892 | (type == 1) ? '!' : '?'); |
914 | (type == 1) ? '!' : '?'); |
| 893 | strcpy(kibitz_text, buffer); |
915 | strcpy(kibitz_text, buffer); |
| 894 | if (time >= |
916 | if (time >= noise_level || force) { |
| 895 | noise_block = 0; |
917 | noise_block = 0; |
| 896 | Lock(lock_io); |
918 | Lock(lock_io); |
| 897 | Print(4, "%s", buffer); |
919 | Print(4, "%s", buffer); |
| 898 | Unlock(lock_io); |
920 | Unlock(lock_io); |
| 899 | if (type == 1) |
921 | if (type == 1) |
| Line 954... | Line 976... | ||
| 954 | t_move_number++; |
976 | t_move_number++; |
| 955 | } |
977 | } |
| 956 | if (pv->pathh == 1) |
978 | if (pv->pathh == 1) |
| 957 | sprintf(buffer + strlen(buffer), " <HT>"); |
979 | sprintf(buffer + strlen(buffer), " <HT>"); |
| 958 | else if (pv->pathh == 2) |
980 | else if (pv->pathh == 2) |
| 959 | sprintf(buffer + strlen(buffer), " <EGTB>"); |
- | |
| 960 | else if (pv->pathh == 3) |
- | |
| 961 | sprintf(buffer + strlen(buffer), " <3-fold>"); |
981 | sprintf(buffer + strlen(buffer), " <3-fold>"); |
| 962 | else if (pv->pathh == 3) |
982 | else if (pv->pathh == 3) |
| 963 | sprintf(buffer + strlen(buffer), " <50-move>"); |
983 | sprintf(buffer + strlen(buffer), " <50-move>"); |
| - | 984 | else if (pv->pathh == 4) |
|
| - | 985 | sprintf(buffer + strlen(buffer), " <EGTB>"); |
|
| 964 | if (nskip > 1 && smp_max_threads > 1) |
986 | if (nskip > 1 && smp_max_threads > 1) |
| 965 | sprintf(buffer + strlen(buffer), " (s=%d)", nskip); |
987 | sprintf(buffer + strlen(buffer), " (s=%d)", nskip); |
| 966 | if (strlen(buffer) < 30) { |
988 | if (strlen(buffer) < 30) { |
| 967 | len = 30 - strlen(buffer); |
989 | len = 30 - strlen(buffer); |
| 968 | for (i = 0; i < len; i++) |
990 | for (i = 0; i < len; i++) |
| 969 | strcat(buffer, " "); |
991 | strcat(buffer, " "); |
| 970 | } |
992 | } |
| 971 | strcpy(kibitz_text, buffer); |
993 | strcpy(kibitz_text, buffer); |
| 972 | if (time >= |
994 | if (time >= noise_level || force) { |
| 973 | noise_block = 0; |
995 | noise_block = 0; |
| 974 | Lock(lock_io); |
996 | Lock(lock_io); |
| 975 | Print(2, " "); |
997 | Print(2, " "); |
| 976 | if (level == 6) |
998 | if (level == 6) |
| 977 | Print(2, "%2i %s%s ", pv_depth, Display2Times(time), |
999 | Print(2, "%2i %s%s ", pv_depth, Display2Times(time), |
| Line 998... | Line 1020... | ||
| 998 | bufftemp = 0; |
1020 | bufftemp = 0; |
| 999 | if (bufftemp) |
1021 | if (bufftemp) |
| 1000 | Print(2, " "); |
1022 | Print(2, " "); |
| 1001 | } while (bufftemp); |
1023 | } while (bufftemp); |
| 1002 | idle_time = 0; |
1024 | idle_time = 0; |
| 1003 | for (i = 0; i < |
1025 | for (i = 0; i < smp_max_threads; i++) |
| 1004 | idle_time += thread[i].idle; |
1026 | idle_time += thread[i].idle; |
| 1005 | busy_percent = |
1027 | busy_percent = |
| 1006 | 100 - Min(100, |
1028 | 100 - Min(100, |
| 1007 | 100 * idle_time / (smp_max_threads * (end_time - start_time) + 1)); |
1029 | 100 * idle_time / (smp_max_threads * (end_time - start_time) + 1)); |
| 1008 | Kibitz(level, twtm, pv_depth, end_time - start_time, pv->pathv, |
1030 | Kibitz(level, twtm, pv_depth, end_time - start_time, pv->pathv, |
| 1009 | tree->nodes_searched, busy_percent, |
1031 | tree->nodes_searched, busy_percent, tree->egtb_hits, kibitz_text); |
| 1010 | Unlock(lock_io); |
1032 | Unlock(lock_io); |
| 1011 | } |
1033 | } |
| 1012 | for (i = pv->pathl - 1; i > 0; i--) { |
1034 | for (i = pv->pathl - 1; i > 0; i--) { |
| 1013 | wtm = Flip(wtm); |
1035 | wtm = Flip(wtm); |
| 1014 | UnmakeMove(tree, i, wtm, pv->path[i]); |
1036 | UnmakeMove(tree, i, wtm, pv->path[i]); |
| Line 1146... | Line 1168... | ||
| 1146 | sprintf(tout, "%3u:%02u", ttime / 60, ttime % 60); |
1168 | sprintf(tout, "%3u:%02u", ttime / 60, ttime % 60); |
| 1147 | } |
1169 | } |
| 1148 | c = strspn(tout, " "); |
1170 | c = strspn(tout, " "); |
| 1149 | strcat(out, "/"); |
1171 | strcat(out, "/"); |
| 1150 | strcat(out, tout + c); |
1172 | strcat(out, tout + c); |
| 1151 | } |
1173 | } else |
| - | 1174 | strcat(out, " "); |
|
| 1152 | spaces = 13 - strlen(out); |
1175 | spaces = 13 - strlen(out); |
| 1153 | for (c = 0; c < spaces; c++) |
1176 | for (c = 0; c < spaces; c++) |
| 1154 | strcat(out, " "); |
1177 | strcat(out, " "); |
| 1155 | return out; |
1178 | return out; |
| 1156 | } |
1179 | } |
| Line 1173... | Line 1196... | ||
| 1173 | time = time / 100; |
1196 | time = time / 100; |
| 1174 | sprintf(out, "%u:%02u", time / 60, time % 60); |
1197 | sprintf(out, "%u:%02u", time / 60, time % 60); |
| 1175 | } |
1198 | } |
| 1176 | return out; |
1199 | return out; |
| 1177 | } |
1200 | } |
| 1178 | - | ||
| 1179 | /* |
- | |
| 1180 | ******************************************************************************* |
- | |
| 1181 | * * |
- | |
| 1182 | * EGTBPV() is used to display the PV for a known EGTB position. It simply * |
- | |
| 1183 | * makes moves, looks up the position to find the shortest mate, then it * |
- | |
| 1184 | * follows that PV. It appends a "!" to a move that is the only move to * |
- | |
| 1185 | * preserve the shortest path to mate (all other moves lead to longer mates * |
- | |
| 1186 | * or even draws.) * |
- | |
| 1187 | * * |
- | |
| 1188 | ******************************************************************************* |
- | |
| 1189 | */ |
- | |
| 1190 | #if !defined(NOEGTB) |
- | |
| 1191 | void EGTBPV(TREE * RESTRICT tree, int wtm) { |
- | |
| 1192 | uint64_t hk[1024], phk[1024], pos[1024]; |
- | |
| 1193 | unsigned moves[1024], current[256], *last; |
- | |
| 1194 | int value, ply, i, j, nmoves; |
- | |
| 1195 | int t_move_number, best = 0, bestmv = 0, optimal_mv = 0, legal; |
- | |
| 1196 | char buffer[16384], *next; |
- | |
| 1197 | - | ||
| 1198 | /* |
- | |
| 1199 | ************************************************************ |
- | |
| 1200 | * * |
- | |
| 1201 | * First, see if this is a known EGTB position. If not, * |
- | |
| 1202 | * we can bug out right now. * |
- | |
| 1203 | * * |
- | |
| 1204 | ************************************************************ |
- | |
| 1205 | */ |
- | |
| 1206 | if (!EGTB_setup) |
- | |
| 1207 | return; |
- | |
| 1208 | tree->status[1] = tree->status[0]; |
- | |
| 1209 | if (Castle(1, white) + Castle(1, white)) |
- | |
| 1210 | return; |
- | |
| 1211 | if (!EGTBProbe(tree, 1, wtm, &value)) |
- | |
| 1212 | return; |
- | |
| 1213 | t_move_number = move_number; |
- | |
| 1214 | sprintf(buffer, "%d.", move_number); |
- | |
| 1215 | if (!wtm) |
- | |
| 1216 | sprintf(buffer + strlen(buffer), " ..."); |
- | |
| 1217 | /* |
- | |
| 1218 | ************************************************************ |
- | |
| 1219 | * * |
- | |
| 1220 | * The rest is simple, but messy. Generate all moves, * |
- | |
| 1221 | * then find the move with the best egtb score and make it * |
- | |
| 1222 | * (note that if there is only one that is optimal, it is * |
- | |
| 1223 | * flagged as such). We then repeat this over and over * |
- | |
| 1224 | * until we reach the end, or until we repeat a move and * |
- | |
| 1225 | * can call it a repetition. * |
- | |
| 1226 | * * |
- | |
| 1227 | ************************************************************ |
- | |
| 1228 | */ |
- | |
| 1229 | for (ply = 1; ply < 1024; ply++) { |
- | |
| 1230 | pos[ply] = HashKey; |
- | |
| 1231 | last = GenerateCaptures(tree, 1, wtm, current); |
- | |
| 1232 | last = GenerateNoncaptures(tree, 1, wtm, last); |
- | |
| 1233 | nmoves = last - current; |
- | |
| 1234 | best = -MATE - 1; |
- | |
| 1235 | legal = 0; |
- | |
| 1236 | for (i = 0; i < nmoves; i++) { |
- | |
| 1237 | MakeMove(tree, 1, wtm, current[i]); |
- | |
| 1238 | if (!Check(wtm)) { |
- | |
| 1239 | legal++; |
- | |
| 1240 | if (TotalAllPieces == 2 || EGTBProbe(tree, 2, Flip(wtm), &value)) { |
- | |
| 1241 | if (TotalAllPieces > 2) |
- | |
| 1242 | value = -value; |
- | |
| 1243 | else |
- | |
| 1244 | value = DrawScore(wtm); |
- | |
| 1245 | if (value > best) { |
- | |
| 1246 | best = value; |
- | |
| 1247 | bestmv = current[i]; |
- | |
| 1248 | optimal_mv = 1; |
- | |
| 1249 | } else if (value == best) |
- | |
| 1250 | optimal_mv = 0; |
- | |
| 1251 | } |
- | |
| 1252 | } |
- | |
| 1253 | UnmakeMove(tree, 1, wtm, current[i]); |
- | |
| 1254 | } |
- | |
| 1255 | if (best > -MATE - 1) { |
- | |
| 1256 | moves[ply] = bestmv; |
- | |
| 1257 | if (ply > 1 && wtm) |
- | |
| 1258 | sprintf(buffer + strlen(buffer), " %d.", t_move_number); |
- | |
| 1259 | sprintf(buffer + strlen(buffer), " %s", OutputMove(tree, 1, wtm, |
- | |
| 1260 | bestmv)); |
- | |
| 1261 | if (!strchr(buffer, '#') && legal > 1 && optimal_mv) |
- | |
| 1262 | sprintf(buffer + strlen(buffer), "!"); |
- | |
| 1263 | hk[ply] = HashKey; |
- | |
| 1264 | phk[ply] = PawnHashKey; |
- | |
| 1265 | MakeMove(tree, 1, wtm, bestmv); |
- | |
| 1266 | tree->status[1] = tree->status[2]; |
- | |
| 1267 | wtm = Flip(wtm); |
- | |
| 1268 | for (j = 2 - (ply & 1); j < ply; j += 2) |
- | |
| 1269 | if (pos[ply] == pos[j]) |
- | |
| 1270 | break; |
- | |
| 1271 | if (j < ply) |
- | |
| 1272 | break; |
- | |
| 1273 | if (wtm) |
- | |
| 1274 | t_move_number++; |
- | |
| 1275 | if (strchr(buffer, '#')) |
- | |
| 1276 | break; |
- | |
| 1277 | } else { |
- | |
| 1278 | ply--; |
- | |
| 1279 | break; |
- | |
| 1280 | } |
- | |
| 1281 | } |
- | |
| 1282 | nmoves = ply; |
- | |
| 1283 | for (; ply > 0; ply--) { |
- | |
| 1284 | wtm = Flip(wtm); |
- | |
| 1285 | tree->save_hash_key[1] = hk[ply]; |
- | |
| 1286 | tree->save_pawn_hash_key[1] = phk[ply]; |
- | |
| 1287 | UnmakeMove(tree, 1, wtm, moves[ply]); |
- | |
| 1288 | tree->status[2] = tree->status[1]; |
- | |
| 1289 | } |
- | |
| 1290 | next = buffer; |
- | |
| 1291 | while (nmoves) { |
- | |
| 1292 | if ((int) strlen(next) > line_length) { // Pierre-Marie Baty -- added type cast |
- | |
| 1293 | int i; |
- | |
| 1294 | - | ||
| 1295 | for (i = 0; i < 16; i++) |
- | |
| 1296 | if (*(next + 64 + i) == ' ') |
- | |
| 1297 | break; |
- | |
| 1298 | *(next + 64 + i) = 0; |
- | |
| 1299 | printf("%s\n", next); |
- | |
| 1300 | next += 64 + i + 1; |
- | |
| 1301 | } else { |
- | |
| 1302 | printf("%s\n", next); |
- | |
| 1303 | break; |
- | |
| 1304 | } |
- | |
| 1305 | } |
- | |
| 1306 | } |
- | |
| 1307 | #endif |
- | |
| 1308 | 1201 | ||
| 1309 | /* |
1202 | /* |
| 1310 | ******************************************************************************* |
1203 | ******************************************************************************* |
| 1311 | * * |
1204 | * * |
| 1312 | * FormatPV() is used to display a PV during the search. It will also note * |
1205 | * FormatPV() is used to display a PV during the search. It will also note * |
| Line 1417... | Line 1310... | ||
| 1417 | */ |
1310 | */ |
| 1418 | unsigned int ReadClock(void) { |
1311 | unsigned int ReadClock(void) { |
| 1419 | #if defined(UNIX) |
1312 | #if defined(UNIX) |
| 1420 | struct timeval timeval; |
1313 | struct timeval timeval; |
| 1421 | struct timezone timezone; |
1314 | struct timezone timezone; |
| 1422 | #else |
- | |
| 1423 | //HANDLE hThread; // Pierre-Marie Baty -- unreferenced variable |
- | |
| 1424 | //FILETIME ftCreate, ftExit, ftKernel, ftUser; // Pierre-Marie Baty -- unreferenced variables |
- | |
| 1425 | //uint64_t tUser64; // Pierre-Marie Baty -- unreferenced variable |
- | |
| 1426 | #endif |
1315 | #endif |
| 1427 | #if defined(UNIX) |
1316 | #if defined(UNIX) |
| 1428 | gettimeofday(&timeval, &timezone); |
1317 | gettimeofday(&timeval, &timezone); |
| 1429 | return timeval.tv_sec * 100 + (timeval.tv_usec / 10000); |
1318 | return timeval.tv_sec * 100 + (timeval.tv_usec / 10000); |
| 1430 | #else |
1319 | #else |
| Line 1441... | Line 1330... | ||
| 1441 | ******************************************************************************* |
1330 | ******************************************************************************* |
| 1442 | */ |
1331 | */ |
| 1443 | int FindBlockID(TREE * RESTRICT which) { |
1332 | int FindBlockID(TREE * RESTRICT which) { |
| 1444 | int i; |
1333 | int i; |
| 1445 | 1334 | ||
| 1446 | for (i = 0; i <= |
1335 | for (i = 0; i <= smp_max_threads * 64; i++) |
| 1447 | if (which == block[i]) |
1336 | if (which == block[i]) |
| 1448 | return i; |
1337 | return i; |
| 1449 | return -1; |
1338 | return -1; |
| 1450 | } |
1339 | } |
| 1451 | 1340 | ||
| Line 1568... | Line 1457... | ||
| 1568 | pdist = Abs(Rank(pawn) - Rank(queen)) + !ptm; |
1457 | pdist = Abs(Rank(pawn) - Rank(queen)) + !ptm; |
| 1569 | kdist = Distance(king, queen); |
1458 | kdist = Distance(king, queen); |
| 1570 | return pdist >= kdist; |
1459 | return pdist >= kdist; |
| 1571 | } |
1460 | } |
| 1572 | 1461 | ||
| 1573 | /* last modified |
1462 | /* last modified 07/13/16 */ |
| 1574 | /* |
1463 | /* |
| 1575 | ******************************************************************************* |
1464 | ******************************************************************************* |
| 1576 | * * |
1465 | * * |
| 1577 | * |
1466 | * Mated() is used to determine if the game has ended by checkmate. * |
| 1578 | * |
1467 | * * |
| - | 1468 | * We return 0 if the game doesn't end here, 1 if the side on move is mated * |
|
| - | 1469 | * and 2 if the side on move is stalemated. * |
|
| 1579 | * * |
1470 | * * |
| 1580 | ******************************************************************************* |
1471 | ******************************************************************************* |
| 1581 | */ |
1472 | */ |
| 1582 | void NewGame(int save) { |
- | |
| 1583 |
|
1473 | int Mated(TREE * RESTRICT tree, int ply, int wtm) { |
| 1584 |
|
1474 | unsigned int rmoves[256], *mvp, *lastm; |
| 1585 | static int save_resign = 0, save_resign_count = 0, save_draw_count = 0; |
- | |
| 1586 | static int save_learning = 0, save_learn = 0, save_accept_draws = 0; |
- | |
| 1587 | int |
1475 | int temp = 0; |
| 1588 | 1476 | ||
| 1589 | new_game = 0; |
- | |
| 1590 |
|
1477 | /* |
| 1591 |
|
1478 | ************************************************************ |
| 1592 | save_kibitz = kibitz; |
- | |
| 1593 | save_resign = resign; |
- | |
| 1594 |
|
1479 | * * |
| 1595 |
|
1480 | * first, use GenerateMoves() to generate the set of * |
| 1596 |
|
1481 | * legal moves from the root position, after making the * |
| 1597 | save_learn = learn; |
- | |
| 1598 |
|
1482 | * test move passed in. * |
| 1599 | } else { |
- | |
| 1600 |
|
1483 | * * |
| 1601 | learn_value = |
- | |
| 1602 |
|
1484 | ************************************************************ |
| 1603 | LearnBook(); |
- | |
| 1604 |
|
1485 | */ |
| 1605 | if (xboard) { |
- | |
| 1606 |
|
1486 | lastm = GenerateCaptures(tree, ply, wtm, rmoves); |
| 1607 |
|
1487 | lastm = GenerateNoncaptures(tree, ply, wtm, lastm); |
| 1608 |
|
1488 | /* |
| 1609 | over = 0; |
- | |
| 1610 | moves_out_of_book = 0; |
- | |
| 1611 | learn_positions_count = 0; |
- | |
| 1612 | learn_value = 0; |
- | |
| 1613 | ponder_move = 0; |
- | |
| 1614 | last_search_value = 0; |
- | |
| 1615 | last_pv.pathd = 0; |
- | |
| 1616 | last_pv.pathl = 0; |
- | |
| 1617 | strcpy(initial_position, ""); |
- | |
| 1618 | InitializeChessBoard(tree); |
- | |
| 1619 | InitializeHashTables(0); |
- | |
| 1620 | force = 0; |
- | |
| 1621 | books_file = normal_bs_file; |
- | |
| 1622 | draw_score[0] = 0; |
- | |
| 1623 | draw_score[1] = 0; |
- | |
| 1624 | game_wtm = 1; |
- | |
| 1625 | move_number = 1; |
- | |
| 1626 | tc_time_remaining[white] = tc_time; |
- | |
| 1627 | tc_time_remaining[black] = tc_time; |
- | |
| 1628 | tc_moves_remaining[white] = tc_moves; |
- | |
| 1629 |
|
1489 | ************************************************************ |
| 1630 | if (move_actually_played) { |
- | |
| 1631 | if (log_file) { |
- | |
| 1632 | fclose(log_file); |
- | |
| 1633 | fclose(history_file); |
- | |
| 1634 | id = InitializeGetLogID(); |
- | |
| 1635 |
|
1490 | * * |
| 1636 |
|
1491 | * now make each move and use eliminate any that leave * |
| 1637 |
|
1492 | * king in check (which makes those moves illegal.) * |
| 1638 |
|
1493 | * * |
| 1639 | if (!history_file) { |
- | |
| 1640 |
|
1494 | ************************************************************ |
| 1641 | CraftyExit(1); |
- | |
| 1642 | } |
- | |
| 1643 | } |
- | |
| 1644 |
|
1495 | */ |
| 1645 |
|
1496 | for (mvp = rmoves; mvp < lastm; mvp++) { |
| 1646 | book_selection_width = save_book_selection_width; |
- | |
| 1647 |
|
1497 | MakeMove(tree, ply, wtm, *mvp); |
| 1648 |
|
1498 | temp = Check(wtm); |
| 1649 | resign_count = save_resign_count; |
- | |
| 1650 | resign_counter = 0; |
- | |
| 1651 |
|
1499 | UnmakeMove(tree, ply, wtm, *mvp); |
| 1652 | accept_draws = save_accept_draws; |
- | |
| 1653 | draw_counter = 0; |
- | |
| 1654 | usage_level = 0; |
- | |
| 1655 | learning = save_learning; |
- | |
| 1656 | learn = save_learn; |
- | |
| 1657 |
|
1500 | if (!temp) |
| 1658 |
|
1501 | break; |
| 1659 | tree->nodes_searched = 0; |
- | |
| 1660 | kibitz_text[0] = 0; |
- | |
| 1661 | } |
1502 | } |
| - | 1503 | /* |
|
| - | 1504 | ************************************************************ |
|
| - | 1505 | * * |
|
| - | 1506 | * if there is one move that did not leave us in check, * |
|
| - | 1507 | * then it can't be checkmate/stalemate. * |
|
| - | 1508 | * * |
|
| - | 1509 | ************************************************************ |
|
| - | 1510 | */ |
|
| - | 1511 | if (!temp) |
|
| - | 1512 | return 0; |
|
| - | 1513 | /* |
|
| - | 1514 | ************************************************************ |
|
| - | 1515 | * * |
|
| - | 1516 | * No legal moves. If we are in check, we have been * |
|
| - | 1517 | * checkmated, otherwise we are stalemated. * |
|
| - | 1518 | * * |
|
| - | 1519 | ************************************************************ |
|
| - | 1520 | */ |
|
| - | 1521 | if (Check(wtm)) |
|
| - | 1522 | return 1; |
|
| - | 1523 | return 2; |
|
| 1662 | } |
1524 | } |
| 1663 | 1525 | ||
| 1664 | /* |
1526 | /* |
| 1665 | ******************************************************************************* |
1527 | ******************************************************************************* |
| 1666 | * * |
1528 | * * |
| Line 1959... | Line 1821... | ||
| 1959 | int ReadInput(void) { |
1821 | int ReadInput(void) { |
| 1960 | int bytes; |
1822 | int bytes; |
| 1961 | char buffer[4096], *end; |
1823 | char buffer[4096], *end; |
| 1962 | 1824 | ||
| 1963 | do |
1825 | do |
| 1964 | bytes = |
1826 | bytes = read(fileno(input_stream), buffer, 2048); |
| 1965 | while (bytes < 0 && errno == EINTR); |
1827 | while (bytes < 0 && errno == EINTR); |
| 1966 | if (bytes == 0) { |
1828 | if (bytes == 0) { |
| 1967 | if (input_stream != stdin) |
1829 | if (input_stream != stdin) |
| 1968 | fclose(input_stream); |
1830 | fclose(input_stream); |
| 1969 | input_stream = stdin; |
1831 | input_stream = stdin; |
| Line 2082... | Line 1944... | ||
| 2082 | * If we don't have any data in the buffer, the first step * |
1944 | * If we don't have any data in the buffer, the first step * |
| 2083 | * is to read the next line. * |
1945 | * is to read the next line. * |
| 2084 | * * |
1946 | * * |
| 2085 | ************************************************************ |
1947 | ************************************************************ |
| 2086 | */ |
1948 | */ |
| 2087 | while ( |
1949 | while (FOREVER) { |
| 2088 | if (!data) { |
1950 | if (!data) { |
| 2089 | eof = fgets(input_buffer, 4096, input); |
1951 | eof = fgets(input_buffer, 4096, input); |
| 2090 | if (!eof) |
1952 | if (!eof) |
| 2091 | return -1; |
1953 | return -1; |
| 2092 | if (strchr(input_buffer, '\n')) |
1954 | if (strchr(input_buffer, '\n')) |
| Line 2171... | Line 2033... | ||
| 2171 | ************************************************************ |
2033 | ************************************************************ |
| 2172 | */ |
2034 | */ |
| 2173 | last_good_line = lines_read; |
2035 | last_good_line = lines_read; |
| 2174 | analysis_move[0] = 0; |
2036 | analysis_move[0] = 0; |
| 2175 | if (strchr(buffer, '{') || strchr(buffer, '(')) |
2037 | if (strchr(buffer, '{') || strchr(buffer, '(')) |
| 2176 | while ( |
2038 | while (FOREVER) { |
| 2177 | char *skip, *ch; |
2039 | char *skip, *ch; |
| 2178 | 2040 | ||
| 2179 | analysis = 1; |
2041 | analysis = 1; |
| 2180 | while ((ch = strpbrk(buffer, "(){}[]"))) { |
2042 | while ((ch = strpbrk(buffer, "(){}[]"))) { |
| 2181 | if (*ch == '(') { |
2043 | if (*ch == '(') { |
| Line 2341... | Line 2203... | ||
| 2341 | else |
2203 | else |
| 2342 | sprintf(prefix, "whisper"); |
2204 | sprintf(prefix, "whisper"); |
| 2343 | switch (level) { |
2205 | switch (level) { |
| 2344 | case 1: |
2206 | case 1: |
| 2345 | if ((kibitz & 15) >= 1) { |
2207 | if ((kibitz & 15) >= 1) { |
| 2346 | if (value > 0) |
2208 | if (value > 0) |
| 2347 | printf("%s mate in %d moves.\n\n", prefix, value); |
2209 | printf("%s mate in %d moves.\n\n", prefix, value); |
| 2348 | } |
- | |
| 2349 | if (value < 0) |
2210 | if (value < 0) |
| 2350 | printf("%s mated in %d moves.\n\n", prefix, -value); |
2211 | printf("%s mated in %d moves.\n\n", prefix, -value); |
| 2351 | } |
- | |
| 2352 | } |
2212 | } |
| 2353 | break; |
2213 | break; |
| 2354 | case 2: |
2214 | case 2: |
| 2355 | if ((kibitz & 15) >= 2) |
2215 | if ((kibitz & 15) >= 2) { |
| 2356 | printf("%s ply=%d; eval=%s; nps=%s; time=%s(%d%%) |
2216 | printf("%s ply=%d; eval=%s; nps=%s; time=%s(%d%%)", prefix, depth, |
| 2357 |
|
2217 | DisplayEvaluationKibitz(value, wtm), DisplayKMB(nps, 0), |
| 2358 |
|
2218 | DisplayTimeKibitz(time), ip); |
| - | 2219 | printf("; egtb=%s\n", DisplayKMB(tb_hits, 0)); |
|
| - | 2220 | } |
|
| - | 2221 | break; |
|
| 2359 | case 3: |
2222 | case 3: |
| 2360 | if ((kibitz & 15) >= 3 && (nodes > 5000 || level == 2)) |
2223 | if ((kibitz & 15) >= 3 && (nodes > 5000 || level == 2)) |
| 2361 | printf("%s %s\n", prefix, pv); |
2224 | printf("%s %s\n", prefix, pv); |
| 2362 | break; |
2225 | break; |
| 2363 | case 4: |
2226 | case 4: |
| Line 2368... | Line 2231... | ||
| 2368 | if ((kibitz & 15) >= 5 && nodes > 5000) { |
2231 | if ((kibitz & 15) >= 5 && nodes > 5000) { |
| 2369 | printf("%s d%d-> %s/s %s(%d%%) %s %s ", prefix, depth, |
2232 | printf("%s d%d-> %s/s %s(%d%%) %s %s ", prefix, depth, |
| 2370 | DisplayKMB(nps, 0), DisplayTimeKibitz(time), ip, |
2233 | DisplayKMB(nps, 0), DisplayTimeKibitz(time), ip, |
| 2371 | DisplayEvaluationKibitz(value, wtm), pv); |
2234 | DisplayEvaluationKibitz(value, wtm), pv); |
| 2372 | if (tb_hits) |
2235 | if (tb_hits) |
| 2373 | printf(" |
2236 | printf("egtb=%s", DisplayKMB(tb_hits, 0)); |
| 2374 | printf("\n"); |
2237 | printf("\n"); |
| 2375 | } |
2238 | } |
| 2376 | break; |
2239 | break; |
| 2377 | } |
2240 | } |
| 2378 | value = (wtm) ? value : -value; |
2241 | value = (wtm) ? value : -value; |
| Line 2417... | Line 2280... | ||
| 2417 | if (tree->pv[1].path[1] == root_moves[i].move) |
2280 | if (tree->pv[1].path[1] == root_moves[i].move) |
| 2418 | break; |
2281 | break; |
| 2419 | root_moves[i].path = tree->pv[1]; |
2282 | root_moves[i].path = tree->pv[1]; |
| 2420 | root_moves[i].bm_age = 4; |
2283 | root_moves[i].bm_age = 4; |
| 2421 | } |
2284 | } |
| 2422 | } |
- | |
| 2423 | - | ||
| 2424 | /* |
- | |
| 2425 | ******************************************************************************* |
- | |
| 2426 | * * |
- | |
| 2427 | * SortRootMoves() is used to sort the root move list based on the value * |
- | |
| 2428 | * saved for each move. After a fail high or fail low, we always re-sort * |
- | |
| 2429 | * the root move list so that the best move found so far is first in the * |
- | |
| 2430 | * list. This is primarily intended as a defense against getting a score * |
- | |
| 2431 | * for the first root move, and then getting a fail-high on the second move, * |
- | |
| 2432 | * which should move this move to the front of the moves. But if the move * |
- | |
| 2433 | * then fails low, we want to move it back down since a deeper/less-reduced * |
- | |
| 2434 | * search did not verify the fail-high. * |
- | |
| 2435 | * * |
- | |
| 2436 | ******************************************************************************* |
- | |
| 2437 | */ |
- | |
| 2438 | void SortRootMoves() { |
- | |
| 2439 | ROOT_MOVE rtemp; |
- | |
| 2440 | int mvp, done; |
- | |
| 2441 | - | ||
| 2442 | do { |
- | |
| 2443 | done = 1; |
- | |
| 2444 | for (mvp = 0; mvp < n_root_moves - 1; mvp++) { |
- | |
| 2445 | if (root_moves[mvp].path.pathv < root_moves[mvp + 1].path.pathv) { |
- | |
| 2446 | rtemp = root_moves[mvp]; |
- | |
| 2447 | root_moves[mvp] = root_moves[mvp + 1]; |
- | |
| 2448 | root_moves[mvp + 1] = rtemp; |
- | |
| 2449 | done = 0; |
- | |
| 2450 | } |
- | |
| 2451 | } |
- | |
| 2452 | } while (!done); |
- | |
| 2453 | } |
2285 | } |
| 2454 | 2286 | ||
| 2455 | /* |
2287 | /* |
| 2456 | ******************************************************************************* |
2288 | ******************************************************************************* |
| 2457 | * * |
2289 | * * |
| Line 2491... | Line 2323... | ||
| 2491 | ******************************************************************************* |
2323 | ******************************************************************************* |
| 2492 | */ |
2324 | */ |
| 2493 | int StrCnt(char *string, char testchar) { |
2325 | int StrCnt(char *string, char testchar) { |
| 2494 | int count = 0, i; |
2326 | int count = 0, i; |
| 2495 | 2327 | ||
| 2496 | for (i = 0; i < |
2328 | for (i = 0; i < strlen(string); i++) |
| 2497 | if (string[i] == testchar) |
2329 | if (string[i] == testchar) |
| 2498 | count++; |
2330 | count++; |
| 2499 | return count; |
2331 | return count; |
| 2500 | } |
2332 | } |
| 2501 | 2333 | ||
| Line 2574... | Line 2406... | ||
| 2574 | */ |
2406 | */ |
| 2575 | case pawn: |
2407 | case pawn: |
| 2576 | if (((wtm) ? To(move) - From(move) : From(move) - To(move)) < 0) |
2408 | if (((wtm) ? To(move) - From(move) : From(move) - To(move)) < 0) |
| 2577 | return 0; |
2409 | return 0; |
| 2578 | if (Abs(From(move) - To(move)) == 8) |
2410 | if (Abs(From(move) - To(move)) == 8) |
| 2579 | return |
2411 | return PcOnSq(To(move)) ? 0 : 1; |
| 2580 | if (Abs(From(move) - To(move)) == 16) |
2412 | if (Abs(From(move) - To(move)) == 16) |
| 2581 | return (PcOnSq(To(move)) || PcOnSq(To(move) + epdir[wtm])) ? 0 : 1; |
2413 | return (PcOnSq(To(move)) || PcOnSq(To(move) + epdir[wtm])) ? 0 : 1; |
| 2582 | if (!Captured(move)) |
2414 | if (!Captured(move)) |
| 2583 | return 0; |
2415 | return 0; |
| 2584 | /* |
2416 | /* |
| Line 2674... | Line 2506... | ||
| 2674 | static ULONG ulNumaNodes; |
2506 | static ULONG ulNumaNodes; |
| 2675 | static ULONG ulNumaNode = 0; |
2507 | static ULONG ulNumaNode = 0; |
| 2676 | 2508 | ||
| 2677 | // Get NUMA-related information from Windows |
2509 | // Get NUMA-related information from Windows |
| 2678 | static void WinNumaInit(void) { |
2510 | static void WinNumaInit(void) { |
| 2679 | //DWORD_PTR dwMask; // Pierre-Marie Baty -- unreferenced variable |
- | |
| 2680 | HMODULE hModule; |
2511 | HMODULE hModule; |
| 2681 | ULONG ulCPU, ulNode; |
2512 | ULONG ulCPU, ulNode; |
| 2682 | ULONGLONG ullMask; |
2513 | ULONGLONG ullMask; |
| 2683 | DWORD dwCPU; |
2514 | DWORD dwCPU; |
| 2684 | 2515 | ||
| Line 2697... | Line 2528... | ||
| 2697 | if (pGetNumaHighestNodeNumber && pGetNumaNodeProcessorMask && |
2528 | if (pGetNumaHighestNodeNumber && pGetNumaNodeProcessorMask && |
| 2698 | pGetNumaHighestNodeNumber(&ulNumaNodes) && (ulNumaNodes > 0)) { |
2529 | pGetNumaHighestNodeNumber(&ulNumaNodes) && (ulNumaNodes > 0)) { |
| 2699 | fSystemIsNUMA = TRUE; |
2530 | fSystemIsNUMA = TRUE; |
| 2700 | if (ulNumaNodes > 255) |
2531 | if (ulNumaNodes > 255) |
| 2701 | ulNumaNodes = 255; |
2532 | ulNumaNodes = 255; |
| 2702 | printf("System is NUMA. |
2533 | printf("System is NUMA. " PRId64 " nodes reported by Windows\n", |
| 2703 | ulNumaNodes + 1); |
2534 | ulNumaNodes + 1); |
| 2704 | for (ulNode = 0; ulNode <= ulNumaNodes; ulNode++) { |
2535 | for (ulNode = 0; ulNode <= ulNumaNodes; ulNode++) { |
| 2705 | pGetNumaNodeProcessorMask((UCHAR) ulNode, |
2536 | pGetNumaNodeProcessorMask((UCHAR) ulNode, |
| 2706 | &ullProcessorMask[ulNode]); |
2537 | &ullProcessorMask[ulNode]); |
| 2707 | printf("Node |
2538 | printf("Node " PRId64 " CPUs: ", ulNode); |
| 2708 | ullMask = ullProcessorMask[ulNode]; |
2539 | ullMask = ullProcessorMask[ulNode]; |
| 2709 | if (0 == ullMask) |
2540 | if (0 == ullMask) |
| 2710 | fSystemIsNUMA = FALSE; |
2541 | fSystemIsNUMA = FALSE; |
| 2711 | else { |
2542 | else { |
| 2712 | ulCPU = 0; |
2543 | ulCPU = 0; |
| 2713 | do { |
2544 | do { |
| 2714 | if (ullMask & 1) |
2545 | if (ullMask & 1) |
| 2715 | printf(" |
2546 | printf("" PRId64 " ", ulCPU); |
| 2716 | ulCPU++; |
2547 | ulCPU++; |
| 2717 | ullMask >>= 1; |
2548 | ullMask >>= 1; |
| 2718 | } while (ullMask); |
2549 | } while (ullMask); |
| 2719 | } |
2550 | } |
| 2720 | printf("\n"); |
2551 | printf("\n"); |
| 2721 | } |
2552 | } |
| 2722 | // Thread 0 was already started on some CPU. To simplify things further, |
2553 | // Thread 0 was already started on some CPU. To simplify things further, |
| 2723 | // exchange |
2554 | // exchange ProcessorMask[0] and ProcessorMask[node for that CPU], |
| 2724 | // so |
2555 | // so ProcessorMask[0] would always be node for thread 0 |
| 2725 | dwCPU = |
2556 | dwCPU = |
| 2726 | pSetThreadIdealProcessor(GetCurrentThread(), MAXIMUM_PROCESSORS); |
2557 | pSetThreadIdealProcessor(GetCurrentThread(), MAXIMUM_PROCESSORS); |
| 2727 | printf("Current ideal CPU is |
2558 | printf("Current ideal CPU is %llu\n", dwCPU); |
| 2728 | pSetThreadIdealProcessor(GetCurrentThread(), dwCPU); |
2559 | pSetThreadIdealProcessor(GetCurrentThread(), dwCPU); |
| 2729 | if ((((DWORD) - 1) != dwCPU) && (MAXIMUM_PROCESSORS != dwCPU) |
2560 | if ((((DWORD) - 1) != dwCPU) && (MAXIMUM_PROCESSORS != dwCPU) |
| 2730 | && !(ullProcessorMask[0] & ( |
2561 | && !(ullProcessorMask[0] & (1u << dwCPU))) { |
| 2731 | for (ulNode = 1; ulNode <= ulNumaNodes; ulNode++) { |
2562 | for (ulNode = 1; ulNode <= ulNumaNodes; ulNode++) { |
| 2732 | if (ullProcessorMask[ulNode] & ( |
2563 | if (ullProcessorMask[ulNode] & (1u << dwCPU)) { |
| 2733 | printf("Exchanging nodes 0 and |
2564 | printf("Exchanging nodes 0 and " PRId64 "\n", ulNode); |
| 2734 | ullMask = ullProcessorMask[ulNode]; |
2565 | ullMask = ullProcessorMask[ulNode]; |
| 2735 | ullProcessorMask[ulNode] = ullProcessorMask[0]; |
2566 | ullProcessorMask[ulNode] = ullProcessorMask[0]; |
| 2736 | ullProcessorMask[0] = ullMask; |
2567 | ullProcessorMask[0] = ullMask; |
| 2737 | break; |
2568 | break; |
| 2738 | } |
2569 | } |
| Line 2755... | Line 2586... | ||
| 2755 | if (fSystemIsNUMA) { |
2586 | if (fSystemIsNUMA) { |
| 2756 | ulNumaNode++; |
2587 | ulNumaNode++; |
| 2757 | if (ulNumaNode > ulNumaNodes) |
2588 | if (ulNumaNode > ulNumaNodes) |
| 2758 | ulNumaNode = 0; |
2589 | ulNumaNode = 0; |
| 2759 | ullMask = ullProcessorMask[ulNumaNode]; |
2590 | ullMask = ullProcessorMask[ulNumaNode]; |
| 2760 | printf("Starting thread on node |
2591 | printf("Starting thread on node " PRId64 " CPU mask %I64d\n", ulNumaNode, |
| 2761 | ullMask); |
2592 | ullMask); |
| 2762 | SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR) ullMask); |
2593 | SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR) ullMask); |
| 2763 | hThread = (HANDLE) _beginthreadex(0, 0, func, args, CREATE_SUSPENDED, 0); |
2594 | hThread = (HANDLE) _beginthreadex(0, 0, func, args, CREATE_SUSPENDED, 0); |
| 2764 | SetThreadAffinityMask(hThread, (DWORD_PTR) ullMask); |
2595 | SetThreadAffinityMask(hThread, (DWORD_PTR) ullMask); |
| 2765 | ResumeThread(hThread); |
2596 | ResumeThread(hThread); |
| 2766 | SetThreadAffinityMask(GetCurrentThread(), |
2597 | SetThreadAffinityMask(GetCurrentThread(), ullProcessorMask[0]); |
| 2767 | } else |
2598 | } else |
| 2768 | hThread = (HANDLE) _beginthreadex(0, 0, func, args, 0, 0); |
2599 | hThread = (HANDLE) _beginthreadex(0, 0, func, args, 0, 0); |
| 2769 | return hThread; |
2600 | return hThread; |
| 2770 | } |
2601 | } |
| 2771 | # endif |
2602 | # endif |
| Line 2779... | Line 2610... | ||
| 2779 | 2610 | ||
| 2780 | WinNumaInit(); |
2611 | WinNumaInit(); |
| 2781 | if (fSystemIsNUMA) { |
2612 | if (fSystemIsNUMA) { |
| 2782 | ulNode = iThread % (ulNumaNodes + 1); |
2613 | ulNode = iThread % (ulNumaNodes + 1); |
| 2783 | hThread = GetCurrentThread(); |
2614 | hThread = GetCurrentThread(); |
| 2784 | dwAffinityMask = SetThreadAffinityMask(hThread, |
2615 | dwAffinityMask = SetThreadAffinityMask(hThread, ullProcessorMask[ulNode]); |
| 2785 | pBytes = VirtualAlloc(NULL, cbBytes, MEM_COMMIT, PAGE_READWRITE); |
2616 | pBytes = VirtualAlloc(NULL, cbBytes, MEM_COMMIT, PAGE_READWRITE); |
| 2786 | if (pBytes == NULL) |
2617 | if (pBytes == NULL) |
| 2787 | ExitProcess(GetLastError()); |
2618 | ExitProcess(GetLastError()); |
| 2788 | memset(pBytes, 0, cbBytes); |
2619 | memset(pBytes, 0, cbBytes); |
| 2789 | SetThreadAffinityMask(hThread, dwAffinityMask); |
2620 | SetThreadAffinityMask(hThread, dwAffinityMask); |
| Line 2825... | Line 2656... | ||
| 2825 | dwStep = dwPageSize * cThreads; |
2656 | dwStep = dwPageSize * cThreads; |
| 2826 | pEnd = pBase + cbBytes; |
2657 | pEnd = pBase + cbBytes; |
| 2827 | for (iThread = 0; iThread < cThreads; iThread++) { |
2658 | for (iThread = 0; iThread < cThreads; iThread++) { |
| 2828 | ulNode = iThread % (ulNumaNodes + 1); |
2659 | ulNode = iThread % (ulNumaNodes + 1); |
| 2829 | dwAffinityMask = |
2660 | dwAffinityMask = |
| 2830 | SetThreadAffinityMask(hThread, |
2661 | SetThreadAffinityMask(hThread, ullProcessorMask[ulNode]); |
| 2831 | for (pch = pBase + iThread * dwPageSize; pch < pEnd; pch += dwStep) { |
2662 | for (pch = pBase + iThread * dwPageSize; pch < pEnd; pch += dwStep) { |
| 2832 | lpvResult = VirtualAlloc(pch, // next page to commit |
2663 | lpvResult = VirtualAlloc(pch, // next page to commit |
| 2833 | dwPageSize, // page size, in bytes |
2664 | dwPageSize, // page size, in bytes |
| 2834 | MEM_COMMIT, // allocate a committed page |
2665 | MEM_COMMIT, // allocate a committed page |
| 2835 | PAGE_READWRITE); // read/write access |
2666 | PAGE_READWRITE); // read/write access |