Changeset 3313 for trunk/src/kmk


Ignore:
Timestamp:
Mar 16, 2020, 3:31:38 AM (5 years ago)
Author:
bird
Message:

kmk,kWorker: Assign processor groups to kWorker processes. Added --special-env hack for having a mspdbsrv.exe instance per processor group (using _MSPDBSRV_ENDPOINT_). This was complicated by PCH requiring to share .pdb file and therefore mspdbsrv.exe instance, requiring a mspdb100.dll re-init hack to disconnect kWorker from the previous mspdbsrv when switching. fun.

Location:
trunk/src/kmk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/kmkbuiltin/kSubmit.c

    r3224 r3313  
    121121    int                     fdSocket;
    122122#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];
    123134
    124135    /** What it's busy with.  NULL if idle. */
     
    181192
    182193#ifdef KBUILD_OS_WINDOWS
     194/** The processor group allocator state. */
     195static MKWINCHILDCPUGROUPALLOCSTATE g_SubmitProcessorGroupAllocator;
     196# if K_ARCH_BITS == 64
     197/** The processor group allocator state for 32-bit processes. */
     198static MKWINCHILDCPUGROUPALLOCSTATE g_SubmitProcessorGroupAllocator32;
     199# endif
     200#endif
     201
     202#ifdef KBUILD_OS_WINDOWS
    183203/** Pointer to kernel32!SetThreadGroupAffinity. */
    184204static BOOL (WINAPI *g_pfnSetThreadGroupAffinity)(HANDLE, const GROUP_AFFINITY*, GROUP_AFFINITY *);
     
    428448    {
    429449#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
    434464
    435465        /*
     
    464494                {
    465495                    extern int          process_priority; /* main.c */
    466                     wchar_t             wszCommandLine[MAX_PATH * 3];
     496                    wchar_t             wszCommandLine[MAX_PATH * 3 + 32];
    467497                    wchar_t            *pwszDst = wszCommandLine;
    468498                    size_t              cwcDst = K_ELEMENTS(wszCommandLine);
     
    490520                        cwcDst  -= cwc;
    491521                    }
     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                    }
    492529                    *pwszDst = '\0';
    493530
     
    549586                                warnx(pCtx, "warning: failed to set kWorker thread priority: %u\n", GetLastError());
    550587
    551                             if (iProcessorGroup >= 0)
     588                            if (iProcessorGroup >= 0 && g_pfnSetThreadGroupAffinity)
    552589                            {
    553590                                GROUP_AFFINITY NewAff = { ~(uintptr_t)0, (WORD)iProcessorGroup, 0, 0, 0 };
     
    789826 * @param   fWatcomBrainDamage  The wcc/wcc386 workaround.
    790827 * @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.
    791830 * @param   papszPostCmdArgs    The post command and it's arguments.
    792831 * @param   cPostCmdArgs        Number of post command argument, including the
     
    795834 */
    796835static 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,
    798837                                      char **papszPostCmdArgs, uint32_t cPostCmdArgs, uint32_t *pcbMsg)
    799838{
    800839    size_t   cbTmp;
     840    size_t   cbSpecialEnv;
    801841    uint32_t i;
    802842    uint32_t cbMsg;
     
    833873    cbMsg += 1; /* fNoPchCaching */
    834874
     875    cbSpecialEnv = pszSpecialEnv ? strchr(pszSpecialEnv, '=') - pszSpecialEnv : 0;
     876    cbMsg += cbSpecialEnv + 1;
     877
    835878    cbMsg += sizeof(cPostCmdArgs);
    836879    for (i = 0; i < cPostCmdArgs; i++)
     
    858901    pbCursor += cbTmp;
    859902
    860     /* argument */
     903    /* arguments */
    861904    memcpy(pbCursor, &cArgs, sizeof(cArgs));
    862905    pbCursor += sizeof(cArgs);
     
    884927    *pbCursor++ = fWatcomBrainDamage != 0;
    885928    *pbCursor++ = fNoPchCaching != 0;
     929
     930    /* Special environment variable name. */
     931    memcpy(pbCursor, pszSpecialEnv, cbSpecialEnv);
     932    pbCursor += cbSpecialEnv;
     933    *pbCursor++ = '\0';
    886934
    887935    /* post command */
     
    11081156#endif /* KBUILD_OS_WINDOWS */
    11091157
     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 */
     1167static 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
     1178typedef struct HISTORYDUMPBUF
     1179{
     1180    char           *pszBuf;
     1181    size_t          cbBuf;
     1182    size_t          off;
     1183    PKMKBUILTINCTX  pCtx;
     1184} HISTORYDUMPBUF;
     1185
     1186
     1187static 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
     1203static 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
     1276static 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 */
     1290static 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
    11101412/**
    11111413 * Marks the worker active.
     
    11681470        if (pWorker->Result.s.bWorkerExiting)
    11691471            kSubmitCloseConnectOnExitingWorker(pCtx, pWorker);
     1472        if (pWorker->Result.s.rcExit && 1)
     1473            kSubmitDumpHistory(pCtx, pWorker);
    11701474        *pPidSpawned = 0;
    11711475        return pWorker->Result.s.rcExit;
     
    12471551        case STATUS_ILLEGAL_INSTRUCTION:        *piSigNo = SIGILL; break;
    12481552    }
     1553    if (pWorker->Result.s.rcExit && 1)
     1554        kSubmitDumpHistory(pCtx, pWorker);
    12491555    if (pWorker->Result.s.bWorkerExiting)
    12501556        kSubmitCloseConnectOnExitingWorker(pCtx, pWorker);
     
    14101716                           "usage: %s [-Z|--zap-env] [-E|--set <var=val>] [-U|--unset <var=val>]\n"
    14111717                           "           [-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"
    14141721                           "           [-P|--post-cmd <cmd> [args]] -- <program> [args]\n"
    14151722                           "   or: %s --help\n"
     
    14201727                           "    Zaps the environment. Position dependent.\n"
    14211728                           "  -E, --set <var>=[value]\n"
    1422                            "    Sets an enviornment variable putenv fashion. Position dependent.\n"
     1729                           "    Sets an environment variable putenv fashion. Position dependent.\n"
    14231730                           "  -U, --unset <var>\n"
    14241731                           "    Removes an environment variable. Position dependent.\n"
     
    14271734                           "  -D,--prepend <var>=<value>\n"
    14281735                           "    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"
    14291744                           "  -C, --chdir <dir>\n"
    14301745                           "    Specifies the current directory for the program.  Relative paths\n"
     
    14411756                           "  -v,--verbose\n"
    14421757                           "    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"
    14431761                           "  -P|--post-cmd <cmd> ...\n"
    14441762                           "    For running a built-in command on the output, specifying the command\n"
     
    14581776int kmk_builtin_kSubmit(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned)
    14591777{
     1778#ifdef KBUILD_OS_WINDOWS
     1779    static int      s_fInitialized      = 0;
     1780#endif
    14601781    int             rcExit = 0;
    14611782    int             iArg;
     
    14641785    char          **papszEnvVars;
    14651786    const char     *pszExecutable       = NULL;
     1787    const char     *pszSpecialEnv       = NULL;
    14661788    int             iPostCmd            = argc;
    14671789    int             cPostCmdArgs        = 0;
     
    14691791    int             fWatcomBrainDamage  = 0;
    14701792    int             fNoPchCaching       = 0;
     1793    int             fDebugDumpHistory   = 0;
    14711794    int             cVerbosity          = 0;
    14721795    size_t const    cbCwdBuf            = GET_PATH_MAX;
    14731796    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
    14741814
    14751815    /*
     
    15331873                }
    15341874
     1875                if (strcmp(pszArg, "debug-dump-history") == 0)
     1876                {
     1877                    fDebugDumpHistory = 1;
     1878                    continue;
     1879                }
     1880
     1881
    15351882                /* convert to short. */
    15361883                if (strcmp(pszArg, "help") == 0)
     
    15511898                else if (strcmp(pszArg, "chdir") == 0)
    15521899                    chOpt = 'C';
     1900                else if (strcmp(pszArg, "set-special") == 0)
     1901                    chOpt = 's';
    15531902                else if (strcmp(pszArg, "post-cmd") == 0)
    15541903                    chOpt = 'P';
     
    15811930                    case 'D':
    15821931                    case 'e':
     1932                    case 's':
    15831933                        if (*pszArg != '\0')
    15841934                            pszValue = pszArg + (*pszArg == ':' || *pszArg == '=');
     
    16281978                    case 'C':
    16291979                        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);
    16301989                        if (rcExit == 0)
    16311990                            break;
     
    16872046        uint32_t        cbMsg;
    16882047        void           *pvMsg   = kSubmitComposeJobMessage(pszExecutable, &argv[iArg], papszEnvVars, szCwd,
    1689                                                            fWatcomBrainDamage, fNoPchCaching,
     2048                                                           fWatcomBrainDamage, fNoPchCaching, pszSpecialEnv,
    16902049                                                           &argv[iPostCmd], cPostCmdArgs, &cbMsg);
    16912050        PWORKERINSTANCE pWorker = kSubmitSelectWorkSpawnNewIfNecessary(pCtx, cBitsWorker, cVerbosity);
     
    17032062            rcExit = kSubmitSendJobMessage(pCtx, pWorker, pvMsg, cbMsg, 0 /*fNoRespawning*/, cVerbosity);
    17042063            if (rcExit == 0)
     2064            {
     2065                pvMsg = kSubmitUpdateHistory(pWorker, pvMsg, cbMsg);
     2066                if (fDebugDumpHistory)
     2067                    kSubmitDumpHistory(pCtx, pWorker);
    17052068                rcExit = kSubmitMarkActive(pCtx, pWorker, cVerbosity, pChild, pPidSpawned);
     2069            }
    17062070
    17072071            if (!g_fAtExitRegistered)
     
    17232087}
    17242088
    1725 
    1726 
  • trunk/src/kmk/w32/winchildren.c

    r3224 r3313  
    334334/** Pointer to childcare workers. */
    335335static 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. */
     337static MKWINCHILDCPUGROUPALLOCSTATE g_ProcessorGroupAllocator;
    341338/** Number of processor groups in the system.   */
    342339static unsigned             g_cProcessorGroups = 1;
     
    468465                pacProcessorsInGroup[iGroup] = g_pfnGetActiveProcessorCount(iGroup);
    469466
    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);
    473468        }
    474469        else
     
    26352630
    26362631/**
     2632 * Initializes the processor group allocator.
     2633 *
     2634 * @param   pState              The allocator to initialize.
     2635 */
     2636void 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 */
     2651unsigned 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/**
    26372683 * Creates another childcare worker.
    26382684 *
     
    26542700            {
    26552701                /* 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);
    26812703
    26822704                /* Try start the thread. */
     
    34143436 * that completed children is the typical source of these tokens (esp. for kmk).
    34153437 *
    3416  * @returns Zero if completed children, event handle if waiting is required.
     3438 * @returns Zero if no active children, event handle if waiting is required.
    34173439 */
    34183440intptr_t MkWinChildGetCompleteEventHandle(void)
  • trunk/src/kmk/w32/winchildren.h

    r3200 r3313  
    2626#ifndef INCLUDED_WINCHILDREN_H
    2727#define INCLUDED_WINCHILDREN_H
     28
     29/** Child processor group allocator state. */
     30typedef 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.   */
     39typedef MKWINCHILDCPUGROUPALLOCSTATE *PMKWINCHILDCPUGROUPALLOCSTATE;
    2840
    2941#ifdef DECLARE_HANDLE
     
    6880int     MkWinChildCreate(char **papszArgs, char **papszEnv, const char *pszShell, struct child *pMkChild, pid_t *pPid);
    6981int     MkWinChildCreateWithStdOutPipe(char **papszArgs, char **papszEnv, int fdErr, pid_t *pPid, int *pfdReadPipe);
     82void    MkWinChildInitCpuGroupAllocator(PMKWINCHILDCPUGROUPALLOCSTATE pState);
     83unsigned int MkWinChildAllocateCpuGroup(PMKWINCHILDCPUGROUPALLOCSTATE pState);
     84
    7085#ifdef KMK
    7186struct KMKBUILTINENTRY;
     
    86101                                   char **papszEnvVars, const char *pszCwd, BOOL pafReplace[3], HANDLE pahReplace[3]);
    87102# endif
    88 #endif
     103#endif /* KMK */
    89104int     MkWinChildKill(pid_t pid, int iSignal, struct child *pMkChild);
    90105int     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.