Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/make meta_oodate(): we should track 'latestdir' on a...



details:   https://anonhg.NetBSD.org/src/rev/48711a9a1b1b
branches:  trunk
changeset: 759444:48711a9a1b1b
user:      sjg <sjg%NetBSD.org@localhost>
date:      Thu Dec 09 22:30:16 2010 +0000

description:
meta_oodate(): we should track 'latestdir' on a per process basis.
Also, only consider target out of date if a not-found file is outside
'CWD'.  Ignore anything in "/tmp/" or tmpdir.

diffstat:

 usr.bin/make/main.c    |   43 ++++++----
 usr.bin/make/meta.c    |  184 ++++++++++++++++++++++++++++++++++++++++--------
 usr.bin/make/nonints.h |    3 +-
 3 files changed, 181 insertions(+), 49 deletions(-)

diffs (truncated from 362 to 300 lines):

diff -r f6f974c6a4c1 -r 48711a9a1b1b usr.bin/make/main.c
--- a/usr.bin/make/main.c       Thu Dec 09 21:27:31 2010 +0000
+++ b/usr.bin/make/main.c       Thu Dec 09 22:30:16 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: main.c,v 1.190 2010/09/13 15:36:57 sjg Exp $   */
+/*     $NetBSD: main.c,v 1.191 2010/12/09 22:30:16 sjg Exp $   */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -69,7 +69,7 @@
  */
 
 #ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: main.c,v 1.190 2010/09/13 15:36:57 sjg Exp $";
+static char rcsid[] = "$NetBSD: main.c,v 1.191 2010/12/09 22:30:16 sjg Exp $";
 #else
 #include <sys/cdefs.h>
 #ifndef lint
@@ -81,7 +81,7 @@
 #if 0
 static char sccsid[] = "@(#)main.c     8.3 (Berkeley) 3/19/94";
 #else
-__RCSID("$NetBSD: main.c,v 1.190 2010/09/13 15:36:57 sjg Exp $");
+__RCSID("$NetBSD: main.c,v 1.191 2010/12/09 22:30:16 sjg Exp $");
 #endif
 #endif /* not lint */
 #endif
@@ -1966,6 +1966,27 @@
     }
 }
 
+char *
+getTmpdir(void)
+{
+    static char *tmpdir = NULL;
+
+    if (!tmpdir) {
+       struct stat st;
+
+       /*
+        * Honor $TMPDIR but only if it is valid.
+        * Ensure it ends with /.
+        */
+       tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL, 0);
+       if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
+           free(tmpdir);
+           tmpdir = bmake_strdup(_PATH_TMP);
+       }
+    }
+    return tmpdir;
+}
+
 /*
  * Create and open a temp file using "pattern".
  * If "fnamep" is provided set it to a copy of the filename created.
@@ -1980,20 +2001,8 @@
     
     if (!pattern)
        pattern = TMPPAT;
-
-    if (!tmpdir) {
-       struct stat st;
-
-       /*
-        * Honor $TMPDIR but only if it is valid.
-        * Ensure it ends with /.
-        */
-       tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL, 0);
-       if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
-           free(tmpdir);
-           tmpdir = bmake_strdup(_PATH_TMP);
-       }
-    }
+    if (!tmpdir)
+       tmpdir = getTmpdir();
     if (pattern[0] == '/') {
        snprintf(tfile, sizeof(tfile), "%s", pattern);
     } else {
diff -r f6f974c6a4c1 -r 48711a9a1b1b usr.bin/make/meta.c
--- a/usr.bin/make/meta.c       Thu Dec 09 21:27:31 2010 +0000
+++ b/usr.bin/make/meta.c       Thu Dec 09 22:30:16 2010 +0000
@@ -695,15 +695,24 @@
 /*
  * When running with 'meta' functionality, a target can be out-of-date
  * if any of the references in it's meta data file is more recent.
+ * We have to track the latestdir on a per-process basis.
  */
+#define LDIR_VNAME_FMT ".meta.%d.ldir"
+
 Boolean
 meta_oodate(GNode *gn, Boolean oodate)
 {
+    static char *tmpdir = NULL;
+    char ldir_vname[64];
+    char cwd[MAXPATHLEN];
     char latestdir[MAXPATHLEN];
     char fname[MAXPATHLEN];
     char fname1[MAXPATHLEN];
+    char fname2[MAXPATHLEN];
     char *p;
     char *cp;
+    size_t cwdlen;
+    size_t tmplen = 0;
     FILE *fp;
     Boolean ignoreOODATE = FALSE;
 
@@ -718,7 +727,7 @@
      */
     Make_DoAllVar(gn);
 
-    if (getcwd(latestdir, sizeof(latestdir)) == NULL)
+    if (getcwd(cwd, sizeof(cwd)) == NULL)
        err(1, "Could not get current working directory");
 
     meta_name(gn, fname, sizeof(fname), NULL, NULL);
@@ -727,6 +736,8 @@
        static char *buf = NULL;
        static size_t bufsz;
        int lineno = 0;
+       int lastpid = 0;
+       int pid;
        int f = 0;
        int x;
        LstNode ln;
@@ -736,10 +747,17 @@
            bufsz = 8 * BUFSIZ;
            buf = bmake_malloc(bufsz);
        }
-       
+
+       if (!tmpdir) {
+           tmpdir = getTmpdir();
+           tmplen = strlen(tmpdir);
+       }
+
        /* we want to track all the .meta we read */
        Var_Append(".MAKE.META.FILES", fname, VAR_GLOBAL);
 
+       cwdlen = strlen(cwd);
+
        ln = Lst_First(gn->commands);
        while (!oodate && (x = fgetLine(&buf, &bufsz, 0, fp)) > 0) {
            lineno++;
@@ -764,28 +782,102 @@
            p = buf;
            strsep(&p, " ");
            if (f) {
+               /*
+                * We are in the 'filemon' output section.
+                * Each record from filemon follows the general form:
+                *
+                * <key> <pid> <data>
+                *
+                * Where:
+                * <key> is a single letter, denoting the syscall.
+                * <pid> is the process that made the syscall.
+                * <data> is the arguments (of interest).
+                */
+               switch(buf[0]) {
+               case '#':               /* comment */
+               case 'V':               /* version */
+                   break;
+               default:
+                   /*
+                    * We need to track pathnames per-process.
+                    *
+                    * Each process run by make, starts off in the 'CWD'
+                    * recorded in the .meta file, if it chdirs ('C')
+                    * elsewhere we need to track that - but only for
+                    * that process.  If it forks ('F'), we initialize
+                    * the child to have the same cwd as its parent.
+                    *
+                    * We also need to track the 'latestdir' of
+                    * interest.  This is usually the same as cwd, but
+                    * not if a process is reading directories.
+                    *
+                    * Each time we spot a different process ('pid')
+                    * we save the current value of 'latestdir' in a
+                    * variable qualified by 'lastpid', and
+                    * re-initialize 'latestdir' to any pre-saved
+                    * value for the current 'pid' and 'CWD' if none.
+                    */
+                   pid = atoi(p);
+                   if (pid > 0 && pid != lastpid) {
+                       char *ldir;
+                       char *tp;
+                   
+                       if (lastpid > 0) {
+                           /* We need to remember this. */
+                           Var_Set(ldir_vname, latestdir, VAR_GLOBAL, 0);
+                       }
+                       snprintf(ldir_vname, sizeof(ldir_vname), LDIR_VNAME_FMT, pid);
+                       lastpid = pid;
+                       ldir = Var_Value(ldir_vname, VAR_GLOBAL, &tp);
+                       if (ldir) {
+                           strlcpy(latestdir, ldir, sizeof(latestdir));
+                           if (tp)
+                               free(tp);
+                       } else 
+                           strlcpy(latestdir, cwd, sizeof(latestdir));
+                   }
+                   /* Skip past the pid. */
+                   if (strsep(&p, " ") == NULL)
+                       continue;
+                   break;
+               }
+
                /* Process according to record type. */
                switch (buf[0]) {
-               case 'C':
-                   /* Skip the pid. */
-                   if (strsep(&p, " ") == NULL)
-                       break;
+               case 'X':               /* eXit */
+                   Var_Delete(ldir_vname, VAR_GLOBAL);
+                   lastpid = 0;        /* no need to save ldir_vname */
+                   break;
+
+               case 'F':               /* [v]Fork */
+                   {
+                       char cldir[64];
+                       int child;
 
+                       child = atoi(p);
+                       if (child > 0) {
+                           snprintf(cldir, sizeof(cldir), LDIR_VNAME_FMT, child);
+                           Var_Set(cldir, latestdir, VAR_GLOBAL, 0);
+                       }
+                   }
+                   break;
+
+               case 'C':               /* Chdir */
                    /* Update the latest directory. */
                    strlcpy(latestdir, p, sizeof(latestdir));
                    break;
 
-               case 'R':
-               case 'E':
-                   /* Skip the pid. */
-                   if (strsep(&p, " ") == NULL)
-                       break;
-
+               case 'R':               /* Read */
+               case 'E':               /* Exec */
                    /*
                     * Check for runtime files that can't
                     * be part of the dependencies because
                     * they are _expected_ to change.
                     */
+                   if (strncmp(p, "/tmp/", 5) == 0 ||
+                       strncmp(p, tmpdir, tmplen) == 0)
+                       break;
+
                    if (strncmp(p, "/var/", 5) == 0)
                        break;
 
@@ -798,39 +890,69 @@
                        break;
 
                    /*
-                    * The rest of the record is the
-                    * file name.
-                    * Check if it's not an absolute
-                    * path.
+                    * The rest of the record is the file name.
+                    * Check if it's not an absolute path.
                     */
-                   if (*p != '/') {
-                       /* Use the latest path seen. */
-                       snprintf(fname1, sizeof(fname1), "%s/%s", latestdir, p);
-                       p = fname1;
-                   }
+                   {
+                       char *sdirs[4];
+                       char **sdp;
+                       int sdx = 0;
+                       int found = 0;
+
+                       if (*p == '/') {
+                           sdirs[sdx++] = p; /* done */
+                       } else {
+                           if (strcmp(".", p) == 0)
+                               continue;  /* no point */
+
+                           /* Check vs latestdir */
+                           snprintf(fname1, sizeof(fname1), "%s/%s", latestdir, p);
+                           sdirs[sdx++] = fname1;
+
+                           if (strcmp(latestdir, cwd) != 0) {
+                               /* Check vs cwd */
+                               snprintf(fname2, sizeof(fname2), "%s/%s", cwd, p);
+                               sdirs[sdx++] = fname2;
+                           }
+                       }
+                       sdirs[sdx++] = NULL;
 
-                   if (stat(p, &fs) == 0) {
-                       if (!S_ISDIR(fs.st_mode) &&
-                           fs.st_mtime > gn->mtime) {
+                       for (sdp = sdirs; *sdp && !found; sdp++) {



Home | Main Index | Thread Index | Old Index