Changeset 3313 for trunk/src/kmk
- Timestamp:
- Mar 16, 2020, 3:31:38 AM (5 years ago)
- Location:
- trunk/src/kmk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/kmkbuiltin/kSubmit.c
r3224 r3313 121 121 int fdSocket; 122 122 #endif 123 124 /** Current history index (must mod with aHistory element count). */ 125 unsigned iHistory; 126 /** History. */ 127 struct 128 { 129 /** Pointer to the message, NULL if none. */ 130 void *pvMsg; 131 /** The message size, zero if not present. */ 132 size_t cbMsg; 133 } aHistory[4]; 123 134 124 135 /** What it's busy with. NULL if idle. */ … … 181 192 182 193 #ifdef KBUILD_OS_WINDOWS 194 /** The processor group allocator state. */ 195 static MKWINCHILDCPUGROUPALLOCSTATE g_SubmitProcessorGroupAllocator; 196 # if K_ARCH_BITS == 64 197 /** The processor group allocator state for 32-bit processes. */ 198 static MKWINCHILDCPUGROUPALLOCSTATE g_SubmitProcessorGroupAllocator32; 199 # endif 200 #endif 201 202 #ifdef KBUILD_OS_WINDOWS 183 203 /** Pointer to kernel32!SetThreadGroupAffinity. */ 184 204 static BOOL (WINAPI *g_pfnSetThreadGroupAffinity)(HANDLE, const GROUP_AFFINITY*, GROUP_AFFINITY *); … … 428 448 { 429 449 #ifdef KBUILD_OS_WINDOWS 430 static DWORD s_fDenyRemoteClients = ~(DWORD)0; 431 wchar_t wszPipeName[128]; 432 HANDLE hWorkerPipe; 433 int iProcessorGroup = -1; /** @todo determine process group. */ 450 static DWORD s_fDenyRemoteClients = ~(DWORD)0; 451 wchar_t wszPipeName[128]; 452 HANDLE hWorkerPipe; 453 int iProcessorGroup; 454 455 # if K_ARCH_BITS == 64 456 /** @todo make it return -1 if not applicable (e.g only one group). */ 457 if (pWorker->cBits != 32) 458 iProcessorGroup = MkWinChildAllocateCpuGroup(&g_SubmitProcessorGroupAllocator); 459 else 460 iProcessorGroup = MkWinChildAllocateCpuGroup(&g_SubmitProcessorGroupAllocator32); 461 # else 462 iProcessorGroup = MkWinChildAllocateCpuGroup(&g_SubmitProcessorGroupAllocator); 463 # endif 434 464 435 465 /* … … 464 494 { 465 495 extern int process_priority; /* main.c */ 466 wchar_t wszCommandLine[MAX_PATH * 3 ];496 wchar_t wszCommandLine[MAX_PATH * 3 + 32]; 467 497 wchar_t *pwszDst = wszCommandLine; 468 498 size_t cwcDst = K_ELEMENTS(wszCommandLine); … … 490 520 cwcDst -= cwc; 491 521 } 522 if (iProcessorGroup >= 0) 523 { 524 cwc = _snwprintf(pwszDst, cwcDst, L" --group %d", iProcessorGroup); 525 assert(cwc > 0 && cwc < cwcDst); 526 pwszDst += cwc; 527 cwcDst -= cwc; 528 } 492 529 *pwszDst = '\0'; 493 530 … … 549 586 warnx(pCtx, "warning: failed to set kWorker thread priority: %u\n", GetLastError()); 550 587 551 if (iProcessorGroup >= 0 )588 if (iProcessorGroup >= 0 && g_pfnSetThreadGroupAffinity) 552 589 { 553 590 GROUP_AFFINITY NewAff = { ~(uintptr_t)0, (WORD)iProcessorGroup, 0, 0, 0 }; … … 789 826 * @param fWatcomBrainDamage The wcc/wcc386 workaround. 790 827 * @param fNoPchCaching Whether to disable precompiled header caching. 828 * @param pszSpecialEnv Environment variable (name=value) subject to 829 * special expansion in kWorker. NULL if none. 791 830 * @param papszPostCmdArgs The post command and it's arguments. 792 831 * @param cPostCmdArgs Number of post command argument, including the … … 795 834 */ 796 835 static void *kSubmitComposeJobMessage(const char *pszExecutable, char **papszArgs, char **papszEnvVars, 797 const char *pszCwd, int fWatcomBrainDamage, int fNoPchCaching, 836 const char *pszCwd, int fWatcomBrainDamage, int fNoPchCaching, const char *pszSpecialEnv, 798 837 char **papszPostCmdArgs, uint32_t cPostCmdArgs, uint32_t *pcbMsg) 799 838 { 800 839 size_t cbTmp; 840 size_t cbSpecialEnv; 801 841 uint32_t i; 802 842 uint32_t cbMsg; … … 833 873 cbMsg += 1; /* fNoPchCaching */ 834 874 875 cbSpecialEnv = pszSpecialEnv ? strchr(pszSpecialEnv, '=') - pszSpecialEnv : 0; 876 cbMsg += cbSpecialEnv + 1; 877 835 878 cbMsg += sizeof(cPostCmdArgs); 836 879 for (i = 0; i < cPostCmdArgs; i++) … … 858 901 pbCursor += cbTmp; 859 902 860 /* argument */903 /* arguments */ 861 904 memcpy(pbCursor, &cArgs, sizeof(cArgs)); 862 905 pbCursor += sizeof(cArgs); … … 884 927 *pbCursor++ = fWatcomBrainDamage != 0; 885 928 *pbCursor++ = fNoPchCaching != 0; 929 930 /* Special environment variable name. */ 931 memcpy(pbCursor, pszSpecialEnv, cbSpecialEnv); 932 pbCursor += cbSpecialEnv; 933 *pbCursor++ = '\0'; 886 934 887 935 /* post command */ … … 1108 1156 #endif /* KBUILD_OS_WINDOWS */ 1109 1157 1158 1159 /** 1160 * Adds the given message to the history. 1161 * 1162 * @returns Pointer to old message, or NULL if no old msg to free. 1163 * @param pWorker The worker instance. 1164 * @param pvMsg The message. 1165 * @param cbMsg The message size. 1166 */ 1167 static void *kSubmitUpdateHistory(PWORKERINSTANCE pWorker, void *pvMsg, size_t cbMsg) 1168 { 1169 unsigned iHistory = pWorker->iHistory % K_ELEMENTS(pWorker->aHistory); 1170 void *pvRet; 1171 pWorker->iHistory++; 1172 pvRet = pWorker->aHistory[iHistory].pvMsg; 1173 pWorker->aHistory[iHistory].pvMsg = pvMsg; 1174 pWorker->aHistory[iHistory].cbMsg = cbMsg; 1175 return pvRet; 1176 } 1177 1178 typedef struct HISTORYDUMPBUF 1179 { 1180 char *pszBuf; 1181 size_t cbBuf; 1182 size_t off; 1183 PKMKBUILTINCTX pCtx; 1184 } HISTORYDUMPBUF; 1185 1186 1187 static void kSubmitDumpHistoryWrite(HISTORYDUMPBUF *pBuf, const char *pch, size_t cch) 1188 { 1189 if (pBuf->off + cch >= pBuf->cbBuf) 1190 { 1191 size_t cbNew = pBuf->cbBuf ? pBuf->cbBuf * 2 : 65536; 1192 while (pBuf->off + cch >= cbNew) 1193 cbNew *= 2; 1194 pBuf->pszBuf = (char *)xrealloc(pBuf->pszBuf, cbNew); 1195 pBuf->cbBuf = cbNew; 1196 } 1197 1198 memcpy(&pBuf->pszBuf[pBuf->off], pch, cch); 1199 pBuf->off += cch; 1200 pBuf->pszBuf[pBuf->off] = '\0'; 1201 } 1202 1203 static void kSubmitDumpHistoryPrintf(HISTORYDUMPBUF *pBuf, const char *pszFormat, ...) 1204 { 1205 char szTmp[32]; 1206 va_list va; 1207 va_start(va, pszFormat); 1208 for (;;) 1209 { 1210 const char *pszPct = strchr(pszFormat, '%'); 1211 if (!pszPct) 1212 { 1213 kSubmitDumpHistoryWrite(pBuf, pszFormat, strlen(pszFormat)); 1214 return; 1215 } 1216 if (pszPct != pszFormat) 1217 { 1218 kSubmitDumpHistoryWrite(pBuf, pszFormat, pszPct - pszFormat); 1219 pszFormat = pszPct; 1220 } 1221 pszFormat++; 1222 switch (*pszFormat++) 1223 { 1224 case 's': 1225 { 1226 const char * const psz = va_arg(va, const char *); 1227 size_t const cch = strlen(psz); 1228 if (memchr(psz, '\'', cch)) 1229 { 1230 kSubmitDumpHistoryWrite(pBuf, TUPLE("\"")); /** @todo what if there are '"' in the string? */ 1231 kSubmitDumpHistoryWrite(pBuf, psz, cch); 1232 kSubmitDumpHistoryWrite(pBuf, TUPLE("\"")); 1233 } 1234 else if ( !memchr(psz, ' ', cch) 1235 && !memchr(psz, '\t', cch) 1236 && !memchr(psz, '\n', cch) 1237 && !memchr(psz, '\r', cch) 1238 && !memchr(psz, '&', cch) 1239 && !memchr(psz, ';', cch) 1240 && !memchr(psz, '|', cch)) 1241 kSubmitDumpHistoryWrite(pBuf, psz, cch); 1242 else 1243 { 1244 kSubmitDumpHistoryWrite(pBuf, TUPLE("'")); 1245 kSubmitDumpHistoryWrite(pBuf, psz, strlen(psz)); 1246 kSubmitDumpHistoryWrite(pBuf, TUPLE("'")); 1247 } 1248 break; 1249 } 1250 1251 case 'd': 1252 { 1253 int iValue = va_arg(va, int); 1254 kSubmitDumpHistoryWrite(pBuf, szTmp, snprintf(szTmp, sizeof(szTmp), "%d", iValue)); 1255 break; 1256 } 1257 1258 case 'u': 1259 { 1260 unsigned uValue = va_arg(va, unsigned); 1261 kSubmitDumpHistoryWrite(pBuf, szTmp, snprintf(szTmp, sizeof(szTmp), "%u", uValue)); 1262 break; 1263 } 1264 1265 case '%': 1266 kSubmitDumpHistoryWrite(pBuf, "%s", 1); 1267 break; 1268 1269 default: 1270 assert(0); 1271 } 1272 } 1273 va_end(va); 1274 } 1275 1276 static void kSubmitDumpHistoryFlush(HISTORYDUMPBUF *pBuf) 1277 { 1278 if (pBuf->off > 0) 1279 output_write_text(pBuf->pCtx->pOut, 1, pBuf->pszBuf, pBuf->off); 1280 pBuf->off = 0; 1281 } 1282 1283 /** 1284 * Dumps the history for this worker to stderr in the given context. 1285 * 1286 * @param pCtx The command execution context. (Typically not a 1287 * real context.) 1288 * @param pWorker The worker instance. 1289 */ 1290 static void kSubmitDumpHistory(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker) 1291 { 1292 HISTORYDUMPBUF Buf = { NULL, 0, 0, pCtx }; 1293 int iHistory = pWorker->iHistory; 1294 unsigned cDumped = 0; 1295 1296 while (cDumped < K_ELEMENTS(pWorker->aHistory) && iHistory > 0) 1297 { 1298 unsigned const idx = (unsigned)--iHistory % K_ELEMENTS(pWorker->aHistory); 1299 const char *pszMsg = (const char *)pWorker->aHistory[idx].pvMsg; 1300 ssize_t cbMsg = pWorker->aHistory[idx].cbMsg; 1301 const char *pszExe; 1302 const char *pszCwd; 1303 uint32_t i; 1304 uint32_t cArgs; 1305 const char *pszArgs; 1306 size_t cbArgs; 1307 uint32_t cEnvVars; 1308 const char *pszEnvVars; 1309 size_t cbEnvVars; 1310 const char *pszSpecialEnv; 1311 char fNoPchCaching; 1312 char fWatcomBrainDamage; 1313 uint32_t cPostArgs; 1314 const char *pszPostArgs; 1315 size_t cbPostArgs; 1316 1317 cDumped++; 1318 if (!pszMsg || !cbMsg) 1319 break; 1320 1321 #define SKIP_BYTES(a_cbSkip) do { pszMsg += (a_cbSkip); cbMsg -= (a_cbSkip); } while (0) 1322 #define SKIP_STR() do { size_t const cbToSkip = strlen(pszMsg) + 1; SKIP_BYTES(cbToSkip); } while (0) 1323 #define SKIP_STRING_ARRAY(a_cStrings, a_cbPreable) do { \ 1324 for (i = 0; i < (a_cStrings) && cbMsg > 0; i++) { \ 1325 size_t const cbToSkip = (a_cbPreable) + strlen(pszMsg + (a_cbPreable)) + 1; \ 1326 SKIP_BYTES(cbToSkip); \ 1327 } } while (0) 1328 1329 /* Decode it: */ 1330 SKIP_BYTES(sizeof(uint32_t) + sizeof("JOB")); 1331 pszExe = pszMsg; 1332 SKIP_STR(); 1333 pszCwd = pszMsg; 1334 SKIP_STR(); 1335 1336 cArgs = *(uint32_t *)pszMsg; 1337 SKIP_BYTES(sizeof(uint32_t)); 1338 pszArgs = pszMsg; 1339 SKIP_STRING_ARRAY(cArgs, 1 /*fbFlags*/); 1340 cbArgs = pszMsg - pszArgs; 1341 1342 cEnvVars = *(uint32_t *)pszMsg; 1343 SKIP_BYTES(sizeof(uint32_t)); 1344 pszEnvVars = pszMsg; 1345 SKIP_STRING_ARRAY(cEnvVars, 0); 1346 cbEnvVars = pszMsg - pszEnvVars; 1347 1348 fWatcomBrainDamage = pszMsg[0] != '\0'; 1349 fNoPchCaching = pszMsg[1] != '\0'; 1350 SKIP_BYTES(2); 1351 1352 pszSpecialEnv = pszMsg; 1353 SKIP_STR(); 1354 1355 cPostArgs = *(uint32_t *)pszMsg; 1356 SKIP_BYTES(sizeof(uint32_t)); 1357 pszPostArgs = pszMsg; 1358 SKIP_STRING_ARRAY(cPostArgs, 0); 1359 cbPostArgs = pszMsg - pszPostArgs; 1360 1361 /* Produce parseable output: */ 1362 kSubmitDumpHistoryPrintf(&Buf, "kWorker %u/%u:\n\tkSubmit", (long)pWorker->pid, iHistory, pszExe); 1363 if (fNoPchCaching) 1364 kSubmitDumpHistoryWrite(&Buf, TUPLE(" --no-pch-caching")); 1365 if (fWatcomBrainDamage) 1366 kSubmitDumpHistoryWrite(&Buf, TUPLE(" --watcom-brain-damage")); 1367 if (pszSpecialEnv) 1368 kSubmitDumpHistoryPrintf(&Buf, " --special-env %s", pszSpecialEnv); 1369 kSubmitDumpHistoryPrintf(&Buf, " --chdir %s \\\n", pszCwd); 1370 1371 pszMsg = pszEnvVars; 1372 cbMsg = cbEnvVars; 1373 for (i = 0; i < cEnvVars && cbMsg > 0; i++) 1374 { 1375 kSubmitDumpHistoryPrintf(&Buf, "\t--putenv %s \\\n", pszMsg); 1376 SKIP_STR(); 1377 } 1378 1379 if (cPostArgs > 0) 1380 { 1381 kSubmitDumpHistoryWrite(&Buf, TUPLE("\t--post-cmd ")); 1382 pszMsg = pszPostArgs; 1383 cbMsg = cbPostArgs; 1384 for (i = 0; i < cPostArgs && cbMsg > 0; i++) 1385 { 1386 kSubmitDumpHistoryPrintf(&Buf, " %s", pszMsg); 1387 SKIP_STR(); 1388 } 1389 kSubmitDumpHistoryWrite(&Buf, TUPLE(" \\\n")); 1390 } 1391 kSubmitDumpHistoryWrite(&Buf, TUPLE("\t-- \\\n")); 1392 1393 pszMsg = pszArgs; 1394 cbMsg = cbArgs; 1395 for (i = 0; i < cArgs && cbMsg > 0; i++) 1396 { 1397 SKIP_BYTES(1); 1398 kSubmitDumpHistoryPrintf(&Buf, i + 1 < cArgs ? "\t%s \\\n" : "\t%s\n", pszMsg); 1399 SKIP_STR(); 1400 } 1401 1402 #undef SKIP_BYTES 1403 #undef SKIP_STR 1404 #undef SKIP_STRING_ARRAY 1405 } 1406 1407 kSubmitDumpHistoryFlush(&Buf); 1408 free(Buf.pszBuf); 1409 } 1410 1411 1110 1412 /** 1111 1413 * Marks the worker active. … … 1168 1470 if (pWorker->Result.s.bWorkerExiting) 1169 1471 kSubmitCloseConnectOnExitingWorker(pCtx, pWorker); 1472 if (pWorker->Result.s.rcExit && 1) 1473 kSubmitDumpHistory(pCtx, pWorker); 1170 1474 *pPidSpawned = 0; 1171 1475 return pWorker->Result.s.rcExit; … … 1247 1551 case STATUS_ILLEGAL_INSTRUCTION: *piSigNo = SIGILL; break; 1248 1552 } 1553 if (pWorker->Result.s.rcExit && 1) 1554 kSubmitDumpHistory(pCtx, pWorker); 1249 1555 if (pWorker->Result.s.bWorkerExiting) 1250 1556 kSubmitCloseConnectOnExitingWorker(pCtx, pWorker); … … 1410 1716 "usage: %s [-Z|--zap-env] [-E|--set <var=val>] [-U|--unset <var=val>]\n" 1411 1717 " [-A|--append <var=val>] [-D|--prepend <var=val>]\n" 1412 " [-C|--chdir <dir>] [--wcc-brain-damage] [--no-pch-caching]\n" 1413 " [-3|--32-bit] [-6|--64-bit] [-v]\n" 1718 " [-s|--special-env <var=val>] [-C|--chdir <dir>]\n" 1719 " [--wcc-brain-damage] [--no-pch-caching]\n" 1720 " [-3|--32-bit] [-6|--64-bit] [-v] [--debug-dump-history]\n" 1414 1721 " [-P|--post-cmd <cmd> [args]] -- <program> [args]\n" 1415 1722 " or: %s --help\n" … … 1420 1727 " Zaps the environment. Position dependent.\n" 1421 1728 " -E, --set <var>=[value]\n" 1422 " Sets an envi ornment variable putenv fashion. Position dependent.\n"1729 " Sets an environment variable putenv fashion. Position dependent.\n" 1423 1730 " -U, --unset <var>\n" 1424 1731 " Removes an environment variable. Position dependent.\n" … … 1427 1734 " -D,--prepend <var>=<value>\n" 1428 1735 " Prepends the given value to the environment variable.\n" 1736 " -s,--special-env <var>=<value>\n" 1737 " Same as --set, but flags the variable for further expansion\n" 1738 " within kWorker. Replacements:\n" 1739 " @@PROCESSOR_GROUP@@ - The processor group number.\n" 1740 " @@AUTHENTICATION_ID@@ - The authentication ID from the process token.\n" 1741 " @@PID@@ - The kWorker process ID.\n" 1742 " @@@@ - Escaped \"@@\".\n" 1743 " @@DEBUG_COUNTER@@ - An ever increasing counter (starts at zero).\n" 1429 1744 " -C, --chdir <dir>\n" 1430 1745 " Specifies the current directory for the program. Relative paths\n" … … 1441 1756 " -v,--verbose\n" 1442 1757 " More verbose execution.\n" 1758 " --debug-dump-history\n" 1759 " Dump the history as of the submitted command. Handy for debuging\n" 1760 " trouble caused by a previous job.\n" 1443 1761 " -P|--post-cmd <cmd> ...\n" 1444 1762 " For running a built-in command on the output, specifying the command\n" … … 1458 1776 int kmk_builtin_kSubmit(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned) 1459 1777 { 1778 #ifdef KBUILD_OS_WINDOWS 1779 static int s_fInitialized = 0; 1780 #endif 1460 1781 int rcExit = 0; 1461 1782 int iArg; … … 1464 1785 char **papszEnvVars; 1465 1786 const char *pszExecutable = NULL; 1787 const char *pszSpecialEnv = NULL; 1466 1788 int iPostCmd = argc; 1467 1789 int cPostCmdArgs = 0; … … 1469 1791 int fWatcomBrainDamage = 0; 1470 1792 int fNoPchCaching = 0; 1793 int fDebugDumpHistory = 0; 1471 1794 int cVerbosity = 0; 1472 1795 size_t const cbCwdBuf = GET_PATH_MAX; 1473 1796 PATH_VAR(szCwd); 1797 1798 #ifdef KBUILD_OS_WINDOWS 1799 /* 1800 * First time thru we must perform some initializations. 1801 */ 1802 if (s_fInitialized) 1803 { } 1804 else 1805 { 1806 MkWinChildInitCpuGroupAllocator(&g_SubmitProcessorGroupAllocator); 1807 # if K_ARCH_BITS == 64 1808 MkWinChildInitCpuGroupAllocator(&g_SubmitProcessorGroupAllocator32); 1809 # endif 1810 *(FARPROC *)&g_pfnSetThreadGroupAffinity = GetProcAddress(GetModuleHandleW(L"KERNEL32.DLL"), "SetThreadGroupAffinity"); 1811 s_fInitialized = 1; 1812 } 1813 #endif 1474 1814 1475 1815 /* … … 1533 1873 } 1534 1874 1875 if (strcmp(pszArg, "debug-dump-history") == 0) 1876 { 1877 fDebugDumpHistory = 1; 1878 continue; 1879 } 1880 1881 1535 1882 /* convert to short. */ 1536 1883 if (strcmp(pszArg, "help") == 0) … … 1551 1898 else if (strcmp(pszArg, "chdir") == 0) 1552 1899 chOpt = 'C'; 1900 else if (strcmp(pszArg, "set-special") == 0) 1901 chOpt = 's'; 1553 1902 else if (strcmp(pszArg, "post-cmd") == 0) 1554 1903 chOpt = 'P'; … … 1581 1930 case 'D': 1582 1931 case 'e': 1932 case 's': 1583 1933 if (*pszArg != '\0') 1584 1934 pszValue = pszArg + (*pszArg == ':' || *pszArg == '='); … … 1628 1978 case 'C': 1629 1979 rcExit = kBuiltinOptChDir(pCtx, szCwd, cbCwdBuf, pszValue); 1980 if (rcExit == 0) 1981 break; 1982 return rcExit; 1983 1984 case 's': 1985 if (pszSpecialEnv) 1986 return errx(pCtx, 1, "The -s option can only be used once!"); 1987 pszSpecialEnv = pszValue; 1988 rcExit = kBuiltinOptEnvSet(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); 1630 1989 if (rcExit == 0) 1631 1990 break; … … 1687 2046 uint32_t cbMsg; 1688 2047 void *pvMsg = kSubmitComposeJobMessage(pszExecutable, &argv[iArg], papszEnvVars, szCwd, 1689 fWatcomBrainDamage, fNoPchCaching, 2048 fWatcomBrainDamage, fNoPchCaching, pszSpecialEnv, 1690 2049 &argv[iPostCmd], cPostCmdArgs, &cbMsg); 1691 2050 PWORKERINSTANCE pWorker = kSubmitSelectWorkSpawnNewIfNecessary(pCtx, cBitsWorker, cVerbosity); … … 1703 2062 rcExit = kSubmitSendJobMessage(pCtx, pWorker, pvMsg, cbMsg, 0 /*fNoRespawning*/, cVerbosity); 1704 2063 if (rcExit == 0) 2064 { 2065 pvMsg = kSubmitUpdateHistory(pWorker, pvMsg, cbMsg); 2066 if (fDebugDumpHistory) 2067 kSubmitDumpHistory(pCtx, pWorker); 1705 2068 rcExit = kSubmitMarkActive(pCtx, pWorker, cVerbosity, pChild, pPidSpawned); 2069 } 1706 2070 1707 2071 if (!g_fAtExitRegistered) … … 1723 2087 } 1724 2088 1725 1726 -
trunk/src/kmk/w32/winchildren.c
r3224 r3313 334 334 /** Pointer to childcare workers. */ 335 335 static PWINCHILDCAREWORKER *g_papChildCareworkers = NULL; 336 /** The group index for the worker allocator. 337 * This is ever increasing and must be modded by g_cProcessorGroups. */ 338 static unsigned g_idxProcessorGroupAllocator = 0; 339 /** The processor in group index for the worker allocator. */ 340 static unsigned g_idxProcessorInGroupAllocator = 0; 336 /** The processor group allocator state. */ 337 static MKWINCHILDCPUGROUPALLOCSTATE g_ProcessorGroupAllocator; 341 338 /** Number of processor groups in the system. */ 342 339 static unsigned g_cProcessorGroups = 1; … … 468 465 pacProcessorsInGroup[iGroup] = g_pfnGetActiveProcessorCount(iGroup); 469 466 470 /* We shift the starting group with the make nesting level as part of 471 our very simple distribution strategy. */ 472 g_idxProcessorGroupAllocator = makelevel; 467 MkWinChildInitCpuGroupAllocator(&g_ProcessorGroupAllocator); 473 468 } 474 469 else … … 2635 2630 2636 2631 /** 2632 * Initializes the processor group allocator. 2633 * 2634 * @param pState The allocator to initialize. 2635 */ 2636 void MkWinChildInitCpuGroupAllocator(PMKWINCHILDCPUGROUPALLOCSTATE pState) 2637 { 2638 /* We shift the starting group with the make nesting level as part of 2639 our very simple distribution strategy. */ 2640 pState->idxGroup = makelevel; 2641 pState->idxProcessorInGroup = 0; 2642 } 2643 2644 /** 2645 * Allocate CPU group for the next child process. 2646 * 2647 * @returns CPU group. 2648 * @param pState The allocator state. Must be initialized by 2649 * MkWinChildInitCpuGroupAllocator(). 2650 */ 2651 unsigned int MkWinChildAllocateCpuGroup(PMKWINCHILDCPUGROUPALLOCSTATE pState) 2652 { 2653 unsigned int iGroup = 0; 2654 if (g_cProcessorGroups > 1) 2655 { 2656 unsigned int cMaxInGroup; 2657 unsigned int cInGroup; 2658 2659 iGroup = pState->idxGroup % g_cProcessorGroups; 2660 2661 /* Advance. We employ a very simple strategy that does 50% in 2662 each group for each group cycle. Odd processor counts are 2663 caught in odd group cycles. The init function selects the 2664 starting group based on make nesting level to avoid stressing 2665 out the first group. */ 2666 cInGroup = ++pState->idxProcessorInGroup; 2667 cMaxInGroup = g_pacProcessorsInGroup[iGroup]; 2668 if ( !(cMaxInGroup & 1) 2669 || !((pState->idxGroup / g_cProcessorGroups) & 1)) 2670 cMaxInGroup /= 2; 2671 else 2672 cMaxInGroup = cMaxInGroup / 2 + 1; 2673 if (cInGroup >= cMaxInGroup) 2674 { 2675 pState->idxProcessorInGroup = 0; 2676 pState->idxGroup++; 2677 } 2678 } 2679 return iGroup; 2680 } 2681 2682 /** 2637 2683 * Creates another childcare worker. 2638 2684 * … … 2654 2700 { 2655 2701 /* Before we start the thread, assign it to a processor group. */ 2656 if (g_cProcessorGroups > 1) 2657 { 2658 unsigned int cMaxInGroup; 2659 unsigned int cInGroup; 2660 unsigned int iGroup = g_idxProcessorGroupAllocator % g_cProcessorGroups; 2661 pWorker->iProcessorGroup = iGroup; 2662 2663 /* Advance. We employ a very simple strategy that does 50% in 2664 each group for each group cycle. Odd processor counts are 2665 caught in odd group cycles. The init function selects the 2666 starting group based on make nesting level to avoid stressing 2667 out the first group. */ 2668 cInGroup = ++g_idxProcessorInGroupAllocator; 2669 cMaxInGroup = g_pacProcessorsInGroup[iGroup]; 2670 if ( !(cMaxInGroup & 1) 2671 || !((g_idxProcessorGroupAllocator / g_cProcessorGroups) & 1)) 2672 cMaxInGroup /= 2; 2673 else 2674 cMaxInGroup = cMaxInGroup / 2 + 1; 2675 if (cInGroup >= cMaxInGroup) 2676 { 2677 g_idxProcessorInGroupAllocator = 0; 2678 g_idxProcessorGroupAllocator++; 2679 } 2680 } 2702 pWorker->iProcessorGroup = MkWinChildAllocateCpuGroup(&g_ProcessorGroupAllocator); 2681 2703 2682 2704 /* Try start the thread. */ … … 3414 3436 * that completed children is the typical source of these tokens (esp. for kmk). 3415 3437 * 3416 * @returns Zero if completedchildren, event handle if waiting is required.3438 * @returns Zero if no active children, event handle if waiting is required. 3417 3439 */ 3418 3440 intptr_t MkWinChildGetCompleteEventHandle(void) -
trunk/src/kmk/w32/winchildren.h
r3200 r3313 26 26 #ifndef INCLUDED_WINCHILDREN_H 27 27 #define INCLUDED_WINCHILDREN_H 28 29 /** Child processor group allocator state. */ 30 typedef struct MKWINCHILDCPUGROUPALLOCSTATE 31 { 32 /** The group index for the worker allocator. 33 * This is ever increasing and must be modded by g_cProcessorGroups. */ 34 unsigned int idxGroup; 35 /** The processor in group index for the worker allocator. */ 36 unsigned int idxProcessorInGroup; 37 } MKWINCHILDCPUGROUPALLOCSTATE; 38 /** Pointer to a CPU group allocator state. */ 39 typedef MKWINCHILDCPUGROUPALLOCSTATE *PMKWINCHILDCPUGROUPALLOCSTATE; 28 40 29 41 #ifdef DECLARE_HANDLE … … 68 80 int MkWinChildCreate(char **papszArgs, char **papszEnv, const char *pszShell, struct child *pMkChild, pid_t *pPid); 69 81 int MkWinChildCreateWithStdOutPipe(char **papszArgs, char **papszEnv, int fdErr, pid_t *pPid, int *pfdReadPipe); 82 void MkWinChildInitCpuGroupAllocator(PMKWINCHILDCPUGROUPALLOCSTATE pState); 83 unsigned int MkWinChildAllocateCpuGroup(PMKWINCHILDCPUGROUPALLOCSTATE pState); 84 70 85 #ifdef KMK 71 86 struct KMKBUILTINENTRY; … … 86 101 char **papszEnvVars, const char *pszCwd, BOOL pafReplace[3], HANDLE pahReplace[3]); 87 102 # endif 88 #endif 103 #endif /* KMK */ 89 104 int MkWinChildKill(pid_t pid, int iSignal, struct child *pMkChild); 90 105 int MkWinChildWait(int fBlock, pid_t *pPid, int *piExitCode, int *piSignal, int *pfCoreDumped, struct child **ppMkChild);
Note:
See TracChangeset
for help on using the changeset viewer.