Module Name:    src
Committed By:   sjg
Date:           Tue Jun  7 00:40:00 UTC 2016

Modified Files:
        src/usr.bin/make: dir.c hash.h make.h meta.c

Log Message:
Extend the mtimes cache used by dir.c so it can be used by others.

We store both st_mtime and st_mode, since some callers care about the
later.

Reviewed by: christos


To generate a diff of this commit:
cvs rdiff -u -r1.67 -r1.68 src/usr.bin/make/dir.c
cvs rdiff -u -r1.10 -r1.11 src/usr.bin/make/hash.h
cvs rdiff -u -r1.99 -r1.100 src/usr.bin/make/make.h
cvs rdiff -u -r1.60 -r1.61 src/usr.bin/make/meta.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/dir.c
diff -u src/usr.bin/make/dir.c:1.67 src/usr.bin/make/dir.c:1.68
--- src/usr.bin/make/dir.c:1.67	Tue Mar  5 22:01:43 2013
+++ src/usr.bin/make/dir.c	Tue Jun  7 00:40:00 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: dir.c,v 1.67 2013/03/05 22:01:43 christos Exp $	*/
+/*	$NetBSD: dir.c,v 1.68 2016/06/07 00:40:00 sjg Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -70,14 +70,14 @@
  */
 
 #ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: dir.c,v 1.67 2013/03/05 22:01:43 christos Exp $";
+static char rcsid[] = "$NetBSD: dir.c,v 1.68 2016/06/07 00:40:00 sjg Exp $";
 #else
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)dir.c	8.2 (Berkeley) 1/2/94";
 #else
-__RCSID("$NetBSD: dir.c,v 1.67 2013/03/05 22:01:43 christos Exp $");
+__RCSID("$NetBSD: dir.c,v 1.68 2016/06/07 00:40:00 sjg Exp $");
 #endif
 #endif /* not lint */
 #endif
@@ -244,6 +244,7 @@ static Hash_Table mtimes;   /* Results o
 			     * be two rules to update a single file, so this
 			     * should be ok, but... */
 
+static Hash_Table lmtimes;  /* same as mtimes but for lstat */
 
 static int DirFindName(const void *, const void *);
 static int DirMatchFiles(const char *, Path *, Lst);
@@ -256,6 +257,80 @@ static char *DirLookupSubdir(Path *, con
 static char *DirFindDot(Boolean, const char *, const char *);
 static char *DirLookupAbs(Path *, const char *, const char *);
 
+
+/*
+ * We use stat(2) a lot, cache the results
+ * mtime and mode are all we care about.
+ */
+struct cache_st {
+    time_t mtime;
+    mode_t  mode;
+};
+
+/* minimize changes below */
+static time_t
+Hash_GetTimeValue(Hash_Entry *entry)
+{
+    struct cache_st *cst;
+
+    cst = entry->clientPtr;
+    return cst->mtime;
+}
+
+#define CST_LSTAT 1
+#define CST_UPDATE 2
+
+static int
+cached_stats(Hash_Table *htp, const char *pathname, struct stat *st, int flags)
+{
+    Hash_Entry *entry;
+    struct cache_st *cst;
+    int rc;
+
+    if (!pathname || !pathname[0])
+	return -1;
+
+    entry = Hash_FindEntry(htp, pathname);
+
+    if (entry && (flags & CST_UPDATE) == 0) {
+	cst = entry->clientPtr;
+
+	memset(st, 0, sizeof(*st));
+	st->st_mtime = cst->mtime;
+	st->st_mode = cst->mode;
+	return 0;
+    }
+
+    rc = (flags & CST_LSTAT) ? lstat(pathname, st) : stat(pathname, st);
+    if (rc == -1)
+	return -1;
+
+    if (st->st_mtime == 0)
+	st->st_mtime = 1;      /* avoid confusion with missing file */
+
+    if (!entry)
+	entry = Hash_CreateEntry(htp, pathname, NULL);
+    if (!entry->clientPtr)
+	entry->clientPtr = bmake_malloc(sizeof(*cst));
+    cst = entry->clientPtr;
+    cst->mtime = st->st_mtime;
+    cst->mode = st->st_mode;
+
+    return 0;
+}
+
+int
+cached_stat(const char *pathname, void *st)
+{
+    return cached_stats(&mtimes, pathname, st, 0);
+}
+
+int
+cached_lstat(const char *pathname, void *st)
+{
+    return cached_stats(&lmtimes, pathname, st, CST_LSTAT);
+}
+
 /*-
  *-----------------------------------------------------------------------
  * Dir_Init --
@@ -274,6 +349,7 @@ Dir_Init(const char *cdname)
     dirSearchPath = Lst_Init(FALSE);
     openDirectories = Lst_Init(FALSE);
     Hash_InitTable(&mtimes, 0);
+    Hash_InitTable(&lmtimes, 0);
 
     Dir_InitCur(cdname);
 
@@ -901,7 +977,6 @@ static char *
 DirLookupSubdir(Path *p, const char *name)
 {
     struct stat	  stb;		/* Buffer for stat, if necessary */
-    Hash_Entry	 *entry;	/* Entry for mtimes table */
     char 	 *file;		/* the current filename to check */
 
     if (p != dot) {
@@ -917,9 +992,7 @@ DirLookupSubdir(Path *p, const char *nam
 	fprintf(debug_file, "checking %s ...\n", file);
     }
 
-    if (stat(file, &stb) == 0) {
-	if (stb.st_mtime == 0)
-		stb.st_mtime = 1;
+    if (cached_stat(file, &stb) == 0) {
 	/*
 	 * Save the modification time so if it's needed, we don't have
 	 * to fetch it again.
@@ -928,8 +1001,6 @@ DirLookupSubdir(Path *p, const char *nam
 	    fprintf(debug_file, "   Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
 		    file);
 	}
-	entry = Hash_CreateEntry(&mtimes, file, NULL);
-	Hash_SetTimeValue(entry, stb.st_mtime);
 	nearmisses += 1;
 	return (file);
     }
@@ -1312,15 +1383,11 @@ Dir_FindFile(const char *name, Lst path)
 	    fprintf(debug_file, "   got it (in mtime cache)\n");
 	}
 	return(bmake_strdup(name));
-    } else if (stat(name, &stb) == 0) {
-	if (stb.st_mtime == 0)
-		stb.st_mtime = 1;
-	entry = Hash_CreateEntry(&mtimes, name, NULL);
+    } else if (cached_stat(name, &stb) == 0) {
 	if (DEBUG(DIR)) {
 	    fprintf(debug_file, "   Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
 		    name);
 	}
-	Hash_SetTimeValue(entry, stb.st_mtime);
 	return (bmake_strdup(name));
     } else {
 	if (DEBUG(DIR)) {
@@ -1368,7 +1435,7 @@ Dir_FindHereOrAbove(char *here, char *se
 
 		/* try and stat(2) it ... */
 		snprintf(try, sizeof(try), "%s/%s", dirbase, search_path);
-		if (stat(try, &st) != -1) {
+		if (cached_stat(try, &st) != -1) {
 			/*
 			 * success!  if we found a file, chop off
 			 * the filename so we return a directory.
@@ -1489,12 +1556,12 @@ Dir_MTime(GNode *gn, Boolean recheck)
     else
 	entry = NULL;
     if (entry != NULL) {
+	stb.st_mtime = Hash_GetTimeValue(entry);
 	if (DEBUG(DIR)) {
 	    fprintf(debug_file, "Using cached time %s for %s\n",
-		    Targ_FmtTime(Hash_GetTimeValue(entry)), fullName);
+		    Targ_FmtTime(stb.st_mtime), fullName);
 	}
-	stb.st_mtime = Hash_GetTimeValue(entry);
-    } else if (stat(fullName, &stb) < 0) {
+    } else if (cached_stats(&mtimes, fullName, &stb, recheck ? CST_UPDATE : 0) < 0) {
 	if (gn->type & OP_MEMBER) {
 	    if (fullName != gn->path)
 		free(fullName);
@@ -1502,18 +1569,8 @@ Dir_MTime(GNode *gn, Boolean recheck)
 	} else {
 	    stb.st_mtime = 0;
 	}
-    } else {
-	if (stb.st_mtime == 0) {
-		/*
-		 * 0 handled specially by the code, if the time is really 0,
-		 * return something else instead
-		 */
-		stb.st_mtime = 1;
-	}
-	entry = Hash_CreateEntry(&mtimes, fullName, NULL);
-	Hash_SetTimeValue(entry, stb.st_mtime);
     }
-	
+
     if (fullName && gn->path == NULL) {
 	gn->path = fullName;
     }

Index: src/usr.bin/make/hash.h
diff -u src/usr.bin/make/hash.h:1.10 src/usr.bin/make/hash.h:1.11
--- src/usr.bin/make/hash.h:1.10	Sat Jan 24 10:59:09 2009
+++ src/usr.bin/make/hash.h	Tue Jun  7 00:40:00 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: hash.h,v 1.10 2009/01/24 10:59:09 dsl Exp $	*/
+/*	$NetBSD: hash.h,v 1.11 2016/06/07 00:40:00 sjg Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -89,10 +89,7 @@ typedef struct Hash_Entry {
     struct Hash_Entry *next;		/* Used to link together all the
     					 * entries associated with the same
 					 * bucket. */
-    union {
-	void	      *clientPtr;	/* Arbitrary pointer */
-	time_t	      clientTime;	/* Arbitrary Time */
-    } clientInfo;
+    void	      *clientPtr;	/* Arbitrary pointer */
     unsigned	      namehash;		/* hash value of key */
     char	      name[1];		/* key string */
 } Hash_Entry;
@@ -125,8 +122,7 @@ typedef struct Hash_Search {
  *     Hash_Entry *h;
  */
 
-#define Hash_GetValue(h) ((h)->clientInfo.clientPtr)
-#define Hash_GetTimeValue(h) ((h)->clientInfo.clientTime)
+#define Hash_GetValue(h) ((h)->clientPtr)
 
 /*
  * Hash_SetValue(h, val);
@@ -134,8 +130,7 @@ typedef struct Hash_Search {
  *     char *val;
  */
 
-#define Hash_SetValue(h, val) ((h)->clientInfo.clientPtr = (val))
-#define Hash_SetTimeValue(h, val) ((h)->clientInfo.clientTime = (val))
+#define Hash_SetValue(h, val) ((h)->clientPtr = (val))
 
 /*
  * Hash_Size(n) returns the number of words in an object of n bytes

Index: src/usr.bin/make/make.h
diff -u src/usr.bin/make/make.h:1.99 src/usr.bin/make/make.h:1.100
--- src/usr.bin/make/make.h:1.99	Fri Jun  3 01:21:59 2016
+++ src/usr.bin/make/make.h	Tue Jun  7 00:40:00 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: make.h,v 1.99 2016/06/03 01:21:59 sjg Exp $	*/
+/*	$NetBSD: make.h,v 1.100 2016/06/07 00:40:00 sjg Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -490,6 +490,8 @@ void Main_ExportMAKEFLAGS(Boolean);
 Boolean Main_SetObjdir(const char *);
 int mkTempFile(const char *, char **);
 int str2Lst_Append(Lst, char *, const char *);
+int cached_lstat(const char *, void *);
+int cached_stat(const char *, void *);
 
 #define	VARF_UNDEFERR	1
 #define	VARF_WANTRES	2

Index: src/usr.bin/make/meta.c
diff -u src/usr.bin/make/meta.c:1.60 src/usr.bin/make/meta.c:1.61
--- src/usr.bin/make/meta.c:1.60	Sat Jun  4 22:17:14 2016
+++ src/usr.bin/make/meta.c	Tue Jun  7 00:40:00 2016
@@ -1,4 +1,4 @@
-/*      $NetBSD: meta.c,v 1.60 2016/06/04 22:17:14 sjg Exp $ */
+/*      $NetBSD: meta.c,v 1.61 2016/06/07 00:40:00 sjg Exp $ */
 
 /*
  * Implement 'meta' mode.
@@ -425,7 +425,7 @@ meta_needed(GNode *gn, const char *dname
     }
 
     /* The object directory may not exist. Check it.. */
-    if (stat(dname, &fs) != 0) {
+    if (cached_stat(dname, &fs) != 0) {
 	if (verbose)
 	    fprintf(debug_file, "Skipping meta for %s: no .OBJDIR\n",
 		    gn->name);
@@ -1234,8 +1234,8 @@ meta_oodate(GNode *gn, Boolean oodate)
 		    if ((strstr("tmp", p)))
 			break;
 
-		    if ((link_src != NULL && lstat(p, &fs) < 0) ||
-			(link_src == NULL && stat(p, &fs) < 0)) {
+		    if ((link_src != NULL && cached_lstat(p, &fs) < 0) ||
+			(link_src == NULL && cached_stat(p, &fs) < 0)) {
 			if (Lst_Find(missingFiles, p, string_match) == NULL)
 				Lst_AtEnd(missingFiles, bmake_strdup(p));
 		    }
@@ -1324,7 +1324,7 @@ meta_oodate(GNode *gn, Boolean oodate)
 			    if (DEBUG(META))
 				fprintf(debug_file, "%s: %d: looking for: %s\n", fname, lineno, *sdp);
 #endif
-			    if (stat(*sdp, &fs) == 0) {
+			    if (cached_stat(*sdp, &fs) == 0) {
 				found = 1;
 				p = *sdp;
 			    }

Reply via email to