VirtualBox

Changeset 1008 in kBuild


Ignore:
Timestamp:
Jun 2, 2007 4:22:27 PM (18 years ago)
Author:
bird
Message:

precompile pipe.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kObjCache/kObjCache.c

    r1005 r1008  
    7474# define IS_SLASH_DRV(ch)   ((ch) == '/')
    7575#endif
     76/** Use pipe instead of temp files when possible (speed). */
     77#define USE_PIPE 1
    7678
    7779
     
    108110    /** Set if the object needs to be (re)compiled. */
    109111    unsigned fNeedCompiling;
     112    /** Whether the precompiler runs in piped mode. If clear it's file
     113     * mode (it could be redirected stdout, but that's essentially the
     114     * same from our point of view). */
     115    unsigned fPiped;
    110116
    111117    /** The name of new precompiled output. */
     
    114120    char *pszNewCppMapping;
    115121    /** The size of the new precompiled output 'mapping'. */
    116     size_t cbNewCppMapping;
     122    size_t cbNewCpp;
    117123    /** The new checksum. */
    118124    KOCSUM NewSum;
     
    124130    /** Pointer to the 'mapping' of the old precompiled output. */
    125131    char *pszOldCppMapping;
    126     /** The size of the old precompiled output 'mapping'. */
    127     size_t cbOldCppMapping;
     132    /** The size of the old precompiled output. */
     133    size_t cbOldCpp;
    128134
    129135    /** The head of the checksum list. */
     
    333339                        break;
    334340                    pEntry->pszOldCppName = xstrdup(pszVal);
     341                }
     342                else if (!strcmp(s_szLine, "cpp-size"))
     343                {
     344                    char *pszNext;
     345                    if ((fBad = pEntry->cbOldCpp != 0))
     346                        break;
     347                    pEntry->cbOldCpp = strtoul(pszVal, &pszNext, 0);
     348                    if ((fBad = pszNext && *pszNext))
     349                        break;
    335350                }
    336351                else if (!strcmp(s_szLine, "cc-argc"))
     
    462477    CHECK_LEN(fprintf(pFile, "obj=%s\n", pEntry->pszNewObjName ? pEntry->pszNewObjName : pEntry->pszObjName));
    463478    CHECK_LEN(fprintf(pFile, "cpp=%s\n", pEntry->pszNewCppName ? pEntry->pszNewCppName : pEntry->pszOldCppName));
     479    CHECK_LEN(fprintf(pFile, "cpp-size=%lu\n", pEntry->pszNewCppName ? pEntry->cbNewCpp : pEntry->cbOldCpp));
    464480    CHECK_LEN(fprintf(pFile, "cc-argc=%u\n", pEntry->cArgvCompile));
    465481    for (i = 0; i < pEntry->cArgvCompile; i++)
     
    509525            kObjCacheFatal(pEntry, "%s - failed to create stdout redirection file '%s': %s\n",
    510526                           pszMsg, pszStdOut, strerror(errno));
     527
    511528        if (fdReDir != 1)
    512529        {
     
    555572                       pszMsg, rc, errno, strerror(errno));
    556573    }
     574    if (pid == -1)
     575        kObjCacheFatal(pEntry, "%s - fork() failed: %s\n", pszMsg, strerror(errno));
     576
    557577    pidWait = waitpid(pid, &iStatus);
    558578    while (pidWait < 0 && errno == EINTR)
    559579        pidWait = waitpid(pid, &iStatus);
    560580    if (pidWait != pid)
    561         kObjCacheFatal(pEntry, "%s - waitpid failed rc=%d errno=%d %s\n",
    562                        pszMsg, rc, errno, strerror(errno));
     581        kObjCacheFatal(pEntry, "%s - waitpid failed rc=%d: %s\n",
     582                       pszMsg, pidWait, strerror(errno));
    563583    if (!WIFEXITED(iStatus))
    564584        kObjCacheFatal(pEntry, "%s - abended (iStatus=%#x)\n", pszMsg, iStatus);
     
    570590
    571591
    572 /**
    573  * Worker for kObjCachePreCompile and calculates the checksum of
    574  * the precompiler output.
    575  *
    576  * @param   pEntry      The cache entry. NewSum will be updated.
    577  */
    578 static void kObjCacheCalcChecksum(PKOBJCACHE pEntry)
    579 {
    580     struct MD5Context MD5Ctx;
    581 
    582     /*
    583      * Read/maps the entire file into a buffer and does the crc sums
    584      * on the buffer. This assumes the precompiler output isn't
    585      * gigantic, but that's a pretty safe assumption I hope...
    586      */
    587     pEntry->pszNewCppMapping = ReadFileInDir(pEntry->pszNewCppName, pEntry->pszDir, &pEntry->cbNewCppMapping);
     592#ifdef USE_PIPE
     593/**
     594 * Spawns a child in a synchronous fashion.
     595 * Terminating on failure.
     596 *
     597 * @param   papszArgv       Argument vector. The cArgv element is NULL.
     598 * @param   cArgv           The number of arguments in the vector.
     599 */
     600static void kObjCacheSpawnPipe(PCKOBJCACHE pEntry, const char **papszArgv, unsigned cArgv, const char *pszMsg, char **ppszOutput, size_t *pcchOutput)
     601{
     602    int fds[2];
     603    int iStatus;
     604#if defined(__WIN__)
     605    intptr_t pid, pidWait;
     606#else
     607    pid_t pid, pidWait;
     608#endif
     609    int fdStdOut;
     610    size_t cbAlloc;
     611    size_t cbLeft;
     612    char *psz;
     613
     614    /*
     615     * Setup the pipe.
     616     */
     617#if defined(__WIN__)
     618    if (_pipe(fds, 0, _O_NOINHERIT | _O_BINARY) < 0)
     619#else
     620    if (pipe(fds) < 0)
     621#endif
     622        kObjCacheFatal(pEntry, "pipe failed: %s\n", strerror(errno));
     623    fdStdOut = dup(1);
     624    if (dup2(fds[1 /* write */], 1) < 0)
     625        kObjCacheFatal(pEntry, "dup2(,1) failed: %s\n", strerror(errno));
     626    close(fds[1]);
     627    fds[1] = -1;
     628#ifndef __WIN__
     629    fcntl(fds[0], F_SETFD, FD_CLOEXEC);
     630    fcntl(fdStdOut, F_SETFD, FD_CLOEXEC);
     631#endif
     632
     633    /*
     634     * Create the child process.
     635     */
     636#if defined(__OS2__) || defined(__WIN__)
     637    errno = 0;
     638    pid = _spawnvp(_P_NOWAIT, papszArgv[0], papszArgv);
     639    if (pid == -1)
     640        kObjCacheFatal(pEntry, "%s - _spawnvp failed: %s\n", pszMsg, strerror(errno));
     641
     642#else
     643    pid = fork();
     644    if (!pid)
     645    {
     646        execvp(papszArgv[0], papszArgv);
     647        kObjCacheFatal(pEntry, "%s - execvp failed rc=%d errno=%d %s\n",
     648                       pszMsg, rc, errno, strerror(errno));
     649    }
     650    if (pid == -1)
     651        kObjCacheFatal(pEntry, "%s - fork() failed: %s\n", pszMsg, strerror(errno));
     652#endif
     653
     654    /*
     655     * Restore stdout.
     656     */
     657    close(1);
     658    fdStdOut = dup2(fdStdOut, 1);
     659
     660    /*
     661     * Read data from the child.
     662     */
     663    cbAlloc = pEntry->cbOldCpp ? (pEntry->cbOldCpp + 4*1024*1024) & ~(4*1024*1024 - 1) : 4*1024*1024;
     664    cbLeft = cbAlloc;
     665    *ppszOutput = psz = xmalloc(cbAlloc);
     666    for (;;)
     667    {
     668        long cbRead = _read(fds[0], psz, cbLeft);
     669        if (!cbRead)
     670            break;
     671        if (cbRead < 0 && errno != EINTR)
     672            kObjCacheFatal(pEntry, "%s - read(%d,,%ld) failed: %s\n", pszMsg, fds[0], (long)cbLeft, strerror(errno));
     673        psz += cbRead;
     674        cbLeft -= cbRead;
     675
     676        /* expand the buffer? */
     677        if (!cbLeft)
     678        {
     679            size_t off = psz - *ppszOutput;
     680            assert(off == cbAlloc);
     681            cbLeft = 4*1024*1024;
     682            cbAlloc += cbLeft;
     683            *ppszOutput = xrealloc(*ppszOutput, cbAlloc);
     684            psz = *ppszOutput + off;
     685        }
     686    }
     687    close(fds[0]);
     688    *pcchOutput = cbAlloc - cbLeft;
     689
     690    /*
     691     * Reap the child.
     692     */
     693#ifdef __WIN__
     694    pidWait = _cwait(&iStatus, pid, _WAIT_CHILD);
     695    if (pidWait == -1)
     696        kObjCacheFatal(pEntry, "%s - waitpid failed: %s\n",
     697                       pszMsg, strerror(errno));
     698    if (iStatus)
     699        kObjCacheFatal(pEntry, "%s - failed with rc %d\n", pszMsg, iStatus);
     700#else
     701    pidWait = waitpid(pid, &iStatus);
     702    while (pidWait < 0 && errno == EINTR)
     703        pidWait = waitpid(pid, &iStatus);
     704    if (pidWait != pid)
     705        kObjCacheFatal(pEntry, "%s - waitpid failed rc=%d: %s\n",
     706                       pszMsg, pidWait, strerror(errno));
     707    if (!WIFEXITED(iStatus))
     708        kObjCacheFatal(pEntry, "%s - abended (iStatus=%#x)\n", pszMsg, iStatus);
     709    if (WEXITSTATUS(iStatus))
     710        kObjCacheFatal(pEntry, "%s - failed with rc %d\n", pszMsg, WEXITSTATUS(iStatus));
     711#endif
     712    (void)cArgv;
     713}
     714#endif /* USE_PIPE */
     715
     716
     717/**
     718 * Reads the (new) output of the precompiler.
     719 *
     720 * Not used when using pipes.
     721 *
     722 * @param   pEntry      The cache entry. cbNewCpp and pszNewCppMapping will be updated.
     723 */
     724static void kObjCacheReadPrecompileOutput(PKOBJCACHE pEntry)
     725{
     726    pEntry->pszNewCppMapping = ReadFileInDir(pEntry->pszNewCppName, pEntry->pszDir, &pEntry->cbNewCpp);
    588727    if (!pEntry->pszNewCppMapping)
    589728        kObjCacheFatal(pEntry, "failed to open/read '%s' in '%s': %s\n",
    590729                       pEntry->pszNewCppName, pEntry->pszDir, strerror(errno));
    591     kObjCacheVerbose(pEntry, "precompiled file is %lu bytes long\n", (unsigned long)pEntry->cbNewCppMapping);
     730    kObjCacheVerbose(pEntry, "precompiled file is %lu bytes long\n", (unsigned long)pEntry->cbNewCpp);
     731}
     732
     733
     734/**
     735 * Worker for kObjCachePreCompile and calculates the checksum of
     736 * the precompiler output.
     737 *
     738 * @param   pEntry      The cache entry. NewSum will be updated.
     739 */
     740static void kObjCacheCalcChecksum(PKOBJCACHE pEntry)
     741{
     742    struct MD5Context MD5Ctx;
    592743
    593744    memset(&pEntry->NewSum, 0, sizeof(pEntry->NewSum));
    594     pEntry->NewSum.crc32 = crc32(0, pEntry->pszNewCppMapping, pEntry->cbNewCppMapping);
     745    pEntry->NewSum.crc32 = crc32(0, pEntry->pszNewCppMapping, pEntry->cbNewCpp);
    595746    MD5Init(&MD5Ctx);
    596     MD5Update(&MD5Ctx, pEntry->pszNewCppMapping, pEntry->cbNewCppMapping);
     747    MD5Update(&MD5Ctx, pEntry->pszNewCppMapping, pEntry->cbNewCpp);
    597748    MD5Final(&pEntry->NewSum.md5[0], &MD5Ctx);
    598749    kObjCacheVerbose(pEntry, "crc32=%#lx md5=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
     
    617768static void kObjCachePreCompile(PKOBJCACHE pEntry, const char **papszArgvPreComp, unsigned cArgvPreComp, const char *pszPreCompName, int fRedirStdOut)
    618769{
     770#ifdef USE_PIPE
     771    /*
     772     * Flag it as piped or non-piped.
     773     */
     774    if (fRedirStdOut)
     775        pEntry->fPiped = 1;
     776    else
     777#endif
     778        pEntry->fPiped = 0;
     779
    619780    /*
    620781     * Rename the old precompiled output to '-old'.
    621782     * We'll discard the old output and keep the new output, but because
    622783     * we might with to do a quick matchup later we can't remove it just now.
     784     * If we're using the pipe strategy, we will not do any renaming.
    623785     */
    624786    if (    pEntry->pszOldCppName
     787        &&  !pEntry->fPiped
    625788        &&  DoesFileInDirExist(pEntry->pszOldCppName, pEntry->pszDir))
    626789    {
     
    644807     */
    645808    kObjCacheVerbose(pEntry, "precompiling -> '%s'...\n", pEntry->pszNewCppName);
    646     if (fRedirStdOut)
    647         kObjCacheSpawn(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", pszPreCompName);
     809#ifdef USE_PIPE
     810    if (pEntry->fPiped)
     811        kObjCacheSpawnPipe(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", &pEntry->pszNewCppMapping, &pEntry->cbNewCpp);
    648812    else
    649         kObjCacheSpawn(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", NULL);
     813#endif
     814    {
     815        if (fRedirStdOut)
     816            kObjCacheSpawn(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", pszPreCompName);
     817        else
     818            kObjCacheSpawn(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", NULL);
     819        kObjCacheReadPrecompileOutput(pEntry);
     820    }
    650821    kObjCacheCalcChecksum(pEntry);
    651822}
     
    690861    }
    691862    pEntry->pszNewObjName = CalcRelativeName(pszObjName, pEntry->pszDir);
     863
     864    /*
     865     * If we executed the precompiled in piped mode we'll have to write the
     866     * precompiler output to disk so the compile has some thing to chew on.
     867     */
     868    if (pEntry->fPiped)
     869    {
     870        FILE *pFile = FOpenFileInDir(pEntry->pszNewCppName, pEntry->pszDir, "wb");
     871        if (!pFile)
     872            kObjCacheFatal(pEntry, "failed to create file '%s' in '%s': %s\n",
     873                           pEntry->pszNewCppName, pEntry->pszDir, strerror(errno));
     874        if (fwrite(pEntry->pszNewCppMapping, pEntry->cbNewCpp, 1, pFile) != 1)
     875            kObjCacheFatal(pEntry, "fwrite failed: %s\n", strerror(errno));
     876        if (fclose(pFile))
     877            kObjCacheFatal(pEntry, "fclose failed: %s\n", strerror(errno));
     878    }
    692879
    693880    /*
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette